From patchwork Thu May 17 10:39:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yishai Hadas X-Patchwork-Id: 10406315 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1EACA602C2 for ; Thu, 17 May 2018 10:40:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B7A1F28A64 for ; Thu, 17 May 2018 10:40:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B529B28AA4; Thu, 17 May 2018 10:40:12 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3199228A64 for ; Thu, 17 May 2018 10:40:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751971AbeEQKkH (ORCPT ); Thu, 17 May 2018 06:40:07 -0400 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:45012 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751815AbeEQKkD (ORCPT ); Thu, 17 May 2018 06:40:03 -0400 Received: from Internal Mail-Server by MTLPINE1 (envelope-from yishaih@mellanox.com) with ESMTPS (AES256-SHA encrypted); 17 May 2018 13:41:48 +0300 Received: from vnc17.mtl.labs.mlnx (vnc17.mtl.labs.mlnx [10.7.2.17]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id w4HAdvF3002351; Thu, 17 May 2018 13:39:57 +0300 Received: from vnc17.mtl.labs.mlnx (vnc17.mtl.labs.mlnx [127.0.0.1]) by vnc17.mtl.labs.mlnx (8.13.8/8.13.8) with ESMTP id w4HAduvT032432; Thu, 17 May 2018 13:39:56 +0300 Received: (from yishaih@localhost) by vnc17.mtl.labs.mlnx (8.13.8/8.13.8/Submit) id w4HAduCD032431; Thu, 17 May 2018 13:39:56 +0300 From: Yishai Hadas To: linux-rdma@vger.kernel.org Cc: yishaih@mellanox.com, raeds@mellanox.com Subject: [PATCH rdma-core 11/11] mlx5: Add flow counters support Date: Thu, 17 May 2018 13:39:37 +0300 Message-Id: <1526553577-32273-12-git-send-email-yishaih@mellanox.com> X-Mailer: git-send-email 1.8.2.3 In-Reply-To: <1526553577-32273-1-git-send-email-yishaih@mellanox.com> References: <1526553577-32273-1-git-send-email-yishaih@mellanox.com> Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Raed Salem This implements the binding action of previously created counters object with an ibv_flow. At this stage there is a need to pass the counters object information as a private data to mlx5 kernel driver if it wasn't previously bound. Signed-off-by: Raed Salem Signed-off-by: Yishai Hadas --- providers/mlx5/mlx5.h | 12 ++++ providers/mlx5/verbs.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 157 insertions(+), 8 deletions(-) diff --git a/providers/mlx5/mlx5.h b/providers/mlx5/mlx5.h index 4890e65..e26e291 100644 --- a/providers/mlx5/mlx5.h +++ b/providers/mlx5/mlx5.h @@ -546,6 +546,13 @@ struct mlx5_counters { struct list_head counters_list; pthread_mutex_t lock; uint32_t ncounters; + /* number of bounded objects */ + int refcount; +}; + +struct mlx5_flow { + struct ibv_flow flow_id; + struct mlx5_counters *mcounters; }; static inline int mlx5_ilog2(int n) @@ -683,6 +690,11 @@ static inline struct mlx5_counters *to_mcounters(struct ibv_counters *ibcounters return container_of(ibcounters, struct mlx5_counters, vcounters.counters); } +static inline struct mlx5_flow *to_mflow(struct ibv_flow *flow_id) +{ + return container_of(flow_id, struct mlx5_flow, flow_id); +} + int mlx5_alloc_buf(struct mlx5_buf *buf, size_t size, int page_size); void mlx5_free_buf(struct mlx5_buf *buf); int mlx5_alloc_buf_contig(struct mlx5_context *mctx, struct mlx5_buf *buf, diff --git a/providers/mlx5/verbs.c b/providers/mlx5/verbs.c index 63701b8..f2877e4 100644 --- a/providers/mlx5/verbs.c +++ b/providers/mlx5/verbs.c @@ -2933,33 +2933,158 @@ int mlx5_destroy_wq(struct ibv_wq *wq) return 0; } +static void free_flow_counters_descriptions(struct mlx5_ib_create_flow *cmd) +{ + int i; + + for (i = 0; i < cmd->ncounters_data; i++) + free((void *)(uintptr_t)cmd->data[i].counters_data); +} + +static int get_flow_mcounters(struct mlx5_flow *mflow, + struct ibv_flow_attr *flow_attr, + struct mlx5_counters **mcounters, + uint32_t *data_size) +{ + struct ibv_flow_spec *ib_spec; + uint32_t ncounters_used = 0; + int i; + + ib_spec = (struct ibv_flow_spec *)(flow_attr + 1); + for (i = 0; i < flow_attr->num_of_specs; i++, ib_spec = (void *)ib_spec + ib_spec->hdr.size) { + if (ib_spec->hdr.type != IBV_FLOW_SPEC_ACTION_COUNT) + continue; + + /* currently support only one counters data */ + if (ncounters_used > 0) + return EINVAL; + + *mcounters = to_mcounters(ib_spec->flow_count.counters); + ncounters_used++; + } + + *data_size = ncounters_used * sizeof(struct mlx5_ib_flow_counters_data); + return 0; +} + +static int allocate_flow_counters_descriptions(struct mlx5_counters *mcounters, + struct mlx5_ib_create_flow *cmd) +{ + struct mlx5_ib_flow_counters_data *mcntrs_data; + uint32_t *cntrs_indexes, *cntrs_data; + struct mlx5_counter_node *cntr_node; + uint32_t ncounters; + int j = 0; + + mcntrs_data = cmd->data; + ncounters = mcounters->ncounters; + + /* mlx5_attach_counters_point_flow was never called */ + if (!ncounters) + return EINVAL; + + /* each counter has both index and description */ + cntrs_data = calloc(ncounters * 2, sizeof(uint32_t)); + if (!cntrs_data) + return ENOMEM; + + cntrs_indexes = cntrs_data + ncounters; + list_for_each(&mcounters->counters_list, cntr_node, entry) { + cntrs_indexes[j] = cntr_node->index; + cntrs_data[j] = cntr_node->desc; + j++; + } + + mcntrs_data[cmd->ncounters_data].counters_data = ioctl_ptr_to_u64(cntrs_data); + mcntrs_data[cmd->ncounters_data].ncounters = ncounters; + cmd->ncounters_data++; + + return 0; +} + struct ibv_flow *mlx5_create_flow(struct ibv_qp *qp, struct ibv_flow_attr *flow_attr) { + struct mlx5_ib_create_flow *cmd; + uint32_t required_cmd_size = 0; struct ibv_flow *flow_id; + struct mlx5_flow *mflow; int ret; - flow_id = calloc(1, sizeof *flow_id); - if (!flow_id) + mflow = calloc(1, sizeof(*mflow)); + if (!mflow) { + errno = ENOMEM; return NULL; + } + ret = get_flow_mcounters(mflow, flow_attr, &mflow->mcounters, &required_cmd_size); + if (ret) { + errno = ret; + goto err_get_mcounters; + } + + required_cmd_size += sizeof(*cmd); + cmd = calloc(1, required_cmd_size); + if (!cmd) { + errno = ENOMEM; + goto err_get_mcounters; + } + + if (mflow->mcounters) { + pthread_mutex_lock(&mflow->mcounters->lock); + /* if the counters already bound no need to pass its description */ + if (!mflow->mcounters->refcount) { + ret = allocate_flow_counters_descriptions(mflow->mcounters, cmd); + if (ret) { + errno = ret; + goto err_desc_alloc; + } + } + } + + flow_id = &mflow->flow_id; ret = ibv_cmd_create_flow(qp, flow_id, flow_attr, - NULL, 0); - if (!ret) - return flow_id; + cmd, required_cmd_size); + if (ret) + goto err_create_flow; + + if (mflow->mcounters) { + free_flow_counters_descriptions(cmd); + mflow->mcounters->refcount++; + pthread_mutex_unlock(&mflow->mcounters->lock); + } - free(flow_id); + free(cmd); + + return flow_id; + +err_create_flow: + if (mflow->mcounters) { + free_flow_counters_descriptions(cmd); + pthread_mutex_unlock(&mflow->mcounters->lock); + } +err_desc_alloc: + free(cmd); +err_get_mcounters: + free(mflow); return NULL; } int mlx5_destroy_flow(struct ibv_flow *flow_id) { + struct mlx5_flow *mflow = to_mflow(flow_id); int ret; ret = ibv_cmd_destroy_flow(flow_id); if (ret) return ret; - free(flow_id); + if (mflow->mcounters) { + pthread_mutex_lock(&mflow->mcounters->lock); + mflow->mcounters->refcount--; + pthread_mutex_unlock(&mflow->mcounters->lock); + } + + free(mflow); return 0; } @@ -3297,6 +3422,7 @@ int mlx5_attach_counters_point_flow(struct ibv_counters *counters, { struct mlx5_counters *mcntrs = to_mcounters(counters); struct mlx5_counter_node *cntrs_node; + int ret; /* The driver supports only the static binding mode as part of ibv_create_flow */ if (flow) @@ -3314,14 +3440,25 @@ int mlx5_attach_counters_point_flow(struct ibv_counters *counters, if (!cntrs_node) return ENOMEM; + pthread_mutex_lock(&mcntrs->lock); + /* The counter is bound to a flow, attach is not allowed */ + if (mcntrs->refcount) { + ret = EBUSY; + goto err_already_bound; + } + cntrs_node->index = attr->index; cntrs_node->desc = attr->counter_desc; - pthread_mutex_lock(&mcntrs->lock); list_add(&mcntrs->counters_list, &cntrs_node->entry); mcntrs->ncounters++; pthread_mutex_unlock(&mcntrs->lock); return 0; + +err_already_bound: + pthread_mutex_unlock(&mcntrs->lock); + free(cntrs_node); + return ret; } int mlx5_read_counters(struct ibv_counters *counters,