Received: by 2002:a05:6359:6284:b0:131:369:b2a3 with SMTP id se4csp1126023rwb; Sat, 5 Aug 2023 07:51:52 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHrgF0UYiYX6bHTwy2KunlADjlysHejXoinorIml2Npmn//wfQQEqYYirgyLwQsrPwrsQ00 X-Received: by 2002:a17:906:5345:b0:989:450:e567 with SMTP id j5-20020a170906534500b009890450e567mr4903800ejo.65.1691247111904; Sat, 05 Aug 2023 07:51:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691247111; cv=none; d=google.com; s=arc-20160816; b=KjcRr62NCouWTyQFb5V65nSOL10zTSUmgv3oQ6GkGrF5Zd4+uXb1U5vaPcdkdBmPMJ UvcvFs4WDFghpiePWxdNUYfviF3RXRbKwWIi/1lsOe1bAhVtT+3+C+2sZoqhKfP/ELy0 s9LPmN16ayJUpOa78kYf5l12EMDJIuuYNsfyv8+ZSJRhf45Tc7Rhv/q8pAn7sJFPCweP 2wqy/IaRTP81FUxaVj8g9079iyvLWeskjGsc6gdq+Zd079e/5E64gztTxYmgo5In+4+7 hNzUCyTF031Ay5qBCdfJARtCY6+SHuto5I6aq8YoaVs6uFDJgH5sdNmi+PzwpZY2w4Fn bUVw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:in-reply-to:from :references:cc:to:subject:mime-version:date:dkim-signature :message-id; bh=0d2/HWw/t4KftogUmOniaysvCJK7HhLWbKWsyTbkz+0=; fh=XjpxwjOMFMMaurqKf1OqfMZa3YkRtaK3PIbYvZXWzY0=; b=RlikKsll21dcxEwRw/1z4kE338PCgVwJuIbiNEQRyvYljLMJH857CX6sAlB1z3ZSVv 8ibnUmfifrtWyO0h7BvlSf+vgrVsAKDd+vH6zxcfqx5CU9RI/mlRR2tTpa1o+rB7nz+M DixrCD5Nt67pE7QKys2RqhxSTR0yo7q5jEEB4zxSDou8X4CXoyzHDo3nLb9weW9N779X 2POQh9GwsrutdHDCAU2PT39AlDeSwQTlI9TeMUlRiZ9w+SYGblzGVXnShBxww0rxWhPA m5Cwz6pK03//lY0tl1kkCycHdoNa4f0mXeegJH9auSsQbYF5mfYWKjMjdDkMAtntmB7j M2Zw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linux.dev header.s=key1 header.b=L5JmuClv; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.dev Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id z10-20020a170906714a00b0099cb34fc75dsi1270251ejj.1029.2023.08.05.07.51.26; Sat, 05 Aug 2023 07:51:51 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linux.dev header.s=key1 header.b=L5JmuClv; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.dev Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229672AbjHEOaI (ORCPT + 99 others); Sat, 5 Aug 2023 10:30:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48446 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229481AbjHEOaG (ORCPT ); Sat, 5 Aug 2023 10:30:06 -0400 Received: from out-68.mta1.migadu.com (out-68.mta1.migadu.com [95.215.58.68]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 54C8F44A4 for ; Sat, 5 Aug 2023 07:29:44 -0700 (PDT) Message-ID: <72a98e55-46b0-66d6-b4b3-4f6d14e1fd7b@linux.dev> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1691245782; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0d2/HWw/t4KftogUmOniaysvCJK7HhLWbKWsyTbkz+0=; b=L5JmuClvl8yxJqbTomikxt1FaaRynUJHsKi1bKAxeFsZVoZ2u6njLiy42IP0PlhNbJnMLV 8cwaSAc5kJ7/kXhE1CkjdC6Tcvv5pjiNK9Ijo46qs8CiWYt2T86qfz6x8+88C6xQZGXx3K r2LcEbnXdJ2dvyygA2LX8H8maJZS+8Y= Date: Sat, 5 Aug 2023 22:29:29 +0800 MIME-Version: 1.0 Subject: Re: [PATCH net-next 03/10] mlx4: Replace the mlx4_interface.event callback with a notifier To: Petr Pavlu , tariqt@nvidia.com, yishaih@nvidia.com, leon@kernel.org Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, jgg@ziepe.ca, netdev@vger.kernel.org, linux-rdma@vger.kernel.org, linux-kernel@vger.kernel.org References: <20230804150527.6117-1-petr.pavlu@suse.com> <20230804150527.6117-4-petr.pavlu@suse.com> X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. From: Zhu Yanjun In-Reply-To: <20230804150527.6117-4-petr.pavlu@suse.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 在 2023/8/4 23:05, Petr Pavlu 写道: > Use a notifier to implement mlx4_dispatch_event() in preparation to > switch mlx4_en and mlx4_ib to be an auxiliary device. > > A problem is that if the mlx4_interface.event callback was replaced with > something as mlx4_adrv.event then the implementation of > mlx4_dispatch_event() would need to acquire a lock on a given device > before executing this callback. That is necessary because otherwise > there is no guarantee that the associated driver cannot get unbound when > the callback is running. However, taking this lock is not possible > because mlx4_dispatch_event() can be invoked from the hardirq context. > Using an atomic notifier allows the driver to accurately record when it > wants to receive these events and solves this problem. > > A handler registration is done by both mlx4_en and mlx4_ib at the end of > their mlx4_interface.add callback. This matches the current situation > when mlx4_add_device() would enable events for a given device > immediately after this callback, by adding the device on the > mlx4_priv.list. > > Signed-off-by: Petr Pavlu > Tested-by: Leon Romanovsky > --- > drivers/infiniband/hw/mlx4/main.c | 41 +++++++++++++------- > drivers/infiniband/hw/mlx4/mlx4_ib.h | 2 + > drivers/net/ethernet/mellanox/mlx4/en_main.c | 25 ++++++++---- > drivers/net/ethernet/mellanox/mlx4/intf.c | 24 ++++++++---- > drivers/net/ethernet/mellanox/mlx4/main.c | 2 + > drivers/net/ethernet/mellanox/mlx4/mlx4.h | 2 + > drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 2 + > include/linux/mlx4/driver.h | 8 +++- > 8 files changed, 76 insertions(+), 30 deletions(-) > > diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c > index 7dd70d778b6b..458b4b11dffa 100644 > --- a/drivers/infiniband/hw/mlx4/main.c > +++ b/drivers/infiniband/hw/mlx4/main.c > @@ -82,6 +82,8 @@ static const char mlx4_ib_version[] = > static void do_slave_init(struct mlx4_ib_dev *ibdev, int slave, int do_init); > static enum rdma_link_layer mlx4_ib_port_link_layer(struct ib_device *device, > u32 port_num); > +static int mlx4_ib_event(struct notifier_block *this, unsigned long event, > + void *ptr); > > static struct workqueue_struct *wq; > > @@ -2836,6 +2838,12 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) > do_slave_init(ibdev, j, 1); > } > } > + > + /* register mlx4 core notifier */ > + ibdev->mlx_nb.notifier_call = mlx4_ib_event; > + err = mlx4_register_event_notifier(dev, &ibdev->mlx_nb); > + WARN(err, "failed to register mlx4 event notifier (%d)", err); > + > return ibdev; > > err_notif: > @@ -2953,6 +2961,8 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) > int p; > int i; > > + mlx4_unregister_event_notifier(dev, &ibdev->mlx_nb); > + > mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) > devlink_port_type_clear(mlx4_get_devlink_port(dev, i)); > ibdev->ib_active = false; > @@ -3173,11 +3183,14 @@ void mlx4_sched_ib_sl2vl_update_work(struct mlx4_ib_dev *ibdev, > } > } > > -static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, > - enum mlx4_dev_event event, unsigned long param) > +static int mlx4_ib_event(struct notifier_block *this, > + unsigned long event /*mlx4_dev_event*/, void *ptr) /*mlx4_dev_event*/ should be removed? Zhu Yanjun > { > + struct mlx4_ib_dev *ibdev = > + container_of(this, struct mlx4_ib_dev, mlx_nb); > + struct mlx4_dev *dev = ibdev->dev; > + unsigned long param = *(unsigned long *)ptr; > struct ib_event ibev; > - struct mlx4_ib_dev *ibdev = to_mdev((struct ib_device *) ibdev_ptr); > struct mlx4_eqe *eqe = NULL; > struct ib_event_work *ew; > int p = 0; > @@ -3187,11 +3200,11 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, > (event == MLX4_DEV_EVENT_PORT_DOWN))) { > ew = kmalloc(sizeof(*ew), GFP_ATOMIC); > if (!ew) > - return; > + return NOTIFY_DONE; > INIT_WORK(&ew->work, handle_bonded_port_state_event); > ew->ib_dev = ibdev; > queue_work(wq, &ew->work); > - return; > + return NOTIFY_DONE; > } > > if (event == MLX4_DEV_EVENT_PORT_MGMT_CHANGE) > @@ -3202,7 +3215,7 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, > switch (event) { > case MLX4_DEV_EVENT_PORT_UP: > if (p > ibdev->num_ports) > - return; > + return NOTIFY_DONE; > if (!mlx4_is_slave(dev) && > rdma_port_get_link_layer(&ibdev->ib_dev, p) == > IB_LINK_LAYER_INFINIBAND) { > @@ -3217,7 +3230,7 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, > > case MLX4_DEV_EVENT_PORT_DOWN: > if (p > ibdev->num_ports) > - return; > + return NOTIFY_DONE; > ibev.event = IB_EVENT_PORT_ERR; > break; > > @@ -3230,7 +3243,7 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, > case MLX4_DEV_EVENT_PORT_MGMT_CHANGE: > ew = kmalloc(sizeof *ew, GFP_ATOMIC); > if (!ew) > - return; > + return NOTIFY_DONE; > > INIT_WORK(&ew->work, handle_port_mgmt_change_event); > memcpy(&ew->ib_eqe, eqe, sizeof *eqe); > @@ -3240,7 +3253,7 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, > queue_work(wq, &ew->work); > else > handle_port_mgmt_change_event(&ew->work); > - return; > + return NOTIFY_DONE; > > case MLX4_DEV_EVENT_SLAVE_INIT: > /* here, p is the slave id */ > @@ -3256,7 +3269,7 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, > 1); > } > } > - return; > + return NOTIFY_DONE; > > case MLX4_DEV_EVENT_SLAVE_SHUTDOWN: > if (mlx4_is_master(dev)) { > @@ -3272,22 +3285,22 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, > } > /* here, p is the slave id */ > do_slave_init(ibdev, p, 0); > - return; > + return NOTIFY_DONE; > > default: > - return; > + return NOTIFY_DONE; > } > > - ibev.device = ibdev_ptr; > + ibev.device = &ibdev->ib_dev; > ibev.element.port_num = mlx4_is_bonded(ibdev->dev) ? 1 : (u8)p; > > ib_dispatch_event(&ibev); > + return NOTIFY_DONE; > } > > static struct mlx4_interface mlx4_ib_interface = { > .add = mlx4_ib_add, > .remove = mlx4_ib_remove, > - .event = mlx4_ib_event, > .protocol = MLX4_PROT_IB_IPV6, > .flags = MLX4_INTFF_BONDING > }; > diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h > index 17fee1e73a45..41ca1114a995 100644 > --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h > +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h > @@ -38,6 +38,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -644,6 +645,7 @@ struct mlx4_ib_dev { > spinlock_t reset_flow_resource_lock; > struct list_head qp_list; > struct mlx4_ib_diag_counters diag_counters[MLX4_DIAG_COUNTERS_TYPES]; > + struct notifier_block mlx_nb; > }; > > struct ib_event_work { > diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c > index be8ba34c9025..8384bff5c37d 100644 > --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c > +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c > @@ -183,17 +183,20 @@ static void mlx4_en_get_profile(struct mlx4_en_dev *mdev) > } > } > > -static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, > - enum mlx4_dev_event event, unsigned long port) > +static int mlx4_en_event(struct notifier_block *this, > + unsigned long event /*mlx4_dev_event*/, void *ptr) > { > - struct mlx4_en_dev *mdev = (struct mlx4_en_dev *) endev_ptr; > + struct mlx4_en_dev *mdev = > + container_of(this, struct mlx4_en_dev, mlx_nb); > + struct mlx4_dev *dev = mdev->dev; > + unsigned long port = *(unsigned long *)ptr; > struct mlx4_en_priv *priv; > > switch (event) { > case MLX4_DEV_EVENT_PORT_UP: > case MLX4_DEV_EVENT_PORT_DOWN: > if (!mdev->pndev[port]) > - return; > + return NOTIFY_DONE; > priv = netdev_priv(mdev->pndev[port]); > /* To prevent races, we poll the link state in a separate > task rather than changing it here */ > @@ -211,10 +214,12 @@ static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, > default: > if (port < 1 || port > dev->caps.num_ports || > !mdev->pndev[port]) > - return; > - mlx4_warn(mdev, "Unhandled event %d for port %d\n", event, > + return NOTIFY_DONE; > + mlx4_warn(mdev, "Unhandled event %d for port %d\n", (int) event, > (int) port); > } > + > + return NOTIFY_DONE; > } > > static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr) > @@ -222,6 +227,8 @@ static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr) > struct mlx4_en_dev *mdev = endev_ptr; > int i; > > + mlx4_unregister_event_notifier(dev, &mdev->mlx_nb); > + > mutex_lock(&mdev->state_lock); > mdev->device_up = false; > mutex_unlock(&mdev->state_lock); > @@ -326,6 +333,11 @@ static void *mlx4_en_add(struct mlx4_dev *dev) > mutex_init(&mdev->state_lock); > mdev->device_up = true; > > + /* register mlx4 core notifier */ > + mdev->mlx_nb.notifier_call = mlx4_en_event; > + err = mlx4_register_event_notifier(dev, &mdev->mlx_nb); > + WARN(err, "failed to register mlx4 event notifier (%d)", err); > + > return mdev; > > err_mr: > @@ -346,7 +358,6 @@ static void *mlx4_en_add(struct mlx4_dev *dev) > static struct mlx4_interface mlx4_en_interface = { > .add = mlx4_en_add, > .remove = mlx4_en_remove, > - .event = mlx4_en_event, > .protocol = MLX4_PROT_ETH, > .activate = mlx4_en_activate, > }; > diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c > index 28d7da925d36..a7c3e2efa464 100644 > --- a/drivers/net/ethernet/mellanox/mlx4/intf.c > +++ b/drivers/net/ethernet/mellanox/mlx4/intf.c > @@ -183,17 +183,27 @@ void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, > unsigned long param) > { > struct mlx4_priv *priv = mlx4_priv(dev); > - struct mlx4_device_context *dev_ctx; > - unsigned long flags; > > - spin_lock_irqsave(&priv->ctx_lock, flags); > + atomic_notifier_call_chain(&priv->event_nh, type, ¶m); > +} > > - list_for_each_entry(dev_ctx, &priv->ctx_list, list) > - if (dev_ctx->intf->event) > - dev_ctx->intf->event(dev, dev_ctx->context, type, param); > +int mlx4_register_event_notifier(struct mlx4_dev *dev, > + struct notifier_block *nb) > +{ > + struct mlx4_priv *priv = mlx4_priv(dev); > > - spin_unlock_irqrestore(&priv->ctx_lock, flags); > + return atomic_notifier_chain_register(&priv->event_nh, nb); > +} > +EXPORT_SYMBOL(mlx4_register_event_notifier); > + > +int mlx4_unregister_event_notifier(struct mlx4_dev *dev, > + struct notifier_block *nb) > +{ > + struct mlx4_priv *priv = mlx4_priv(dev); > + > + return atomic_notifier_chain_unregister(&priv->event_nh, nb); > } > +EXPORT_SYMBOL(mlx4_unregister_event_notifier); > > int mlx4_register_device(struct mlx4_dev *dev) > { > diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c > index 8a5409b00530..5f3ba8385e23 100644 > --- a/drivers/net/ethernet/mellanox/mlx4/main.c > +++ b/drivers/net/ethernet/mellanox/mlx4/main.c > @@ -3378,6 +3378,8 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, > INIT_LIST_HEAD(&priv->ctx_list); > spin_lock_init(&priv->ctx_lock); > > + ATOMIC_INIT_NOTIFIER_HEAD(&priv->event_nh); > + > mutex_init(&priv->port_mutex); > mutex_init(&priv->bond_mutex); > > diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h > index 6ccf340660d9..10f12e4992f1 100644 > --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h > +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h > @@ -47,6 +47,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -878,6 +879,7 @@ struct mlx4_priv { > struct list_head dev_list; > struct list_head ctx_list; > spinlock_t ctx_lock; > + struct atomic_notifier_head event_nh; > > int pci_dev_data; > int removed; > diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h > index 72a3fea36702..efe3f97b874f 100644 > --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h > +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h > @@ -49,6 +49,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -433,6 +434,7 @@ struct mlx4_en_dev { > struct ptp_clock *ptp_clock; > struct ptp_clock_info ptp_clock_info; > struct notifier_block netdev_nb; > + struct notifier_block mlx_nb; > }; > > > diff --git a/include/linux/mlx4/driver.h b/include/linux/mlx4/driver.h > index 923951e19300..228da8ed7e75 100644 > --- a/include/linux/mlx4/driver.h > +++ b/include/linux/mlx4/driver.h > @@ -34,6 +34,7 @@ > #define MLX4_DRIVER_H > > #include > +#include > #include > > struct mlx4_dev; > @@ -57,8 +58,6 @@ enum { > struct mlx4_interface { > void * (*add) (struct mlx4_dev *dev); > void (*remove)(struct mlx4_dev *dev, void *context); > - void (*event) (struct mlx4_dev *dev, void *context, > - enum mlx4_dev_event event, unsigned long param); > void (*activate)(struct mlx4_dev *dev, void *context); > struct list_head list; > enum mlx4_protocol protocol; > @@ -87,6 +86,11 @@ struct mlx4_port_map { > > int mlx4_port_map_set(struct mlx4_dev *dev, struct mlx4_port_map *v2p); > > +int mlx4_register_event_notifier(struct mlx4_dev *dev, > + struct notifier_block *nb); > +int mlx4_unregister_event_notifier(struct mlx4_dev *dev, > + struct notifier_block *nb); > + > struct devlink_port *mlx4_get_devlink_port(struct mlx4_dev *dev, int port); > > #endif /* MLX4_DRIVER_H */