From patchwork Wed Feb 27 06:15:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Parav Pandit X-Patchwork-Id: 10831245 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C8A0F922 for ; Wed, 27 Feb 2019 06:15:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B46952C932 for ; Wed, 27 Feb 2019 06:15:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A92FB2CB80; Wed, 27 Feb 2019 06:15:51 +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 18DAA2C932 for ; Wed, 27 Feb 2019 06:15:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729592AbfB0GPt (ORCPT ); Wed, 27 Feb 2019 01:15:49 -0500 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:45039 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729905AbfB0GPt (ORCPT ); Wed, 27 Feb 2019 01:15:49 -0500 Received: from Internal Mail-Server by MTLPINE1 (envelope-from parav@mellanox.com) with ESMTPS (AES256-SHA encrypted); 27 Feb 2019 08:15:43 +0200 Received: from sw-mtx-036.mtx.labs.mlnx (sw-mtx-036.mtx.labs.mlnx [10.12.150.149]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id x1R6Febj000709; Wed, 27 Feb 2019 08:15:42 +0200 From: Parav Pandit To: bvanassche@acm.org, linux-rdma@vger.kernel.org Cc: parav@mellanox.com Subject: [EXPERIMENTAL 1/3] RDMA/loopback: Add helper lib for resources and cqe fifo Date: Wed, 27 Feb 2019 00:15:37 -0600 Message-Id: <1551248139-62411-2-git-send-email-parav@mellanox.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1551248139-62411-1-git-send-email-parav@mellanox.com> References: <1551248139-62411-1-git-send-email-parav@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 Implement xarray based resource table ids for CQ, QP and MR. Implement Fifo for CQEs and QP's RQEs to be reused later in SRQ. Signed-off-by: Parav Pandit --- drivers/infiniband/sw/loopback/helper.c | 139 +++++++++++++++++++++++ drivers/infiniband/sw/loopback/loopback_helper.h | 68 +++++++++++ 2 files changed, 207 insertions(+) create mode 100644 drivers/infiniband/sw/loopback/helper.c create mode 100644 drivers/infiniband/sw/loopback/loopback_helper.h diff --git a/drivers/infiniband/sw/loopback/helper.c b/drivers/infiniband/sw/loopback/helper.c new file mode 100644 index 0000000..1294338 --- /dev/null +++ b/drivers/infiniband/sw/loopback/helper.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* + * Copyright (c) 2019 Mellanox Technologies. All rights reserved. + */ + +#include +#include +#include "loopback_helper.h" + +void init_table(struct loopback_resource_table *table, + u32 min_id, u32 max_id, u32 id_mask, u8 id_shift) +{ + spin_lock_init(&table->lock); + xa_init_flags(&table->ids, XA_FLAGS_ALLOC); + table->max_id = max_id; + table->min_id = min_id; + table->id_mask = id_mask; + table->id_shift = id_shift; +} + +void put_table_entry(struct loopback_resource *entry) +{ + if (refcount_dec_and_test(&entry->refcount)) + complete(&entry->completion); +} + +struct loopback_resource * +get_table_entry_by_id(struct loopback_resource_table *table, u32 id) +{ + struct loopback_resource *entry; + + id = (id & table->id_mask) >> table->id_shift; + rcu_read_lock(); + entry = xa_load(&table->ids, id); + if (entry) { + if (!xa_get_mark(&table->ids, id, + LOOPBACK_RESOURCE_STATE_VALID) || + !refcount_inc_not_zero(&entry->refcount)) + entry = NULL; + } + rcu_read_unlock(); + return entry; +} + +int _attach_table_id(struct loopback_resource_table *table, + struct loopback_resource *entry, + int desired_id, bool valid) +{ + u32 start_id = table->min_id; + u32 stop_id = table->max_id; + int ret; + + refcount_set(&entry->refcount, 1); + init_completion(&entry->completion); + + if (desired_id > 0) { + /* need the exact match id */ + start_id = desired_id << table->id_shift; + stop_id = desired_id << table->id_shift; + } + entry->id = start_id; + ret = xa_alloc(&table->ids, &entry->id, stop_id, entry, GFP_KERNEL); + if (ret) + return ret; + if (valid) + xa_set_mark(&table->ids, entry->id, + LOOPBACK_RESOURCE_STATE_VALID); + return 0; +} + +int attach_table_id_for_id(struct loopback_resource_table *table, + struct loopback_resource *entry, int desired_id) +{ + return _attach_table_id(table, entry, desired_id, true); +} + +int attach_table_id_free_state(struct loopback_resource_table *table, + struct loopback_resource *entry) +{ + return _attach_table_id(table, entry, -1, false); +} + +int attach_table_id(struct loopback_resource_table *table, + struct loopback_resource *entry) +{ + return _attach_table_id(table, entry, -1, true); +} + +void detach_table_id(struct loopback_resource_table *table, + struct loopback_resource *entry) +{ + /* Mark entry invalid, so no new references can be taken */ + xa_clear_mark(&table->ids, entry->id, + LOOPBACK_RESOURCE_STATE_VALID); + + /* Now wait for all readers to stop using the resource */ + synchronize_rcu(); + + put_table_entry(entry); + wait_for_completion(&entry->completion); + /* At this point there cannot be any active reader */ + WARN_ON(refcount_read(&entry->refcount)); + + /* Now that all references dropped, its free to reassign this id */ + xa_erase(&table->ids, entry->id); +} + +void init_fifo(struct loopback_fifo *fifo) +{ + spin_lock_init(&fifo->lock); + INIT_LIST_HEAD(&fifo->list); +} + +void push_to_fifo(struct loopback_fifo *fifo, struct list_head *entry) +{ + unsigned long flags; + + spin_lock_irqsave(&fifo->lock, flags); + list_add_tail(entry, &fifo->list); + fifo->entries++; + spin_unlock_irqrestore(&fifo->lock, flags); +} + +struct list_head *pop_from_fifo(struct loopback_fifo *fifo) +{ + struct list_head *entry = NULL; + unsigned long flags; + + spin_lock_irqsave(&fifo->lock, flags); + if (!list_empty(&fifo->list)) { + entry = fifo->list.next; + list_del(fifo->list.next); + fifo->entries--; + } + if (!entry && fifo->entries) + pr_debug("%s fifo entries = %u\n", __func__, fifo->entries); + spin_unlock_irqrestore(&fifo->lock, flags); + return entry; +} diff --git a/drivers/infiniband/sw/loopback/loopback_helper.h b/drivers/infiniband/sw/loopback/loopback_helper.h new file mode 100644 index 0000000..8ea93f4 --- /dev/null +++ b/drivers/infiniband/sw/loopback/loopback_helper.h @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* + * Copyright (c) 2019 Mellanox Technologies. All rights reserved. + */ + +#ifndef LOOPBACK_HELPER_H +#define LOOPBACK_HELPER_H + +#include +struct loopback_resource { + struct completion completion; + /* wait for all datapath references to drop, we don't want to do + * large memcpy while holding rcu, refcount doesn't hurt the + * performance. + */ + refcount_t refcount; + u32 id; +}; + +#define LOOPBACK_RESOURCE_STATE_VALID XA_MARK_1 + +/** + * struct loopback_resource_table - resource table + */ + +struct loopback_resource_table { + /* Protects xarray of resources (ids) */ + spinlock_t lock; + struct xarray ids; + u32 min_id; + u32 max_id; + u32 id_mask; + u8 id_shift; +}; + +/* TODO: replace with kernel pfifo, which consumes more memory */ +struct loopback_fifo { + /* Protect insert, remove to list */ + spinlock_t lock; + /* head of entries, FIFO order */ + struct list_head list; + u32 entries; +}; + +static inline u64 get_fifo_entries(struct loopback_fifo *fifo) +{ + return fifo->entries; +} + +void init_fifo(struct loopback_fifo *fifo); +void push_to_fifo(struct loopback_fifo *fifo, struct list_head *entry); +struct list_head *pop_from_fifo(struct loopback_fifo *fifo); + +void init_table(struct loopback_resource_table *table, + u32 min_id, u32 max_id, u32 id_mask, u8 id_shift); +struct loopback_resource * +get_table_entry_by_id(struct loopback_resource_table *table, u32 id); +void put_table_entry(struct loopback_resource *entry); +int attach_table_id_for_id(struct loopback_resource_table *table, + struct loopback_resource *entry, int desired_id); +int attach_table_id_free_state(struct loopback_resource_table *table, + struct loopback_resource *entry); +int attach_table_id(struct loopback_resource_table *table, + struct loopback_resource *entry); +void detach_table_id(struct loopback_resource_table *table, + struct loopback_resource *entry); + +#endif