From owner-svn-src-all@freebsd.org Tue Dec 1 13:03:11 2020 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 131624A9129; Tue, 1 Dec 2020 13:03:11 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Clj2R00r9z3lPp; Tue, 1 Dec 2020 13:03:11 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id E735115DFC; Tue, 1 Dec 2020 13:03:10 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 0B1D3A2v054947; Tue, 1 Dec 2020 13:03:10 GMT (envelope-from hselasky@FreeBSD.org) Received: (from hselasky@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 0B1D3ARj054944; Tue, 1 Dec 2020 13:03:10 GMT (envelope-from hselasky@FreeBSD.org) Message-Id: <202012011303.0B1D3ARj054944@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: hselasky set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky Date: Tue, 1 Dec 2020 13:03:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r368223 - in stable/12/sys/dev/mlx5: . mlx5_core mlx5_en X-SVN-Group: stable-12 X-SVN-Commit-Author: hselasky X-SVN-Commit-Paths: in stable/12/sys/dev/mlx5: . mlx5_core mlx5_en X-SVN-Commit-Revision: 368223 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 Dec 2020 13:03:11 -0000 Author: hselasky Date: Tue Dec 1 13:03:09 2020 New Revision: 368223 URL: https://svnweb.freebsd.org/changeset/base/368223 Log: MFC r357294: Widen EPOCH(9) usage in mlx5en(4). Make completion event path mostly lockless using EPOCH(9). Implement a mechanism using EPOCH(9) which allows us to make the callback path for completion events mostly lockless. Simplify draining callback events using epoch_wait(). While at it make sure all receive completion callbacks are covered by the network EPOCH(9), because this is required when calling if_input() and ether_input() after r357012. Sponsored by: Mellanox Technologies Modified: stable/12/sys/dev/mlx5/cq.h stable/12/sys/dev/mlx5/driver.h stable/12/sys/dev/mlx5/mlx5_core/mlx5_cq.c stable/12/sys/dev/mlx5/mlx5_en/mlx5_en_main.c Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/dev/mlx5/cq.h ============================================================================== --- stable/12/sys/dev/mlx5/cq.h Tue Dec 1 12:52:15 2020 (r368222) +++ stable/12/sys/dev/mlx5/cq.h Tue Dec 1 13:03:09 2020 (r368223) @@ -38,8 +38,6 @@ struct mlx5_core_cq { int cqe_sz; __be32 *set_ci_db; __be32 *arm_db; - atomic_t refcount; - struct completion free; unsigned vector; int irqn; void (*comp) (struct mlx5_core_cq *); Modified: stable/12/sys/dev/mlx5/driver.h ============================================================================== --- stable/12/sys/dev/mlx5/driver.h Tue Dec 1 12:52:15 2020 (r368222) +++ stable/12/sys/dev/mlx5/driver.h Tue Dec 1 13:03:09 2020 (r368223) @@ -515,21 +515,17 @@ struct mlx5_core_health { struct workqueue_struct *wq_cmd; }; -#ifdef RATELIMIT -#define MLX5_CQ_LINEAR_ARRAY_SIZE (128 * 1024) -#else #define MLX5_CQ_LINEAR_ARRAY_SIZE 1024 -#endif struct mlx5_cq_linear_array_entry { - spinlock_t lock; struct mlx5_core_cq * volatile cq; }; struct mlx5_cq_table { /* protect radix tree */ - spinlock_t lock; + spinlock_t writerlock; + atomic_t writercount; struct radix_tree_root tree; struct mlx5_cq_linear_array_entry linear_array[MLX5_CQ_LINEAR_ARRAY_SIZE]; }; Modified: stable/12/sys/dev/mlx5/mlx5_core/mlx5_cq.c ============================================================================== --- stable/12/sys/dev/mlx5/mlx5_core/mlx5_cq.c Tue Dec 1 12:52:15 2020 (r368222) +++ stable/12/sys/dev/mlx5/mlx5_core/mlx5_cq.c Tue Dec 1 13:03:09 2020 (r368223) @@ -33,72 +33,92 @@ #include #include "mlx5_core.h" +#include +#include + +static void +mlx5_cq_table_write_lock(struct mlx5_cq_table *table) +{ + + atomic_inc(&table->writercount); + /* make sure all see the updated writercount */ + NET_EPOCH_WAIT(); + spin_lock(&table->writerlock); +} + +static void +mlx5_cq_table_write_unlock(struct mlx5_cq_table *table) +{ + + spin_unlock(&table->writerlock); + atomic_dec(&table->writercount); + /* drain all pending CQ callers */ + NET_EPOCH_WAIT(); +} + void mlx5_cq_completion(struct mlx5_core_dev *dev, u32 cqn) { - struct mlx5_core_cq *cq; struct mlx5_cq_table *table = &dev->priv.cq_table; + struct mlx5_core_cq *cq; + struct epoch_tracker et; + bool do_lock; - if (cqn < MLX5_CQ_LINEAR_ARRAY_SIZE) { - struct mlx5_cq_linear_array_entry *entry; + NET_EPOCH_ENTER_ET(et); - entry = &table->linear_array[cqn]; - spin_lock(&entry->lock); - cq = entry->cq; - if (cq == NULL) { - mlx5_core_warn(dev, - "Completion event for bogus CQ 0x%x\n", cqn); - } else { - ++cq->arm_sn; - cq->comp(cq); - } - spin_unlock(&entry->lock); - return; - } + do_lock = atomic_read(&table->writercount) != 0; + if (unlikely(do_lock)) + spin_lock(&table->writerlock); - spin_lock(&table->lock); - cq = radix_tree_lookup(&table->tree, cqn); - if (likely(cq)) - atomic_inc(&cq->refcount); - spin_unlock(&table->lock); + if (likely(cqn < MLX5_CQ_LINEAR_ARRAY_SIZE)) + cq = table->linear_array[cqn].cq; + else + cq = radix_tree_lookup(&table->tree, cqn); - if (!cq) { - mlx5_core_warn(dev, "Completion event for bogus CQ 0x%x\n", cqn); - return; + if (unlikely(do_lock)) + spin_unlock(&table->writerlock); + + if (likely(cq != NULL)) { + ++cq->arm_sn; + cq->comp(cq); + } else { + mlx5_core_warn(dev, + "Completion event for bogus CQ 0x%x\n", cqn); } - ++cq->arm_sn; - - cq->comp(cq); - - if (atomic_dec_and_test(&cq->refcount)) - complete(&cq->free); + NET_EPOCH_EXIT_ET(et); } void mlx5_cq_event(struct mlx5_core_dev *dev, u32 cqn, int event_type) { struct mlx5_cq_table *table = &dev->priv.cq_table; struct mlx5_core_cq *cq; + struct epoch_tracker et; + bool do_lock; - spin_lock(&table->lock); + NET_EPOCH_ENTER_ET(et); - cq = radix_tree_lookup(&table->tree, cqn); - if (cq) - atomic_inc(&cq->refcount); + do_lock = atomic_read(&table->writercount) != 0; + if (unlikely(do_lock)) + spin_lock(&table->writerlock); - spin_unlock(&table->lock); + if (likely(cqn < MLX5_CQ_LINEAR_ARRAY_SIZE)) + cq = table->linear_array[cqn].cq; + else + cq = radix_tree_lookup(&table->tree, cqn); - if (!cq) { - mlx5_core_warn(dev, "Async event for bogus CQ 0x%x\n", cqn); - return; + if (unlikely(do_lock)) + spin_unlock(&table->writerlock); + + if (likely(cq != NULL)) { + cq->event(cq, event_type); + } else { + mlx5_core_warn(dev, + "Asynchronous event for bogus CQ 0x%x\n", cqn); } - cq->event(cq, event_type); - - if (atomic_dec_and_test(&cq->refcount)) - complete(&cq->free); + NET_EPOCH_EXIT_ET(et); } - int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, u32 *in, int inlen, u32 *out, int outlen) { @@ -116,24 +136,16 @@ int mlx5_core_create_cq(struct mlx5_core_dev *dev, str cq->cqn = MLX5_GET(create_cq_out, out, cqn); cq->cons_index = 0; cq->arm_sn = 0; - atomic_set(&cq->refcount, 1); - init_completion(&cq->free); - spin_lock_irq(&table->lock); + mlx5_cq_table_write_lock(table); err = radix_tree_insert(&table->tree, cq->cqn, cq); - spin_unlock_irq(&table->lock); + if (likely(err == 0 && cq->cqn < MLX5_CQ_LINEAR_ARRAY_SIZE)) + table->linear_array[cq->cqn].cq = cq; + mlx5_cq_table_write_unlock(table); + if (err) goto err_cmd; - if (cq->cqn < MLX5_CQ_LINEAR_ARRAY_SIZE) { - struct mlx5_cq_linear_array_entry *entry; - - entry = &table->linear_array[cq->cqn]; - spin_lock_irq(&entry->lock); - entry->cq = cq; - spin_unlock_irq(&entry->lock); - } - cq->pid = curthread->td_proc->p_pid; return 0; @@ -152,44 +164,24 @@ int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, st u32 out[MLX5_ST_SZ_DW(destroy_cq_out)] = {0}; u32 in[MLX5_ST_SZ_DW(destroy_cq_in)] = {0}; struct mlx5_core_cq *tmp; - int err; - if (cq->cqn < MLX5_CQ_LINEAR_ARRAY_SIZE) { - struct mlx5_cq_linear_array_entry *entry; - - entry = &table->linear_array[cq->cqn]; - spin_lock_irq(&entry->lock); - entry->cq = NULL; - spin_unlock_irq(&entry->lock); - } - - spin_lock_irq(&table->lock); + mlx5_cq_table_write_lock(table); + if (likely(cq->cqn < MLX5_CQ_LINEAR_ARRAY_SIZE)) + table->linear_array[cq->cqn].cq = NULL; tmp = radix_tree_delete(&table->tree, cq->cqn); - spin_unlock_irq(&table->lock); - if (!tmp) { + mlx5_cq_table_write_unlock(table); + + if (unlikely(tmp == NULL)) { mlx5_core_warn(dev, "cq 0x%x not found in tree\n", cq->cqn); return -EINVAL; - } - if (tmp != cq) { - mlx5_core_warn(dev, "corruption on srqn 0x%x\n", cq->cqn); + } else if (unlikely(tmp != cq)) { + mlx5_core_warn(dev, "corrupted cqn 0x%x\n", cq->cqn); return -EINVAL; } MLX5_SET(destroy_cq_in, in, opcode, MLX5_CMD_OP_DESTROY_CQ); MLX5_SET(destroy_cq_in, in, cqn, cq->cqn); - err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); - if (err) - goto out; - - synchronize_irq(cq->irqn); - - if (atomic_dec_and_test(&cq->refcount)) - complete(&cq->free); - wait_for_completion(&cq->free); - -out: - - return err; + return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); } EXPORT_SYMBOL(mlx5_core_destroy_cq); @@ -259,17 +251,12 @@ int mlx5_core_modify_cq_moderation_mode(struct mlx5_co int mlx5_init_cq_table(struct mlx5_core_dev *dev) { struct mlx5_cq_table *table = &dev->priv.cq_table; - int err; - int x; memset(table, 0, sizeof(*table)); - spin_lock_init(&table->lock); - for (x = 0; x != MLX5_CQ_LINEAR_ARRAY_SIZE; x++) - spin_lock_init(&table->linear_array[x].lock); + spin_lock_init(&table->writerlock); INIT_RADIX_TREE(&table->tree, GFP_ATOMIC); - err = 0; - return err; + return 0; } void mlx5_cleanup_cq_table(struct mlx5_core_dev *dev) Modified: stable/12/sys/dev/mlx5/mlx5_en/mlx5_en_main.c ============================================================================== --- stable/12/sys/dev/mlx5/mlx5_en/mlx5_en_main.c Tue Dec 1 12:52:15 2020 (r368222) +++ stable/12/sys/dev/mlx5/mlx5_en/mlx5_en_main.c Tue Dec 1 13:03:09 2020 (r368223) @@ -2171,6 +2171,7 @@ mlx5e_open_channel(struct mlx5e_priv *priv, struct mlx5e_channel_param *cparam, struct mlx5e_channel *c) { + struct epoch_tracker et; int i, err; /* zero non-persistant data */ @@ -2198,7 +2199,9 @@ mlx5e_open_channel(struct mlx5e_priv *priv, goto err_close_sqs; /* poll receive queue initially */ + NET_EPOCH_ENTER_ET(et); c->rq.cq.mcq.comp(&c->rq.cq.mcq); + NET_EPOCH_EXIT_ET(et); return (0); @@ -3740,6 +3743,7 @@ static void mlx5e_disable_rx_dma(struct mlx5e_channel *ch) { struct mlx5e_rq *rq = &ch->rq; + struct epoch_tracker et; int err; mtx_lock(&rq->mtx); @@ -3755,7 +3759,9 @@ mlx5e_disable_rx_dma(struct mlx5e_channel *ch) while (!mlx5_wq_ll_is_empty(&rq->wq)) { msleep(1); + NET_EPOCH_ENTER_ET(et); rq->cq.mcq.comp(&rq->cq.mcq); + NET_EPOCH_EXIT_ET(et); } /* @@ -3773,6 +3779,7 @@ static void mlx5e_enable_rx_dma(struct mlx5e_channel *ch) { struct mlx5e_rq *rq = &ch->rq; + struct epoch_tracker et; int err; rq->wq.wqe_ctr = 0; @@ -3785,7 +3792,9 @@ mlx5e_enable_rx_dma(struct mlx5e_channel *ch) rq->enabled = 1; + NET_EPOCH_ENTER_ET(et); rq->cq.mcq.comp(&rq->cq.mcq); + NET_EPOCH_EXIT_ET(et); } void