Message ID | 1550763193-14128-9-git-send-email-galpress@amazon.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | RDMA/efa: Elastic Fabric Adapter (EFA) driver | expand |
On Thu, Feb 21, 2019 at 05:33:10PM +0200, Gal Pressman wrote: > Add the EFA common commands implementation. > > Signed-off-by: Gal Pressman <galpress@amazon.com> > --- > drivers/infiniband/hw/efa/efa_com_cmd.c | 726 ++++++++++++++++++++++++++++++++ > 1 file changed, 726 insertions(+) > create mode 100644 drivers/infiniband/hw/efa/efa_com_cmd.c > > diff --git a/drivers/infiniband/hw/efa/efa_com_cmd.c b/drivers/infiniband/hw/efa/efa_com_cmd.c > new file mode 100644 > index 000000000000..05eb8f723197 > --- /dev/null > +++ b/drivers/infiniband/hw/efa/efa_com_cmd.c > @@ -0,0 +1,726 @@ > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause > +/* > + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All rights reserved. > + */ > + > +#include "efa.h" > +#include "efa_com.h" > +#include "efa_com_cmd.h" > + > +void efa_com_set_dma_addr(dma_addr_t addr, u32 *addr_high, u32 *addr_low) > +{ > + *addr_low = addr & GENMASK(31, 0); > + *addr_high = (addr >> 32) & GENMASK(31, 0); > +} > + > +int efa_com_create_qp(struct efa_com_dev *edev, > + struct efa_com_create_qp_params *params, > + struct efa_com_create_qp_result *res) > +{ > + struct efa_admin_create_qp_resp cmd_completion; > + struct efa_admin_create_qp_cmd create_qp_cmd; > + struct efa_com_admin_queue *aq = &edev->aq; > + int err; > + > + memset(&create_qp_cmd, 0x0, sizeof(create_qp_cmd)); Prefer {} initialization over memset(). > + > + create_qp_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_QP; > + > + create_qp_cmd.pd = params->pd; > + create_qp_cmd.qp_type = params->qp_type; > + create_qp_cmd.flags = 0; > + create_qp_cmd.sq_base_addr = 0; > + create_qp_cmd.rq_base_addr = params->rq_base_addr; > + create_qp_cmd.send_cq_idx = params->send_cq_idx; > + create_qp_cmd.recv_cq_idx = params->recv_cq_idx; > + create_qp_cmd.qp_alloc_size.send_queue_ring_size = > + params->sq_ring_size_in_bytes; > + create_qp_cmd.qp_alloc_size.send_queue_depth = > + params->sq_depth; > + create_qp_cmd.qp_alloc_size.recv_queue_ring_size = > + params->rq_ring_size_in_bytes; > + create_qp_cmd.qp_alloc_size.recv_queue_depth = > + params->rq_depth; > + create_qp_cmd.uar = params->uarn; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&create_qp_cmd, > + sizeof(create_qp_cmd), > + (struct efa_admin_acq_entry *)&cmd_completion, > + sizeof(cmd_completion)); > + if (unlikely(err)) { There is no need to add likely/unlikely not in data path. > + efa_err(edev->dmadev, "Failed to create qp [%d]\n", err); > + return err; > + } > + > + res->qp_handle = cmd_completion.qp_handle; > + res->qp_num = cmd_completion.qp_num; > + res->sq_db_offset = cmd_completion.sq_db_offset; > + res->rq_db_offset = cmd_completion.rq_db_offset; > + res->llq_descriptors_offset = cmd_completion.llq_descriptors_offset; > + res->send_sub_cq_idx = cmd_completion.send_sub_cq_idx; > + res->recv_sub_cq_idx = cmd_completion.recv_sub_cq_idx; > + > + return err; > +} > + > +int efa_com_modify_qp(struct efa_com_dev *edev, > + struct efa_com_modify_qp_params *params) > +{ > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_modify_qp_resp resp; > + struct efa_admin_modify_qp_cmd cmd; > + int err; > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.aq_common_desc.opcode = EFA_ADMIN_MODIFY_QP; > + cmd.modify_mask = params->modify_mask; > + cmd.qp_handle = params->qp_handle; > + cmd.qp_state = params->qp_state; > + cmd.cur_qp_state = params->cur_qp_state; > + cmd.qkey = params->qkey; > + cmd.sq_psn = params->sq_psn; > + cmd.sq_drained_async_notify = params->sq_drained_async_notify; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&cmd, > + sizeof(cmd), > + (struct efa_admin_acq_entry *)&resp, > + sizeof(resp)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to modify qp-%u modify_mask[%#x] [%d]\n", > + cmd.qp_handle, cmd.modify_mask, err); > + return err; > + } > + > + return 0; > +} > + > +int efa_com_query_qp(struct efa_com_dev *edev, > + struct efa_com_query_qp_params *params, > + struct efa_com_query_qp_result *result) > +{ > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_query_qp_resp resp; > + struct efa_admin_query_qp_cmd cmd; > + int err; > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.aq_common_desc.opcode = EFA_ADMIN_QUERY_QP; > + cmd.qp_handle = params->qp_handle; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&cmd, > + sizeof(cmd), > + (struct efa_admin_acq_entry *)&resp, > + sizeof(resp)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to query qp-%u [%d]\n", > + cmd.qp_handle, err); > + return err; > + } > + > + result->qp_state = resp.qp_state; > + result->qkey = resp.qkey; > + result->sq_draining = resp.sq_draining; > + result->sq_psn = resp.sq_psn; > + > + return 0; > +} > + > +int efa_com_destroy_qp(struct efa_com_dev *edev, > + struct efa_com_destroy_qp_params *params) > +{ > + struct efa_admin_destroy_qp_resp cmd_completion; > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_destroy_qp_cmd qp_cmd; > + int err; > + > + memset(&qp_cmd, 0x0, sizeof(qp_cmd)); > + > + qp_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_QP; > + > + qp_cmd.qp_handle = params->qp_handle; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&qp_cmd, > + sizeof(qp_cmd), > + (struct efa_admin_acq_entry *)&cmd_completion, > + sizeof(cmd_completion)); > + if (unlikely(err)) > + efa_err(edev->dmadev, "Failed to destroy qp-%u [%d]\n", > + qp_cmd.qp_handle, err); > + > + return err; > +} > + > +int efa_com_create_cq(struct efa_com_dev *edev, > + struct efa_com_create_cq_params *params, > + struct efa_com_create_cq_result *result) > +{ > + struct efa_admin_create_cq_resp cmd_completion; > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_create_cq_cmd create_cmd; > + int err; > + > + memset(&create_cmd, 0x0, sizeof(create_cmd)); > + create_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_CQ; > + create_cmd.cq_caps_2 = (params->entry_size_in_bytes / 4) & > + EFA_ADMIN_CREATE_CQ_CMD_CQ_ENTRY_SIZE_WORDS_MASK; > + create_cmd.msix_vector_idx = 0; You already initialized everything to zero. > + create_cmd.cq_depth = params->cq_depth; > + create_cmd.num_sub_cqs = params->num_sub_cqs; > + create_cmd.uar = params->uarn; > + > + efa_com_set_dma_addr(params->dma_addr, > + &create_cmd.cq_ba.mem_addr_high, > + &create_cmd.cq_ba.mem_addr_low); > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&create_cmd, > + sizeof(create_cmd), > + (struct efa_admin_acq_entry *)&cmd_completion, > + sizeof(cmd_completion)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to create cq[%d]\n", err); > + return err; > + } > + > + result->cq_idx = cmd_completion.cq_idx; > + result->actual_depth = params->cq_depth; > + > + return err; > +} > + > +int efa_com_destroy_cq(struct efa_com_dev *edev, > + struct efa_com_destroy_cq_params *params) > +{ > + struct efa_admin_destroy_cq_resp destroy_resp; > + struct efa_admin_destroy_cq_cmd destroy_cmd; > + struct efa_com_admin_queue *aq = &edev->aq; > + int err; > + > + memset(&destroy_cmd, 0x0, sizeof(destroy_cmd)); > + > + destroy_cmd.cq_idx = params->cq_idx; > + destroy_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_CQ; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&destroy_cmd, > + sizeof(destroy_cmd), > + (struct efa_admin_acq_entry *)&destroy_resp, > + sizeof(destroy_resp)); > + > + if (unlikely(err)) > + efa_err(edev->dmadev, > + "Failed to destroy CQ-%u [%d]\n", params->cq_idx, err); > + > + return err; > +} > + > +int efa_com_register_mr(struct efa_com_dev *edev, > + struct efa_com_reg_mr_params *params, > + struct efa_com_reg_mr_result *result) > +{ > + struct efa_admin_reg_mr_resp cmd_completion; > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_reg_mr_cmd mr_cmd; > + int err; > + > + memset(&mr_cmd, 0x0, sizeof(mr_cmd)); > + > + mr_cmd.aq_common_desc.opcode = EFA_ADMIN_REG_MR; > + mr_cmd.aq_common_desc.flags = 0; > + > + mr_cmd.pd = params->pd; > + mr_cmd.mr_length = params->mr_length_in_bytes; > + > + mr_cmd.flags |= 0 & > + EFA_ADMIN_REG_MR_CMD_MEM_ADDR_PHY_MODE_EN_MASK; > + mr_cmd.flags |= params->page_shift & > + EFA_ADMIN_REG_MR_CMD_PHYS_PAGE_SIZE_SHIFT_MASK; > + mr_cmd.iova = params->iova; > + mr_cmd.permissions |= params->permissions & > + EFA_ADMIN_REG_MR_CMD_LOCAL_WRITE_ENABLE_MASK; > + > + if (params->inline_pbl) { > + memcpy(mr_cmd.pbl.inline_pbl_array, > + params->pbl.inline_pbl_array, > + sizeof(mr_cmd.pbl.inline_pbl_array)); > + } else { > + mr_cmd.pbl.pbl.length = params->pbl.pbl.length; > + mr_cmd.pbl.pbl.address.mem_addr_low = > + params->pbl.pbl.address.mem_addr_low; > + mr_cmd.pbl.pbl.address.mem_addr_high = > + params->pbl.pbl.address.mem_addr_high; > + mr_cmd.aq_common_desc.flags |= > + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_MASK; > + if (params->indirect) > + mr_cmd.aq_common_desc.flags |= > + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; > + } > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&mr_cmd, > + sizeof(mr_cmd), > + (struct efa_admin_acq_entry *)&cmd_completion, > + sizeof(cmd_completion)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to register mr [%d]\n", err); > + return err; > + } > + > + result->l_key = cmd_completion.l_key; > + result->r_key = cmd_completion.r_key; > + > + return err; > +} > + > +int efa_com_dereg_mr(struct efa_com_dev *edev, > + struct efa_com_dereg_mr_params *params) > +{ > + struct efa_admin_dereg_mr_resp cmd_completion; > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_dereg_mr_cmd mr_cmd; > + int err; > + > + memset(&mr_cmd, 0x0, sizeof(mr_cmd)); > + > + mr_cmd.aq_common_desc.opcode = EFA_ADMIN_DEREG_MR; > + mr_cmd.l_key = params->l_key; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&mr_cmd, > + sizeof(mr_cmd), > + (struct efa_admin_acq_entry *)&cmd_completion, > + sizeof(cmd_completion)); > + if (unlikely(err)) > + efa_err(edev->dmadev, > + "Failed to de-register mr(lkey-%u) [%d]\n", > + mr_cmd.l_key, err); > + > + return err; > +} > + > +int efa_com_create_ah(struct efa_com_dev *edev, > + struct efa_com_create_ah_params *params, > + struct efa_com_create_ah_result *result) > +{ > + struct efa_admin_create_ah_resp cmd_completion; > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_create_ah_cmd ah_cmd; > + int err; > + > + memset(&ah_cmd, 0x0, sizeof(ah_cmd)); > + > + ah_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_AH; > + > + memcpy(ah_cmd.dest_addr, params->dest_addr, sizeof(ah_cmd.dest_addr)); > + ah_cmd.pd = params->pdn; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&ah_cmd, > + sizeof(ah_cmd), > + (struct efa_admin_acq_entry *)&cmd_completion, > + sizeof(cmd_completion)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to create ah [%d]\n", err); > + return err; > + } > + > + result->ah = cmd_completion.ah; > + > + return err; > +} > + > +int efa_com_destroy_ah(struct efa_com_dev *edev, > + struct efa_com_destroy_ah_params *params) > +{ > + struct efa_admin_destroy_ah_resp cmd_completion; > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_destroy_ah_cmd ah_cmd; > + int err; > + > + memset(&ah_cmd, 0x0, sizeof(ah_cmd)); > + > + ah_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_AH; > + ah_cmd.ah = params->ah; > + ah_cmd.pd = params->pdn; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&ah_cmd, > + sizeof(ah_cmd), > + (struct efa_admin_acq_entry *)&cmd_completion, > + sizeof(cmd_completion)); > + if (unlikely(err)) > + efa_err(edev->dmadev, > + "Failed to destroy ah-%d pd-%d [%d]\n", > + ah_cmd.ah, ah_cmd.pd, err); > + > + return err; > +} > + > +static bool > +efa_com_check_supported_feature_id(struct efa_com_dev *edev, > + enum efa_admin_aq_feature_id feature_id) > +{ > + u32 feature_mask = 1 << feature_id; > + > + /* Device attributes is always supported */ > + if (feature_id != EFA_ADMIN_DEVICE_ATTR && > + !(edev->supported_features & feature_mask)) > + return false; > + > + return true; > +} > + > +static int efa_com_get_feature_ex(struct efa_com_dev *edev, > + struct efa_admin_get_feature_resp *get_resp, > + enum efa_admin_aq_feature_id feature_id, > + dma_addr_t control_buf_dma_addr, > + u32 control_buff_size) > +{ > + struct efa_admin_get_feature_cmd get_cmd; > + struct efa_com_admin_queue *aq; > + int err; > + > + if (!efa_com_check_supported_feature_id(edev, feature_id)) { > + efa_err(edev->dmadev, "Feature %d isn't supported\n", feature_id); > + return -EOPNOTSUPP; > + } > + > + memset(&get_cmd, 0x0, sizeof(get_cmd)); > + aq = &edev->aq; > + > + get_cmd.aq_common_descriptor.opcode = EFA_ADMIN_GET_FEATURE; > + > + if (control_buff_size) > + get_cmd.aq_common_descriptor.flags = > + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; > + else > + get_cmd.aq_common_descriptor.flags = 0; > + > + efa_com_set_dma_addr(control_buf_dma_addr, > + &get_cmd.control_buffer.address.mem_addr_high, > + &get_cmd.control_buffer.address.mem_addr_low); > + > + get_cmd.control_buffer.length = control_buff_size; > + get_cmd.feature_common.feature_id = feature_id; > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *) > + &get_cmd, > + sizeof(get_cmd), > + (struct efa_admin_acq_entry *) > + get_resp, > + sizeof(*get_resp)); > + > + if (unlikely(err)) > + efa_err(edev->dmadev, > + "Failed to submit get_feature command %d [%d]\n", > + feature_id, err); > + > + return err; > +} > + > +static int efa_com_get_feature(struct efa_com_dev *edev, > + struct efa_admin_get_feature_resp *get_resp, > + enum efa_admin_aq_feature_id feature_id) > +{ > + return efa_com_get_feature_ex(edev, get_resp, feature_id, 0, 0); > +} > + > +int efa_com_get_network_attr(struct efa_com_dev *edev, > + struct efa_com_get_network_attr_result *result) > +{ > + struct efa_admin_get_feature_resp resp; > + int err; > + > + err = efa_com_get_feature(edev, &resp, > + EFA_ADMIN_NETWORK_ATTR); > + if (unlikely(err)) { > + efa_err(edev->dmadev, > + "Failed to get network attributes %d\n", err); > + return err; > + } > + > + memcpy(result->addr, resp.u.network_attr.addr, > + sizeof(resp.u.network_attr.addr)); > + result->mtu = resp.u.network_attr.mtu; > + > + return 0; > +} > + > +int efa_com_get_device_attr(struct efa_com_dev *edev, > + struct efa_com_get_device_attr_result *result) > +{ > + struct efa_admin_get_feature_resp resp; > + int err; > + > + err = efa_com_get_feature(edev, &resp, EFA_ADMIN_DEVICE_ATTR); > + if (unlikely(err)) { > + efa_err(edev->dmadev, > + "Failed to get device attributes %d\n", err); > + return err; > + } > + > + result->page_size_cap = resp.u.device_attr.page_size_cap; > + result->fw_version = resp.u.device_attr.fw_version; > + result->admin_api_version = resp.u.device_attr.admin_api_version; > + result->device_version = resp.u.device_attr.device_version; > + result->supported_features = resp.u.device_attr.supported_features; > + result->phys_addr_width = resp.u.device_attr.phys_addr_width; > + result->virt_addr_width = resp.u.device_attr.virt_addr_width; > + result->db_bar = resp.u.device_attr.db_bar; > + > + if (unlikely(result->admin_api_version < 1)) { > + efa_err(edev->dmadev, > + "Failed to get device attr api version [%u < 1]\n", > + result->admin_api_version); > + return -EINVAL; > + } > + > + edev->supported_features = resp.u.device_attr.supported_features; > + err = efa_com_get_feature(edev, &resp, > + EFA_ADMIN_QUEUE_ATTR); > + if (unlikely(err)) { > + efa_err(edev->dmadev, > + "Failed to get network attributes %d\n", err); > + return err; > + } > + > + result->max_qp = resp.u.queue_attr.max_qp; > + result->max_sq_depth = resp.u.queue_attr.max_sq_depth; > + result->max_rq_depth = resp.u.queue_attr.max_rq_depth; > + result->max_cq = resp.u.queue_attr.max_cq; > + result->max_cq_depth = resp.u.queue_attr.max_cq_depth; > + result->inline_buf_size = resp.u.queue_attr.inline_buf_size; > + result->max_sq_sge = resp.u.queue_attr.max_wr_send_sges; > + result->max_rq_sge = resp.u.queue_attr.max_wr_recv_sges; > + result->max_mr = resp.u.queue_attr.max_mr; > + result->max_mr_pages = resp.u.queue_attr.max_mr_pages; > + result->max_pd = resp.u.queue_attr.max_pd; > + result->max_ah = resp.u.queue_attr.max_ah; > + result->max_llq_size = resp.u.queue_attr.max_llq_size; > + result->sub_cqs_per_cq = resp.u.queue_attr.sub_cqs_per_cq; > + > + return 0; > +} > + > +int efa_com_get_hw_hints(struct efa_com_dev *edev, > + struct efa_com_get_hw_hints_result *result) > +{ > + struct efa_admin_get_feature_resp resp; > + int err; > + > + err = efa_com_get_feature(edev, &resp, EFA_ADMIN_HW_HINTS); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to get hw hints %d\n", err); > + return err; > + } > + > + result->admin_completion_timeout = resp.u.hw_hints.admin_completion_timeout; > + result->driver_watchdog_timeout = resp.u.hw_hints.driver_watchdog_timeout; > + result->mmio_read_timeout = resp.u.hw_hints.mmio_read_timeout; > + result->poll_interval = resp.u.hw_hints.poll_interval; > + > + return 0; > +} > + > +static int efa_com_set_feature_ex(struct efa_com_dev *edev, > + struct efa_admin_set_feature_resp *set_resp, > + struct efa_admin_set_feature_cmd *set_cmd, > + enum efa_admin_aq_feature_id feature_id, > + dma_addr_t control_buf_dma_addr, > + u32 control_buff_size) > +{ > + struct efa_com_admin_queue *aq; > + int err; > + > + if (!efa_com_check_supported_feature_id(edev, feature_id)) { > + efa_err(edev->dmadev, "Feature %d isn't supported\n", feature_id); > + return -EOPNOTSUPP; > + } > + > + aq = &edev->aq; > + > + set_cmd->aq_common_descriptor.opcode = EFA_ADMIN_SET_FEATURE; > + if (control_buff_size) { > + set_cmd->aq_common_descriptor.flags = > + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; > + efa_com_set_dma_addr(control_buf_dma_addr, > + &set_cmd->control_buffer.address.mem_addr_high, > + &set_cmd->control_buffer.address.mem_addr_low); > + } else { > + set_cmd->aq_common_descriptor.flags = 0; > + } > + > + set_cmd->control_buffer.length = control_buff_size; > + set_cmd->feature_common.feature_id = feature_id; > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)set_cmd, > + sizeof(*set_cmd), > + (struct efa_admin_acq_entry *)set_resp, > + sizeof(*set_resp)); > + > + if (unlikely(err)) > + efa_err(edev->dmadev, > + "Failed to submit set_feature command %d error: %d\n", > + feature_id, err); > + > + return err; > +} > + > +static int efa_com_set_feature(struct efa_com_dev *edev, > + struct efa_admin_set_feature_resp *set_resp, > + struct efa_admin_set_feature_cmd *set_cmd, > + enum efa_admin_aq_feature_id feature_id) > +{ > + return efa_com_set_feature_ex(edev, set_resp, set_cmd, feature_id, > + 0, 0); > +} > + > +int efa_com_set_aenq_config(struct efa_com_dev *edev, u32 groups) > +{ > + struct efa_admin_get_feature_resp get_resp; > + struct efa_admin_set_feature_resp set_resp; > + struct efa_admin_set_feature_cmd cmd; > + int err; > + > + efa_dbg(edev->dmadev, > + "Configuring aenq with groups[0x%x]\n", groups); > + > + err = efa_com_get_feature(edev, &get_resp, EFA_ADMIN_AENQ_CONFIG); > + if (unlikely(err)) { > + efa_err(edev->dmadev, > + "Failed to get aenq attributes: %d\n", err); > + return err; > + } > + > + efa_dbg(edev->dmadev, > + "Get aenq groups: supported[0x%x] enabled[0x%x]\n", > + get_resp.u.aenq.supported_groups, > + get_resp.u.aenq.enabled_groups); > + > + if ((get_resp.u.aenq.supported_groups & groups) != groups) { > + efa_err(edev->dmadev, > + "Trying to set unsupported aenq groups[0x%x] supported[0x%x]\n", > + groups, get_resp.u.aenq.supported_groups); > + return -EOPNOTSUPP; > + } > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.u.aenq.enabled_groups = groups; > + err = efa_com_set_feature(edev, &set_resp, &cmd, > + EFA_ADMIN_AENQ_CONFIG); > + if (unlikely(err)) { > + efa_err(edev->dmadev, > + "Failed to set aenq attributes: %d\n", err); > + return err; > + } > + > + return 0; > +} > + > +int efa_com_alloc_pd(struct efa_com_dev *edev, > + struct efa_com_alloc_pd_result *result) > +{ > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_alloc_pd_resp resp; > + struct efa_admin_alloc_pd_cmd cmd; > + int err; > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.aq_common_descriptor.opcode = EFA_ADMIN_ALLOC_PD; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&cmd, > + sizeof(cmd), > + (struct efa_admin_acq_entry *)&resp, > + sizeof(resp)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to allocate pd[%d]\n", err); > + return err; > + } > + > + result->pdn = resp.pd; > + > + return 0; > +} > + > +int efa_com_dealloc_pd(struct efa_com_dev *edev, > + struct efa_com_dealloc_pd_params *params) > +{ > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_dealloc_pd_resp resp; > + struct efa_admin_dealloc_pd_cmd cmd; > + int err; > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.aq_common_descriptor.opcode = EFA_ADMIN_DEALLOC_PD; > + cmd.pd = params->pdn; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&cmd, > + sizeof(cmd), > + (struct efa_admin_acq_entry *)&resp, > + sizeof(resp)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to deallocate pd-%u [%d]\n", > + cmd.pd, err); > + return err; > + } > + > + return 0; > +} > + > +int efa_com_alloc_uar(struct efa_com_dev *edev, > + struct efa_com_alloc_uar_result *result) > +{ > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_alloc_uar_resp resp; > + struct efa_admin_alloc_uar_cmd cmd; > + int err; > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.aq_common_descriptor.opcode = EFA_ADMIN_ALLOC_UAR; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&cmd, > + sizeof(cmd), > + (struct efa_admin_acq_entry *)&resp, > + sizeof(resp)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to allocate uar[%d]\n", err); > + return err; > + } > + > + result->uarn = resp.uar; > + > + return 0; > +} > + > +int efa_com_dealloc_uar(struct efa_com_dev *edev, > + struct efa_com_dealloc_uar_params *params) > +{ > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_dealloc_uar_resp resp; > + struct efa_admin_dealloc_uar_cmd cmd; > + int err; > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.aq_common_descriptor.opcode = EFA_ADMIN_DEALLOC_UAR; > + cmd.uar = params->uarn; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&cmd, > + sizeof(cmd), > + (struct efa_admin_acq_entry *)&resp, > + sizeof(resp)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to deallocate uar-%u [%d]\n", > + cmd.uar, err); > + return err; > + } > + > + return 0; > +} > -- > 2.7.4 >
On 2/21/2019 9:33 AM, Gal Pressman wrote: > Add the EFA common commands implementation. > > Signed-off-by: Gal Pressman <galpress@amazon.com> > --- > drivers/infiniband/hw/efa/efa_com_cmd.c | 726 ++++++++++++++++++++++++++++++++ > 1 file changed, 726 insertions(+) > create mode 100644 drivers/infiniband/hw/efa/efa_com_cmd.c > > diff --git a/drivers/infiniband/hw/efa/efa_com_cmd.c b/drivers/infiniband/hw/efa/efa_com_cmd.c > new file mode 100644 > index 000000000000..05eb8f723197 > --- /dev/null > +++ b/drivers/infiniband/hw/efa/efa_com_cmd.c > @@ -0,0 +1,726 @@ > +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause > +/* > + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All rights reserved. > + */ > + > +#include "efa.h" > +#include "efa_com.h" > +#include "efa_com_cmd.h" > + > +void efa_com_set_dma_addr(dma_addr_t addr, u32 *addr_high, u32 *addr_low) > +{ > + *addr_low = addr & GENMASK(31, 0); > + *addr_high = (addr >> 32) & GENMASK(31, 0); > +} > + > +int efa_com_create_qp(struct efa_com_dev *edev, > + struct efa_com_create_qp_params *params, > + struct efa_com_create_qp_result *res) > +{ > + struct efa_admin_create_qp_resp cmd_completion; > + struct efa_admin_create_qp_cmd create_qp_cmd; > + struct efa_com_admin_queue *aq = &edev->aq; > + int err; > + > + memset(&create_qp_cmd, 0x0, sizeof(create_qp_cmd)); > + > + create_qp_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_QP; > + > + create_qp_cmd.pd = params->pd; > + create_qp_cmd.qp_type = params->qp_type; > + create_qp_cmd.flags = 0; > + create_qp_cmd.sq_base_addr = 0; > + create_qp_cmd.rq_base_addr = params->rq_base_addr; > + create_qp_cmd.send_cq_idx = params->send_cq_idx; > + create_qp_cmd.recv_cq_idx = params->recv_cq_idx; > + create_qp_cmd.qp_alloc_size.send_queue_ring_size = > + params->sq_ring_size_in_bytes; > + create_qp_cmd.qp_alloc_size.send_queue_depth = > + params->sq_depth; > + create_qp_cmd.qp_alloc_size.recv_queue_ring_size = > + params->rq_ring_size_in_bytes; > + create_qp_cmd.qp_alloc_size.recv_queue_depth = > + params->rq_depth; > + create_qp_cmd.uar = params->uarn; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&create_qp_cmd, > + sizeof(create_qp_cmd), > + (struct efa_admin_acq_entry *)&cmd_completion, > + sizeof(cmd_completion)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to create qp [%d]\n", err); > + return err; > + } > + > + res->qp_handle = cmd_completion.qp_handle; > + res->qp_num = cmd_completion.qp_num; > + res->sq_db_offset = cmd_completion.sq_db_offset; > + res->rq_db_offset = cmd_completion.rq_db_offset; > + res->llq_descriptors_offset = cmd_completion.llq_descriptors_offset; > + res->send_sub_cq_idx = cmd_completion.send_sub_cq_idx; > + res->recv_sub_cq_idx = cmd_completion.recv_sub_cq_idx; > + > + return err; > +} > + > +int efa_com_modify_qp(struct efa_com_dev *edev, > + struct efa_com_modify_qp_params *params) > +{ > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_modify_qp_resp resp; > + struct efa_admin_modify_qp_cmd cmd; > + int err; > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.aq_common_desc.opcode = EFA_ADMIN_MODIFY_QP; > + cmd.modify_mask = params->modify_mask; > + cmd.qp_handle = params->qp_handle; > + cmd.qp_state = params->qp_state; > + cmd.cur_qp_state = params->cur_qp_state; > + cmd.qkey = params->qkey; > + cmd.sq_psn = params->sq_psn; > + cmd.sq_drained_async_notify = params->sq_drained_async_notify; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&cmd, > + sizeof(cmd), > + (struct efa_admin_acq_entry *)&resp, > + sizeof(resp)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to modify qp-%u modify_mask[%#x] [%d]\n", > + cmd.qp_handle, cmd.modify_mask, err); > + return err; > + } > + > + return 0; > +} > + > +int efa_com_query_qp(struct efa_com_dev *edev, > + struct efa_com_query_qp_params *params, > + struct efa_com_query_qp_result *result) > +{ > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_query_qp_resp resp; > + struct efa_admin_query_qp_cmd cmd; > + int err; > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.aq_common_desc.opcode = EFA_ADMIN_QUERY_QP; > + cmd.qp_handle = params->qp_handle; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&cmd, > + sizeof(cmd), > + (struct efa_admin_acq_entry *)&resp, > + sizeof(resp)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to query qp-%u [%d]\n", > + cmd.qp_handle, err); > + return err; > + } > + > + result->qp_state = resp.qp_state; > + result->qkey = resp.qkey; > + result->sq_draining = resp.sq_draining; > + result->sq_psn = resp.sq_psn; > + > + return 0; > +} > + > +int efa_com_destroy_qp(struct efa_com_dev *edev, > + struct efa_com_destroy_qp_params *params) > +{ > + struct efa_admin_destroy_qp_resp cmd_completion; > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_destroy_qp_cmd qp_cmd; > + int err; > + > + memset(&qp_cmd, 0x0, sizeof(qp_cmd)); > + > + qp_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_QP; > + > + qp_cmd.qp_handle = params->qp_handle; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&qp_cmd, > + sizeof(qp_cmd), > + (struct efa_admin_acq_entry *)&cmd_completion, > + sizeof(cmd_completion)); > + if (unlikely(err)) > + efa_err(edev->dmadev, "Failed to destroy qp-%u [%d]\n", > + qp_cmd.qp_handle, err); > + > + return err; > +} > + > +int efa_com_create_cq(struct efa_com_dev *edev, > + struct efa_com_create_cq_params *params, > + struct efa_com_create_cq_result *result) > +{ > + struct efa_admin_create_cq_resp cmd_completion; > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_create_cq_cmd create_cmd; > + int err; > + > + memset(&create_cmd, 0x0, sizeof(create_cmd)); > + create_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_CQ; > + create_cmd.cq_caps_2 = (params->entry_size_in_bytes / 4) & > + EFA_ADMIN_CREATE_CQ_CMD_CQ_ENTRY_SIZE_WORDS_MASK; > + create_cmd.msix_vector_idx = 0; > + create_cmd.cq_depth = params->cq_depth; > + create_cmd.num_sub_cqs = params->num_sub_cqs; > + create_cmd.uar = params->uarn; > + > + efa_com_set_dma_addr(params->dma_addr, > + &create_cmd.cq_ba.mem_addr_high, > + &create_cmd.cq_ba.mem_addr_low); > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&create_cmd, > + sizeof(create_cmd), > + (struct efa_admin_acq_entry *)&cmd_completion, > + sizeof(cmd_completion)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to create cq[%d]\n", err); > + return err; > + } > + > + result->cq_idx = cmd_completion.cq_idx; > + result->actual_depth = params->cq_depth; > + > + return err; > +} > + > +int efa_com_destroy_cq(struct efa_com_dev *edev, > + struct efa_com_destroy_cq_params *params) > +{ > + struct efa_admin_destroy_cq_resp destroy_resp; > + struct efa_admin_destroy_cq_cmd destroy_cmd; > + struct efa_com_admin_queue *aq = &edev->aq; > + int err; > + > + memset(&destroy_cmd, 0x0, sizeof(destroy_cmd)); > + > + destroy_cmd.cq_idx = params->cq_idx; > + destroy_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_CQ; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&destroy_cmd, > + sizeof(destroy_cmd), > + (struct efa_admin_acq_entry *)&destroy_resp, > + sizeof(destroy_resp)); > + > + if (unlikely(err)) > + efa_err(edev->dmadev, > + "Failed to destroy CQ-%u [%d]\n", params->cq_idx, err); > + > + return err; > +} > + > +int efa_com_register_mr(struct efa_com_dev *edev, > + struct efa_com_reg_mr_params *params, > + struct efa_com_reg_mr_result *result) > +{ > + struct efa_admin_reg_mr_resp cmd_completion; > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_reg_mr_cmd mr_cmd; > + int err; > + > + memset(&mr_cmd, 0x0, sizeof(mr_cmd)); > + > + mr_cmd.aq_common_desc.opcode = EFA_ADMIN_REG_MR; > + mr_cmd.aq_common_desc.flags = 0; > + > + mr_cmd.pd = params->pd; > + mr_cmd.mr_length = params->mr_length_in_bytes; > + > + mr_cmd.flags |= 0 & > + EFA_ADMIN_REG_MR_CMD_MEM_ADDR_PHY_MODE_EN_MASK; > + mr_cmd.flags |= params->page_shift & > + EFA_ADMIN_REG_MR_CMD_PHYS_PAGE_SIZE_SHIFT_MASK; > + mr_cmd.iova = params->iova; > + mr_cmd.permissions |= params->permissions & > + EFA_ADMIN_REG_MR_CMD_LOCAL_WRITE_ENABLE_MASK; > + > + if (params->inline_pbl) { > + memcpy(mr_cmd.pbl.inline_pbl_array, > + params->pbl.inline_pbl_array, > + sizeof(mr_cmd.pbl.inline_pbl_array)); > + } else { > + mr_cmd.pbl.pbl.length = params->pbl.pbl.length; > + mr_cmd.pbl.pbl.address.mem_addr_low = > + params->pbl.pbl.address.mem_addr_low; > + mr_cmd.pbl.pbl.address.mem_addr_high = > + params->pbl.pbl.address.mem_addr_high; > + mr_cmd.aq_common_desc.flags |= > + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_MASK; > + if (params->indirect) > + mr_cmd.aq_common_desc.flags |= > + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; > + } > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&mr_cmd, > + sizeof(mr_cmd), > + (struct efa_admin_acq_entry *)&cmd_completion, > + sizeof(cmd_completion)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to register mr [%d]\n", err); > + return err; > + } > + > + result->l_key = cmd_completion.l_key; > + result->r_key = cmd_completion.r_key; > + > + return err; > +} > + > +int efa_com_dereg_mr(struct efa_com_dev *edev, > + struct efa_com_dereg_mr_params *params) > +{ > + struct efa_admin_dereg_mr_resp cmd_completion; > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_dereg_mr_cmd mr_cmd; > + int err; > + > + memset(&mr_cmd, 0x0, sizeof(mr_cmd)); > + > + mr_cmd.aq_common_desc.opcode = EFA_ADMIN_DEREG_MR; > + mr_cmd.l_key = params->l_key; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&mr_cmd, > + sizeof(mr_cmd), > + (struct efa_admin_acq_entry *)&cmd_completion, > + sizeof(cmd_completion)); > + if (unlikely(err)) > + efa_err(edev->dmadev, > + "Failed to de-register mr(lkey-%u) [%d]\n", > + mr_cmd.l_key, err); > + > + return err; > +} > + > +int efa_com_create_ah(struct efa_com_dev *edev, > + struct efa_com_create_ah_params *params, > + struct efa_com_create_ah_result *result) > +{ > + struct efa_admin_create_ah_resp cmd_completion; > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_create_ah_cmd ah_cmd; > + int err; > + > + memset(&ah_cmd, 0x0, sizeof(ah_cmd)); > + > + ah_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_AH; > + > + memcpy(ah_cmd.dest_addr, params->dest_addr, sizeof(ah_cmd.dest_addr)); > + ah_cmd.pd = params->pdn; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&ah_cmd, > + sizeof(ah_cmd), > + (struct efa_admin_acq_entry *)&cmd_completion, > + sizeof(cmd_completion)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to create ah [%d]\n", err); > + return err; > + } > + > + result->ah = cmd_completion.ah; > + > + return err; > +} > + > +int efa_com_destroy_ah(struct efa_com_dev *edev, > + struct efa_com_destroy_ah_params *params) > +{ > + struct efa_admin_destroy_ah_resp cmd_completion; > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_destroy_ah_cmd ah_cmd; > + int err; > + > + memset(&ah_cmd, 0x0, sizeof(ah_cmd)); > + > + ah_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_AH; > + ah_cmd.ah = params->ah; > + ah_cmd.pd = params->pdn; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&ah_cmd, > + sizeof(ah_cmd), > + (struct efa_admin_acq_entry *)&cmd_completion, > + sizeof(cmd_completion)); > + if (unlikely(err)) > + efa_err(edev->dmadev, > + "Failed to destroy ah-%d pd-%d [%d]\n", > + ah_cmd.ah, ah_cmd.pd, err); > + > + return err; > +} > + > +static bool > +efa_com_check_supported_feature_id(struct efa_com_dev *edev, > + enum efa_admin_aq_feature_id feature_id) > +{ > + u32 feature_mask = 1 << feature_id; > + > + /* Device attributes is always supported */ > + if (feature_id != EFA_ADMIN_DEVICE_ATTR && > + !(edev->supported_features & feature_mask)) > + return false; > + > + return true; > +} > + > +static int efa_com_get_feature_ex(struct efa_com_dev *edev, > + struct efa_admin_get_feature_resp *get_resp, > + enum efa_admin_aq_feature_id feature_id, > + dma_addr_t control_buf_dma_addr, > + u32 control_buff_size) > +{ > + struct efa_admin_get_feature_cmd get_cmd; > + struct efa_com_admin_queue *aq; > + int err; > + > + if (!efa_com_check_supported_feature_id(edev, feature_id)) { > + efa_err(edev->dmadev, "Feature %d isn't supported\n", feature_id); > + return -EOPNOTSUPP; > + } > + > + memset(&get_cmd, 0x0, sizeof(get_cmd)); > + aq = &edev->aq; > + > + get_cmd.aq_common_descriptor.opcode = EFA_ADMIN_GET_FEATURE; > + > + if (control_buff_size) > + get_cmd.aq_common_descriptor.flags = > + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; > + else > + get_cmd.aq_common_descriptor.flags = 0; > + > + efa_com_set_dma_addr(control_buf_dma_addr, > + &get_cmd.control_buffer.address.mem_addr_high, > + &get_cmd.control_buffer.address.mem_addr_low); > + > + get_cmd.control_buffer.length = control_buff_size; > + get_cmd.feature_common.feature_id = feature_id; > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *) > + &get_cmd, > + sizeof(get_cmd), > + (struct efa_admin_acq_entry *) > + get_resp, > + sizeof(*get_resp)); > + > + if (unlikely(err)) > + efa_err(edev->dmadev, > + "Failed to submit get_feature command %d [%d]\n", > + feature_id, err); > + > + return err; > +} > + > +static int efa_com_get_feature(struct efa_com_dev *edev, > + struct efa_admin_get_feature_resp *get_resp, > + enum efa_admin_aq_feature_id feature_id) > +{ > + return efa_com_get_feature_ex(edev, get_resp, feature_id, 0, 0); > +} > + > +int efa_com_get_network_attr(struct efa_com_dev *edev, > + struct efa_com_get_network_attr_result *result) > +{ > + struct efa_admin_get_feature_resp resp; > + int err; > + > + err = efa_com_get_feature(edev, &resp, > + EFA_ADMIN_NETWORK_ATTR); > + if (unlikely(err)) { > + efa_err(edev->dmadev, > + "Failed to get network attributes %d\n", err); > + return err; > + } > + > + memcpy(result->addr, resp.u.network_attr.addr, > + sizeof(resp.u.network_attr.addr)); > + result->mtu = resp.u.network_attr.mtu; > + > + return 0; > +} > + > +int efa_com_get_device_attr(struct efa_com_dev *edev, > + struct efa_com_get_device_attr_result *result) > +{ > + struct efa_admin_get_feature_resp resp; > + int err; > + > + err = efa_com_get_feature(edev, &resp, EFA_ADMIN_DEVICE_ATTR); > + if (unlikely(err)) { > + efa_err(edev->dmadev, > + "Failed to get device attributes %d\n", err); > + return err; > + } > + > + result->page_size_cap = resp.u.device_attr.page_size_cap; > + result->fw_version = resp.u.device_attr.fw_version; > + result->admin_api_version = resp.u.device_attr.admin_api_version; > + result->device_version = resp.u.device_attr.device_version; > + result->supported_features = resp.u.device_attr.supported_features; > + result->phys_addr_width = resp.u.device_attr.phys_addr_width; > + result->virt_addr_width = resp.u.device_attr.virt_addr_width; > + result->db_bar = resp.u.device_attr.db_bar; > + > + if (unlikely(result->admin_api_version < 1)) { > + efa_err(edev->dmadev, > + "Failed to get device attr api version [%u < 1]\n", > + result->admin_api_version); > + return -EINVAL; > + } > + > + edev->supported_features = resp.u.device_attr.supported_features; > + err = efa_com_get_feature(edev, &resp, > + EFA_ADMIN_QUEUE_ATTR); > + if (unlikely(err)) { > + efa_err(edev->dmadev, > + "Failed to get network attributes %d\n", err); > + return err; > + } > + > + result->max_qp = resp.u.queue_attr.max_qp; > + result->max_sq_depth = resp.u.queue_attr.max_sq_depth; > + result->max_rq_depth = resp.u.queue_attr.max_rq_depth; > + result->max_cq = resp.u.queue_attr.max_cq; > + result->max_cq_depth = resp.u.queue_attr.max_cq_depth; > + result->inline_buf_size = resp.u.queue_attr.inline_buf_size; > + result->max_sq_sge = resp.u.queue_attr.max_wr_send_sges; > + result->max_rq_sge = resp.u.queue_attr.max_wr_recv_sges; > + result->max_mr = resp.u.queue_attr.max_mr; > + result->max_mr_pages = resp.u.queue_attr.max_mr_pages; > + result->max_pd = resp.u.queue_attr.max_pd; > + result->max_ah = resp.u.queue_attr.max_ah; > + result->max_llq_size = resp.u.queue_attr.max_llq_size; > + result->sub_cqs_per_cq = resp.u.queue_attr.sub_cqs_per_cq; > + > + return 0; > +} > + > +int efa_com_get_hw_hints(struct efa_com_dev *edev, > + struct efa_com_get_hw_hints_result *result) > +{ > + struct efa_admin_get_feature_resp resp; > + int err; > + > + err = efa_com_get_feature(edev, &resp, EFA_ADMIN_HW_HINTS); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to get hw hints %d\n", err); > + return err; > + } > + > + result->admin_completion_timeout = resp.u.hw_hints.admin_completion_timeout; > + result->driver_watchdog_timeout = resp.u.hw_hints.driver_watchdog_timeout; > + result->mmio_read_timeout = resp.u.hw_hints.mmio_read_timeout; > + result->poll_interval = resp.u.hw_hints.poll_interval; > + > + return 0; > +} > + > +static int efa_com_set_feature_ex(struct efa_com_dev *edev, > + struct efa_admin_set_feature_resp *set_resp, > + struct efa_admin_set_feature_cmd *set_cmd, > + enum efa_admin_aq_feature_id feature_id, > + dma_addr_t control_buf_dma_addr, > + u32 control_buff_size) > +{ > + struct efa_com_admin_queue *aq; > + int err; > + > + if (!efa_com_check_supported_feature_id(edev, feature_id)) { > + efa_err(edev->dmadev, "Feature %d isn't supported\n", feature_id); > + return -EOPNOTSUPP; > + } > + > + aq = &edev->aq; > + > + set_cmd->aq_common_descriptor.opcode = EFA_ADMIN_SET_FEATURE; > + if (control_buff_size) { > + set_cmd->aq_common_descriptor.flags = > + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; > + efa_com_set_dma_addr(control_buf_dma_addr, > + &set_cmd->control_buffer.address.mem_addr_high, > + &set_cmd->control_buffer.address.mem_addr_low); > + } else { > + set_cmd->aq_common_descriptor.flags = 0; > + } > + > + set_cmd->control_buffer.length = control_buff_size; > + set_cmd->feature_common.feature_id = feature_id; > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)set_cmd, > + sizeof(*set_cmd), > + (struct efa_admin_acq_entry *)set_resp, > + sizeof(*set_resp)); > + > + if (unlikely(err)) > + efa_err(edev->dmadev, > + "Failed to submit set_feature command %d error: %d\n", > + feature_id, err); > + > + return err; > +} > + > +static int efa_com_set_feature(struct efa_com_dev *edev, > + struct efa_admin_set_feature_resp *set_resp, > + struct efa_admin_set_feature_cmd *set_cmd, > + enum efa_admin_aq_feature_id feature_id) > +{ > + return efa_com_set_feature_ex(edev, set_resp, set_cmd, feature_id, > + 0, 0); > +} > + > +int efa_com_set_aenq_config(struct efa_com_dev *edev, u32 groups) > +{ > + struct efa_admin_get_feature_resp get_resp; > + struct efa_admin_set_feature_resp set_resp; > + struct efa_admin_set_feature_cmd cmd; > + int err; > + > + efa_dbg(edev->dmadev, > + "Configuring aenq with groups[0x%x]\n", groups); > + > + err = efa_com_get_feature(edev, &get_resp, EFA_ADMIN_AENQ_CONFIG); > + if (unlikely(err)) { > + efa_err(edev->dmadev, > + "Failed to get aenq attributes: %d\n", err); > + return err; > + } > + > + efa_dbg(edev->dmadev, > + "Get aenq groups: supported[0x%x] enabled[0x%x]\n", > + get_resp.u.aenq.supported_groups, > + get_resp.u.aenq.enabled_groups); > + > + if ((get_resp.u.aenq.supported_groups & groups) != groups) { > + efa_err(edev->dmadev, > + "Trying to set unsupported aenq groups[0x%x] supported[0x%x]\n", > + groups, get_resp.u.aenq.supported_groups); > + return -EOPNOTSUPP; > + } > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.u.aenq.enabled_groups = groups; > + err = efa_com_set_feature(edev, &set_resp, &cmd, > + EFA_ADMIN_AENQ_CONFIG); > + if (unlikely(err)) { > + efa_err(edev->dmadev, > + "Failed to set aenq attributes: %d\n", err); > + return err; > + } > + > + return 0; > +} > + > +int efa_com_alloc_pd(struct efa_com_dev *edev, > + struct efa_com_alloc_pd_result *result) > +{ > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_alloc_pd_resp resp; > + struct efa_admin_alloc_pd_cmd cmd; > + int err; > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.aq_common_descriptor.opcode = EFA_ADMIN_ALLOC_PD; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&cmd, > + sizeof(cmd), > + (struct efa_admin_acq_entry *)&resp, > + sizeof(resp)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to allocate pd[%d]\n", err); > + return err; > + } > + > + result->pdn = resp.pd; > + > + return 0; > +} > + > +int efa_com_dealloc_pd(struct efa_com_dev *edev, > + struct efa_com_dealloc_pd_params *params) > +{ > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_dealloc_pd_resp resp; > + struct efa_admin_dealloc_pd_cmd cmd; > + int err; > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.aq_common_descriptor.opcode = EFA_ADMIN_DEALLOC_PD; > + cmd.pd = params->pdn; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&cmd, > + sizeof(cmd), > + (struct efa_admin_acq_entry *)&resp, > + sizeof(resp)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to deallocate pd-%u [%d]\n", > + cmd.pd, err); > + return err; > + } > + > + return 0; > +} > + > +int efa_com_alloc_uar(struct efa_com_dev *edev, > + struct efa_com_alloc_uar_result *result) > +{ > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_alloc_uar_resp resp; > + struct efa_admin_alloc_uar_cmd cmd; > + int err; > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.aq_common_descriptor.opcode = EFA_ADMIN_ALLOC_UAR; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&cmd, > + sizeof(cmd), > + (struct efa_admin_acq_entry *)&resp, > + sizeof(resp)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to allocate uar[%d]\n", err); > + return err; > + } > + > + result->uarn = resp.uar; > + > + return 0; > +} > + > +int efa_com_dealloc_uar(struct efa_com_dev *edev, > + struct efa_com_dealloc_uar_params *params) > +{ > + struct efa_com_admin_queue *aq = &edev->aq; > + struct efa_admin_dealloc_uar_resp resp; > + struct efa_admin_dealloc_uar_cmd cmd; > + int err; > + > + memset(&cmd, 0, sizeof(cmd)); > + cmd.aq_common_descriptor.opcode = EFA_ADMIN_DEALLOC_UAR; > + cmd.uar = params->uarn; > + > + err = efa_com_cmd_exec(aq, > + (struct efa_admin_aq_entry *)&cmd, > + sizeof(cmd), > + (struct efa_admin_acq_entry *)&resp, > + sizeof(resp)); > + if (unlikely(err)) { > + efa_err(edev->dmadev, "Failed to deallocate uar-%u [%d]\n", > + cmd.uar, err); > + return err; > + } > + > + return 0; > +} Reviewed-by: Steve Wise <swise@opengridcomputing.com>
On 26-Feb-19 21:32, Leon Romanovsky wrote: > On Thu, Feb 21, 2019 at 05:33:10PM +0200, Gal Pressman wrote: >> Add the EFA common commands implementation. >> >> Signed-off-by: Gal Pressman <galpress@amazon.com> >> --- >> drivers/infiniband/hw/efa/efa_com_cmd.c | 726 ++++++++++++++++++++++++++++++++ >> 1 file changed, 726 insertions(+) >> create mode 100644 drivers/infiniband/hw/efa/efa_com_cmd.c >> >> diff --git a/drivers/infiniband/hw/efa/efa_com_cmd.c b/drivers/infiniband/hw/efa/efa_com_cmd.c >> new file mode 100644 >> index 000000000000..05eb8f723197 >> --- /dev/null >> +++ b/drivers/infiniband/hw/efa/efa_com_cmd.c >> @@ -0,0 +1,726 @@ >> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause >> +/* >> + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All rights reserved. >> + */ >> + >> +#include "efa.h" >> +#include "efa_com.h" >> +#include "efa_com_cmd.h" >> + >> +void efa_com_set_dma_addr(dma_addr_t addr, u32 *addr_high, u32 *addr_low) >> +{ >> + *addr_low = addr & GENMASK(31, 0); >> + *addr_high = (addr >> 32) & GENMASK(31, 0); >> +} >> + >> +int efa_com_create_qp(struct efa_com_dev *edev, >> + struct efa_com_create_qp_params *params, >> + struct efa_com_create_qp_result *res) >> +{ >> + struct efa_admin_create_qp_resp cmd_completion; >> + struct efa_admin_create_qp_cmd create_qp_cmd; >> + struct efa_com_admin_queue *aq = &edev->aq; >> + int err; >> + >> + memset(&create_qp_cmd, 0x0, sizeof(create_qp_cmd)); > > Prefer {} initialization over memset(). ACK. > >> + >> + create_qp_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_QP; >> + >> + create_qp_cmd.pd = params->pd; >> + create_qp_cmd.qp_type = params->qp_type; >> + create_qp_cmd.flags = 0; >> + create_qp_cmd.sq_base_addr = 0; >> + create_qp_cmd.rq_base_addr = params->rq_base_addr; >> + create_qp_cmd.send_cq_idx = params->send_cq_idx; >> + create_qp_cmd.recv_cq_idx = params->recv_cq_idx; >> + create_qp_cmd.qp_alloc_size.send_queue_ring_size = >> + params->sq_ring_size_in_bytes; >> + create_qp_cmd.qp_alloc_size.send_queue_depth = >> + params->sq_depth; >> + create_qp_cmd.qp_alloc_size.recv_queue_ring_size = >> + params->rq_ring_size_in_bytes; >> + create_qp_cmd.qp_alloc_size.recv_queue_depth = >> + params->rq_depth; >> + create_qp_cmd.uar = params->uarn; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&create_qp_cmd, >> + sizeof(create_qp_cmd), >> + (struct efa_admin_acq_entry *)&cmd_completion, >> + sizeof(cmd_completion)); >> + if (unlikely(err)) { > > There is no need to add likely/unlikely not in data path. Doesn't hurt though, right? > >> + efa_err(edev->dmadev, "Failed to create qp [%d]\n", err); >> + return err; >> + } >> + >> + res->qp_handle = cmd_completion.qp_handle; >> + res->qp_num = cmd_completion.qp_num; >> + res->sq_db_offset = cmd_completion.sq_db_offset; >> + res->rq_db_offset = cmd_completion.rq_db_offset; >> + res->llq_descriptors_offset = cmd_completion.llq_descriptors_offset; >> + res->send_sub_cq_idx = cmd_completion.send_sub_cq_idx; >> + res->recv_sub_cq_idx = cmd_completion.recv_sub_cq_idx; >> + >> + return err; >> +} >> + >> +int efa_com_modify_qp(struct efa_com_dev *edev, >> + struct efa_com_modify_qp_params *params) >> +{ >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_modify_qp_resp resp; >> + struct efa_admin_modify_qp_cmd cmd; >> + int err; >> + >> + memset(&cmd, 0, sizeof(cmd)); >> + cmd.aq_common_desc.opcode = EFA_ADMIN_MODIFY_QP; >> + cmd.modify_mask = params->modify_mask; >> + cmd.qp_handle = params->qp_handle; >> + cmd.qp_state = params->qp_state; >> + cmd.cur_qp_state = params->cur_qp_state; >> + cmd.qkey = params->qkey; >> + cmd.sq_psn = params->sq_psn; >> + cmd.sq_drained_async_notify = params->sq_drained_async_notify; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&cmd, >> + sizeof(cmd), >> + (struct efa_admin_acq_entry *)&resp, >> + sizeof(resp)); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, "Failed to modify qp-%u modify_mask[%#x] [%d]\n", >> + cmd.qp_handle, cmd.modify_mask, err); >> + return err; >> + } >> + >> + return 0; >> +} >> + >> +int efa_com_query_qp(struct efa_com_dev *edev, >> + struct efa_com_query_qp_params *params, >> + struct efa_com_query_qp_result *result) >> +{ >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_query_qp_resp resp; >> + struct efa_admin_query_qp_cmd cmd; >> + int err; >> + >> + memset(&cmd, 0, sizeof(cmd)); >> + cmd.aq_common_desc.opcode = EFA_ADMIN_QUERY_QP; >> + cmd.qp_handle = params->qp_handle; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&cmd, >> + sizeof(cmd), >> + (struct efa_admin_acq_entry *)&resp, >> + sizeof(resp)); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, "Failed to query qp-%u [%d]\n", >> + cmd.qp_handle, err); >> + return err; >> + } >> + >> + result->qp_state = resp.qp_state; >> + result->qkey = resp.qkey; >> + result->sq_draining = resp.sq_draining; >> + result->sq_psn = resp.sq_psn; >> + >> + return 0; >> +} >> + >> +int efa_com_destroy_qp(struct efa_com_dev *edev, >> + struct efa_com_destroy_qp_params *params) >> +{ >> + struct efa_admin_destroy_qp_resp cmd_completion; >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_destroy_qp_cmd qp_cmd; >> + int err; >> + >> + memset(&qp_cmd, 0x0, sizeof(qp_cmd)); >> + >> + qp_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_QP; >> + >> + qp_cmd.qp_handle = params->qp_handle; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&qp_cmd, >> + sizeof(qp_cmd), >> + (struct efa_admin_acq_entry *)&cmd_completion, >> + sizeof(cmd_completion)); >> + if (unlikely(err)) >> + efa_err(edev->dmadev, "Failed to destroy qp-%u [%d]\n", >> + qp_cmd.qp_handle, err); >> + >> + return err; >> +} >> + >> +int efa_com_create_cq(struct efa_com_dev *edev, >> + struct efa_com_create_cq_params *params, >> + struct efa_com_create_cq_result *result) >> +{ >> + struct efa_admin_create_cq_resp cmd_completion; >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_create_cq_cmd create_cmd; >> + int err; >> + >> + memset(&create_cmd, 0x0, sizeof(create_cmd)); >> + create_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_CQ; >> + create_cmd.cq_caps_2 = (params->entry_size_in_bytes / 4) & >> + EFA_ADMIN_CREATE_CQ_CMD_CQ_ENTRY_SIZE_WORDS_MASK; >> + create_cmd.msix_vector_idx = 0; > > You already initialized everything to zero. ACK.
On 26-Feb-19 23:30, Steve Wise wrote: > > On 2/21/2019 9:33 AM, Gal Pressman wrote: >> Add the EFA common commands implementation. >> >> Signed-off-by: Gal Pressman <galpress@amazon.com> >> --- >> drivers/infiniband/hw/efa/efa_com_cmd.c | 726 ++++++++++++++++++++++++++++++++ >> 1 file changed, 726 insertions(+) >> create mode 100644 drivers/infiniband/hw/efa/efa_com_cmd.c >> >> diff --git a/drivers/infiniband/hw/efa/efa_com_cmd.c b/drivers/infiniband/hw/efa/efa_com_cmd.c >> new file mode 100644 >> index 000000000000..05eb8f723197 >> --- /dev/null >> +++ b/drivers/infiniband/hw/efa/efa_com_cmd.c >> @@ -0,0 +1,726 @@ >> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause >> +/* >> + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All rights reserved. >> + */ >> + >> +#include "efa.h" >> +#include "efa_com.h" >> +#include "efa_com_cmd.h" >> + >> +void efa_com_set_dma_addr(dma_addr_t addr, u32 *addr_high, u32 *addr_low) >> +{ >> + *addr_low = addr & GENMASK(31, 0); >> + *addr_high = (addr >> 32) & GENMASK(31, 0); >> +} >> + >> +int efa_com_create_qp(struct efa_com_dev *edev, >> + struct efa_com_create_qp_params *params, >> + struct efa_com_create_qp_result *res) >> +{ >> + struct efa_admin_create_qp_resp cmd_completion; >> + struct efa_admin_create_qp_cmd create_qp_cmd; >> + struct efa_com_admin_queue *aq = &edev->aq; >> + int err; >> + >> + memset(&create_qp_cmd, 0x0, sizeof(create_qp_cmd)); >> + >> + create_qp_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_QP; >> + >> + create_qp_cmd.pd = params->pd; >> + create_qp_cmd.qp_type = params->qp_type; >> + create_qp_cmd.flags = 0; >> + create_qp_cmd.sq_base_addr = 0; >> + create_qp_cmd.rq_base_addr = params->rq_base_addr; >> + create_qp_cmd.send_cq_idx = params->send_cq_idx; >> + create_qp_cmd.recv_cq_idx = params->recv_cq_idx; >> + create_qp_cmd.qp_alloc_size.send_queue_ring_size = >> + params->sq_ring_size_in_bytes; >> + create_qp_cmd.qp_alloc_size.send_queue_depth = >> + params->sq_depth; >> + create_qp_cmd.qp_alloc_size.recv_queue_ring_size = >> + params->rq_ring_size_in_bytes; >> + create_qp_cmd.qp_alloc_size.recv_queue_depth = >> + params->rq_depth; >> + create_qp_cmd.uar = params->uarn; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&create_qp_cmd, >> + sizeof(create_qp_cmd), >> + (struct efa_admin_acq_entry *)&cmd_completion, >> + sizeof(cmd_completion)); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, "Failed to create qp [%d]\n", err); >> + return err; >> + } >> + >> + res->qp_handle = cmd_completion.qp_handle; >> + res->qp_num = cmd_completion.qp_num; >> + res->sq_db_offset = cmd_completion.sq_db_offset; >> + res->rq_db_offset = cmd_completion.rq_db_offset; >> + res->llq_descriptors_offset = cmd_completion.llq_descriptors_offset; >> + res->send_sub_cq_idx = cmd_completion.send_sub_cq_idx; >> + res->recv_sub_cq_idx = cmd_completion.recv_sub_cq_idx; >> + >> + return err; >> +} >> + >> +int efa_com_modify_qp(struct efa_com_dev *edev, >> + struct efa_com_modify_qp_params *params) >> +{ >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_modify_qp_resp resp; >> + struct efa_admin_modify_qp_cmd cmd; >> + int err; >> + >> + memset(&cmd, 0, sizeof(cmd)); >> + cmd.aq_common_desc.opcode = EFA_ADMIN_MODIFY_QP; >> + cmd.modify_mask = params->modify_mask; >> + cmd.qp_handle = params->qp_handle; >> + cmd.qp_state = params->qp_state; >> + cmd.cur_qp_state = params->cur_qp_state; >> + cmd.qkey = params->qkey; >> + cmd.sq_psn = params->sq_psn; >> + cmd.sq_drained_async_notify = params->sq_drained_async_notify; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&cmd, >> + sizeof(cmd), >> + (struct efa_admin_acq_entry *)&resp, >> + sizeof(resp)); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, "Failed to modify qp-%u modify_mask[%#x] [%d]\n", >> + cmd.qp_handle, cmd.modify_mask, err); >> + return err; >> + } >> + >> + return 0; >> +} >> + >> +int efa_com_query_qp(struct efa_com_dev *edev, >> + struct efa_com_query_qp_params *params, >> + struct efa_com_query_qp_result *result) >> +{ >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_query_qp_resp resp; >> + struct efa_admin_query_qp_cmd cmd; >> + int err; >> + >> + memset(&cmd, 0, sizeof(cmd)); >> + cmd.aq_common_desc.opcode = EFA_ADMIN_QUERY_QP; >> + cmd.qp_handle = params->qp_handle; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&cmd, >> + sizeof(cmd), >> + (struct efa_admin_acq_entry *)&resp, >> + sizeof(resp)); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, "Failed to query qp-%u [%d]\n", >> + cmd.qp_handle, err); >> + return err; >> + } >> + >> + result->qp_state = resp.qp_state; >> + result->qkey = resp.qkey; >> + result->sq_draining = resp.sq_draining; >> + result->sq_psn = resp.sq_psn; >> + >> + return 0; >> +} >> + >> +int efa_com_destroy_qp(struct efa_com_dev *edev, >> + struct efa_com_destroy_qp_params *params) >> +{ >> + struct efa_admin_destroy_qp_resp cmd_completion; >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_destroy_qp_cmd qp_cmd; >> + int err; >> + >> + memset(&qp_cmd, 0x0, sizeof(qp_cmd)); >> + >> + qp_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_QP; >> + >> + qp_cmd.qp_handle = params->qp_handle; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&qp_cmd, >> + sizeof(qp_cmd), >> + (struct efa_admin_acq_entry *)&cmd_completion, >> + sizeof(cmd_completion)); >> + if (unlikely(err)) >> + efa_err(edev->dmadev, "Failed to destroy qp-%u [%d]\n", >> + qp_cmd.qp_handle, err); >> + >> + return err; >> +} >> + >> +int efa_com_create_cq(struct efa_com_dev *edev, >> + struct efa_com_create_cq_params *params, >> + struct efa_com_create_cq_result *result) >> +{ >> + struct efa_admin_create_cq_resp cmd_completion; >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_create_cq_cmd create_cmd; >> + int err; >> + >> + memset(&create_cmd, 0x0, sizeof(create_cmd)); >> + create_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_CQ; >> + create_cmd.cq_caps_2 = (params->entry_size_in_bytes / 4) & >> + EFA_ADMIN_CREATE_CQ_CMD_CQ_ENTRY_SIZE_WORDS_MASK; >> + create_cmd.msix_vector_idx = 0; >> + create_cmd.cq_depth = params->cq_depth; >> + create_cmd.num_sub_cqs = params->num_sub_cqs; >> + create_cmd.uar = params->uarn; >> + >> + efa_com_set_dma_addr(params->dma_addr, >> + &create_cmd.cq_ba.mem_addr_high, >> + &create_cmd.cq_ba.mem_addr_low); >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&create_cmd, >> + sizeof(create_cmd), >> + (struct efa_admin_acq_entry *)&cmd_completion, >> + sizeof(cmd_completion)); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, "Failed to create cq[%d]\n", err); >> + return err; >> + } >> + >> + result->cq_idx = cmd_completion.cq_idx; >> + result->actual_depth = params->cq_depth; >> + >> + return err; >> +} >> + >> +int efa_com_destroy_cq(struct efa_com_dev *edev, >> + struct efa_com_destroy_cq_params *params) >> +{ >> + struct efa_admin_destroy_cq_resp destroy_resp; >> + struct efa_admin_destroy_cq_cmd destroy_cmd; >> + struct efa_com_admin_queue *aq = &edev->aq; >> + int err; >> + >> + memset(&destroy_cmd, 0x0, sizeof(destroy_cmd)); >> + >> + destroy_cmd.cq_idx = params->cq_idx; >> + destroy_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_CQ; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&destroy_cmd, >> + sizeof(destroy_cmd), >> + (struct efa_admin_acq_entry *)&destroy_resp, >> + sizeof(destroy_resp)); >> + >> + if (unlikely(err)) >> + efa_err(edev->dmadev, >> + "Failed to destroy CQ-%u [%d]\n", params->cq_idx, err); >> + >> + return err; >> +} >> + >> +int efa_com_register_mr(struct efa_com_dev *edev, >> + struct efa_com_reg_mr_params *params, >> + struct efa_com_reg_mr_result *result) >> +{ >> + struct efa_admin_reg_mr_resp cmd_completion; >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_reg_mr_cmd mr_cmd; >> + int err; >> + >> + memset(&mr_cmd, 0x0, sizeof(mr_cmd)); >> + >> + mr_cmd.aq_common_desc.opcode = EFA_ADMIN_REG_MR; >> + mr_cmd.aq_common_desc.flags = 0; >> + >> + mr_cmd.pd = params->pd; >> + mr_cmd.mr_length = params->mr_length_in_bytes; >> + >> + mr_cmd.flags |= 0 & >> + EFA_ADMIN_REG_MR_CMD_MEM_ADDR_PHY_MODE_EN_MASK; >> + mr_cmd.flags |= params->page_shift & >> + EFA_ADMIN_REG_MR_CMD_PHYS_PAGE_SIZE_SHIFT_MASK; >> + mr_cmd.iova = params->iova; >> + mr_cmd.permissions |= params->permissions & >> + EFA_ADMIN_REG_MR_CMD_LOCAL_WRITE_ENABLE_MASK; >> + >> + if (params->inline_pbl) { >> + memcpy(mr_cmd.pbl.inline_pbl_array, >> + params->pbl.inline_pbl_array, >> + sizeof(mr_cmd.pbl.inline_pbl_array)); >> + } else { >> + mr_cmd.pbl.pbl.length = params->pbl.pbl.length; >> + mr_cmd.pbl.pbl.address.mem_addr_low = >> + params->pbl.pbl.address.mem_addr_low; >> + mr_cmd.pbl.pbl.address.mem_addr_high = >> + params->pbl.pbl.address.mem_addr_high; >> + mr_cmd.aq_common_desc.flags |= >> + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_MASK; >> + if (params->indirect) >> + mr_cmd.aq_common_desc.flags |= >> + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; >> + } >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&mr_cmd, >> + sizeof(mr_cmd), >> + (struct efa_admin_acq_entry *)&cmd_completion, >> + sizeof(cmd_completion)); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, "Failed to register mr [%d]\n", err); >> + return err; >> + } >> + >> + result->l_key = cmd_completion.l_key; >> + result->r_key = cmd_completion.r_key; >> + >> + return err; >> +} >> + >> +int efa_com_dereg_mr(struct efa_com_dev *edev, >> + struct efa_com_dereg_mr_params *params) >> +{ >> + struct efa_admin_dereg_mr_resp cmd_completion; >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_dereg_mr_cmd mr_cmd; >> + int err; >> + >> + memset(&mr_cmd, 0x0, sizeof(mr_cmd)); >> + >> + mr_cmd.aq_common_desc.opcode = EFA_ADMIN_DEREG_MR; >> + mr_cmd.l_key = params->l_key; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&mr_cmd, >> + sizeof(mr_cmd), >> + (struct efa_admin_acq_entry *)&cmd_completion, >> + sizeof(cmd_completion)); >> + if (unlikely(err)) >> + efa_err(edev->dmadev, >> + "Failed to de-register mr(lkey-%u) [%d]\n", >> + mr_cmd.l_key, err); >> + >> + return err; >> +} >> + >> +int efa_com_create_ah(struct efa_com_dev *edev, >> + struct efa_com_create_ah_params *params, >> + struct efa_com_create_ah_result *result) >> +{ >> + struct efa_admin_create_ah_resp cmd_completion; >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_create_ah_cmd ah_cmd; >> + int err; >> + >> + memset(&ah_cmd, 0x0, sizeof(ah_cmd)); >> + >> + ah_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_AH; >> + >> + memcpy(ah_cmd.dest_addr, params->dest_addr, sizeof(ah_cmd.dest_addr)); >> + ah_cmd.pd = params->pdn; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&ah_cmd, >> + sizeof(ah_cmd), >> + (struct efa_admin_acq_entry *)&cmd_completion, >> + sizeof(cmd_completion)); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, "Failed to create ah [%d]\n", err); >> + return err; >> + } >> + >> + result->ah = cmd_completion.ah; >> + >> + return err; >> +} >> + >> +int efa_com_destroy_ah(struct efa_com_dev *edev, >> + struct efa_com_destroy_ah_params *params) >> +{ >> + struct efa_admin_destroy_ah_resp cmd_completion; >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_destroy_ah_cmd ah_cmd; >> + int err; >> + >> + memset(&ah_cmd, 0x0, sizeof(ah_cmd)); >> + >> + ah_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_AH; >> + ah_cmd.ah = params->ah; >> + ah_cmd.pd = params->pdn; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&ah_cmd, >> + sizeof(ah_cmd), >> + (struct efa_admin_acq_entry *)&cmd_completion, >> + sizeof(cmd_completion)); >> + if (unlikely(err)) >> + efa_err(edev->dmadev, >> + "Failed to destroy ah-%d pd-%d [%d]\n", >> + ah_cmd.ah, ah_cmd.pd, err); >> + >> + return err; >> +} >> + >> +static bool >> +efa_com_check_supported_feature_id(struct efa_com_dev *edev, >> + enum efa_admin_aq_feature_id feature_id) >> +{ >> + u32 feature_mask = 1 << feature_id; >> + >> + /* Device attributes is always supported */ >> + if (feature_id != EFA_ADMIN_DEVICE_ATTR && >> + !(edev->supported_features & feature_mask)) >> + return false; >> + >> + return true; >> +} >> + >> +static int efa_com_get_feature_ex(struct efa_com_dev *edev, >> + struct efa_admin_get_feature_resp *get_resp, >> + enum efa_admin_aq_feature_id feature_id, >> + dma_addr_t control_buf_dma_addr, >> + u32 control_buff_size) >> +{ >> + struct efa_admin_get_feature_cmd get_cmd; >> + struct efa_com_admin_queue *aq; >> + int err; >> + >> + if (!efa_com_check_supported_feature_id(edev, feature_id)) { >> + efa_err(edev->dmadev, "Feature %d isn't supported\n", feature_id); >> + return -EOPNOTSUPP; >> + } >> + >> + memset(&get_cmd, 0x0, sizeof(get_cmd)); >> + aq = &edev->aq; >> + >> + get_cmd.aq_common_descriptor.opcode = EFA_ADMIN_GET_FEATURE; >> + >> + if (control_buff_size) >> + get_cmd.aq_common_descriptor.flags = >> + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; >> + else >> + get_cmd.aq_common_descriptor.flags = 0; >> + >> + efa_com_set_dma_addr(control_buf_dma_addr, >> + &get_cmd.control_buffer.address.mem_addr_high, >> + &get_cmd.control_buffer.address.mem_addr_low); >> + >> + get_cmd.control_buffer.length = control_buff_size; >> + get_cmd.feature_common.feature_id = feature_id; >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *) >> + &get_cmd, >> + sizeof(get_cmd), >> + (struct efa_admin_acq_entry *) >> + get_resp, >> + sizeof(*get_resp)); >> + >> + if (unlikely(err)) >> + efa_err(edev->dmadev, >> + "Failed to submit get_feature command %d [%d]\n", >> + feature_id, err); >> + >> + return err; >> +} >> + >> +static int efa_com_get_feature(struct efa_com_dev *edev, >> + struct efa_admin_get_feature_resp *get_resp, >> + enum efa_admin_aq_feature_id feature_id) >> +{ >> + return efa_com_get_feature_ex(edev, get_resp, feature_id, 0, 0); >> +} >> + >> +int efa_com_get_network_attr(struct efa_com_dev *edev, >> + struct efa_com_get_network_attr_result *result) >> +{ >> + struct efa_admin_get_feature_resp resp; >> + int err; >> + >> + err = efa_com_get_feature(edev, &resp, >> + EFA_ADMIN_NETWORK_ATTR); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, >> + "Failed to get network attributes %d\n", err); >> + return err; >> + } >> + >> + memcpy(result->addr, resp.u.network_attr.addr, >> + sizeof(resp.u.network_attr.addr)); >> + result->mtu = resp.u.network_attr.mtu; >> + >> + return 0; >> +} >> + >> +int efa_com_get_device_attr(struct efa_com_dev *edev, >> + struct efa_com_get_device_attr_result *result) >> +{ >> + struct efa_admin_get_feature_resp resp; >> + int err; >> + >> + err = efa_com_get_feature(edev, &resp, EFA_ADMIN_DEVICE_ATTR); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, >> + "Failed to get device attributes %d\n", err); >> + return err; >> + } >> + >> + result->page_size_cap = resp.u.device_attr.page_size_cap; >> + result->fw_version = resp.u.device_attr.fw_version; >> + result->admin_api_version = resp.u.device_attr.admin_api_version; >> + result->device_version = resp.u.device_attr.device_version; >> + result->supported_features = resp.u.device_attr.supported_features; >> + result->phys_addr_width = resp.u.device_attr.phys_addr_width; >> + result->virt_addr_width = resp.u.device_attr.virt_addr_width; >> + result->db_bar = resp.u.device_attr.db_bar; >> + >> + if (unlikely(result->admin_api_version < 1)) { >> + efa_err(edev->dmadev, >> + "Failed to get device attr api version [%u < 1]\n", >> + result->admin_api_version); >> + return -EINVAL; >> + } >> + >> + edev->supported_features = resp.u.device_attr.supported_features; >> + err = efa_com_get_feature(edev, &resp, >> + EFA_ADMIN_QUEUE_ATTR); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, >> + "Failed to get network attributes %d\n", err); >> + return err; >> + } >> + >> + result->max_qp = resp.u.queue_attr.max_qp; >> + result->max_sq_depth = resp.u.queue_attr.max_sq_depth; >> + result->max_rq_depth = resp.u.queue_attr.max_rq_depth; >> + result->max_cq = resp.u.queue_attr.max_cq; >> + result->max_cq_depth = resp.u.queue_attr.max_cq_depth; >> + result->inline_buf_size = resp.u.queue_attr.inline_buf_size; >> + result->max_sq_sge = resp.u.queue_attr.max_wr_send_sges; >> + result->max_rq_sge = resp.u.queue_attr.max_wr_recv_sges; >> + result->max_mr = resp.u.queue_attr.max_mr; >> + result->max_mr_pages = resp.u.queue_attr.max_mr_pages; >> + result->max_pd = resp.u.queue_attr.max_pd; >> + result->max_ah = resp.u.queue_attr.max_ah; >> + result->max_llq_size = resp.u.queue_attr.max_llq_size; >> + result->sub_cqs_per_cq = resp.u.queue_attr.sub_cqs_per_cq; >> + >> + return 0; >> +} >> + >> +int efa_com_get_hw_hints(struct efa_com_dev *edev, >> + struct efa_com_get_hw_hints_result *result) >> +{ >> + struct efa_admin_get_feature_resp resp; >> + int err; >> + >> + err = efa_com_get_feature(edev, &resp, EFA_ADMIN_HW_HINTS); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, "Failed to get hw hints %d\n", err); >> + return err; >> + } >> + >> + result->admin_completion_timeout = resp.u.hw_hints.admin_completion_timeout; >> + result->driver_watchdog_timeout = resp.u.hw_hints.driver_watchdog_timeout; >> + result->mmio_read_timeout = resp.u.hw_hints.mmio_read_timeout; >> + result->poll_interval = resp.u.hw_hints.poll_interval; >> + >> + return 0; >> +} >> + >> +static int efa_com_set_feature_ex(struct efa_com_dev *edev, >> + struct efa_admin_set_feature_resp *set_resp, >> + struct efa_admin_set_feature_cmd *set_cmd, >> + enum efa_admin_aq_feature_id feature_id, >> + dma_addr_t control_buf_dma_addr, >> + u32 control_buff_size) >> +{ >> + struct efa_com_admin_queue *aq; >> + int err; >> + >> + if (!efa_com_check_supported_feature_id(edev, feature_id)) { >> + efa_err(edev->dmadev, "Feature %d isn't supported\n", feature_id); >> + return -EOPNOTSUPP; >> + } >> + >> + aq = &edev->aq; >> + >> + set_cmd->aq_common_descriptor.opcode = EFA_ADMIN_SET_FEATURE; >> + if (control_buff_size) { >> + set_cmd->aq_common_descriptor.flags = >> + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; >> + efa_com_set_dma_addr(control_buf_dma_addr, >> + &set_cmd->control_buffer.address.mem_addr_high, >> + &set_cmd->control_buffer.address.mem_addr_low); >> + } else { >> + set_cmd->aq_common_descriptor.flags = 0; >> + } >> + >> + set_cmd->control_buffer.length = control_buff_size; >> + set_cmd->feature_common.feature_id = feature_id; >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)set_cmd, >> + sizeof(*set_cmd), >> + (struct efa_admin_acq_entry *)set_resp, >> + sizeof(*set_resp)); >> + >> + if (unlikely(err)) >> + efa_err(edev->dmadev, >> + "Failed to submit set_feature command %d error: %d\n", >> + feature_id, err); >> + >> + return err; >> +} >> + >> +static int efa_com_set_feature(struct efa_com_dev *edev, >> + struct efa_admin_set_feature_resp *set_resp, >> + struct efa_admin_set_feature_cmd *set_cmd, >> + enum efa_admin_aq_feature_id feature_id) >> +{ >> + return efa_com_set_feature_ex(edev, set_resp, set_cmd, feature_id, >> + 0, 0); >> +} >> + >> +int efa_com_set_aenq_config(struct efa_com_dev *edev, u32 groups) >> +{ >> + struct efa_admin_get_feature_resp get_resp; >> + struct efa_admin_set_feature_resp set_resp; >> + struct efa_admin_set_feature_cmd cmd; >> + int err; >> + >> + efa_dbg(edev->dmadev, >> + "Configuring aenq with groups[0x%x]\n", groups); >> + >> + err = efa_com_get_feature(edev, &get_resp, EFA_ADMIN_AENQ_CONFIG); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, >> + "Failed to get aenq attributes: %d\n", err); >> + return err; >> + } >> + >> + efa_dbg(edev->dmadev, >> + "Get aenq groups: supported[0x%x] enabled[0x%x]\n", >> + get_resp.u.aenq.supported_groups, >> + get_resp.u.aenq.enabled_groups); >> + >> + if ((get_resp.u.aenq.supported_groups & groups) != groups) { >> + efa_err(edev->dmadev, >> + "Trying to set unsupported aenq groups[0x%x] supported[0x%x]\n", >> + groups, get_resp.u.aenq.supported_groups); >> + return -EOPNOTSUPP; >> + } >> + >> + memset(&cmd, 0, sizeof(cmd)); >> + cmd.u.aenq.enabled_groups = groups; >> + err = efa_com_set_feature(edev, &set_resp, &cmd, >> + EFA_ADMIN_AENQ_CONFIG); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, >> + "Failed to set aenq attributes: %d\n", err); >> + return err; >> + } >> + >> + return 0; >> +} >> + >> +int efa_com_alloc_pd(struct efa_com_dev *edev, >> + struct efa_com_alloc_pd_result *result) >> +{ >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_alloc_pd_resp resp; >> + struct efa_admin_alloc_pd_cmd cmd; >> + int err; >> + >> + memset(&cmd, 0, sizeof(cmd)); >> + cmd.aq_common_descriptor.opcode = EFA_ADMIN_ALLOC_PD; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&cmd, >> + sizeof(cmd), >> + (struct efa_admin_acq_entry *)&resp, >> + sizeof(resp)); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, "Failed to allocate pd[%d]\n", err); >> + return err; >> + } >> + >> + result->pdn = resp.pd; >> + >> + return 0; >> +} >> + >> +int efa_com_dealloc_pd(struct efa_com_dev *edev, >> + struct efa_com_dealloc_pd_params *params) >> +{ >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_dealloc_pd_resp resp; >> + struct efa_admin_dealloc_pd_cmd cmd; >> + int err; >> + >> + memset(&cmd, 0, sizeof(cmd)); >> + cmd.aq_common_descriptor.opcode = EFA_ADMIN_DEALLOC_PD; >> + cmd.pd = params->pdn; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&cmd, >> + sizeof(cmd), >> + (struct efa_admin_acq_entry *)&resp, >> + sizeof(resp)); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, "Failed to deallocate pd-%u [%d]\n", >> + cmd.pd, err); >> + return err; >> + } >> + >> + return 0; >> +} >> + >> +int efa_com_alloc_uar(struct efa_com_dev *edev, >> + struct efa_com_alloc_uar_result *result) >> +{ >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_alloc_uar_resp resp; >> + struct efa_admin_alloc_uar_cmd cmd; >> + int err; >> + >> + memset(&cmd, 0, sizeof(cmd)); >> + cmd.aq_common_descriptor.opcode = EFA_ADMIN_ALLOC_UAR; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&cmd, >> + sizeof(cmd), >> + (struct efa_admin_acq_entry *)&resp, >> + sizeof(resp)); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, "Failed to allocate uar[%d]\n", err); >> + return err; >> + } >> + >> + result->uarn = resp.uar; >> + >> + return 0; >> +} >> + >> +int efa_com_dealloc_uar(struct efa_com_dev *edev, >> + struct efa_com_dealloc_uar_params *params) >> +{ >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_dealloc_uar_resp resp; >> + struct efa_admin_dealloc_uar_cmd cmd; >> + int err; >> + >> + memset(&cmd, 0, sizeof(cmd)); >> + cmd.aq_common_descriptor.opcode = EFA_ADMIN_DEALLOC_UAR; >> + cmd.uar = params->uarn; >> + >> + err = efa_com_cmd_exec(aq, >> + (struct efa_admin_aq_entry *)&cmd, >> + sizeof(cmd), >> + (struct efa_admin_acq_entry *)&resp, >> + sizeof(resp)); >> + if (unlikely(err)) { >> + efa_err(edev->dmadev, "Failed to deallocate uar-%u [%d]\n", >> + cmd.uar, err); >> + return err; >> + } >> + >> + return 0; >> +} > > > Reviewed-by: Steve Wise <swise@opengridcomputing.com> Thanks Steve!
On Wed, Feb 27, 2019 at 10:31:29AM +0200, Gal Pressman wrote: > On 26-Feb-19 21:32, Leon Romanovsky wrote: > > On Thu, Feb 21, 2019 at 05:33:10PM +0200, Gal Pressman wrote: > >> Add the EFA common commands implementation. > >> > >> Signed-off-by: Gal Pressman <galpress@amazon.com> > >> --- <...> > >> + err = efa_com_cmd_exec(aq, > >> + (struct efa_admin_aq_entry *)&create_qp_cmd, > >> + sizeof(create_qp_cmd), > >> + (struct efa_admin_acq_entry *)&cmd_completion, > >> + sizeof(cmd_completion)); > >> + if (unlikely(err)) { > > > > There is no need to add likely/unlikely not in data path. > > Doesn't hurt though, right? Right, if readability is not important, it won't hurt. Thanks
On 27-Feb-19 10:36, Leon Romanovsky wrote: > On Wed, Feb 27, 2019 at 10:31:29AM +0200, Gal Pressman wrote: >> On 26-Feb-19 21:32, Leon Romanovsky wrote: >>> On Thu, Feb 21, 2019 at 05:33:10PM +0200, Gal Pressman wrote: >>>> Add the EFA common commands implementation. >>>> >>>> Signed-off-by: Gal Pressman <galpress@amazon.com> >>>> --- > > <...> > >>>> + err = efa_com_cmd_exec(aq, >>>> + (struct efa_admin_aq_entry *)&create_qp_cmd, >>>> + sizeof(create_qp_cmd), >>>> + (struct efa_admin_acq_entry *)&cmd_completion, >>>> + sizeof(cmd_completion)); >>>> + if (unlikely(err)) { >>> >>> There is no need to add likely/unlikely not in data path. >> >> Doesn't hurt though, right? > > Right, if readability is not important, it won't hurt. Actually, I find likely/unlikely easier to read as it helps you identify the main flows. In this case the main flow is clear, but I wouldn't say that it hurts readability.
On Wed, Feb 27, 2019 at 10:57:16AM +0200, Gal Pressman wrote: > On 27-Feb-19 10:36, Leon Romanovsky wrote: > > On Wed, Feb 27, 2019 at 10:31:29AM +0200, Gal Pressman wrote: > >> On 26-Feb-19 21:32, Leon Romanovsky wrote: > >>> On Thu, Feb 21, 2019 at 05:33:10PM +0200, Gal Pressman wrote: > >>>> Add the EFA common commands implementation. > >>>> > >>>> Signed-off-by: Gal Pressman <galpress@amazon.com> > >>>> --- > > > > <...> > > > >>>> + err = efa_com_cmd_exec(aq, > >>>> + (struct efa_admin_aq_entry *)&create_qp_cmd, > >>>> + sizeof(create_qp_cmd), > >>>> + (struct efa_admin_acq_entry *)&cmd_completion, > >>>> + sizeof(cmd_completion)); > >>>> + if (unlikely(err)) { > >>> > >>> There is no need to add likely/unlikely not in data path. > >> > >> Doesn't hurt though, right? > > > > Right, if readability is not important, it won't hurt. > > Actually, I find likely/unlikely easier to read as it helps you identify the > main flows. > In this case the main flow is clear, but I wouldn't say that it hurts readability. Can you please point me the place in the code where "err" is expected behaviour and such place needs extra help to identify the main flow, instead of naming "err" to be something else, more descriptive? Thanks
On 27-Feb-19 11:10, Leon Romanovsky wrote: > On Wed, Feb 27, 2019 at 10:57:16AM +0200, Gal Pressman wrote: >> On 27-Feb-19 10:36, Leon Romanovsky wrote: >>> On Wed, Feb 27, 2019 at 10:31:29AM +0200, Gal Pressman wrote: >>>> On 26-Feb-19 21:32, Leon Romanovsky wrote: >>>>> On Thu, Feb 21, 2019 at 05:33:10PM +0200, Gal Pressman wrote: >>>>>> Add the EFA common commands implementation. >>>>>> >>>>>> Signed-off-by: Gal Pressman <galpress@amazon.com> >>>>>> --- >>> >>> <...> >>> >>>>>> + err = efa_com_cmd_exec(aq, >>>>>> + (struct efa_admin_aq_entry *)&create_qp_cmd, >>>>>> + sizeof(create_qp_cmd), >>>>>> + (struct efa_admin_acq_entry *)&cmd_completion, >>>>>> + sizeof(cmd_completion)); >>>>>> + if (unlikely(err)) { >>>>> >>>>> There is no need to add likely/unlikely not in data path. >>>> >>>> Doesn't hurt though, right? >>> >>> Right, if readability is not important, it won't hurt. >> >> Actually, I find likely/unlikely easier to read as it helps you identify the >> main flows. >> In this case the main flow is clear, but I wouldn't say that it hurts readability. > > Can you please point me the place in the code where "err" is expected > behaviour and such place needs extra help to identify the main flow, > instead of naming "err" to be something else, more descriptive? My point was that these annotations are a hint to the reader as well, not just the compiler. In many places the hint is obvious, but that doesn't make the code less readable.
>Subject: [PATCH rdma-next v2 08/11] RDMA/efa: Add common command >handlers > >Add the EFA common commands implementation. > >Signed-off-by: Gal Pressman <galpress@amazon.com> >--- > drivers/infiniband/hw/efa/efa_com_cmd.c | 726 >++++++++++++++++++++++++++++++++ > 1 file changed, 726 insertions(+) > create mode 100644 drivers/infiniband/hw/efa/efa_com_cmd.c > >diff --git a/drivers/infiniband/hw/efa/efa_com_cmd.c >b/drivers/infiniband/hw/efa/efa_com_cmd.c >new file mode 100644 >index 000000000000..05eb8f723197 >--- /dev/null >+++ b/drivers/infiniband/hw/efa/efa_com_cmd.c >@@ -0,0 +1,726 @@ >+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause >+/* >+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All rights reserved. >+ */ >+ >+#include "efa.h" >+#include "efa_com.h" >+#include "efa_com_cmd.h" >+ >+void efa_com_set_dma_addr(dma_addr_t addr, u32 *addr_high, u32 >+*addr_low) { >+ *addr_low = addr & GENMASK(31, 0); >+ *addr_high = (addr >> 32) & GENMASK(31, 0); } >+ >+int efa_com_create_qp(struct efa_com_dev *edev, >+ struct efa_com_create_qp_params *params, >+ struct efa_com_create_qp_result *res) { >+ struct efa_admin_create_qp_resp cmd_completion; >+ struct efa_admin_create_qp_cmd create_qp_cmd; >+ struct efa_com_admin_queue *aq = &edev->aq; >+ int err; >+ >+ memset(&create_qp_cmd, 0x0, sizeof(create_qp_cmd)); Use = {}. Few hits of these here... >+ [..] >+int efa_com_register_mr(struct efa_com_dev *edev, >+ struct efa_com_reg_mr_params *params, >+ struct efa_com_reg_mr_result *result) { >+ struct efa_admin_reg_mr_resp cmd_completion; >+ struct efa_com_admin_queue *aq = &edev->aq; >+ struct efa_admin_reg_mr_cmd mr_cmd; >+ int err; >+ >+ memset(&mr_cmd, 0x0, sizeof(mr_cmd)); >+ >+ mr_cmd.aq_common_desc.opcode = EFA_ADMIN_REG_MR; >+ mr_cmd.aq_common_desc.flags = 0; >+ >+ mr_cmd.pd = params->pd; >+ mr_cmd.mr_length = params->mr_length_in_bytes; >+ >+ mr_cmd.flags |= 0 & >+ > EFA_ADMIN_REG_MR_CMD_MEM_ADDR_PHY_MODE_EN_MASK; Doesn't look right.
On 27-Feb-19 22:57, Saleem, Shiraz wrote: >> Subject: [PATCH rdma-next v2 08/11] RDMA/efa: Add common command >> handlers >> >> Add the EFA common commands implementation. >> >> Signed-off-by: Gal Pressman <galpress@amazon.com> >> --- >> drivers/infiniband/hw/efa/efa_com_cmd.c | 726 >> ++++++++++++++++++++++++++++++++ >> 1 file changed, 726 insertions(+) >> create mode 100644 drivers/infiniband/hw/efa/efa_com_cmd.c >> >> diff --git a/drivers/infiniband/hw/efa/efa_com_cmd.c >> b/drivers/infiniband/hw/efa/efa_com_cmd.c >> new file mode 100644 >> index 000000000000..05eb8f723197 >> --- /dev/null >> +++ b/drivers/infiniband/hw/efa/efa_com_cmd.c >> @@ -0,0 +1,726 @@ >> +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause >> +/* >> + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All rights reserved. >> + */ >> + >> +#include "efa.h" >> +#include "efa_com.h" >> +#include "efa_com_cmd.h" >> + >> +void efa_com_set_dma_addr(dma_addr_t addr, u32 *addr_high, u32 >> +*addr_low) { >> + *addr_low = addr & GENMASK(31, 0); >> + *addr_high = (addr >> 32) & GENMASK(31, 0); } >> + >> +int efa_com_create_qp(struct efa_com_dev *edev, >> + struct efa_com_create_qp_params *params, >> + struct efa_com_create_qp_result *res) { >> + struct efa_admin_create_qp_resp cmd_completion; >> + struct efa_admin_create_qp_cmd create_qp_cmd; >> + struct efa_com_admin_queue *aq = &edev->aq; >> + int err; >> + >> + memset(&create_qp_cmd, 0x0, sizeof(create_qp_cmd)); > > Use = {}. Few hits of these here... Will fix. >> + > > [..] > >> +int efa_com_register_mr(struct efa_com_dev *edev, >> + struct efa_com_reg_mr_params *params, >> + struct efa_com_reg_mr_result *result) { >> + struct efa_admin_reg_mr_resp cmd_completion; >> + struct efa_com_admin_queue *aq = &edev->aq; >> + struct efa_admin_reg_mr_cmd mr_cmd; >> + int err; >> + >> + memset(&mr_cmd, 0x0, sizeof(mr_cmd)); >> + >> + mr_cmd.aq_common_desc.opcode = EFA_ADMIN_REG_MR; >> + mr_cmd.aq_common_desc.flags = 0; >> + >> + mr_cmd.pd = params->pd; >> + mr_cmd.mr_length = params->mr_length_in_bytes; >> + >> + mr_cmd.flags |= 0 & >> + >> EFA_ADMIN_REG_MR_CMD_MEM_ADDR_PHY_MODE_EN_MASK; > > Doesn't look right. I think the original intention was to explicitly disable the phy mode bit. Indeed looks weird, will remove.
On Wed, Feb 27, 2019 at 10:57:16AM +0200, Gal Pressman wrote: > On 27-Feb-19 10:36, Leon Romanovsky wrote: > > On Wed, Feb 27, 2019 at 10:31:29AM +0200, Gal Pressman wrote: > >> On 26-Feb-19 21:32, Leon Romanovsky wrote: > >>> On Thu, Feb 21, 2019 at 05:33:10PM +0200, Gal Pressman wrote: > >>>> Add the EFA common commands implementation. > >>>> > >>>> Signed-off-by: Gal Pressman <galpress@amazon.com> > > > > <...> > > > >>>> + err = efa_com_cmd_exec(aq, > >>>> + (struct efa_admin_aq_entry *)&create_qp_cmd, > >>>> + sizeof(create_qp_cmd), > >>>> + (struct efa_admin_acq_entry *)&cmd_completion, > >>>> + sizeof(cmd_completion)); > >>>> + if (unlikely(err)) { > >>> > >>> There is no need to add likely/unlikely not in data path. > >> > >> Doesn't hurt though, right? > > > > Right, if readability is not important, it won't hurt. > > Actually, I find likely/unlikely easier to read as it helps you identify the > main flows. > In this case the main flow is clear, but I wouldn't say that it hurts readability. The general guidance in the kernel is to follow the 'success oriented flow', so if you are looking at an 'if (thing) {goto exit/return}' it really should be a failure path. Jason
On 04-Mar-19 23:15, Jason Gunthorpe wrote: > On Wed, Feb 27, 2019 at 10:57:16AM +0200, Gal Pressman wrote: >> On 27-Feb-19 10:36, Leon Romanovsky wrote: >>> On Wed, Feb 27, 2019 at 10:31:29AM +0200, Gal Pressman wrote: >>>> On 26-Feb-19 21:32, Leon Romanovsky wrote: >>>>> On Thu, Feb 21, 2019 at 05:33:10PM +0200, Gal Pressman wrote: >>>>>> Add the EFA common commands implementation. >>>>>> >>>>>> Signed-off-by: Gal Pressman <galpress@amazon.com> >>> >>> <...> >>> >>>>>> + err = efa_com_cmd_exec(aq, >>>>>> + (struct efa_admin_aq_entry *)&create_qp_cmd, >>>>>> + sizeof(create_qp_cmd), >>>>>> + (struct efa_admin_acq_entry *)&cmd_completion, >>>>>> + sizeof(cmd_completion)); >>>>>> + if (unlikely(err)) { >>>>> >>>>> There is no need to add likely/unlikely not in data path. >>>> >>>> Doesn't hurt though, right? >>> >>> Right, if readability is not important, it won't hurt. >> >> Actually, I find likely/unlikely easier to read as it helps you identify the >> main flows. >> In this case the main flow is clear, but I wouldn't say that it hurts readability. > > The general guidance in the kernel is to follow the 'success oriented > flow', so if you are looking at an 'if (thing) {goto exit/return}' it > really should be a failure path. Agree, and it does. Anyway, I'll remove the likely/unlikely's. Thanks Leon and Jason.
diff --git a/drivers/infiniband/hw/efa/efa_com_cmd.c b/drivers/infiniband/hw/efa/efa_com_cmd.c new file mode 100644 index 000000000000..05eb8f723197 --- /dev/null +++ b/drivers/infiniband/hw/efa/efa_com_cmd.c @@ -0,0 +1,726 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All rights reserved. + */ + +#include "efa.h" +#include "efa_com.h" +#include "efa_com_cmd.h" + +void efa_com_set_dma_addr(dma_addr_t addr, u32 *addr_high, u32 *addr_low) +{ + *addr_low = addr & GENMASK(31, 0); + *addr_high = (addr >> 32) & GENMASK(31, 0); +} + +int efa_com_create_qp(struct efa_com_dev *edev, + struct efa_com_create_qp_params *params, + struct efa_com_create_qp_result *res) +{ + struct efa_admin_create_qp_resp cmd_completion; + struct efa_admin_create_qp_cmd create_qp_cmd; + struct efa_com_admin_queue *aq = &edev->aq; + int err; + + memset(&create_qp_cmd, 0x0, sizeof(create_qp_cmd)); + + create_qp_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_QP; + + create_qp_cmd.pd = params->pd; + create_qp_cmd.qp_type = params->qp_type; + create_qp_cmd.flags = 0; + create_qp_cmd.sq_base_addr = 0; + create_qp_cmd.rq_base_addr = params->rq_base_addr; + create_qp_cmd.send_cq_idx = params->send_cq_idx; + create_qp_cmd.recv_cq_idx = params->recv_cq_idx; + create_qp_cmd.qp_alloc_size.send_queue_ring_size = + params->sq_ring_size_in_bytes; + create_qp_cmd.qp_alloc_size.send_queue_depth = + params->sq_depth; + create_qp_cmd.qp_alloc_size.recv_queue_ring_size = + params->rq_ring_size_in_bytes; + create_qp_cmd.qp_alloc_size.recv_queue_depth = + params->rq_depth; + create_qp_cmd.uar = params->uarn; + + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)&create_qp_cmd, + sizeof(create_qp_cmd), + (struct efa_admin_acq_entry *)&cmd_completion, + sizeof(cmd_completion)); + if (unlikely(err)) { + efa_err(edev->dmadev, "Failed to create qp [%d]\n", err); + return err; + } + + res->qp_handle = cmd_completion.qp_handle; + res->qp_num = cmd_completion.qp_num; + res->sq_db_offset = cmd_completion.sq_db_offset; + res->rq_db_offset = cmd_completion.rq_db_offset; + res->llq_descriptors_offset = cmd_completion.llq_descriptors_offset; + res->send_sub_cq_idx = cmd_completion.send_sub_cq_idx; + res->recv_sub_cq_idx = cmd_completion.recv_sub_cq_idx; + + return err; +} + +int efa_com_modify_qp(struct efa_com_dev *edev, + struct efa_com_modify_qp_params *params) +{ + struct efa_com_admin_queue *aq = &edev->aq; + struct efa_admin_modify_qp_resp resp; + struct efa_admin_modify_qp_cmd cmd; + int err; + + memset(&cmd, 0, sizeof(cmd)); + cmd.aq_common_desc.opcode = EFA_ADMIN_MODIFY_QP; + cmd.modify_mask = params->modify_mask; + cmd.qp_handle = params->qp_handle; + cmd.qp_state = params->qp_state; + cmd.cur_qp_state = params->cur_qp_state; + cmd.qkey = params->qkey; + cmd.sq_psn = params->sq_psn; + cmd.sq_drained_async_notify = params->sq_drained_async_notify; + + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)&cmd, + sizeof(cmd), + (struct efa_admin_acq_entry *)&resp, + sizeof(resp)); + if (unlikely(err)) { + efa_err(edev->dmadev, "Failed to modify qp-%u modify_mask[%#x] [%d]\n", + cmd.qp_handle, cmd.modify_mask, err); + return err; + } + + return 0; +} + +int efa_com_query_qp(struct efa_com_dev *edev, + struct efa_com_query_qp_params *params, + struct efa_com_query_qp_result *result) +{ + struct efa_com_admin_queue *aq = &edev->aq; + struct efa_admin_query_qp_resp resp; + struct efa_admin_query_qp_cmd cmd; + int err; + + memset(&cmd, 0, sizeof(cmd)); + cmd.aq_common_desc.opcode = EFA_ADMIN_QUERY_QP; + cmd.qp_handle = params->qp_handle; + + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)&cmd, + sizeof(cmd), + (struct efa_admin_acq_entry *)&resp, + sizeof(resp)); + if (unlikely(err)) { + efa_err(edev->dmadev, "Failed to query qp-%u [%d]\n", + cmd.qp_handle, err); + return err; + } + + result->qp_state = resp.qp_state; + result->qkey = resp.qkey; + result->sq_draining = resp.sq_draining; + result->sq_psn = resp.sq_psn; + + return 0; +} + +int efa_com_destroy_qp(struct efa_com_dev *edev, + struct efa_com_destroy_qp_params *params) +{ + struct efa_admin_destroy_qp_resp cmd_completion; + struct efa_com_admin_queue *aq = &edev->aq; + struct efa_admin_destroy_qp_cmd qp_cmd; + int err; + + memset(&qp_cmd, 0x0, sizeof(qp_cmd)); + + qp_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_QP; + + qp_cmd.qp_handle = params->qp_handle; + + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)&qp_cmd, + sizeof(qp_cmd), + (struct efa_admin_acq_entry *)&cmd_completion, + sizeof(cmd_completion)); + if (unlikely(err)) + efa_err(edev->dmadev, "Failed to destroy qp-%u [%d]\n", + qp_cmd.qp_handle, err); + + return err; +} + +int efa_com_create_cq(struct efa_com_dev *edev, + struct efa_com_create_cq_params *params, + struct efa_com_create_cq_result *result) +{ + struct efa_admin_create_cq_resp cmd_completion; + struct efa_com_admin_queue *aq = &edev->aq; + struct efa_admin_create_cq_cmd create_cmd; + int err; + + memset(&create_cmd, 0x0, sizeof(create_cmd)); + create_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_CQ; + create_cmd.cq_caps_2 = (params->entry_size_in_bytes / 4) & + EFA_ADMIN_CREATE_CQ_CMD_CQ_ENTRY_SIZE_WORDS_MASK; + create_cmd.msix_vector_idx = 0; + create_cmd.cq_depth = params->cq_depth; + create_cmd.num_sub_cqs = params->num_sub_cqs; + create_cmd.uar = params->uarn; + + efa_com_set_dma_addr(params->dma_addr, + &create_cmd.cq_ba.mem_addr_high, + &create_cmd.cq_ba.mem_addr_low); + + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)&create_cmd, + sizeof(create_cmd), + (struct efa_admin_acq_entry *)&cmd_completion, + sizeof(cmd_completion)); + if (unlikely(err)) { + efa_err(edev->dmadev, "Failed to create cq[%d]\n", err); + return err; + } + + result->cq_idx = cmd_completion.cq_idx; + result->actual_depth = params->cq_depth; + + return err; +} + +int efa_com_destroy_cq(struct efa_com_dev *edev, + struct efa_com_destroy_cq_params *params) +{ + struct efa_admin_destroy_cq_resp destroy_resp; + struct efa_admin_destroy_cq_cmd destroy_cmd; + struct efa_com_admin_queue *aq = &edev->aq; + int err; + + memset(&destroy_cmd, 0x0, sizeof(destroy_cmd)); + + destroy_cmd.cq_idx = params->cq_idx; + destroy_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_CQ; + + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)&destroy_cmd, + sizeof(destroy_cmd), + (struct efa_admin_acq_entry *)&destroy_resp, + sizeof(destroy_resp)); + + if (unlikely(err)) + efa_err(edev->dmadev, + "Failed to destroy CQ-%u [%d]\n", params->cq_idx, err); + + return err; +} + +int efa_com_register_mr(struct efa_com_dev *edev, + struct efa_com_reg_mr_params *params, + struct efa_com_reg_mr_result *result) +{ + struct efa_admin_reg_mr_resp cmd_completion; + struct efa_com_admin_queue *aq = &edev->aq; + struct efa_admin_reg_mr_cmd mr_cmd; + int err; + + memset(&mr_cmd, 0x0, sizeof(mr_cmd)); + + mr_cmd.aq_common_desc.opcode = EFA_ADMIN_REG_MR; + mr_cmd.aq_common_desc.flags = 0; + + mr_cmd.pd = params->pd; + mr_cmd.mr_length = params->mr_length_in_bytes; + + mr_cmd.flags |= 0 & + EFA_ADMIN_REG_MR_CMD_MEM_ADDR_PHY_MODE_EN_MASK; + mr_cmd.flags |= params->page_shift & + EFA_ADMIN_REG_MR_CMD_PHYS_PAGE_SIZE_SHIFT_MASK; + mr_cmd.iova = params->iova; + mr_cmd.permissions |= params->permissions & + EFA_ADMIN_REG_MR_CMD_LOCAL_WRITE_ENABLE_MASK; + + if (params->inline_pbl) { + memcpy(mr_cmd.pbl.inline_pbl_array, + params->pbl.inline_pbl_array, + sizeof(mr_cmd.pbl.inline_pbl_array)); + } else { + mr_cmd.pbl.pbl.length = params->pbl.pbl.length; + mr_cmd.pbl.pbl.address.mem_addr_low = + params->pbl.pbl.address.mem_addr_low; + mr_cmd.pbl.pbl.address.mem_addr_high = + params->pbl.pbl.address.mem_addr_high; + mr_cmd.aq_common_desc.flags |= + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_MASK; + if (params->indirect) + mr_cmd.aq_common_desc.flags |= + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; + } + + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)&mr_cmd, + sizeof(mr_cmd), + (struct efa_admin_acq_entry *)&cmd_completion, + sizeof(cmd_completion)); + if (unlikely(err)) { + efa_err(edev->dmadev, "Failed to register mr [%d]\n", err); + return err; + } + + result->l_key = cmd_completion.l_key; + result->r_key = cmd_completion.r_key; + + return err; +} + +int efa_com_dereg_mr(struct efa_com_dev *edev, + struct efa_com_dereg_mr_params *params) +{ + struct efa_admin_dereg_mr_resp cmd_completion; + struct efa_com_admin_queue *aq = &edev->aq; + struct efa_admin_dereg_mr_cmd mr_cmd; + int err; + + memset(&mr_cmd, 0x0, sizeof(mr_cmd)); + + mr_cmd.aq_common_desc.opcode = EFA_ADMIN_DEREG_MR; + mr_cmd.l_key = params->l_key; + + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)&mr_cmd, + sizeof(mr_cmd), + (struct efa_admin_acq_entry *)&cmd_completion, + sizeof(cmd_completion)); + if (unlikely(err)) + efa_err(edev->dmadev, + "Failed to de-register mr(lkey-%u) [%d]\n", + mr_cmd.l_key, err); + + return err; +} + +int efa_com_create_ah(struct efa_com_dev *edev, + struct efa_com_create_ah_params *params, + struct efa_com_create_ah_result *result) +{ + struct efa_admin_create_ah_resp cmd_completion; + struct efa_com_admin_queue *aq = &edev->aq; + struct efa_admin_create_ah_cmd ah_cmd; + int err; + + memset(&ah_cmd, 0x0, sizeof(ah_cmd)); + + ah_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_AH; + + memcpy(ah_cmd.dest_addr, params->dest_addr, sizeof(ah_cmd.dest_addr)); + ah_cmd.pd = params->pdn; + + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)&ah_cmd, + sizeof(ah_cmd), + (struct efa_admin_acq_entry *)&cmd_completion, + sizeof(cmd_completion)); + if (unlikely(err)) { + efa_err(edev->dmadev, "Failed to create ah [%d]\n", err); + return err; + } + + result->ah = cmd_completion.ah; + + return err; +} + +int efa_com_destroy_ah(struct efa_com_dev *edev, + struct efa_com_destroy_ah_params *params) +{ + struct efa_admin_destroy_ah_resp cmd_completion; + struct efa_com_admin_queue *aq = &edev->aq; + struct efa_admin_destroy_ah_cmd ah_cmd; + int err; + + memset(&ah_cmd, 0x0, sizeof(ah_cmd)); + + ah_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_AH; + ah_cmd.ah = params->ah; + ah_cmd.pd = params->pdn; + + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)&ah_cmd, + sizeof(ah_cmd), + (struct efa_admin_acq_entry *)&cmd_completion, + sizeof(cmd_completion)); + if (unlikely(err)) + efa_err(edev->dmadev, + "Failed to destroy ah-%d pd-%d [%d]\n", + ah_cmd.ah, ah_cmd.pd, err); + + return err; +} + +static bool +efa_com_check_supported_feature_id(struct efa_com_dev *edev, + enum efa_admin_aq_feature_id feature_id) +{ + u32 feature_mask = 1 << feature_id; + + /* Device attributes is always supported */ + if (feature_id != EFA_ADMIN_DEVICE_ATTR && + !(edev->supported_features & feature_mask)) + return false; + + return true; +} + +static int efa_com_get_feature_ex(struct efa_com_dev *edev, + struct efa_admin_get_feature_resp *get_resp, + enum efa_admin_aq_feature_id feature_id, + dma_addr_t control_buf_dma_addr, + u32 control_buff_size) +{ + struct efa_admin_get_feature_cmd get_cmd; + struct efa_com_admin_queue *aq; + int err; + + if (!efa_com_check_supported_feature_id(edev, feature_id)) { + efa_err(edev->dmadev, "Feature %d isn't supported\n", feature_id); + return -EOPNOTSUPP; + } + + memset(&get_cmd, 0x0, sizeof(get_cmd)); + aq = &edev->aq; + + get_cmd.aq_common_descriptor.opcode = EFA_ADMIN_GET_FEATURE; + + if (control_buff_size) + get_cmd.aq_common_descriptor.flags = + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; + else + get_cmd.aq_common_descriptor.flags = 0; + + efa_com_set_dma_addr(control_buf_dma_addr, + &get_cmd.control_buffer.address.mem_addr_high, + &get_cmd.control_buffer.address.mem_addr_low); + + get_cmd.control_buffer.length = control_buff_size; + get_cmd.feature_common.feature_id = feature_id; + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *) + &get_cmd, + sizeof(get_cmd), + (struct efa_admin_acq_entry *) + get_resp, + sizeof(*get_resp)); + + if (unlikely(err)) + efa_err(edev->dmadev, + "Failed to submit get_feature command %d [%d]\n", + feature_id, err); + + return err; +} + +static int efa_com_get_feature(struct efa_com_dev *edev, + struct efa_admin_get_feature_resp *get_resp, + enum efa_admin_aq_feature_id feature_id) +{ + return efa_com_get_feature_ex(edev, get_resp, feature_id, 0, 0); +} + +int efa_com_get_network_attr(struct efa_com_dev *edev, + struct efa_com_get_network_attr_result *result) +{ + struct efa_admin_get_feature_resp resp; + int err; + + err = efa_com_get_feature(edev, &resp, + EFA_ADMIN_NETWORK_ATTR); + if (unlikely(err)) { + efa_err(edev->dmadev, + "Failed to get network attributes %d\n", err); + return err; + } + + memcpy(result->addr, resp.u.network_attr.addr, + sizeof(resp.u.network_attr.addr)); + result->mtu = resp.u.network_attr.mtu; + + return 0; +} + +int efa_com_get_device_attr(struct efa_com_dev *edev, + struct efa_com_get_device_attr_result *result) +{ + struct efa_admin_get_feature_resp resp; + int err; + + err = efa_com_get_feature(edev, &resp, EFA_ADMIN_DEVICE_ATTR); + if (unlikely(err)) { + efa_err(edev->dmadev, + "Failed to get device attributes %d\n", err); + return err; + } + + result->page_size_cap = resp.u.device_attr.page_size_cap; + result->fw_version = resp.u.device_attr.fw_version; + result->admin_api_version = resp.u.device_attr.admin_api_version; + result->device_version = resp.u.device_attr.device_version; + result->supported_features = resp.u.device_attr.supported_features; + result->phys_addr_width = resp.u.device_attr.phys_addr_width; + result->virt_addr_width = resp.u.device_attr.virt_addr_width; + result->db_bar = resp.u.device_attr.db_bar; + + if (unlikely(result->admin_api_version < 1)) { + efa_err(edev->dmadev, + "Failed to get device attr api version [%u < 1]\n", + result->admin_api_version); + return -EINVAL; + } + + edev->supported_features = resp.u.device_attr.supported_features; + err = efa_com_get_feature(edev, &resp, + EFA_ADMIN_QUEUE_ATTR); + if (unlikely(err)) { + efa_err(edev->dmadev, + "Failed to get network attributes %d\n", err); + return err; + } + + result->max_qp = resp.u.queue_attr.max_qp; + result->max_sq_depth = resp.u.queue_attr.max_sq_depth; + result->max_rq_depth = resp.u.queue_attr.max_rq_depth; + result->max_cq = resp.u.queue_attr.max_cq; + result->max_cq_depth = resp.u.queue_attr.max_cq_depth; + result->inline_buf_size = resp.u.queue_attr.inline_buf_size; + result->max_sq_sge = resp.u.queue_attr.max_wr_send_sges; + result->max_rq_sge = resp.u.queue_attr.max_wr_recv_sges; + result->max_mr = resp.u.queue_attr.max_mr; + result->max_mr_pages = resp.u.queue_attr.max_mr_pages; + result->max_pd = resp.u.queue_attr.max_pd; + result->max_ah = resp.u.queue_attr.max_ah; + result->max_llq_size = resp.u.queue_attr.max_llq_size; + result->sub_cqs_per_cq = resp.u.queue_attr.sub_cqs_per_cq; + + return 0; +} + +int efa_com_get_hw_hints(struct efa_com_dev *edev, + struct efa_com_get_hw_hints_result *result) +{ + struct efa_admin_get_feature_resp resp; + int err; + + err = efa_com_get_feature(edev, &resp, EFA_ADMIN_HW_HINTS); + if (unlikely(err)) { + efa_err(edev->dmadev, "Failed to get hw hints %d\n", err); + return err; + } + + result->admin_completion_timeout = resp.u.hw_hints.admin_completion_timeout; + result->driver_watchdog_timeout = resp.u.hw_hints.driver_watchdog_timeout; + result->mmio_read_timeout = resp.u.hw_hints.mmio_read_timeout; + result->poll_interval = resp.u.hw_hints.poll_interval; + + return 0; +} + +static int efa_com_set_feature_ex(struct efa_com_dev *edev, + struct efa_admin_set_feature_resp *set_resp, + struct efa_admin_set_feature_cmd *set_cmd, + enum efa_admin_aq_feature_id feature_id, + dma_addr_t control_buf_dma_addr, + u32 control_buff_size) +{ + struct efa_com_admin_queue *aq; + int err; + + if (!efa_com_check_supported_feature_id(edev, feature_id)) { + efa_err(edev->dmadev, "Feature %d isn't supported\n", feature_id); + return -EOPNOTSUPP; + } + + aq = &edev->aq; + + set_cmd->aq_common_descriptor.opcode = EFA_ADMIN_SET_FEATURE; + if (control_buff_size) { + set_cmd->aq_common_descriptor.flags = + EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK; + efa_com_set_dma_addr(control_buf_dma_addr, + &set_cmd->control_buffer.address.mem_addr_high, + &set_cmd->control_buffer.address.mem_addr_low); + } else { + set_cmd->aq_common_descriptor.flags = 0; + } + + set_cmd->control_buffer.length = control_buff_size; + set_cmd->feature_common.feature_id = feature_id; + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)set_cmd, + sizeof(*set_cmd), + (struct efa_admin_acq_entry *)set_resp, + sizeof(*set_resp)); + + if (unlikely(err)) + efa_err(edev->dmadev, + "Failed to submit set_feature command %d error: %d\n", + feature_id, err); + + return err; +} + +static int efa_com_set_feature(struct efa_com_dev *edev, + struct efa_admin_set_feature_resp *set_resp, + struct efa_admin_set_feature_cmd *set_cmd, + enum efa_admin_aq_feature_id feature_id) +{ + return efa_com_set_feature_ex(edev, set_resp, set_cmd, feature_id, + 0, 0); +} + +int efa_com_set_aenq_config(struct efa_com_dev *edev, u32 groups) +{ + struct efa_admin_get_feature_resp get_resp; + struct efa_admin_set_feature_resp set_resp; + struct efa_admin_set_feature_cmd cmd; + int err; + + efa_dbg(edev->dmadev, + "Configuring aenq with groups[0x%x]\n", groups); + + err = efa_com_get_feature(edev, &get_resp, EFA_ADMIN_AENQ_CONFIG); + if (unlikely(err)) { + efa_err(edev->dmadev, + "Failed to get aenq attributes: %d\n", err); + return err; + } + + efa_dbg(edev->dmadev, + "Get aenq groups: supported[0x%x] enabled[0x%x]\n", + get_resp.u.aenq.supported_groups, + get_resp.u.aenq.enabled_groups); + + if ((get_resp.u.aenq.supported_groups & groups) != groups) { + efa_err(edev->dmadev, + "Trying to set unsupported aenq groups[0x%x] supported[0x%x]\n", + groups, get_resp.u.aenq.supported_groups); + return -EOPNOTSUPP; + } + + memset(&cmd, 0, sizeof(cmd)); + cmd.u.aenq.enabled_groups = groups; + err = efa_com_set_feature(edev, &set_resp, &cmd, + EFA_ADMIN_AENQ_CONFIG); + if (unlikely(err)) { + efa_err(edev->dmadev, + "Failed to set aenq attributes: %d\n", err); + return err; + } + + return 0; +} + +int efa_com_alloc_pd(struct efa_com_dev *edev, + struct efa_com_alloc_pd_result *result) +{ + struct efa_com_admin_queue *aq = &edev->aq; + struct efa_admin_alloc_pd_resp resp; + struct efa_admin_alloc_pd_cmd cmd; + int err; + + memset(&cmd, 0, sizeof(cmd)); + cmd.aq_common_descriptor.opcode = EFA_ADMIN_ALLOC_PD; + + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)&cmd, + sizeof(cmd), + (struct efa_admin_acq_entry *)&resp, + sizeof(resp)); + if (unlikely(err)) { + efa_err(edev->dmadev, "Failed to allocate pd[%d]\n", err); + return err; + } + + result->pdn = resp.pd; + + return 0; +} + +int efa_com_dealloc_pd(struct efa_com_dev *edev, + struct efa_com_dealloc_pd_params *params) +{ + struct efa_com_admin_queue *aq = &edev->aq; + struct efa_admin_dealloc_pd_resp resp; + struct efa_admin_dealloc_pd_cmd cmd; + int err; + + memset(&cmd, 0, sizeof(cmd)); + cmd.aq_common_descriptor.opcode = EFA_ADMIN_DEALLOC_PD; + cmd.pd = params->pdn; + + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)&cmd, + sizeof(cmd), + (struct efa_admin_acq_entry *)&resp, + sizeof(resp)); + if (unlikely(err)) { + efa_err(edev->dmadev, "Failed to deallocate pd-%u [%d]\n", + cmd.pd, err); + return err; + } + + return 0; +} + +int efa_com_alloc_uar(struct efa_com_dev *edev, + struct efa_com_alloc_uar_result *result) +{ + struct efa_com_admin_queue *aq = &edev->aq; + struct efa_admin_alloc_uar_resp resp; + struct efa_admin_alloc_uar_cmd cmd; + int err; + + memset(&cmd, 0, sizeof(cmd)); + cmd.aq_common_descriptor.opcode = EFA_ADMIN_ALLOC_UAR; + + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)&cmd, + sizeof(cmd), + (struct efa_admin_acq_entry *)&resp, + sizeof(resp)); + if (unlikely(err)) { + efa_err(edev->dmadev, "Failed to allocate uar[%d]\n", err); + return err; + } + + result->uarn = resp.uar; + + return 0; +} + +int efa_com_dealloc_uar(struct efa_com_dev *edev, + struct efa_com_dealloc_uar_params *params) +{ + struct efa_com_admin_queue *aq = &edev->aq; + struct efa_admin_dealloc_uar_resp resp; + struct efa_admin_dealloc_uar_cmd cmd; + int err; + + memset(&cmd, 0, sizeof(cmd)); + cmd.aq_common_descriptor.opcode = EFA_ADMIN_DEALLOC_UAR; + cmd.uar = params->uarn; + + err = efa_com_cmd_exec(aq, + (struct efa_admin_aq_entry *)&cmd, + sizeof(cmd), + (struct efa_admin_acq_entry *)&resp, + sizeof(resp)); + if (unlikely(err)) { + efa_err(edev->dmadev, "Failed to deallocate uar-%u [%d]\n", + cmd.uar, err); + return err; + } + + return 0; +}
Add the EFA common commands implementation. Signed-off-by: Gal Pressman <galpress@amazon.com> --- drivers/infiniband/hw/efa/efa_com_cmd.c | 726 ++++++++++++++++++++++++++++++++ 1 file changed, 726 insertions(+) create mode 100644 drivers/infiniband/hw/efa/efa_com_cmd.c