From patchwork Wed Feb 13 04:12:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 10809099 X-Patchwork-Delegate: jgg@ziepe.ca 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 A6F5C1399 for ; Wed, 13 Feb 2019 04:13:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 945E72BFAF for ; Wed, 13 Feb 2019 04:13:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 887DC2C0C0; Wed, 13 Feb 2019 04:13:05 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 9A8BD2BFAF for ; Wed, 13 Feb 2019 04:13:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727915AbfBMEND (ORCPT ); Tue, 12 Feb 2019 23:13:03 -0500 Received: from mail-pg1-f196.google.com ([209.85.215.196]:33877 "EHLO mail-pg1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727414AbfBMEND (ORCPT ); Tue, 12 Feb 2019 23:13:03 -0500 Received: by mail-pg1-f196.google.com with SMTP id i130so538731pgd.1 for ; Tue, 12 Feb 2019 20:13:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ziepe.ca; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ybPow087qqPYiOx91S6OzFtWsNQF+XDatBCazAyM5rk=; b=T5hXd1oMU3RoW+ydXXqchL4+RWkclKQp9Md+IKX4WtdPfgQlvfJqIgF+1VxBDvDVcd a9ladpoYJuiy40nMeKIoAWgSUgrD8VCLiDN3CYMm273XWzKSW9Ik3/BQ5Wew4ehaPQMd /9DSyVbraFYRW/zQb05JnSeRgioAlsjJNtunMAAwqZS6f51Iri027mFnAPehj2o8SAb5 Atf0qAhqw9iRGOj3NnL1gH0hoWJHa51PGYXtjCw5u25vIN1oxcyglun0YJ664ZhKecSv 5TBtOMJTwiFbXspDP15nNO7+Trb/7RBLjm5v/u5AWxsqJX3frAoxnd2bfMlUxPVuaHJe OqfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ybPow087qqPYiOx91S6OzFtWsNQF+XDatBCazAyM5rk=; b=WK3BfSNS5md1RJCPAXe7ajlR0G8LfLSgdUGLv5AwGO5zZwnboI7iIy4Vs1dd32kgXJ 3ylHgpfm9Yt2ZvXBLWOR7v3Wf3zy9w6wjhiVEkMLynAwsDdr1vV6qoOQm7zjf3YLgCcf Uec+Plfrz4Qd354gXWF+XctHy0Mskl1pwr4Wj4abF5DAD7Uv5fmx2zR/w7IQCriAdNe7 pC/yzHi0SvyRnmkAijjOeg6rN5owTWeuQf9EoQ0tx3/kobXqU7yjTTyFa6Cv0bU0yMnu gcls2O0W85I4WzisesSwTcfNSlXaxIhlqfP/VaPccf4sXi28Zy3sNVFKebNMyaIsKy21 TAbg== X-Gm-Message-State: AHQUAuYI2rzAybY8SxqxwvenSIaX5+f3UQAl3lk4FIQCk8zvEadzP0NJ jSJPN/6uxoSVLnK6bc3ISkhejfy/2ok= X-Google-Smtp-Source: AHgI3IZZWGeJfrMlRiqHT7arDomVUw6HyWRvN/jc+FZbHpQVZrs7p/NshqeQz0+N+Sz5qGDlNJ7gmA== X-Received: by 2002:a63:480c:: with SMTP id v12mr7095852pga.115.1550031181705; Tue, 12 Feb 2019 20:13:01 -0800 (PST) Received: from ziepe.ca (S010614cc2056d97f.ed.shawcable.net. [174.3.196.123]) by smtp.gmail.com with ESMTPSA id f67sm20394729pff.29.2019.02.12.20.13.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 12 Feb 2019 20:13:00 -0800 (PST) Received: from jgg by mlx.ziepe.ca with local (Exim 4.90_1) (envelope-from ) id 1gtlut-0005rz-Nm; Tue, 12 Feb 2019 21:12:59 -0700 From: Jason Gunthorpe To: linux-rdma@vger.kernel.org Cc: Jason Gunthorpe , Parav Pandit Subject: [PATCH 01/10] RDMA: Add and use rdma_for_each_port Date: Tue, 12 Feb 2019 21:12:47 -0700 Message-Id: <20190213041256.22437-2-jgg@ziepe.ca> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190213041256.22437-1-jgg@ziepe.ca> References: <20190213041256.22437-1-jgg@ziepe.ca> MIME-Version: 1.0 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: Jason Gunthorpe We have many loops iterating over all of the end port numbers on a struct ib_device, simplify them with a for_each helper. Reviewed-by: Parav Pandit Signed-off-by: Jason Gunthorpe --- .clang-format | 1 + drivers/infiniband/core/cache.c | 6 +++--- drivers/infiniband/core/cma.c | 7 +++--- drivers/infiniband/core/device.c | 26 +++++++++++------------ drivers/infiniband/core/mad.c | 4 ++-- drivers/infiniband/core/nldev.c | 4 ++-- drivers/infiniband/core/security.c | 11 ++++++---- drivers/infiniband/core/sysfs.c | 12 +++-------- drivers/infiniband/core/user_mad.c | 9 ++++---- drivers/infiniband/ulp/ipoib/ipoib_main.c | 4 ++-- drivers/infiniband/ulp/srp/ib_srp.c | 5 +++-- include/rdma/ib_verbs.h | 10 +++++++++ 12 files changed, 53 insertions(+), 46 deletions(-) diff --git a/.clang-format b/.clang-format index 335ce29ab8132c..201a4f531b90a5 100644 --- a/.clang-format +++ b/.clang-format @@ -361,6 +361,7 @@ ForEachMacros: - 'radix_tree_for_each_slot' - 'radix_tree_for_each_tagged' - 'rbtree_postorder_for_each_entry_safe' + - 'rdma_for_each_port' - 'resource_list_for_each_entry' - 'resource_list_for_each_entry_safe' - 'rhl_for_each_entry_rcu' diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 2338d0b3a0cab8..3d137d8381a944 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -1428,7 +1428,7 @@ static void ib_cache_event(struct ib_event_handler *handler, int ib_cache_setup_one(struct ib_device *device) { - int p; + unsigned int p; int err; rwlock_init(&device->cache.lock); @@ -1447,8 +1447,8 @@ int ib_cache_setup_one(struct ib_device *device) return err; } - for (p = 0; p <= rdma_end_port(device) - rdma_start_port(device); ++p) - ib_cache_update(device, p + rdma_start_port(device), true); + rdma_for_each_port (device, p) + ib_cache_update(device, p, true); INIT_IB_EVENT_HANDLER(&device->cache.event_handler, device, ib_cache_event); diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index c43512752b8ac1..68c997be242930 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -659,7 +659,7 @@ static int cma_acquire_dev_by_src_ip(struct rdma_id_private *id_priv) struct cma_device *cma_dev; enum ib_gid_type gid_type; int ret = -ENODEV; - u8 port; + unsigned int port; if (dev_addr->dev_type != ARPHRD_INFINIBAND && id_priv->id.ps == RDMA_PS_IPOIB) @@ -673,8 +673,7 @@ static int cma_acquire_dev_by_src_ip(struct rdma_id_private *id_priv) mutex_lock(&lock); list_for_each_entry(cma_dev, &dev_list, list) { - for (port = rdma_start_port(cma_dev->device); - port <= rdma_end_port(cma_dev->device); port++) { + rdma_for_each_port (cma_dev->device, port) { gidp = rdma_protocol_roce(cma_dev->device, port) ? &iboe_gid : &gid; gid_type = cma_dev->default_gid_type[port - 1]; @@ -4548,7 +4547,7 @@ static void cma_add_one(struct ib_device *device) if (!cma_dev->default_roce_tos) goto free_gid_type; - for (i = rdma_start_port(device); i <= rdma_end_port(device); i++) { + rdma_for_each_port (device, i) { supported_gids = roce_gid_type_mask_support(device, i); WARN_ON(!supported_gids); if (supported_gids & (1 << CMA_PREFERRED_ROCE_GID_TYPE)) diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 3325be4f91a5fe..d3bd09a6b53891 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -463,10 +463,8 @@ static int verify_immutable(const struct ib_device *dev, u8 port) static int read_port_immutable(struct ib_device *device) { + unsigned int port; int ret; - u8 start_port = rdma_start_port(device); - u8 end_port = rdma_end_port(device); - u8 port; /** * device->port_immutable is indexed directly by the port number to make @@ -475,13 +473,13 @@ static int read_port_immutable(struct ib_device *device) * Therefore port_immutable is declared as a 1 based array with * potential empty slots at the beginning. */ - device->port_immutable = kcalloc(end_port + 1, - sizeof(*device->port_immutable), - GFP_KERNEL); + device->port_immutable = + kcalloc(rdma_end_port(device) + 1, + sizeof(*device->port_immutable), GFP_KERNEL); if (!device->port_immutable) return -ENOMEM; - for (port = start_port; port <= end_port; ++port) { + rdma_for_each_port (device, port) { ret = device->ops.get_port_immutable( device, port, &device->port_immutable[port]); if (ret) @@ -533,9 +531,9 @@ static void ib_policy_change_task(struct work_struct *work) down_read(&devices_rwsem); xa_for_each_marked (&devices, index, dev, DEVICE_REGISTERED) { - int i; + unsigned int i; - for (i = rdma_start_port(dev); i <= rdma_end_port(dev); i++) { + rdma_for_each_port (dev, i) { u64 sp; int ret = ib_get_cached_subnet_prefix(dev, i, @@ -1046,10 +1044,9 @@ void ib_enum_roce_netdev(struct ib_device *ib_dev, roce_netdev_callback cb, void *cookie) { - u8 port; + unsigned int port; - for (port = rdma_start_port(ib_dev); port <= rdma_end_port(ib_dev); - port++) + rdma_for_each_port (ib_dev, port) if (rdma_protocol_roce(ib_dev, port)) { struct net_device *idev = NULL; @@ -1203,9 +1200,10 @@ int ib_find_gid(struct ib_device *device, union ib_gid *gid, u8 *port_num, u16 *index) { union ib_gid tmp_gid; - int ret, port, i; + unsigned int port; + int ret, i; - for (port = rdma_start_port(device); port <= rdma_end_port(device); ++port) { + rdma_for_each_port (device, port) { if (!rdma_protocol_ib(device, port)) continue; diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 7870823bac4726..e742a6a2c1380c 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -3326,9 +3326,9 @@ static void ib_mad_init_device(struct ib_device *device) static void ib_mad_remove_device(struct ib_device *device, void *client_data) { - int i; + unsigned int i; - for (i = rdma_start_port(device); i <= rdma_end_port(device); i++) { + rdma_for_each_port (device, i) { if (!rdma_cap_ib_mad(device, i)) continue; diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c index 5601fa96824472..6708277aad7e4c 100644 --- a/drivers/infiniband/core/nldev.c +++ b/drivers/infiniband/core/nldev.c @@ -784,7 +784,7 @@ static int nldev_port_get_dumpit(struct sk_buff *skb, u32 idx = 0; u32 ifindex; int err; - u32 p; + unsigned int p; err = nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1, nldev_policy, NULL); @@ -796,7 +796,7 @@ static int nldev_port_get_dumpit(struct sk_buff *skb, if (!device) return -EINVAL; - for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) { + rdma_for_each_port (device, p) { /* * The dumpit function returns all information from specific * index. This specific index is taken from the netlink diff --git a/drivers/infiniband/core/security.c b/drivers/infiniband/core/security.c index dad6a94a43f30a..492702b836003c 100644 --- a/drivers/infiniband/core/security.c +++ b/drivers/infiniband/core/security.c @@ -422,12 +422,15 @@ void ib_close_shared_qp_security(struct ib_qp_security *sec) int ib_create_qp_security(struct ib_qp *qp, struct ib_device *dev) { - u8 i = rdma_start_port(dev); + unsigned int i; bool is_ib = false; int ret; - while (i <= rdma_end_port(dev) && !is_ib) + rdma_for_each_port (dev, i) { is_ib = rdma_protocol_ib(dev, i++); + if (is_ib) + break; + } /* If this isn't an IB device don't create the security context */ if (!is_ib) @@ -561,9 +564,9 @@ void ib_security_cache_change(struct ib_device *device, void ib_security_release_port_pkey_list(struct ib_device *device) { struct pkey_index_qp_list *pkey, *tmp_pkey; - int i; + unsigned int i; - for (i = rdma_start_port(device); i <= rdma_end_port(device); i++) { + rdma_for_each_port (device, i) { list_for_each_entry_safe(pkey, tmp_pkey, &device->port_pkey_list[i].pkey_list, diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index c75692802da8b6..8fcb871fa5afef 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -1309,8 +1309,8 @@ static void free_port_list_attributes(struct ib_device *device) int ib_device_register_sysfs(struct ib_device *device) { struct device *class_dev = &device->dev; + unsigned int port; int ret; - int i; device->groups[0] = &dev_attr_group; class_dev->groups = device->groups; @@ -1325,16 +1325,10 @@ int ib_device_register_sysfs(struct ib_device *device) goto err_put; } - if (rdma_cap_ib_switch(device)) { - ret = add_port(device, 0); + rdma_for_each_port (device, port) { + ret = add_port(device, port); if (ret) goto err_put; - } else { - for (i = 1; i <= device->phys_port_cnt; ++i) { - ret = add_port(device, i); - if (ret) - goto err_put; - } } if (device->ops.alloc_hw_stats) diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 3ebd211a87edf2..02b7947ab215b2 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -1323,14 +1323,15 @@ static void ib_umad_add_one(struct ib_device *device) static void ib_umad_remove_one(struct ib_device *device, void *client_data) { struct ib_umad_device *umad_dev = client_data; - int i; + unsigned int i; if (!umad_dev) return; - for (i = 0; i <= rdma_end_port(device) - rdma_start_port(device); ++i) { - if (rdma_cap_ib_mad(device, i + rdma_start_port(device))) - ib_umad_kill_port(&umad_dev->ports[i]); + rdma_for_each_port (device, i) { + if (rdma_cap_ib_mad(device, i)) + ib_umad_kill_port( + &umad_dev->ports[i - rdma_start_port(device)]); } /* balances kref_init() */ ib_umad_dev_put(umad_dev); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 3d3407d1feb453..c867dd5a231dcc 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -2495,7 +2495,7 @@ static void ipoib_add_one(struct ib_device *device) struct list_head *dev_list; struct net_device *dev; struct ipoib_dev_priv *priv; - int p; + unsigned int p; int count = 0; dev_list = kmalloc(sizeof(*dev_list), GFP_KERNEL); @@ -2504,7 +2504,7 @@ static void ipoib_add_one(struct ib_device *device) INIT_LIST_HEAD(dev_list); - for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) { + rdma_for_each_port (device, p) { if (!rdma_protocol_ib(device, p)) continue; dev = ipoib_add_port("ib%d", device, p); diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 84184910f0380c..151f4eba84b872 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -4127,7 +4127,8 @@ static void srp_add_one(struct ib_device *device) struct srp_device *srp_dev; struct ib_device_attr *attr = &device->attrs; struct srp_host *host; - int mr_page_shift, p; + int mr_page_shift; + unsigned int p; u64 max_pages_per_mr; unsigned int flags = 0; @@ -4194,7 +4195,7 @@ static void srp_add_one(struct ib_device *device) WARN_ON_ONCE(srp_dev->global_rkey == 0); } - for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) { + rdma_for_each_port (device, p) { host = srp_add_port(srp_dev, p); if (host) list_add_tail(&host->list, &srp_dev->dev_list); diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 135fab2c016c69..99a4868f4d9c58 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -2828,6 +2828,16 @@ static inline u8 rdma_start_port(const struct ib_device *device) return rdma_cap_ib_switch(device) ? 0 : 1; } +/** + * rdma_for_each_port - Iterate over all valid port numbers of the IB device + * @device - The struct ib_device * to iterate over + * @iter - The unsigned int to store the port number + */ +#define rdma_for_each_port(device, iter) \ + for (iter = rdma_start_port(device + BUILD_BUG_ON_ZERO(!__same_type( \ + unsigned int, iter))); \ + iter <= rdma_end_port(device); (iter)++) + /** * rdma_end_port - Return the last valid port number for the device * specified From patchwork Wed Feb 13 04:12:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 10809107 X-Patchwork-Delegate: jgg@ziepe.ca 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 0A6021399 for ; Wed, 13 Feb 2019 04:13:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EB0462C06B for ; Wed, 13 Feb 2019 04:13:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DFB162C0C0; Wed, 13 Feb 2019 04:13:07 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 D3C9E2BFE1 for ; Wed, 13 Feb 2019 04:13:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727414AbfBMENF (ORCPT ); Tue, 12 Feb 2019 23:13:05 -0500 Received: from mail-pg1-f196.google.com ([209.85.215.196]:42834 "EHLO mail-pg1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729561AbfBMENE (ORCPT ); Tue, 12 Feb 2019 23:13:04 -0500 Received: by mail-pg1-f196.google.com with SMTP id d72so517375pga.9 for ; Tue, 12 Feb 2019 20:13:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ziepe.ca; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=s3vTWV9tkuAKQEx2R62Rj0kaGJPTTsFUxYgbWfcfHHk=; b=V0RGajbUOJGuwaYcFQ2tmJ5gV6sr8cOS1EOREkYDw9Py9dciVeadhDbciNt99aI77x B0pxVEdvN5gs+lEiZ2pVevPE21dkLOI78k8qsijiOPWAEy2zT3ichONQrb9RpLrjQdL2 LBmFv8D45sWnL9MZ+eD9lgXwXjqbsea/iZL6H2JIIvg6+zvjalGudGKSmfuwCja2/ZIa w5zRmcXSxTc4P8lkb64kGn3uGf0xT1MIuvQ3pB0jB8zBdZhW5C3bXQ16QHaAy9d+ajiQ rXoh/G2gPN6lqOh6k1dzOB8zWhGbpMaFYJ6O41YMRplQIK024zCFTjoM4FJ8BZaM9sU9 ZvLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=s3vTWV9tkuAKQEx2R62Rj0kaGJPTTsFUxYgbWfcfHHk=; b=qvlGfuOCMCMIWdkdP5jU8susjM33RIasEjNM9qJueai5qJqRlra9PntsBxDYbsYxT0 Cln4TlD64SFEJLmwr1YXcHyGO5Q7U2w9kM3mmqK0mrgwTvAecVqIPecQyTZ12HOrAfDb iLL7g4bWdw3bSNgufkVGeWfXLHKGdz2R7gyUvof/lCnEnw1uCCOsy0+dncu74GFA4Aht RseEhO2tYZ0rNijtYZ/C54HoKIacOXNwT0oI3IpxP6bw9Dhp8dvsZi5Ws/R93uJ7FC+E 5FxAPyfgG3j3B5iWdr89ypmCYyXejtfvd6gubwMQRmwqlRYJ0ht3EWZTMSI5roE808zo YAxA== X-Gm-Message-State: AHQUAuZ/s6ioo4xWMMpkqEUXYUXiKza4ZdKXyoBcGSETHCNGTKMNXQ7m dfzQdJ5syQ3bmVTWaXW9xf99fgTmDTw= X-Google-Smtp-Source: AHgI3IYdFfzu6CBYA4zI5TqUwk1o4MZNvFZyRCXBb1uAFUYG/o3YiLQ2EO1nr5PGIDOXUOQle1U7fQ== X-Received: by 2002:a63:f141:: with SMTP id o1mr7099395pgk.134.1550031183463; Tue, 12 Feb 2019 20:13:03 -0800 (PST) Received: from ziepe.ca (S010614cc2056d97f.ed.shawcable.net. [174.3.196.123]) by smtp.gmail.com with ESMTPSA id h10sm20786182pgn.11.2019.02.12.20.13.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 12 Feb 2019 20:13:00 -0800 (PST) Received: from jgg by mlx.ziepe.ca with local (Exim 4.90_1) (envelope-from ) id 1gtlut-0005s5-P6; Tue, 12 Feb 2019 21:12:59 -0700 From: Jason Gunthorpe To: linux-rdma@vger.kernel.org Cc: Jason Gunthorpe Subject: [PATCH 02/10] RDMA/device: Consolidate ib_device per_port data into one place Date: Tue, 12 Feb 2019 21:12:48 -0700 Message-Id: <20190213041256.22437-3-jgg@ziepe.ca> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190213041256.22437-1-jgg@ziepe.ca> References: <20190213041256.22437-1-jgg@ziepe.ca> MIME-Version: 1.0 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: Jason Gunthorpe There is no reason to have three allocations of per-port data. Combine them together and make the lifetime for all the per-port data match the struct ib_device. Following patches will require more port-specific data, now there is a good place to put it. Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/cache.c | 4 +- drivers/infiniband/core/device.c | 70 +++++++++------------------- drivers/infiniband/core/security.c | 24 +++++----- include/rdma/ib_verbs.h | 74 +++++++++++++++++------------- 4 files changed, 78 insertions(+), 94 deletions(-) diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 3d137d8381a944..9d0e8aca741a6d 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -881,8 +881,8 @@ static int _gid_table_setup_one(struct ib_device *ib_dev) for (port = 0; port < ib_dev->phys_port_cnt; port++) { u8 rdma_port = port + rdma_start_port(ib_dev); - table = alloc_gid_table( - ib_dev->port_immutable[rdma_port].gid_tbl_len); + table = alloc_gid_table( + ib_dev->port_data[rdma_port].immutable.gid_tbl_len); if (!table) goto rollback_table_setup; diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index d3bd09a6b53891..58591408bb1b35 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -292,8 +292,7 @@ static void ib_device_release(struct device *device) WARN_ON(refcount_read(&dev->refcount)); ib_cache_release_one(dev); ib_security_release_port_pkey_list(dev); - kfree(dev->port_pkey_list); - kfree(dev->port_immutable); + kfree(dev->port_data); xa_destroy(&dev->client_data); kfree(dev); } @@ -461,27 +460,31 @@ static int verify_immutable(const struct ib_device *dev, u8 port) rdma_max_mad_size(dev, port) != 0); } -static int read_port_immutable(struct ib_device *device) +static int setup_port_data(struct ib_device *device) { unsigned int port; int ret; - /** - * device->port_immutable is indexed directly by the port number to make + /* + * device->port_data is indexed directly by the port number to make * access to this data as efficient as possible. * - * Therefore port_immutable is declared as a 1 based array with - * potential empty slots at the beginning. + * Therefore port_data is declared as a 1 based array with potential + * empty slots at the beginning. */ - device->port_immutable = - kcalloc(rdma_end_port(device) + 1, - sizeof(*device->port_immutable), GFP_KERNEL); - if (!device->port_immutable) + device->port_data = kcalloc(rdma_end_port(device) + 1, + sizeof(*device->port_data), GFP_KERNEL); + if (!device->port_data) return -ENOMEM; rdma_for_each_port (device, port) { - ret = device->ops.get_port_immutable( - device, port, &device->port_immutable[port]); + struct ib_port_data *pdata = &device->port_data[port]; + + spin_lock_init(&pdata->pkey_list_lock); + INIT_LIST_HEAD(&pdata->pkey_list); + + ret = device->ops.get_port_immutable(device, port, + &pdata->immutable); if (ret) return ret; @@ -500,30 +503,6 @@ void ib_get_device_fw_str(struct ib_device *dev, char *str) } EXPORT_SYMBOL(ib_get_device_fw_str); -static int setup_port_pkey_list(struct ib_device *device) -{ - int i; - - /** - * device->port_pkey_list is indexed directly by the port number, - * Therefore it is declared as a 1 based array with potential empty - * slots at the beginning. - */ - device->port_pkey_list = kcalloc(rdma_end_port(device) + 1, - sizeof(*device->port_pkey_list), - GFP_KERNEL); - - if (!device->port_pkey_list) - return -ENOMEM; - - for (i = 0; i < (rdma_end_port(device) + 1); i++) { - spin_lock_init(&device->port_pkey_list[i].list_lock); - INIT_LIST_HEAD(&device->port_pkey_list[i].pkey_list); - } - - return 0; -} - static void ib_policy_change_task(struct work_struct *work) { struct ib_device *dev; @@ -661,10 +640,9 @@ static int setup_device(struct ib_device *device) if (ret) return ret; - ret = read_port_immutable(device); + ret = setup_port_data(device); if (ret) { - dev_warn(&device->dev, - "Couldn't create per port immutable data\n"); + dev_warn(&device->dev, "Couldn't create per-port data\n"); return ret; } @@ -676,12 +654,6 @@ static int setup_device(struct ib_device *device) return ret; } - ret = setup_port_pkey_list(device); - if (ret) { - dev_warn(&device->dev, "Couldn't create per port_pkey_list\n"); - return ret; - } - return 0; } @@ -1207,7 +1179,8 @@ int ib_find_gid(struct ib_device *device, union ib_gid *gid, if (!rdma_protocol_ib(device, port)) continue; - for (i = 0; i < device->port_immutable[port].gid_tbl_len; ++i) { + for (i = 0; i < device->port_data[port].immutable.gid_tbl_len; + ++i) { ret = rdma_query_gid(device, port, i, &tmp_gid); if (ret) return ret; @@ -1239,7 +1212,8 @@ int ib_find_pkey(struct ib_device *device, u16 tmp_pkey; int partial_ix = -1; - for (i = 0; i < device->port_immutable[port_num].pkey_tbl_len; ++i) { + for (i = 0; i < device->port_data[port_num].immutable.pkey_tbl_len; + ++i) { ret = ib_query_pkey(device, port_num, i, &tmp_pkey); if (ret) return ret; diff --git a/drivers/infiniband/core/security.c b/drivers/infiniband/core/security.c index 492702b836003c..1ab423b19f778f 100644 --- a/drivers/infiniband/core/security.c +++ b/drivers/infiniband/core/security.c @@ -49,16 +49,15 @@ static struct pkey_index_qp_list *get_pkey_idx_qp_list(struct ib_port_pkey *pp) struct pkey_index_qp_list *tmp_pkey; struct ib_device *dev = pp->sec->dev; - spin_lock(&dev->port_pkey_list[pp->port_num].list_lock); - list_for_each_entry(tmp_pkey, - &dev->port_pkey_list[pp->port_num].pkey_list, - pkey_index_list) { + spin_lock(&dev->port_data[pp->port_num].pkey_list_lock); + list_for_each_entry (tmp_pkey, &dev->port_data[pp->port_num].pkey_list, + pkey_index_list) { if (tmp_pkey->pkey_index == pp->pkey_index) { pkey = tmp_pkey; break; } } - spin_unlock(&dev->port_pkey_list[pp->port_num].list_lock); + spin_unlock(&dev->port_data[pp->port_num].pkey_list_lock); return pkey; } @@ -263,12 +262,12 @@ static int port_pkey_list_insert(struct ib_port_pkey *pp) if (!pkey) return -ENOMEM; - spin_lock(&dev->port_pkey_list[port_num].list_lock); + spin_lock(&dev->port_data[port_num].pkey_list_lock); /* Check for the PKey again. A racing process may * have created it. */ list_for_each_entry(tmp_pkey, - &dev->port_pkey_list[port_num].pkey_list, + &dev->port_data[port_num].pkey_list, pkey_index_list) { if (tmp_pkey->pkey_index == pp->pkey_index) { kfree(pkey); @@ -283,9 +282,9 @@ static int port_pkey_list_insert(struct ib_port_pkey *pp) spin_lock_init(&pkey->qp_list_lock); INIT_LIST_HEAD(&pkey->qp_list); list_add(&pkey->pkey_index_list, - &dev->port_pkey_list[port_num].pkey_list); + &dev->port_data[port_num].pkey_list); } - spin_unlock(&dev->port_pkey_list[port_num].list_lock); + spin_unlock(&dev->port_data[port_num].pkey_list_lock); } spin_lock(&pkey->qp_list_lock); @@ -551,9 +550,8 @@ void ib_security_cache_change(struct ib_device *device, { struct pkey_index_qp_list *pkey; - list_for_each_entry(pkey, - &device->port_pkey_list[port_num].pkey_list, - pkey_index_list) { + list_for_each_entry (pkey, &device->port_data[port_num].pkey_list, + pkey_index_list) { check_pkey_qps(pkey, device, port_num, @@ -569,7 +567,7 @@ void ib_security_release_port_pkey_list(struct ib_device *device) rdma_for_each_port (device, i) { list_for_each_entry_safe(pkey, tmp_pkey, - &device->port_pkey_list[i].pkey_list, + &device->port_data[i].pkey_list, pkey_index_list) { list_del(&pkey->pkey_index_list); kfree(pkey); diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 99a4868f4d9c58..4225cd9eb6f840 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -2198,6 +2198,13 @@ struct ib_port_immutable { u32 max_mad_size; }; +struct ib_port_data { + struct ib_port_immutable immutable; + + spinlock_t pkey_list_lock; + struct list_head pkey_list; +}; + /* rdma netdev type - specifies protocol type */ enum rdma_netdev_t { RDMA_NETDEV_OPA_VNIC, @@ -2243,12 +2250,6 @@ struct rdma_netdev_alloc_params { struct net_device *netdev, void *param); }; -struct ib_port_pkey_list { - /* Lock to hold while modifying the list. */ - spinlock_t list_lock; - struct list_head pkey_list; -}; - struct ib_counters { struct ib_device *device; struct ib_uobject *uobject; @@ -2547,14 +2548,12 @@ struct ib_device { struct ib_cache cache; /** - * port_immutable is indexed by port number + * port_data is indexed by port number */ - struct ib_port_immutable *port_immutable; + struct ib_port_data *port_data; int num_comp_vectors; - struct ib_port_pkey_list *port_pkey_list; - struct iw_cm_verbs *iwcm; struct module *owner; @@ -2861,34 +2860,38 @@ static inline int rdma_is_port_valid(const struct ib_device *device, static inline bool rdma_is_grh_required(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & - RDMA_CORE_PORT_IB_GRH_REQUIRED; + return device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_PORT_IB_GRH_REQUIRED; } static inline bool rdma_protocol_ib(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_PROT_IB; + return device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_CAP_PROT_IB; } static inline bool rdma_protocol_roce(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & - (RDMA_CORE_CAP_PROT_ROCE | RDMA_CORE_CAP_PROT_ROCE_UDP_ENCAP); + return device->port_data[port_num].immutable.core_cap_flags & + (RDMA_CORE_CAP_PROT_ROCE | RDMA_CORE_CAP_PROT_ROCE_UDP_ENCAP); } static inline bool rdma_protocol_roce_udp_encap(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_PROT_ROCE_UDP_ENCAP; + return device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_CAP_PROT_ROCE_UDP_ENCAP; } static inline bool rdma_protocol_roce_eth_encap(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_PROT_ROCE; + return device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_CAP_PROT_ROCE; } static inline bool rdma_protocol_iwarp(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_PROT_IWARP; + return device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_CAP_PROT_IWARP; } static inline bool rdma_ib_or_roce(const struct ib_device *device, u8 port_num) @@ -2899,12 +2902,14 @@ static inline bool rdma_ib_or_roce(const struct ib_device *device, u8 port_num) static inline bool rdma_protocol_raw_packet(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_PROT_RAW_PACKET; + return device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_CAP_PROT_RAW_PACKET; } static inline bool rdma_protocol_usnic(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_PROT_USNIC; + return device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_CAP_PROT_USNIC; } /** @@ -2921,7 +2926,8 @@ static inline bool rdma_protocol_usnic(const struct ib_device *device, u8 port_n */ static inline bool rdma_cap_ib_mad(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_IB_MAD; + return device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_CAP_IB_MAD; } /** @@ -2945,8 +2951,8 @@ static inline bool rdma_cap_ib_mad(const struct ib_device *device, u8 port_num) */ static inline bool rdma_cap_opa_mad(struct ib_device *device, u8 port_num) { - return (device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_OPA_MAD) - == RDMA_CORE_CAP_OPA_MAD; + return (device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_CAP_OPA_MAD) == RDMA_CORE_CAP_OPA_MAD; } /** @@ -2971,7 +2977,8 @@ static inline bool rdma_cap_opa_mad(struct ib_device *device, u8 port_num) */ static inline bool rdma_cap_ib_smi(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_IB_SMI; + return device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_CAP_IB_SMI; } /** @@ -2991,7 +2998,8 @@ static inline bool rdma_cap_ib_smi(const struct ib_device *device, u8 port_num) */ static inline bool rdma_cap_ib_cm(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_IB_CM; + return device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_CAP_IB_CM; } /** @@ -3008,7 +3016,8 @@ static inline bool rdma_cap_ib_cm(const struct ib_device *device, u8 port_num) */ static inline bool rdma_cap_iw_cm(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_IW_CM; + return device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_CAP_IW_CM; } /** @@ -3028,7 +3037,8 @@ static inline bool rdma_cap_iw_cm(const struct ib_device *device, u8 port_num) */ static inline bool rdma_cap_ib_sa(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_IB_SA; + return device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_CAP_IB_SA; } /** @@ -3068,7 +3078,8 @@ static inline bool rdma_cap_ib_mcast(const struct ib_device *device, u8 port_num */ static inline bool rdma_cap_af_ib(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_AF_IB; + return device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_CAP_AF_IB; } /** @@ -3089,7 +3100,8 @@ static inline bool rdma_cap_af_ib(const struct ib_device *device, u8 port_num) */ static inline bool rdma_cap_eth_ah(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_ETH_AH; + return device->port_data[port_num].immutable.core_cap_flags & + RDMA_CORE_CAP_ETH_AH; } /** @@ -3103,7 +3115,7 @@ static inline bool rdma_cap_eth_ah(const struct ib_device *device, u8 port_num) */ static inline bool rdma_cap_opa_ah(struct ib_device *device, u8 port_num) { - return (device->port_immutable[port_num].core_cap_flags & + return (device->port_data[port_num].immutable.core_cap_flags & RDMA_CORE_CAP_OPA_AH) == RDMA_CORE_CAP_OPA_AH; } @@ -3121,7 +3133,7 @@ static inline bool rdma_cap_opa_ah(struct ib_device *device, u8 port_num) */ static inline size_t rdma_max_mad_size(const struct ib_device *device, u8 port_num) { - return device->port_immutable[port_num].max_mad_size; + return device->port_data[port_num].immutable.max_mad_size; } /** From patchwork Wed Feb 13 04:12:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 10809103 X-Patchwork-Delegate: jgg@ziepe.ca 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 6D3921390 for ; Wed, 13 Feb 2019 04:13:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5B4182BFE1 for ; Wed, 13 Feb 2019 04:13:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 501BA2C06B; Wed, 13 Feb 2019 04:13:06 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 3127C2BFE1 for ; Wed, 13 Feb 2019 04:13:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729623AbfBMENE (ORCPT ); Tue, 12 Feb 2019 23:13:04 -0500 Received: from mail-pg1-f193.google.com ([209.85.215.193]:35714 "EHLO mail-pg1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726902AbfBMEND (ORCPT ); Tue, 12 Feb 2019 23:13:03 -0500 Received: by mail-pg1-f193.google.com with SMTP id s198so534917pgs.2 for ; Tue, 12 Feb 2019 20:13:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ziepe.ca; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=of8MsjYkr+7U45wiFWVundbJoy7Pm4aaQIZBujd48pk=; b=i53tuM8jFuFq4TtfIAY0jCZwAMeiEAe4Lds+UOhip10ImhLmABD7stIGTNf1a358XS 2AAs1QO2oGN4S17p9KDnpb1VAbK0IFPiiBXMBXzIkIgZMPsRnI3r5o+2J5sgPctqZOB0 fDCGRxA37BmL1KuFm2eIRSJbqmGK+p/k9btBQ7vnN3l41d6XQUJYipKKe1EO0yI4rmgG CKqF8N7q1ILjEOVvOoHqPZdkpmax2hBVMHuSGNjmgQ1gGsoWITUgvLgCDiwyWjq1crXq eoqWXQ7iHDlbpSxr/ChzlvoMIu92xz6cxGq9mPNjPk+QW/PdlqWup99DSnv8AZLdLdHr JKuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=of8MsjYkr+7U45wiFWVundbJoy7Pm4aaQIZBujd48pk=; b=m8mwI8+4kUdmviJeTKiy4n24Iy6H9qfQB3QpNh1w/9CB5uqZrT/sXK7KQYLUP/H1Bl jA3qZBwZVgKfCuNIZuxrN1usKs8GVqOsHol1ea9/HxzCwgKp8ecur9+T34Y0mmsTlLed fLIplqEMbgdQ/EcK9DGXBQ2ZWBe+69LnjjAn3JiDieE6rkAUwred1cXsEsIczZPAfe9F PVt0fYyE0rxe1mqV20d83DNIKXveqK8wS0uLXt2hnWS7FSu/MDZQr6UMsWLmmMb4OL+B 3GKw5Bofy8zpflsH8RBJ0kLCh+xh5SxZM5xEBzROTn0b2pHbqSxjuZC3PKQf60LrE0QH QPsQ== X-Gm-Message-State: AHQUAuZUM1oq99Q3n3AZ9aQp7mwUdRQfc8t2xljVkUHBHVTxLs6ki6CC iWX6kFK5JUunu/Uf6yn6fIxApV1SO7E= X-Google-Smtp-Source: AHgI3IZCZnClw+df2rE2yNZZMAQ1rweJjmD2e2C+6Lz6DoEDiyLtrIdi1DTwIPGlFQUW+15EyJnqsQ== X-Received: by 2002:a63:ce0e:: with SMTP id y14mr7028430pgf.145.1550031182402; Tue, 12 Feb 2019 20:13:02 -0800 (PST) Received: from ziepe.ca (S010614cc2056d97f.ed.shawcable.net. [174.3.196.123]) by smtp.gmail.com with ESMTPSA id y21sm7175528pfe.57.2019.02.12.20.13.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 12 Feb 2019 20:13:00 -0800 (PST) Received: from jgg by mlx.ziepe.ca with local (Exim 4.90_1) (envelope-from ) id 1gtlut-0005sB-RO; Tue, 12 Feb 2019 21:12:59 -0700 From: Jason Gunthorpe To: linux-rdma@vger.kernel.org Cc: Jason Gunthorpe Subject: [PATCH 03/10] RDMA/cache: Move the cache per-port data into the main ib_port_data Date: Tue, 12 Feb 2019 21:12:49 -0700 Message-Id: <20190213041256.22437-4-jgg@ziepe.ca> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190213041256.22437-1-jgg@ziepe.ca> References: <20190213041256.22437-1-jgg@ziepe.ca> MIME-Version: 1.0 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: Jason Gunthorpe Like the other cases there no real reason to have another array just for the cache. This larger conversion gets its own patch. Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/cache.c | 89 ++++++++++++--------------------- include/rdma/ib_verbs.h | 3 +- 2 files changed, 33 insertions(+), 59 deletions(-) diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 9d0e8aca741a6d..a28dc1901c8000 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -185,7 +185,7 @@ EXPORT_SYMBOL(ib_cache_gid_parse_type_str); static struct ib_gid_table *rdma_gid_table(struct ib_device *device, u8 port) { - return device->cache.ports[port - rdma_start_port(device)].gid; + return device->port_data[port].cache.gid; } static bool is_gid_entry_free(const struct ib_gid_table_entry *entry) @@ -765,7 +765,7 @@ static struct ib_gid_table *alloc_gid_table(int sz) return NULL; } -static void release_gid_table(struct ib_device *device, u8 port, +static void release_gid_table(struct ib_device *device, struct ib_gid_table *table) { bool leak = false; @@ -863,31 +863,27 @@ static void gid_table_reserve_default(struct ib_device *ib_dev, u8 port, static void gid_table_release_one(struct ib_device *ib_dev) { - struct ib_gid_table *table; - u8 port; + unsigned int p; - for (port = 0; port < ib_dev->phys_port_cnt; port++) { - table = ib_dev->cache.ports[port].gid; - release_gid_table(ib_dev, port, table); - ib_dev->cache.ports[port].gid = NULL; + rdma_for_each_port (ib_dev, p) { + release_gid_table(ib_dev, ib_dev->port_data[p].cache.gid); + ib_dev->port_data[p].cache.gid = NULL; } } static int _gid_table_setup_one(struct ib_device *ib_dev) { - u8 port; struct ib_gid_table *table; + unsigned int rdma_port; - for (port = 0; port < ib_dev->phys_port_cnt; port++) { - u8 rdma_port = port + rdma_start_port(ib_dev); - + rdma_for_each_port (ib_dev, rdma_port) { table = alloc_gid_table( ib_dev->port_data[rdma_port].immutable.gid_tbl_len); if (!table) goto rollback_table_setup; gid_table_reserve_default(ib_dev, rdma_port, table); - ib_dev->cache.ports[port].gid = table; + ib_dev->port_data[rdma_port].cache.gid = table; } return 0; @@ -898,14 +894,11 @@ static int _gid_table_setup_one(struct ib_device *ib_dev) static void gid_table_cleanup_one(struct ib_device *ib_dev) { - struct ib_gid_table *table; - u8 port; + unsigned int p; - for (port = 0; port < ib_dev->phys_port_cnt; port++) { - table = ib_dev->cache.ports[port].gid; - cleanup_gid_table_port(ib_dev, port + rdma_start_port(ib_dev), - table); - } + rdma_for_each_port (ib_dev, p) + cleanup_gid_table_port(ib_dev, p, + ib_dev->port_data[p].cache.gid); } static int gid_table_setup_one(struct ib_device *ib_dev) @@ -983,17 +976,17 @@ const struct ib_gid_attr *rdma_find_gid(struct ib_device *device, unsigned long mask = GID_ATTR_FIND_MASK_GID | GID_ATTR_FIND_MASK_GID_TYPE; struct ib_gid_attr gid_attr_val = {.ndev = ndev, .gid_type = gid_type}; - u8 p; + unsigned int p; if (ndev) mask |= GID_ATTR_FIND_MASK_NETDEV; - for (p = 0; p < device->phys_port_cnt; p++) { + rdma_for_each_port(device, p) { struct ib_gid_table *table; unsigned long flags; int index; - table = device->cache.ports[p].gid; + table = device->port_data[p].cache.gid; read_lock_irqsave(&table->rwlock, flags); index = find_gid(table, gid, &gid_attr_val, false, mask, NULL); if (index >= 0) { @@ -1025,7 +1018,7 @@ int ib_get_cached_pkey(struct ib_device *device, read_lock_irqsave(&device->cache.lock, flags); - cache = device->cache.ports[port_num - rdma_start_port(device)].pkey; + cache = device->port_data[port_num].cache.pkey; if (index < 0 || index >= cache->table_len) ret = -EINVAL; @@ -1043,14 +1036,12 @@ int ib_get_cached_subnet_prefix(struct ib_device *device, u64 *sn_pfx) { unsigned long flags; - int p; if (!rdma_is_port_valid(device, port_num)) return -EINVAL; - p = port_num - rdma_start_port(device); read_lock_irqsave(&device->cache.lock, flags); - *sn_pfx = device->cache.ports[p].subnet_prefix; + *sn_pfx = device->port_data[port_num].cache.subnet_prefix; read_unlock_irqrestore(&device->cache.lock, flags); return 0; @@ -1073,7 +1064,7 @@ int ib_find_cached_pkey(struct ib_device *device, read_lock_irqsave(&device->cache.lock, flags); - cache = device->cache.ports[port_num - rdma_start_port(device)].pkey; + cache = device->port_data[port_num].cache.pkey; *index = -1; @@ -1113,7 +1104,7 @@ int ib_find_exact_cached_pkey(struct ib_device *device, read_lock_irqsave(&device->cache.lock, flags); - cache = device->cache.ports[port_num - rdma_start_port(device)].pkey; + cache = device->port_data[port_num].cache.pkey; *index = -1; @@ -1141,7 +1132,7 @@ int ib_get_cached_lmc(struct ib_device *device, return -EINVAL; read_lock_irqsave(&device->cache.lock, flags); - *lmc = device->cache.ports[port_num - rdma_start_port(device)].lmc; + *lmc = device->port_data[port_num].cache.lmc; read_unlock_irqrestore(&device->cache.lock, flags); return ret; @@ -1159,8 +1150,7 @@ int ib_get_cached_port_state(struct ib_device *device, return -EINVAL; read_lock_irqsave(&device->cache.lock, flags); - *port_state = device->cache.ports[port_num - - rdma_start_port(device)].port_state; + *port_state = device->port_data[port_num].cache.port_state; read_unlock_irqrestore(&device->cache.lock, flags); return ret; @@ -1361,16 +1351,13 @@ static void ib_cache_update(struct ib_device *device, write_lock_irq(&device->cache.lock); - old_pkey_cache = device->cache.ports[port - - rdma_start_port(device)].pkey; + old_pkey_cache = device->port_data[port].cache.pkey; - device->cache.ports[port - rdma_start_port(device)].pkey = pkey_cache; - device->cache.ports[port - rdma_start_port(device)].lmc = tprops->lmc; - device->cache.ports[port - rdma_start_port(device)].port_state = - tprops->state; + device->port_data[port].cache.pkey = pkey_cache; + device->port_data[port].cache.lmc = tprops->lmc; + device->port_data[port].cache.port_state = tprops->state; - device->cache.ports[port - rdma_start_port(device)].subnet_prefix = - tprops->subnet_prefix; + device->port_data[port].cache.subnet_prefix = tprops->subnet_prefix; write_unlock_irq(&device->cache.lock); if (enforce_security) @@ -1433,19 +1420,9 @@ int ib_cache_setup_one(struct ib_device *device) rwlock_init(&device->cache.lock); - device->cache.ports = - kcalloc(rdma_end_port(device) - rdma_start_port(device) + 1, - sizeof(*device->cache.ports), - GFP_KERNEL); - if (!device->cache.ports) - return -ENOMEM; - err = gid_table_setup_one(device); - if (err) { - kfree(device->cache.ports); - device->cache.ports = NULL; + if (err) return err; - } rdma_for_each_port (device, p) ib_cache_update(device, p, true); @@ -1458,10 +1435,7 @@ int ib_cache_setup_one(struct ib_device *device) void ib_cache_release_one(struct ib_device *device) { - int p; - - if (!device->cache.ports) - return; + unsigned int p; /* * The release function frees all the cache elements. @@ -1469,11 +1443,10 @@ void ib_cache_release_one(struct ib_device *device) * all the device's resources when the cache could no * longer be accessed. */ - for (p = 0; p <= rdma_end_port(device) - rdma_start_port(device); ++p) - kfree(device->cache.ports[p].pkey); + rdma_for_each_port (device, p) + kfree(device->port_data[p].cache.pkey); gid_table_release_one(device); - kfree(device->cache.ports); } void ib_cache_cleanup_one(struct ib_device *device) diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 4225cd9eb6f840..e5eea5a50e27f2 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -2186,7 +2186,6 @@ struct ib_port_cache { struct ib_cache { rwlock_t lock; struct ib_event_handler event_handler; - struct ib_port_cache *ports; }; struct iw_cm_verbs; @@ -2203,6 +2202,8 @@ struct ib_port_data { spinlock_t pkey_list_lock; struct list_head pkey_list; + + struct ib_port_cache cache; }; /* rdma netdev type - specifies protocol type */ From patchwork Wed Feb 13 04:12:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 10809105 X-Patchwork-Delegate: jgg@ziepe.ca 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 1DBF117E0 for ; Wed, 13 Feb 2019 04:13:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0A0302BFAF for ; Wed, 13 Feb 2019 04:13:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F24E72C06B; Wed, 13 Feb 2019 04:13:06 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 29B862BFAF for ; Wed, 13 Feb 2019 04:13:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730389AbfBMENF (ORCPT ); Tue, 12 Feb 2019 23:13:05 -0500 Received: from mail-pl1-f196.google.com ([209.85.214.196]:40913 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727414AbfBMENE (ORCPT ); Tue, 12 Feb 2019 23:13:04 -0500 Received: by mail-pl1-f196.google.com with SMTP id bj4so536928plb.7 for ; Tue, 12 Feb 2019 20:13:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ziepe.ca; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=BdWyPaOhvb1aTu8CdvpONAdqxrOfLO0+EkPMT13/jwY=; b=PkmngJtEIjPYEr8+MhQg/6u+ykfQ+eS8nNTcNjQhC9hhnS1SsrS4QhQUlOrFmu2Tym 6CMvE7h5YjY47k2qsUFtMnXQO5c2qt+S2iqpll1CDUMpeh9s7VMRd3Kz3k79c95ORiTE b2V3Axy1pyN/JHinucnmqpLoMMdb7wIgTLCKbqKf6Df1GW620IpBhI45/9JvSP071tIJ St4CpneP/xgbH5w4++/zrzDBulSkQUPJQ41wtQDwJH0zWPAggfVIX2y1JjDErpANx9Ek izjhPG4JGUxSDVWkAjKl7lSYlco5qA6TT/8QVUFdKfZVuRtBGKCbKIuxlNLFtZynSGGD 5waw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=BdWyPaOhvb1aTu8CdvpONAdqxrOfLO0+EkPMT13/jwY=; b=dKVFi8/dMvqRvEzTJf4JncnI+/Io913rRErH58qGrGFk7cFW58GMyDX0Xll8DktVaz FkaKYspvUj0+xlhIFm54M+dvYMOlceXdARkmCxQ+etpVQAcfOBB4k+lVKTL/mlPara3C +Fb6iCjs4KusDdMvdDzN64TL//siXfhdM55cSWP8/tFcu42hGEvOweefp64d7QuwkFpD x2CCqRPYorTNZ38BtQPrSHGYUlMFo8qp+VbB45KKQgzjxSduzaeSfD3mry0BZnvGd6hT VdoFB9mn7ugo1Ngwyt0lsn+HOAA5RUmBlTzrSA1SIrZsQzSITPjIUFiJ/NftrtG9OpQu Xu+w== X-Gm-Message-State: AHQUAub53t46zoS/O4LWnZ9F3jKcchTt2r7f6wKmRKqm4kCc6JRoSAsG /tQG8ZDP98iTlNQ48fW2XZwx76NE7Xg= X-Google-Smtp-Source: AHgI3IbgGn0efn29MW7JsDl6+FfUSHv8QaA4vEjoSEdJvrcjqwlrckgzUC6RmWgQsSj1fDmjvASyhA== X-Received: by 2002:a17:902:887:: with SMTP id 7mr7628517pll.164.1550031182887; Tue, 12 Feb 2019 20:13:02 -0800 (PST) Received: from ziepe.ca (S010614cc2056d97f.ed.shawcable.net. [174.3.196.123]) by smtp.gmail.com with ESMTPSA id d21sm17117846pgv.37.2019.02.12.20.13.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 12 Feb 2019 20:13:00 -0800 (PST) Received: from jgg by mlx.ziepe.ca with local (Exim 4.90_1) (envelope-from ) id 1gtlut-0005sH-Sg; Tue, 12 Feb 2019 21:12:59 -0700 From: Jason Gunthorpe To: linux-rdma@vger.kernel.org Cc: Jason Gunthorpe Subject: [PATCH 04/10] RDMA/device: Add ib_device_set_netdev() as an alternative to get_netdev Date: Tue, 12 Feb 2019 21:12:50 -0700 Message-Id: <20190213041256.22437-5-jgg@ziepe.ca> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190213041256.22437-1-jgg@ziepe.ca> References: <20190213041256.22437-1-jgg@ziepe.ca> MIME-Version: 1.0 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: Jason Gunthorpe The associated netdev should not actually be very dynamic, so for most drivers there is no reason for a callback like this. Provide an API to inform the core code about the net dev affiliation and use a core maintained data structure instead. This allows the core code to be more aware of the ndev relationship which will allow some new APIs based around this. This also uses locking that makes some kind of sense, many drivers had a confusing RCU lock, or missing locking which isn't right. Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/cache.c | 24 ++-- drivers/infiniband/core/core_priv.h | 3 + drivers/infiniband/core/device.c | 166 +++++++++++++++++++++++++--- drivers/infiniband/core/nldev.c | 4 +- drivers/infiniband/core/verbs.c | 5 +- include/rdma/ib_verbs.h | 7 ++ 6 files changed, 171 insertions(+), 38 deletions(-) diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index a28dc1901c8000..e191f3d86b41d5 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -547,21 +547,19 @@ int ib_cache_gid_add(struct ib_device *ib_dev, u8 port, unsigned long mask; int ret; - if (ib_dev->ops.get_netdev) { - idev = ib_dev->ops.get_netdev(ib_dev, port); - if (idev && attr->ndev != idev) { - union ib_gid default_gid; - - /* Adding default GIDs in not permitted */ - make_default_gid(idev, &default_gid); - if (!memcmp(gid, &default_gid, sizeof(*gid))) { - dev_put(idev); - return -EPERM; - } - } - if (idev) + idev = ib_device_get_netdev(ib_dev, port); + if (idev && attr->ndev != idev) { + union ib_gid default_gid; + + /* Adding default GIDs in not permitted */ + make_default_gid(idev, &default_gid); + if (!memcmp(gid, &default_gid, sizeof(*gid))) { dev_put(idev); + return -EPERM; + } } + if (idev) + dev_put(idev); mask = GID_ATTR_FIND_MASK_GID | GID_ATTR_FIND_MASK_GID_TYPE | diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h index a1826f4c2e23ee..8aa4872e07a0da 100644 --- a/drivers/infiniband/core/core_priv.h +++ b/drivers/infiniband/core/core_priv.h @@ -64,6 +64,9 @@ typedef void (*roce_netdev_callback)(struct ib_device *device, u8 port, typedef bool (*roce_netdev_filter)(struct ib_device *device, u8 port, struct net_device *idev, void *cookie); +struct net_device *ib_device_get_netdev(struct ib_device *ib_dev, + unsigned int port); + void ib_enum_roce_netdev(struct ib_device *ib_dev, roce_netdev_filter filter, void *filter_cookie, diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 58591408bb1b35..14c91f9af6ccc9 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -133,6 +133,7 @@ static void *xan_find_marked(struct xarray *xa, unsigned long *indexp, !xa_is_err(entry); \ (index)++, entry = xan_find_marked(xa, &(index), filter)) +static void free_netdevs(struct ib_device *ib_dev); static int ib_security_change(struct notifier_block *nb, unsigned long event, void *lsm_data); static void ib_policy_change_task(struct work_struct *work); @@ -289,6 +290,7 @@ static void ib_device_release(struct device *device) { struct ib_device *dev = container_of(device, struct ib_device, dev); + free_netdevs(dev); WARN_ON(refcount_read(&dev->refcount)); ib_cache_release_one(dev); ib_security_release_port_pkey_list(dev); @@ -365,6 +367,9 @@ EXPORT_SYMBOL(_ib_alloc_device); */ void ib_dealloc_device(struct ib_device *device) { + /* Expedite releasing netdev references */ + free_netdevs(device); + WARN_ON(!xa_empty(&device->client_data)); WARN_ON(refcount_read(&device->refcount)); rdma_restrack_clean(device); @@ -454,16 +459,16 @@ static void remove_client_context(struct ib_device *device, up_read(&device->client_data_rwsem); } -static int verify_immutable(const struct ib_device *dev, u8 port) -{ - return WARN_ON(!rdma_cap_ib_mad(dev, port) && - rdma_max_mad_size(dev, port) != 0); -} - -static int setup_port_data(struct ib_device *device) +static int alloc_port_data(struct ib_device *device) { unsigned int port; - int ret; + + if (device->port_data) + return 0; + + /* This can only be called once the physical port range is defined */ + if (WARN_ON(!device->phys_port_cnt)) + return -EINVAL; /* * device->port_data is indexed directly by the port number to make @@ -482,6 +487,28 @@ static int setup_port_data(struct ib_device *device) spin_lock_init(&pdata->pkey_list_lock); INIT_LIST_HEAD(&pdata->pkey_list); + spin_lock_init(&pdata->netdev_lock); + } + return 0; +} + +static int verify_immutable(const struct ib_device *dev, u8 port) +{ + return WARN_ON(!rdma_cap_ib_mad(dev, port) && + rdma_max_mad_size(dev, port) != 0); +} + +static int setup_port_data(struct ib_device *device) +{ + unsigned int port; + int ret; + + ret = alloc_port_data(device); + if (ret) + return ret; + + rdma_for_each_port (device, port) { + struct ib_port_data *pdata = &device->port_data[port]; ret = device->ops.get_port_immutable(device, port, &pdata->immutable); @@ -675,6 +702,9 @@ static void disable_device(struct ib_device *device) /* Pairs with refcount_set in enable_device */ ib_device_put(device); wait_for_completion(&device->unreg_completion); + + /* Expedite removing unregistered pointers from the hash table */ + free_netdevs(device); } /* @@ -998,6 +1028,114 @@ int ib_query_port(struct ib_device *device, } EXPORT_SYMBOL(ib_query_port); +/** + * ib_device_set_netdev - Associate the ib_dev with an underlying net_device + * @ib_dev: Device to modify + * @ndev: net_device to affiliate, may be NULL + * @port: IB port the net_device is connected to + * + * Drivers should use this to link the ib_device to a netdev so the netdev + * shows up in interfaces like ib_enum_roce_netdev. Only one netdev may be + * affiliated with any port. + * + * The caller must ensure that the given ndev is not unregistered or + * unregistering, and that either the ib_device is unregistered or + * ib_device_set_netdev() is called with NULL when the ndev sends a + * NETDEV_UNREGISTER event. + */ +int ib_device_set_netdev(struct ib_device *ib_dev, struct net_device *ndev, + unsigned int port) +{ + struct net_device *old_ndev; + struct ib_port_data *pdata; + unsigned long flags; + int ret; + + /* + * Drivers wish to call this before ib_register_driver, so we have to + * setup the port data early. + */ + ret = alloc_port_data(ib_dev); + if (ret) + return ret; + + if (!rdma_is_port_valid(ib_dev, port)) + return -EINVAL; + + pdata = &ib_dev->port_data[port]; + spin_lock_irqsave(&pdata->netdev_lock, flags); + if (pdata->netdev == ndev) { + spin_unlock_irqrestore(&pdata->netdev_lock, flags); + return 0; + } + old_ndev = pdata->netdev; + + if (ndev) + dev_hold(ndev); + pdata->netdev = ndev; + spin_unlock_irqrestore(&pdata->netdev_lock, flags); + + if (old_ndev) + dev_put(old_ndev); + + return 0; +} +EXPORT_SYMBOL(ib_device_set_netdev); + +static void free_netdevs(struct ib_device *ib_dev) +{ + unsigned long flags; + unsigned int port; + + rdma_for_each_port (ib_dev, port) { + struct ib_port_data *pdata = &ib_dev->port_data[port]; + + spin_lock_irqsave(&pdata->netdev_lock, flags); + if (pdata->netdev) { + dev_put(pdata->netdev); + pdata->netdev = NULL; + } + spin_unlock_irqrestore(&pdata->netdev_lock, flags); + } +} + +struct net_device *ib_device_get_netdev(struct ib_device *ib_dev, + unsigned int port) +{ + struct ib_port_data *pdata; + struct net_device *res; + + if (!rdma_is_port_valid(ib_dev, port)) + return NULL; + + pdata = &ib_dev->port_data[port]; + + /* + * New drivers should use ib_device_set_netdev() not the legacy + * get_netdev(). + */ + if (ib_dev->ops.get_netdev) + res = ib_dev->ops.get_netdev(ib_dev, port); + else { + spin_lock(&pdata->netdev_lock); + res = pdata->netdev; + if (res) + dev_hold(res); + spin_unlock(&pdata->netdev_lock); + } + + /* + * If we are starting to unregister expedite things by preventing + * propagation of an unregistering netdev. + */ + if (res && res->reg_state != NETREG_REGISTERED) { + dev_put(res); + return NULL; + } + + return res; +} + /** * ib_enum_roce_netdev - enumerate all RoCE ports * @ib_dev : IB device we want to query @@ -1020,16 +1158,8 @@ void ib_enum_roce_netdev(struct ib_device *ib_dev, rdma_for_each_port (ib_dev, port) if (rdma_protocol_roce(ib_dev, port)) { - struct net_device *idev = NULL; - - if (ib_dev->ops.get_netdev) - idev = ib_dev->ops.get_netdev(ib_dev, port); - - if (idev && - idev->reg_state >= NETREG_UNREGISTERED) { - dev_put(idev); - idev = NULL; - } + struct net_device *idev = + ib_device_get_netdev(ib_dev, port); if (filter(ib_dev, port, idev, filter_cookie)) cb(ib_dev, port, idev, cookie); diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c index 6708277aad7e4c..a0e635c5715905 100644 --- a/drivers/infiniband/core/nldev.c +++ b/drivers/infiniband/core/nldev.c @@ -262,9 +262,7 @@ static int fill_port_info(struct sk_buff *msg, if (nla_put_u8(msg, RDMA_NLDEV_ATTR_PORT_PHYS_STATE, attr.phys_state)) return -EMSGSIZE; - if (device->ops.get_netdev) - netdev = device->ops.get_netdev(device, port); - + netdev = ib_device_get_netdev(device, port); if (netdev && net_eq(dev_net(netdev), net)) { ret = nla_put_u32(msg, RDMA_NLDEV_ATTR_NDEV_INDEX, netdev->ifindex); diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index de5d895a50544c..5a5e83f5f0fc4c 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -1723,10 +1723,7 @@ int ib_get_eth_speed(struct ib_device *dev, u8 port_num, u8 *speed, u8 *width) if (rdma_port_get_link_layer(dev, port_num) != IB_LINK_LAYER_ETHERNET) return -EINVAL; - if (!dev->ops.get_netdev) - return -EOPNOTSUPP; - - netdev = dev->ops.get_netdev(dev, port_num); + netdev = ib_device_get_netdev(dev, port_num); if (!netdev) return -ENODEV; diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index e5eea5a50e27f2..358bda4a76ff42 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -2204,6 +2204,9 @@ struct ib_port_data { struct list_head pkey_list; struct ib_port_cache cache; + + spinlock_t netdev_lock; + struct net_device *netdev; }; /* rdma netdev type - specifies protocol type */ @@ -3997,6 +4000,10 @@ void ib_device_put(struct ib_device *device); struct net_device *ib_get_net_dev_by_params(struct ib_device *dev, u8 port, u16 pkey, const union ib_gid *gid, const struct sockaddr *addr); +int ib_device_set_netdev(struct ib_device *ib_dev, struct net_device *ndev, + unsigned int port); +struct net_device *ib_device_netdev(struct ib_device *dev, u8 port); + struct ib_wq *ib_create_wq(struct ib_pd *pd, struct ib_wq_init_attr *init_attr); int ib_destroy_wq(struct ib_wq *wq); From patchwork Wed Feb 13 04:12:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 10809101 X-Patchwork-Delegate: jgg@ziepe.ca 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 45B2E17E0 for ; Wed, 13 Feb 2019 04:13:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 32C662BFED for ; Wed, 13 Feb 2019 04:13:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 26B772C06B; Wed, 13 Feb 2019 04:13:06 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 6AFC32BFED for ; Wed, 13 Feb 2019 04:13:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729810AbfBMENE (ORCPT ); Tue, 12 Feb 2019 23:13:04 -0500 Received: from mail-pl1-f194.google.com ([209.85.214.194]:38354 "EHLO mail-pl1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729473AbfBMENE (ORCPT ); Tue, 12 Feb 2019 23:13:04 -0500 Received: by mail-pl1-f194.google.com with SMTP id e5so543048plb.5 for ; Tue, 12 Feb 2019 20:13:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ziepe.ca; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=GVGNiNpRH/vjLcfX9f5wqqayCqQLUbSvcPoPHUt7WIs=; b=lfytZmidEhkAmGz65OTwGjVduZWBd/xSmu27nRBQzuUrG5nT0wA1+B0PwVi4AEwEKA nM8HU0x0jJaAPZ9pJZkvWPnOLcIQIPEj2Ldym4CU8TaX0gNOJZC7aLTXzLBrIwrlonA2 +0GSYiPP/YZLINvx6OzIjWL9Tn5GFrCLOKLvfuYS2A9uipzZxqkpoVOPaezfSOBKpEyT TjhNnA1UZgNUgcc9IfwFgqdIvarQNP/LQgohb2yeE/nJ+Ps/kAmicHqSFbWek+Bz6mXF IYUzzh1Cu4uP1I0kWyCxViQXT1xFxe5z8umO+ClyIxUHsUw2dFnUBP2AcAqxgWXXWkOG DAjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=GVGNiNpRH/vjLcfX9f5wqqayCqQLUbSvcPoPHUt7WIs=; b=K9tw3+xoM5z8F5ouo8FchO4ZKNhx+6RLET6tlOGg2ifEXGYT1QaSYpoWYJofgBV7Rp r7GRZZwnNsdFWU/qmxFrgEopzazl2F2NJMx7g7NsbhYWS3siVcdvySZHsmKf9BVuU753 o2NH+oogv2KzZSFTlNwx36yk6hfDbxTuuBpY9/HbgYff4LFQ/WDBv5jh2YCE9loMH37O 7tEnMnPhmn49ANO8a9lFYi0PxrFf73mE8vq1jLbYus4cDXwWlwkT9n4JEukO/ZFFInh4 moCq4784D2SaeCh9hYlhNLh0XlcmySvMSqJXMKzTsazFbSeO+j6C+jkLUSuQxUog/6ay l7ww== X-Gm-Message-State: AHQUAuZ2OasIqjCxv/Sc6rLVeKGB+2CM/46CfaeJSEP3nzsU/1/eYHTq v+wHmecGDcY4L1969EUFqfZKzZucf8k= X-Google-Smtp-Source: AHgI3IaHnu/4OXZcWGjVwTGSoVQI69OdPimQzjSe7W9O8g2e+7/mn6gAfOnnH/gcil2KX64WSD6Xng== X-Received: by 2002:a17:902:a03:: with SMTP id 3mr7729398plo.112.1550031183204; Tue, 12 Feb 2019 20:13:03 -0800 (PST) Received: from ziepe.ca (S010614cc2056d97f.ed.shawcable.net. [174.3.196.123]) by smtp.gmail.com with ESMTPSA id d129sm24767211pfc.31.2019.02.12.20.13.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 12 Feb 2019 20:13:00 -0800 (PST) Received: from jgg by mlx.ziepe.ca with local (Exim 4.90_1) (envelope-from ) id 1gtlut-0005sO-U6; Tue, 12 Feb 2019 21:12:59 -0700 From: Jason Gunthorpe To: linux-rdma@vger.kernel.org Cc: Jason Gunthorpe Subject: [PATCH 05/10] RDMA/device: Add ib_device_get_by_netdev() Date: Tue, 12 Feb 2019 21:12:51 -0700 Message-Id: <20190213041256.22437-6-jgg@ziepe.ca> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190213041256.22437-1-jgg@ziepe.ca> References: <20190213041256.22437-1-jgg@ziepe.ca> MIME-Version: 1.0 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: Jason Gunthorpe Several drivers need to find the ib_device from a given netdev. rxe needs this at speed in an unsleepable context, so choose to implement the translation using a RCU safe hash table. The hash table can have a many to one mapping. This is intended to support some future case where multiple IB drivers (ie iWarp and RoCE) connect to the same netdevs. driver_ids will need to be different to support this. In the process this makes the struct ib_device and ib_port_data RCU safe by deferring their kfrees. Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/device.c | 119 +++++++++++++++++++++++++++---- include/rdma/ib_verbs.h | 10 ++- 2 files changed, 116 insertions(+), 13 deletions(-) diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 14c91f9af6ccc9..ae70091c20c19f 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -133,6 +134,10 @@ static void *xan_find_marked(struct xarray *xa, unsigned long *indexp, !xa_is_err(entry); \ (index)++, entry = xan_find_marked(xa, &(index), filter)) +/* RCU hash table mapping netdevice pointers to struct ib_port_data */ +static DEFINE_SPINLOCK(ndev_hash_lock); +static DECLARE_HASHTABLE(ndev_hash, 5); + static void free_netdevs(struct ib_device *ib_dev); static int ib_security_change(struct notifier_block *nb, unsigned long event, void *lsm_data); @@ -143,6 +148,12 @@ static struct notifier_block ibdev_lsm_nb = { .notifier_call = ib_security_change, }; +/* Pointer to the RCU head at the start of the ib_port_data array */ +struct ib_port_data_rcu { + struct rcu_head rcu_head; + struct ib_port_data pdata[]; +}; + static int ib_device_check_mandatory(struct ib_device *device) { #define IB_MANDATORY_FUNC(x) { offsetof(struct ib_device_ops, x), #x } @@ -294,9 +305,12 @@ static void ib_device_release(struct device *device) WARN_ON(refcount_read(&dev->refcount)); ib_cache_release_one(dev); ib_security_release_port_pkey_list(dev); - kfree(dev->port_data); xa_destroy(&dev->client_data); - kfree(dev); + if (dev->port_data) + kfree_rcu(container_of(dev->port_data, struct ib_port_data_rcu, + pdata[0]), + rcu_head); + kfree_rcu(dev, rcu_head); } static int ib_device_uevent(struct device *device, @@ -461,6 +475,7 @@ static void remove_client_context(struct ib_device *device, static int alloc_port_data(struct ib_device *device) { + struct ib_port_data_rcu *pdata_rcu; unsigned int port; if (device->port_data) @@ -477,17 +492,26 @@ static int alloc_port_data(struct ib_device *device) * Therefore port_data is declared as a 1 based array with potential * empty slots at the beginning. */ - device->port_data = kcalloc(rdma_end_port(device) + 1, - sizeof(*device->port_data), GFP_KERNEL); - if (!device->port_data) + pdata_rcu = kzalloc(struct_size(pdata_rcu, pdata, + rdma_end_port(device) + 1), + GFP_KERNEL); + if (!pdata_rcu) return -ENOMEM; + /* + * The rcu_head is put in front of the port data array and the stored + * pointer is adjusted since we never need to see that member until + * kfree_rcu. + */ + device->port_data = pdata_rcu->pdata; rdma_for_each_port (device, port) { struct ib_port_data *pdata = &device->port_data[port]; + pdata->ib_dev = device; spin_lock_init(&pdata->pkey_list_lock); INIT_LIST_HEAD(&pdata->pkey_list); spin_lock_init(&pdata->netdev_lock); + INIT_HLIST_NODE(&pdata->ndev_hash_link); } return 0; } @@ -1028,6 +1052,29 @@ int ib_query_port(struct ib_device *device, } EXPORT_SYMBOL(ib_query_port); +static void add_ndev_hash(struct ib_port_data *pdata) +{ + unsigned long flags; + + might_sleep(); + + spin_lock_irqsave(&ndev_hash_lock, flags); + if (hash_hashed(&pdata->ndev_hash_link)) { + hash_del_rcu(&pdata->ndev_hash_link); + spin_unlock_irqrestore(&ndev_hash_lock, flags); + /* + * We cannot do hash_add_rcu after a hash_del_rcu until the + * grace period + */ + synchronize_rcu(); + spin_lock_irqsave(&ndev_hash_lock, flags); + } + if (pdata->netdev) + hash_add_rcu(ndev_hash, &pdata->ndev_hash_link, + (uintptr_t)pdata->netdev); + spin_unlock_irqrestore(&ndev_hash_lock, flags); +} + /** * ib_device_set_netdev - Associate the ib_dev with an underlying net_device * @ib_dev: Device to modify @@ -1064,17 +1111,19 @@ int ib_device_set_netdev(struct ib_device *ib_dev, struct net_device *ndev, pdata = &ib_dev->port_data[port]; spin_lock_irqsave(&pdata->netdev_lock, flags); - if (pdata->netdev == ndev) { + old_ndev = rcu_dereference_protected( + pdata->netdev, lockdep_is_held(&pdata->netdev_lock)); + if (old_ndev == ndev) { spin_unlock_irqrestore(&pdata->netdev_lock, flags); return 0; } - old_ndev = pdata->netdev; if (ndev) dev_hold(ndev); - pdata->netdev = ndev; + rcu_assign_pointer(pdata->netdev, ndev); spin_unlock_irqrestore(&pdata->netdev_lock, flags); + add_ndev_hash(pdata); if (old_ndev) dev_put(old_ndev); @@ -1089,11 +1138,24 @@ static void free_netdevs(struct ib_device *ib_dev) rdma_for_each_port (ib_dev, port) { struct ib_port_data *pdata = &ib_dev->port_data[port]; + struct net_device *ndev; spin_lock_irqsave(&pdata->netdev_lock, flags); - if (pdata->netdev) { - dev_put(pdata->netdev); - pdata->netdev = NULL; + ndev = rcu_dereference_protected( + pdata->netdev, lockdep_is_held(&pdata->netdev_lock)); + if (ndev) { + spin_lock(&ndev_hash_lock); + hash_del_rcu(&pdata->ndev_hash_link); + spin_unlock(&ndev_hash_lock); + + /* + * If this is the last dev_put there is still a + * synchronize_rcu before the netdev is kfreed, so we + * can continue to rely on unlocked pointer + * comparisons after the put + */ + rcu_assign_pointer(pdata->netdev, NULL); + dev_put(ndev); } spin_unlock_irqrestore(&pdata->netdev_lock, flags); } @@ -1118,7 +1180,8 @@ struct net_device *ib_device_get_netdev(struct ib_device *ib_dev, res = ib_dev->ops.get_netdev(ib_dev, port); else { spin_lock(&pdata->netdev_lock); - res = pdata->netdev; + res = rcu_dereference_protected( + pdata->netdev, lockdep_is_held(&pdata->netdev_lock)); if (res) dev_hold(res); spin_unlock(&pdata->netdev_lock); @@ -1136,6 +1199,38 @@ struct net_device *ib_device_get_netdev(struct ib_device *ib_dev, return res; } +/** + * ib_device_get_by_netdev - Find an IB device associated with a netdev + * @ndev: netdev to locate + * @driver_id: The driver ID that must match (RDMA_DRIVER_UNKNOWN matches all) + * + * Find and hold an ib_device that is associated with a netdev via + * ib_device_set_netdev(). The caller must call ib_device_put() on the + * returned pointer. + */ +struct ib_device *ib_device_get_by_netdev(struct net_device *ndev, + enum rdma_driver_id driver_id) +{ + struct ib_device *res = NULL; + struct ib_port_data *cur; + + rcu_read_lock(); + hash_for_each_possible_rcu (ndev_hash, cur, ndev_hash_link, + (uintptr_t)ndev) { + if (rcu_access_pointer(cur->netdev) == ndev && + (driver_id == RDMA_DRIVER_UNKNOWN || + cur->ib_dev->driver_id == driver_id) && + ib_device_try_get(cur->ib_dev)) { + res = cur->ib_dev; + break; + } + } + rcu_read_unlock(); + + return res; +} +EXPORT_SYMBOL(ib_device_get_by_netdev); + /** * ib_enum_roce_netdev - enumerate all RoCE ports * @ib_dev : IB device we want to query diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 358bda4a76ff42..585512daef3cb2 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -2198,6 +2198,8 @@ struct ib_port_immutable { }; struct ib_port_data { + struct ib_device *ib_dev; + struct ib_port_immutable immutable; spinlock_t pkey_list_lock; @@ -2206,7 +2208,8 @@ struct ib_port_data { struct ib_port_cache cache; spinlock_t netdev_lock; - struct net_device *netdev; + struct net_device __rcu *netdev; + struct hlist_node ndev_hash_link; }; /* rdma netdev type - specifies protocol type */ @@ -2543,6 +2546,7 @@ struct ib_device { struct device *dma_device; struct ib_device_ops ops; char name[IB_DEVICE_NAME_MAX]; + struct rcu_head rcu_head; struct list_head event_handler_list; spinlock_t event_handler_lock; @@ -3997,6 +4001,10 @@ static inline bool ib_device_try_get(struct ib_device *dev) } void ib_device_put(struct ib_device *device); +struct ib_device *ib_device_get_by_netdev(struct net_device *ndev, + enum rdma_driver_id driver_id); +struct ib_device *ib_device_get_by_name(const char *name, + enum rdma_driver_id driver_id); struct net_device *ib_get_net_dev_by_params(struct ib_device *dev, u8 port, u16 pkey, const union ib_gid *gid, const struct sockaddr *addr); From patchwork Wed Feb 13 04:12:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 10809097 X-Patchwork-Delegate: jgg@ziepe.ca 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 C18701399 for ; Wed, 13 Feb 2019 04:13:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ADD692BFE1 for ; Wed, 13 Feb 2019 04:13:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A1D512C06B; Wed, 13 Feb 2019 04:13:04 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 087022BFED for ; Wed, 13 Feb 2019 04:13:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729015AbfBMEND (ORCPT ); Tue, 12 Feb 2019 23:13:03 -0500 Received: from mail-pl1-f194.google.com ([209.85.214.194]:40911 "EHLO mail-pl1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727915AbfBMEND (ORCPT ); Tue, 12 Feb 2019 23:13:03 -0500 Received: by mail-pl1-f194.google.com with SMTP id bj4so536921plb.7 for ; Tue, 12 Feb 2019 20:13:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ziepe.ca; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=E8Lxa/NkIuAHp4LzaEi4XW7GDT/KE7+a89lAfPknEwQ=; b=SCXF/PTM/q9KJ/IhSlQvoT0Ku3/l50C/g4eMouRrgG+uQWwb+JhnqFMP+smOZ3Yrcf lTOPsE1rqV5ZI/J0KVr7DpVQqmnwn2xK79TzXSBHVNha0BA1bnVkbpPsPN9vA34FlWQr pFX/+FXkK81GEwk2WiiwmDWevOa5wNQ6DlXHSiWILhoUz6W+wZ6mQVAHEMb46eF1e+KL GrjsrXbATxzDkgleUNozPImTba9PTJRGlpRUjcc7E9wR2LLrMfJ8FKDRNFYNS+knc8V+ mU1gaAGbUid+/uWQ05LjfiC6nnxKw4cfQXwggGWpe4QTl9teN/TRXVuTExlOYPxY1Bn5 2Gaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=E8Lxa/NkIuAHp4LzaEi4XW7GDT/KE7+a89lAfPknEwQ=; b=cDMVQMyuDN6txOHo/q0PnjP9aciuRyloSKyJzseFCZNwc39A0ov/JTvpRn9gpv6Oiv qFv5OVSzSVGI91LMqRAP/BtAe5PhKcwsvOUOdZfJHibeJ0Cq+88kor/5kCCBEU+J0slT 6T5so+pOutpPbEZXqU1SQccUHSJWCc4FbZMcN8+mRnORiASuDoV9CCSCWW0eMTHMEjFs snse+fpDQoGq+aUrnSRcbV6SuWgOJUXyW1GU/R56b47g0WOqmIcx2LFBZoadAegDrSUa CbVX02KMAClXflHuzaoQDOWlrKfO+ZtHAXG/xqn24FjxSFmK6+MYxjc5BTbKYl+iqZhK bdIQ== X-Gm-Message-State: AHQUAuYj8AmjcM7o+cBKqWpIxdmIc7c94zreTfBs8WSCEhzgMdSnuTI4 OW8XRWtLiSTeak7OZAC8QIa2hyUUIDc= X-Google-Smtp-Source: AHgI3IbYULYCJ4VH8QIqgS2amyctjDIlIlMCxuI28oP4vkfg0dJjXUViAnGCrxo61CXtMRu+JA3Z+Q== X-Received: by 2002:a17:902:12f:: with SMTP id 44mr7768605plb.74.1550031181956; Tue, 12 Feb 2019 20:13:01 -0800 (PST) Received: from ziepe.ca (S010614cc2056d97f.ed.shawcable.net. [174.3.196.123]) by smtp.gmail.com with ESMTPSA id l28sm12390572pfi.178.2019.02.12.20.13.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 12 Feb 2019 20:13:00 -0800 (PST) Received: from jgg by mlx.ziepe.ca with local (Exim 4.90_1) (envelope-from ) id 1gtlut-0005sU-WE; Tue, 12 Feb 2019 21:13:00 -0700 From: Jason Gunthorpe To: linux-rdma@vger.kernel.org Cc: Jason Gunthorpe Subject: [PATCH 06/10] RDMA/rxe: Use ib_device_get_by_netdev() instead of open coding Date: Tue, 12 Feb 2019 21:12:52 -0700 Message-Id: <20190213041256.22437-7-jgg@ziepe.ca> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190213041256.22437-1-jgg@ziepe.ca> References: <20190213041256.22437-1-jgg@ziepe.ca> MIME-Version: 1.0 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: Jason Gunthorpe The core API handles the locking correctly and is faster if there are multiple devices. Signed-off-by: Jason Gunthorpe --- drivers/infiniband/sw/rxe/rxe.h | 12 ++++++++- drivers/infiniband/sw/rxe/rxe_net.c | 39 +++++++++++---------------- drivers/infiniband/sw/rxe/rxe_sysfs.c | 17 ++++++------ drivers/infiniband/sw/rxe/rxe_verbs.c | 17 +++--------- 4 files changed, 38 insertions(+), 47 deletions(-) diff --git a/drivers/infiniband/sw/rxe/rxe.h b/drivers/infiniband/sw/rxe/rxe.h index 5bde2ad964d277..2b875875962f6e 100644 --- a/drivers/infiniband/sw/rxe/rxe.h +++ b/drivers/infiniband/sw/rxe/rxe.h @@ -105,9 +105,19 @@ static inline void rxe_dev_put(struct rxe_dev *rxe) { kref_put(&rxe->ref_cnt, rxe_release); } -struct rxe_dev *net_to_rxe(struct net_device *ndev); struct rxe_dev *get_rxe_by_name(const char *name); +/* The caller must do a matching ib_device_put(&dev->ib_dev) */ +static inline struct rxe_dev *rxe_get_dev_from_net(struct net_device *ndev) +{ + struct ib_device *ibdev = + ib_device_get_by_netdev(ndev, RDMA_DRIVER_RXE); + + if (!ibdev) + return NULL; + return container_of(ibdev, struct rxe_dev, ib_dev); +} + void rxe_port_up(struct rxe_dev *rxe); void rxe_port_down(struct rxe_dev *rxe); void rxe_set_port_state(struct rxe_dev *rxe); diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c index 3b162e92e8e8d7..56878453f1aed8 100644 --- a/drivers/infiniband/sw/rxe/rxe_net.c +++ b/drivers/infiniband/sw/rxe/rxe_net.c @@ -48,23 +48,6 @@ static LIST_HEAD(rxe_dev_list); static DEFINE_SPINLOCK(dev_list_lock); /* spinlock for device list */ -struct rxe_dev *net_to_rxe(struct net_device *ndev) -{ - struct rxe_dev *rxe; - struct rxe_dev *found = NULL; - - spin_lock_bh(&dev_list_lock); - list_for_each_entry(rxe, &rxe_dev_list, list) { - if (rxe->ndev == ndev) { - found = rxe; - break; - } - } - spin_unlock_bh(&dev_list_lock); - - return found; -} - struct rxe_dev *get_rxe_by_name(const char *name) { struct rxe_dev *rxe; @@ -81,7 +64,6 @@ struct rxe_dev *get_rxe_by_name(const char *name) return found; } - static struct rxe_recv_sockets recv_sockets; struct device *rxe_dma_device(struct rxe_dev *rxe) @@ -229,18 +211,19 @@ static int rxe_udp_encap_recv(struct sock *sk, struct sk_buff *skb) struct udphdr *udph; struct net_device *ndev = skb->dev; struct net_device *rdev = ndev; - struct rxe_dev *rxe = net_to_rxe(ndev); + struct rxe_dev *rxe = rxe_get_dev_from_net(ndev); struct rxe_pkt_info *pkt = SKB_TO_PKT(skb); if (!rxe && is_vlan_dev(rdev)) { rdev = vlan_dev_real_dev(ndev); - rxe = net_to_rxe(rdev); + rxe = rxe_get_dev_from_net(rdev); } if (!rxe) goto drop; if (skb_linearize(skb)) { pr_err("skb_linearize failed\n"); + ib_device_put(&rxe->ib_dev); goto drop; } @@ -253,6 +236,12 @@ static int rxe_udp_encap_recv(struct sock *sk, struct sk_buff *skb) rxe_rcv(skb); + /* + * FIXME: this is in the wrong place, it needs to be done when pkt is + * destroyed + */ + ib_device_put(&rxe->ib_dev); + return 0; drop: kfree_skb(skb); @@ -635,16 +624,17 @@ static int rxe_notify(struct notifier_block *not_blk, void *arg) { struct net_device *ndev = netdev_notifier_info_to_dev(arg); - struct rxe_dev *rxe = net_to_rxe(ndev); + struct rxe_dev *rxe = rxe_get_dev_from_net(ndev); if (!rxe) - goto out; + return NOTIFY_OK; switch (event) { case NETDEV_UNREGISTER: list_del(&rxe->list); + ib_device_put(&rxe->ib_dev); rxe_remove(rxe); - break; + return NOTIFY_OK; case NETDEV_UP: rxe_port_up(rxe); break; @@ -668,7 +658,8 @@ static int rxe_notify(struct notifier_block *not_blk, event, ndev->name); break; } -out: + + ib_device_put(&rxe->ib_dev); return NOTIFY_OK; } diff --git a/drivers/infiniband/sw/rxe/rxe_sysfs.c b/drivers/infiniband/sw/rxe/rxe_sysfs.c index 95a15892f7e659..6802be71bf9b20 100644 --- a/drivers/infiniband/sw/rxe/rxe_sysfs.c +++ b/drivers/infiniband/sw/rxe/rxe_sysfs.c @@ -58,24 +58,25 @@ static int rxe_param_set_add(const char *val, const struct kernel_param *kp) int len; int err = 0; char intf[32]; - struct net_device *ndev = NULL; + struct net_device *ndev; + struct rxe_dev *exists; struct rxe_dev *rxe; len = sanitize_arg(val, intf, sizeof(intf)); if (!len) { pr_err("add: invalid interface name\n"); - err = -EINVAL; - goto err; + return -EINVAL; } ndev = dev_get_by_name(&init_net, intf); if (!ndev) { pr_err("interface %s not found\n", intf); - err = -EINVAL; - goto err; + return -EINVAL; } - if (net_to_rxe(ndev)) { + exists = rxe_get_dev_from_net(ndev); + if (exists) { + ib_device_put(&exists->ib_dev); pr_err("already configured on %s\n", intf); err = -EINVAL; goto err; @@ -90,9 +91,9 @@ static int rxe_param_set_add(const char *val, const struct kernel_param *kp) rxe_set_port_state(rxe); dev_info(&rxe->ib_dev.dev, "added %s\n", intf); + err: - if (ndev) - dev_put(ndev); + dev_put(ndev); return err; } diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c index 051c3930e808ed..de96c18f09968b 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.c +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c @@ -79,19 +79,6 @@ static int rxe_query_port(struct ib_device *dev, return rc; } -static struct net_device *rxe_get_netdev(struct ib_device *device, - u8 port_num) -{ - struct rxe_dev *rxe = to_rdev(device); - - if (rxe->ndev) { - dev_hold(rxe->ndev); - return rxe->ndev; - } - - return NULL; -} - static int rxe_query_pkey(struct ib_device *device, u8 port_num, u16 index, u16 *pkey) { @@ -1157,7 +1144,6 @@ static const struct ib_device_ops rxe_dev_ops = { .get_dma_mr = rxe_get_dma_mr, .get_hw_stats = rxe_ib_get_hw_stats, .get_link_layer = rxe_get_link_layer, - .get_netdev = rxe_get_netdev, .get_port_immutable = rxe_port_immutable, .map_mr_sg = rxe_map_mr_sg, .mmap = rxe_mmap, @@ -1238,6 +1224,9 @@ int rxe_register_device(struct rxe_dev *rxe) ; ib_set_device_ops(dev, &rxe_dev_ops); + err = ib_device_set_netdev(&rxe->ib_dev, rxe->ndev, 1); + if (err) + return err; tfm = crypto_alloc_shash("crc32", 0, 0); if (IS_ERR(tfm)) { From patchwork Wed Feb 13 04:12:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 10809115 X-Patchwork-Delegate: jgg@ziepe.ca 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 3A73A17E0 for ; Wed, 13 Feb 2019 04:13:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 270E92BFAF for ; Wed, 13 Feb 2019 04:13:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1B3622BFE1; Wed, 13 Feb 2019 04:13:10 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 BFC102BFED for ; Wed, 13 Feb 2019 04:13:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729473AbfBMENG (ORCPT ); Tue, 12 Feb 2019 23:13:06 -0500 Received: from mail-pf1-f194.google.com ([209.85.210.194]:45287 "EHLO mail-pf1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726902AbfBMENF (ORCPT ); Tue, 12 Feb 2019 23:13:05 -0500 Received: by mail-pf1-f194.google.com with SMTP id j3so515669pfi.12 for ; Tue, 12 Feb 2019 20:13:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ziepe.ca; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=edHhzKAR9Iubi+NBMsEux7VIbZ0je5o82e+Fa6QR1Rw=; b=gfvdL2aD4y1xPctceuT6FP0XRhiHfmLV4ZpOei8Xf/md98FjHiTefZm18nZXgEXMyP zF6J5nhQ+UVcb0oGrMskjufejlTapQoTaRxyZwkhyrnxmn5IC774KrQI9bWLoxAgjACT BGV2szM+RHcYUri8dzU6/oHmRIj32PlNVHQSfk20ohhwXatdP1YHGNsOl8fMpeuiUk8l SKdWgnioVQe6m7LIFPmhpuvMFlOOvW/V6QJWfqvNYDVbJjVh0PMmkPw8zvm/X1plIWoJ xIQdWyqugkpQCCSDUxxvmmYsv4gdyQcaZjQthAUkMgwT4xwmdNkSFY068b6f1AHL9hsK zHIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=edHhzKAR9Iubi+NBMsEux7VIbZ0je5o82e+Fa6QR1Rw=; b=MpUD5AtBJ2cicrufRCE9E8+bKl58slKAugm86e/+IepMgWPkuWv3nDNp4ln2nKDXig peCxrzJEu12r066giAETil7wWVR+SKXHHbqpOXJf7rdG3AL1bnL3fLBAswE6VvqcShn+ mE06RadhXN15B/0HHCiOQJ0IIa2p8/0ufpNhLf38TlTjS0LdvtvPDc9NnExpLu7sY15H n5ymXyIkplBBcUxZ3H2EogIR/RRswgYTWwAal5ABhxujsefN13LYfhzcsLihgvoTfFN6 HnWalvIfy/1cy5A9f8HLYQMVo35R3NxhZoMI0blQ/2PVCN5Pe8cpE1NOVRbpiKUbC2pG EJfg== X-Gm-Message-State: AHQUAuZxoNjYpZ9bFKh/Qgxh5M2xHIumz4Z+d6eindgS0dVS1ATZCThJ 3X3saeMPnNZj4KtX2nC8k7LQDypgW28= X-Google-Smtp-Source: AHgI3Ia/BltQYv8j9J/pFdyz1an9BHuD/lM9G4QEhpyQI7GpWGNHehlZLUa+Q/gyDQ3NnE+J0icqCA== X-Received: by 2002:a63:515d:: with SMTP id r29mr6829265pgl.350.1550031183863; Tue, 12 Feb 2019 20:13:03 -0800 (PST) Received: from ziepe.ca (S010614cc2056d97f.ed.shawcable.net. [174.3.196.123]) by smtp.gmail.com with ESMTPSA id e26sm5883309pfi.70.2019.02.12.20.13.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 12 Feb 2019 20:13:01 -0800 (PST) Received: from jgg by mlx.ziepe.ca with local (Exim 4.90_1) (envelope-from ) id 1gtluu-0005sa-1H; Tue, 12 Feb 2019 21:13:00 -0700 From: Jason Gunthorpe To: linux-rdma@vger.kernel.org Cc: Jason Gunthorpe Subject: [PATCH 07/10] RDMA/device: Provide APIs from the core code to help unregistration Date: Tue, 12 Feb 2019 21:12:53 -0700 Message-Id: <20190213041256.22437-8-jgg@ziepe.ca> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190213041256.22437-1-jgg@ziepe.ca> References: <20190213041256.22437-1-jgg@ziepe.ca> MIME-Version: 1.0 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: Jason Gunthorpe These APIs are intended to support drivers that exist outside the usual driver core probe()/remove() callbacks. Normally the driver core will prevent remove() from running concurrently with probe(), once this safety is lost drivers need more support to get the locking and lifetimes right. ib_unregister_driver() is intended to be used during module_exit of a driver using these APIs. It unregisters all the associated ib_devices. ib_unregister_device_and_put() is to be used by a driver-specific removal function (ie removal by name, removal from a netdev notifier, removal from netlink) ib_unregister_queued() is to be used from netdev notifier chains where RTNL is held. The locking is tricky here since once things become async it is possible to race unregister with registration. This is largely solved by relying on the registration refcount, unregistration will only ever work on something that has a positive registration refcount - and then an unregistration mutex serializes all competing unregistrations of the same device. Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/device.c | 240 ++++++++++++++++++++++++++----- include/rdma/ib_verbs.h | 11 ++ 2 files changed, 216 insertions(+), 35 deletions(-) diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index ae70091c20c19f..f6c755b675a86a 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -139,6 +139,8 @@ static DEFINE_SPINLOCK(ndev_hash_lock); static DECLARE_HASHTABLE(ndev_hash, 5); static void free_netdevs(struct ib_device *ib_dev); +static void ib_unregister_work(struct work_struct *work); +static void __ib_unregister_device(struct ib_device *device); static int ib_security_change(struct notifier_block *nb, unsigned long event, void *lsm_data); static void ib_policy_change_task(struct work_struct *work); @@ -360,6 +362,7 @@ struct ib_device *_ib_alloc_device(size_t size) INIT_LIST_HEAD(&device->event_handler_list); spin_lock_init(&device->event_handler_lock); + mutex_init(&device->unregistration_lock); /* * client_data needs to be alloc because we don't want our mark to be * destroyed if the user stores NULL in the client data. @@ -368,6 +371,7 @@ struct ib_device *_ib_alloc_device(size_t size) init_rwsem(&device->client_data_rwsem); INIT_LIST_HEAD(&device->port_list); init_completion(&device->unreg_completion); + INIT_WORK(&device->unregistration_work, ib_unregister_work); return device; } @@ -381,6 +385,20 @@ EXPORT_SYMBOL(_ib_alloc_device); */ void ib_dealloc_device(struct ib_device *device) { + if (device->ops.dealloc_driver) + device->ops.dealloc_driver(device); + + /* + * ib_unregister_driver() requires all devices to remain in the xarray + * while their ops are callable. The last op we call is dealloc_driver + * above. This is needed to create a fence on op callbacks prior to + * allowing the driver module to unload. + */ + down_write(&devices_rwsem); + if (xa_load(&devices, device->index) == device) + xa_erase(&devices, device->index); + up_write(&devices_rwsem); + /* Expedite releasing netdev references */ free_netdevs(device); @@ -592,7 +610,8 @@ static int ib_security_change(struct notifier_block *nb, unsigned long event, } /* - * Assign the unique string device name and the unique device index. + * Assign the unique string device name and the unique device index. This is + * undone by ib_dealloc_device. */ static int assign_name(struct ib_device *device, const char *name) { @@ -633,13 +652,6 @@ static int assign_name(struct ib_device *device, const char *name) return ret; } -static void release_name(struct ib_device *device) -{ - down_write(&devices_rwsem); - xa_erase(&devices, device->index); - up_write(&devices_rwsem); -} - static void setup_dma_device(struct ib_device *device) { struct device *parent = device->dev.parent; @@ -733,30 +745,38 @@ static void disable_device(struct ib_device *device) /* * An enabled device is visible to all clients and to all the public facing - * APIs that return a device pointer. + * APIs that return a device pointer. This always returns with a new get, even + * if it fails. */ -static int enable_device(struct ib_device *device) +static int enable_device_and_get(struct ib_device *device) { struct ib_client *client; unsigned long index; - int ret; + int ret = 0; - refcount_set(&device->refcount, 1); + /* + * One ref belongs to the xa and the other belongs to this + * thread. This is needed to guard against parallel unregistration. + */ + refcount_set(&device->refcount, 2); down_write(&devices_rwsem); xa_set_mark(&devices, device->index, DEVICE_REGISTERED); - up_write(&devices_rwsem); + + /* + * By using downgrade_write() we ensure that no other thread can clear + * DEVICE_REGISTERED while we are completing the client setup. + */ + downgrade_write(&devices_rwsem); down_read(&clients_rwsem); xa_for_each_marked (&clients, index, client, CLIENT_REGISTERED) { ret = add_client_context(device, client); - if (ret) { - up_read(&clients_rwsem); - disable_device(device); - return ret; - } + if (ret) + break; } up_read(&clients_rwsem); - return 0; + up_read(&devices_rwsem); + return ret; } /** @@ -767,6 +787,10 @@ static int enable_device(struct ib_device *device) * devices with the IB core. All registered clients will receive a * callback for each device that is added. @device must be allocated * with ib_alloc_device(). + * + * If the driver uses ops.dealloc_driver and calls any ib_unregister_device() + * asynchronously then the device pointer may become freed as soon as this + * function returns. */ int ib_register_device(struct ib_device *device, const char *name) { @@ -778,13 +802,13 @@ int ib_register_device(struct ib_device *device, const char *name) ret = setup_device(device); if (ret) - goto out; + return ret; ret = ib_cache_setup_one(device); if (ret) { dev_warn(&device->dev, "Couldn't set up InfiniBand P_Key/GID cache\n"); - goto out; + return ret; } ib_device_register_rdmacg(device); @@ -796,39 +820,183 @@ int ib_register_device(struct ib_device *device, const char *name) goto cg_cleanup; } - ret = enable_device(device); - if (ret) - goto sysfs_cleanup; + ret = enable_device_and_get(device); + if (ret) { + void (*dealloc_fn)(struct ib_device *); + + /* + * If we hit this error flow then we don't want to + * automatically dealloc the device since the caller is + * expected to call ib_dealloc_device() after + * ib_register_device() fails. This is tricky due to the + * possibility for a parallel unregistration along with this + * error flow. Since we have a refcount here we know any + * parallel flow is stopped in disable_device and will see the + * NULL pointers, causing the responsibility to + * ib_dealloc_device() to revert back to this thread. + */ + dealloc_fn = device->ops.dealloc_driver; + device->ops.dealloc_driver = NULL; + ib_device_put(device); + __ib_unregister_device(device); + device->ops.dealloc_driver = dealloc_fn; + return ret; + } + ib_device_put(device); return 0; -sysfs_cleanup: - ib_device_unregister_sysfs(device); cg_cleanup: ib_device_unregister_rdmacg(device); ib_cache_cleanup_one(device); -out: - release_name(device); return ret; } EXPORT_SYMBOL(ib_register_device); +/* Callers must hold a get on the device. */ +static void __ib_unregister_device(struct ib_device *ib_dev) +{ + /* + * We have a registration lock so that all the calls to unregister are + * fully fenced, once any unregister returns the device is truely + * unregistered even if multiple callers are unregistering it at the + * same time. This also interacts with the registration flow and + * provides sane semantics if register and unregister are racing. + */ + mutex_lock(&ib_dev->unregistration_lock); + if (!refcount_read(&ib_dev->refcount)) + goto out; + + disable_device(ib_dev); + ib_device_unregister_sysfs(ib_dev); + ib_device_unregister_rdmacg(ib_dev); + ib_cache_cleanup_one(ib_dev); + + /* + * Drivers using the new flow may not call ib_dealloc_device except + * in error unwind prior to registration success. + */ + if (ib_dev->ops.dealloc_driver) { + WARN_ON(kref_read(&ib_dev->dev.kobj.kref) <= 1); + ib_dealloc_device(ib_dev); + } +out: + mutex_unlock(&ib_dev->unregistration_lock); +} + /** * ib_unregister_device - Unregister an IB device - * @device:Device to unregister + * @device: The device to unregister * * Unregister an IB device. All clients will receive a remove callback. + * + * Callers should call this routine only once, and protect against races with + * registration. Typically it should only be called as part of a remove + * callback in an implementation of driver core's struct device_driver and + * related. + * + * If ops.dealloc_driver is used then ib_dev will be freed upon return from + * this function. */ -void ib_unregister_device(struct ib_device *device) +void ib_unregister_device(struct ib_device *ib_dev) { - disable_device(device); - ib_device_unregister_sysfs(device); - ib_device_unregister_rdmacg(device); - ib_cache_cleanup_one(device); - release_name(device); + get_device(&ib_dev->dev); + __ib_unregister_device(ib_dev); + put_device(&ib_dev->dev); } EXPORT_SYMBOL(ib_unregister_device); +/** + * ib_unregister_device_and_put - Unregister a device while holding a 'get' + * device: The device to unregister + * + * This is the same as ib_unregister_device(), except it includes an internal + * ib_device_put() that should match a 'get' obtained by the caller. + * + * It is safe to call this routine concurrently from multiple threads while + * holding the 'get'. When the function returns the device is fully + * unregistered. + * + * Drivers using this flow MUST use the driver_unregister callback to clean up + * their resources associated with the device and dealloc it. + */ +void ib_unregister_device_and_put(struct ib_device *ib_dev) +{ + WARN_ON(!ib_dev->ops.dealloc_driver); + get_device(&ib_dev->dev); + ib_device_put(ib_dev); + __ib_unregister_device(ib_dev); + put_device(&ib_dev->dev); +} +EXPORT_SYMBOL(ib_unregister_device_and_put); + +/** + * ib_unregister_driver - Unregister all IB devices for a driver + * @driver_id: The driver to unregister + * + * This implements a fence for device unregistration. It only returns once all + * devices associated with the driver_id have fully completed their + * unregistration and returned from ib_unregister_device*(). + * + * If device's are not yet unregistered it goes ahead and starts unregistering + * them. + * + * This does not block creation of new devices with the given driver_id, that + * is the responsibility of the caller. + */ +void ib_unregister_driver(enum rdma_driver_id driver_id) +{ + struct ib_device *ib_dev; + unsigned long index; + + down_read(&devices_rwsem); + xa_for_each (&devices, index, ib_dev) { + if (ib_dev->driver_id != driver_id) + continue; + + get_device(&ib_dev->dev); + up_read(&devices_rwsem); + + WARN_ON(!ib_dev->ops.dealloc_driver); + __ib_unregister_device(ib_dev); + + put_device(&ib_dev->dev); + down_read(&devices_rwsem); + } + up_read(&devices_rwsem); +} +EXPORT_SYMBOL(ib_unregister_driver); + +static void ib_unregister_work(struct work_struct *work) +{ + struct ib_device *ib_dev = + container_of(work, struct ib_device, unregistration_work); + + __ib_unregister_device(ib_dev); + put_device(&ib_dev->dev); +} + +/** + * ib_unregister_device_queued - Unregister a device using a work queue + * device: The device to unregister + * + * This schedules an asynchronous unregistration using a WQ for the device. A + * driver should use this to avoid holding locks while doing unregistration, + * such as holding the RTNL lock. + * + * Drivers using this API must use ib_unregister_driver before module unload + * to ensure that all scheduled unregistrations have completed. + */ +void ib_unregister_device_queued(struct ib_device *ib_dev) +{ + WARN_ON(!refcount_read(&ib_dev->refcount)); + WARN_ON(!ib_dev->ops.dealloc_driver); + get_device(&ib_dev->dev); + if (!queue_work(system_unbound_wq, &ib_dev->unregistration_work)) + put_device(&ib_dev->dev); +} +EXPORT_SYMBOL(ib_unregister_device_queued); + static int assign_client_id(struct ib_client *client) { int ret; @@ -1544,6 +1712,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops) SET_DEVICE_OP(dev_ops, create_srq); SET_DEVICE_OP(dev_ops, create_wq); SET_DEVICE_OP(dev_ops, dealloc_dm); + SET_DEVICE_OP(dev_ops, dealloc_driver); SET_DEVICE_OP(dev_ops, dealloc_fmr); SET_DEVICE_OP(dev_ops, dealloc_mw); SET_DEVICE_OP(dev_ops, dealloc_pd); @@ -1730,6 +1899,7 @@ static void __exit ib_core_cleanup(void) destroy_workqueue(ib_comp_wq); /* Make sure that any pending umem accounting work is done. */ destroy_workqueue(ib_wq); + flush_workqueue(system_unbound_wq); WARN_ON(!xa_empty(&clients)); WARN_ON(!xa_empty(&devices)); } diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 585512daef3cb2..282d2903e6d3cf 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -2538,6 +2538,12 @@ struct ib_device_ops { int (*fill_res_entry)(struct sk_buff *msg, struct rdma_restrack_entry *entry); + /* Device lifecycle callbacks */ + /* + * This is called as part of ib_dealloc_device(). + */ + void (*dealloc_driver)(struct ib_device *dev); + DECLARE_RDMA_OBJ_SIZE(ib_pd); }; @@ -2553,6 +2559,7 @@ struct ib_device { struct rw_semaphore client_data_rwsem; struct xarray client_data; + struct mutex unregistration_lock; struct ib_cache cache; /** @@ -2610,6 +2617,7 @@ struct ib_device { */ refcount_t refcount; struct completion unreg_completion; + struct work_struct unregistration_work; }; struct ib_client { @@ -2659,6 +2667,9 @@ void ib_get_device_fw_str(struct ib_device *device, char *str); int ib_register_device(struct ib_device *device, const char *name); void ib_unregister_device(struct ib_device *device); +void ib_unregister_driver(enum rdma_driver_id driver_id); +void ib_unregister_device_and_put(struct ib_device *device); +void ib_unregister_device_queued(struct ib_device *ib_dev); int ib_register_client (struct ib_client *client); void ib_unregister_client(struct ib_client *client); From patchwork Wed Feb 13 04:12:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 10809109 X-Patchwork-Delegate: jgg@ziepe.ca 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 2F26C17E0 for ; Wed, 13 Feb 2019 04:13:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1C9632BFAF for ; Wed, 13 Feb 2019 04:13:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 10F4A2C06B; Wed, 13 Feb 2019 04:13:08 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 55FD92BFAF for ; Wed, 13 Feb 2019 04:13:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729561AbfBMENG (ORCPT ); Tue, 12 Feb 2019 23:13:06 -0500 Received: from mail-pg1-f194.google.com ([209.85.215.194]:45747 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729473AbfBMENF (ORCPT ); Tue, 12 Feb 2019 23:13:05 -0500 Received: by mail-pg1-f194.google.com with SMTP id y4so509706pgc.12 for ; Tue, 12 Feb 2019 20:13:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ziepe.ca; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=kC18HuskTUwgkgY22SOozjeMfC1iM1rGXCPiqjNgLY4=; b=J4dtzYz4P/OmfUvu3DBDyzfLI1dLqQG0jHP5CRQE9Vz2B4A3sSTHbkLBSu31DHgBnq hHa4kGaxpvrC0ZP79DKhFf7t682MhAjGNAAC/MDwNs2t8onag4eX6QfvFatm+usVbTLS lALdiwPZBW+jE3s5l8swC/KyPb0zRMLzqx+V3SIoDBgn1D5iaIvxwYZMlDbZ08TP9ymF uuGz/IBmDr6KPGpOkRtiFZ2MFC42JCl+rUG8xx3oDxipg3BsYG3EU6JTExK3WBzZd7Qn KpkB3FjVB+kvDrRreJAAmVBN3CoD+FLcR26x7byTBKMHCgezShPL+ySHJfBuloT0Hcqh +ADQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=kC18HuskTUwgkgY22SOozjeMfC1iM1rGXCPiqjNgLY4=; b=obEH2kZnr78LpAQgtGPNzv20taGgS260wuRr6ILYqcqdOZpzlJxN07mFHBw+u6mCEq +PNDsV0A2DMKU1MUw0mvMQAH/MSeJyrZAbeoJapysnORXp6o3j6UF3D/7FJROasoHRMW r/MpJLK8T/TF6La3h1+8LafFAiOQhm9VshtGI7k0wJ11+oJFKwBsunE+lbO4q99vXBeu nC1z7gTkAD02AOhyEVPVve/kMt1fOzs+bfDZwvht7joSdVBjKbG8GSAbF3YFOcqzQYMc FD23y60yGuZB9jrTviQS++d2+QMV6RyxglhOSSbj8gygxeHVJD/o6nRTaWuZCs9+uSMq +QEA== X-Gm-Message-State: AHQUAub1yayMdiq1qjcpPYzG6ASBn4a1wApIer2nvRJ9UxKbYxCa4PfN kC+82N+w03aNNJtQmYhpB6fRyyJ2W+Q= X-Google-Smtp-Source: AHgI3IY0LOm7z45qLa6CDVc1s6AmYXOCS93qxonjH9QNNAcBmzJbio+Wt2/i4+LrxEm0YCCdKSfvIg== X-Received: by 2002:a63:2ccb:: with SMTP id s194mr6940424pgs.214.1550031184312; Tue, 12 Feb 2019 20:13:04 -0800 (PST) Received: from ziepe.ca (S010614cc2056d97f.ed.shawcable.net. [174.3.196.123]) by smtp.gmail.com with ESMTPSA id j8sm4980055pfe.130.2019.02.12.20.13.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 12 Feb 2019 20:13:02 -0800 (PST) Received: from jgg by mlx.ziepe.ca with local (Exim 4.90_1) (envelope-from ) id 1gtluu-0005sg-3T; Tue, 12 Feb 2019 21:13:00 -0700 From: Jason Gunthorpe To: linux-rdma@vger.kernel.org Cc: Jason Gunthorpe Subject: [PATCH 08/10] RDMA/rxe: Use driver_unregister and new unregistration API Date: Tue, 12 Feb 2019 21:12:54 -0700 Message-Id: <20190213041256.22437-9-jgg@ziepe.ca> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190213041256.22437-1-jgg@ziepe.ca> References: <20190213041256.22437-1-jgg@ziepe.ca> MIME-Version: 1.0 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: Jason Gunthorpe rxe does not have correct locking for its registration/unregistration paths, use the core code to handle it instead. In this mode ib_unregister_device will also do the dealloc, so rxe is required to do clean up from a callback. The core code ensures that unregistration is done only once, and generally takes care of locking and concurrency problems for rxe. Signed-off-by: Jason Gunthorpe --- drivers/infiniband/sw/rxe/rxe.c | 40 ++++++--------------------- drivers/infiniband/sw/rxe/rxe.h | 6 ---- drivers/infiniband/sw/rxe/rxe_loc.h | 2 +- drivers/infiniband/sw/rxe/rxe_net.c | 21 ++------------ drivers/infiniband/sw/rxe/rxe_pool.c | 14 ++++++---- drivers/infiniband/sw/rxe/rxe_sysfs.c | 5 ++-- drivers/infiniband/sw/rxe/rxe_verbs.c | 17 ++---------- drivers/infiniband/sw/rxe/rxe_verbs.h | 2 -- 8 files changed, 24 insertions(+), 83 deletions(-) diff --git a/drivers/infiniband/sw/rxe/rxe.c b/drivers/infiniband/sw/rxe/rxe.c index 383e65c7bbc057..cd93c546c008cd 100644 --- a/drivers/infiniband/sw/rxe/rxe.c +++ b/drivers/infiniband/sw/rxe/rxe.c @@ -50,8 +50,10 @@ static void rxe_cleanup_ports(struct rxe_dev *rxe) /* free resources for a rxe device all objects created for this device must * have been destroyed */ -static void rxe_cleanup(struct rxe_dev *rxe) +void rxe_dealloc(struct ib_device *ib_dev) { + struct rxe_dev *rxe = container_of(ib_dev, struct rxe_dev, ib_dev); + rxe_pool_cleanup(&rxe->uc_pool); rxe_pool_cleanup(&rxe->pd_pool); rxe_pool_cleanup(&rxe->ah_pool); @@ -65,16 +67,10 @@ static void rxe_cleanup(struct rxe_dev *rxe) rxe_cleanup_ports(rxe); - crypto_free_shash(rxe->tfm); -} + if (rxe->tfm) + crypto_free_shash(rxe->tfm); -/* called when all references have been dropped */ -void rxe_release(struct kref *kref) -{ - struct rxe_dev *rxe = container_of(kref, struct rxe_dev, ref_cnt); - - rxe_cleanup(rxe); - ib_dealloc_device(&rxe->ib_dev); + list_del(&rxe->list); } /* initialize rxe device parameters */ @@ -312,31 +308,13 @@ int rxe_add(struct rxe_dev *rxe, unsigned int mtu) { int err; - kref_init(&rxe->ref_cnt); - err = rxe_init(rxe); if (err) - goto err1; + return err; rxe_set_mtu(rxe, mtu); - err = rxe_register_device(rxe); - if (err) - goto err1; - - return 0; - -err1: - rxe_dev_put(rxe); - return err; -} - -/* called by the ifc layer to remove a device */ -void rxe_remove(struct rxe_dev *rxe) -{ - rxe_unregister_device(rxe); - - rxe_dev_put(rxe); + return rxe_register_device(rxe); } static int __init rxe_module_init(void) @@ -360,7 +338,7 @@ static int __init rxe_module_init(void) static void __exit rxe_module_exit(void) { - rxe_remove_all(); + ib_unregister_driver(RDMA_DRIVER_RXE); rxe_net_exit(); rxe_cache_exit(); diff --git a/drivers/infiniband/sw/rxe/rxe.h b/drivers/infiniband/sw/rxe/rxe.h index 2b875875962f6e..ce4bf05cd85550 100644 --- a/drivers/infiniband/sw/rxe/rxe.h +++ b/drivers/infiniband/sw/rxe/rxe.h @@ -96,15 +96,9 @@ static inline u32 rxe_crc32(struct rxe_dev *rxe, void rxe_set_mtu(struct rxe_dev *rxe, unsigned int dev_mtu); int rxe_add(struct rxe_dev *rxe, unsigned int mtu); -void rxe_remove(struct rxe_dev *rxe); -void rxe_remove_all(void); void rxe_rcv(struct sk_buff *skb); -static inline void rxe_dev_put(struct rxe_dev *rxe) -{ - kref_put(&rxe->ref_cnt, rxe_release); -} struct rxe_dev *get_rxe_by_name(const char *name); /* The caller must do a matching ib_device_put(&dev->ib_dev) */ diff --git a/drivers/infiniband/sw/rxe/rxe_loc.h b/drivers/infiniband/sw/rxe/rxe_loc.h index b517a6c86922fc..3d8cef836f0dec 100644 --- a/drivers/infiniband/sw/rxe/rxe_loc.h +++ b/drivers/infiniband/sw/rxe/rxe_loc.h @@ -232,7 +232,7 @@ int rxe_srq_from_attr(struct rxe_dev *rxe, struct rxe_srq *srq, struct ib_srq_attr *attr, enum ib_srq_attr_mask mask, struct rxe_modify_srq_cmd *ucmd); -void rxe_release(struct kref *kref); +void rxe_dealloc(struct ib_device *ib_dev); int rxe_completer(void *arg); int rxe_requester(void *arg); diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c index 56878453f1aed8..d56a967ff90be2 100644 --- a/drivers/infiniband/sw/rxe/rxe_net.c +++ b/drivers/infiniband/sw/rxe/rxe_net.c @@ -559,21 +559,6 @@ struct rxe_dev *rxe_net_add(struct net_device *ndev) return rxe; } -void rxe_remove_all(void) -{ - spin_lock_bh(&dev_list_lock); - while (!list_empty(&rxe_dev_list)) { - struct rxe_dev *rxe = - list_first_entry(&rxe_dev_list, struct rxe_dev, list); - - list_del(&rxe->list); - spin_unlock_bh(&dev_list_lock); - rxe_remove(rxe); - spin_lock_bh(&dev_list_lock); - } - spin_unlock_bh(&dev_list_lock); -} - static void rxe_port_event(struct rxe_dev *rxe, enum ib_event_type event) { @@ -631,10 +616,8 @@ static int rxe_notify(struct notifier_block *not_blk, switch (event) { case NETDEV_UNREGISTER: - list_del(&rxe->list); - ib_device_put(&rxe->ib_dev); - rxe_remove(rxe); - return NOTIFY_OK; + ib_unregister_device_queued(&rxe->ib_dev); + break; case NETDEV_UP: rxe_port_up(rxe); break; diff --git a/drivers/infiniband/sw/rxe/rxe_pool.c b/drivers/infiniband/sw/rxe/rxe_pool.c index cd3f14629ba873..30470fb8c17a84 100644 --- a/drivers/infiniband/sw/rxe/rxe_pool.c +++ b/drivers/infiniband/sw/rxe/rxe_pool.c @@ -398,25 +398,27 @@ void *rxe_alloc(struct rxe_pool *pool) kref_get(&pool->ref_cnt); read_unlock_irqrestore(&pool->pool_lock, flags); - kref_get(&pool->rxe->ref_cnt); + if (!ib_device_try_get(&pool->rxe->ib_dev)) + goto out_put_pool; if (atomic_inc_return(&pool->num_elem) > pool->max_elem) - goto out_put_pool; + goto out_cnt; elem = kmem_cache_zalloc(pool_cache(pool), (pool->flags & RXE_POOL_ATOMIC) ? GFP_ATOMIC : GFP_KERNEL); if (!elem) - goto out_put_pool; + goto out_cnt; elem->pool = pool; kref_init(&elem->ref_cnt); return elem; -out_put_pool: +out_cnt: atomic_dec(&pool->num_elem); - rxe_dev_put(pool->rxe); + ib_device_put(&pool->rxe->ib_dev); +out_put_pool: rxe_pool_put(pool); return NULL; } @@ -464,7 +466,7 @@ void rxe_elem_release(struct kref *kref) if (!(pool->flags & RXE_POOL_NO_ALLOC)) kmem_cache_free(pool_cache(pool), elem); atomic_dec(&pool->num_elem); - rxe_dev_put(pool->rxe); + ib_device_put(&pool->rxe->ib_dev); rxe_pool_put(pool); } diff --git a/drivers/infiniband/sw/rxe/rxe_sysfs.c b/drivers/infiniband/sw/rxe/rxe_sysfs.c index 6802be71bf9b20..c8630638cd57ad 100644 --- a/drivers/infiniband/sw/rxe/rxe_sysfs.c +++ b/drivers/infiniband/sw/rxe/rxe_sysfs.c @@ -111,7 +111,7 @@ static int rxe_param_set_remove(const char *val, const struct kernel_param *kp) if (strncmp("all", intf, len) == 0) { pr_info("rxe_sys: remove all"); - rxe_remove_all(); + ib_unregister_driver(RDMA_DRIVER_RXE); return 0; } @@ -122,8 +122,7 @@ static int rxe_param_set_remove(const char *val, const struct kernel_param *kp) return -EINVAL; } - list_del(&rxe->list); - rxe_remove(rxe); + ib_unregister_device(&rxe->ib_dev); return 0; } diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c index de96c18f09968b..c7b7a59c0b2048 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.c +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c @@ -1133,6 +1133,7 @@ static const struct ib_device_ops rxe_dev_ops = { .create_cq = rxe_create_cq, .create_qp = rxe_create_qp, .create_srq = rxe_create_srq, + .dealloc_driver = rxe_dealloc, .dealloc_pd = rxe_dealloc_pd, .dealloc_ucontext = rxe_dealloc_ucontext, .dereg_mr = rxe_dereg_mr, @@ -1239,22 +1240,8 @@ int rxe_register_device(struct rxe_dev *rxe) rdma_set_device_sysfs_group(dev, &rxe_attr_group); dev->driver_id = RDMA_DRIVER_RXE; err = ib_register_device(dev, "rxe%d"); - if (err) { + if (err) pr_warn("%s failed with error %d\n", __func__, err); - goto err1; - } - - return 0; - -err1: - crypto_free_shash(rxe->tfm); return err; } - -void rxe_unregister_device(struct rxe_dev *rxe) -{ - struct ib_device *dev = &rxe->ib_dev; - - ib_unregister_device(dev); -} diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h index 70839d3f55d941..ad5574d8e8ba77 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.h +++ b/drivers/infiniband/sw/rxe/rxe_verbs.h @@ -385,7 +385,6 @@ struct rxe_dev { struct ib_device_attr attr; int max_ucontext; int max_inline_data; - struct kref ref_cnt; struct mutex usdev_lock; struct net_device *ndev; @@ -467,7 +466,6 @@ static inline struct rxe_mem *to_rmw(struct ib_mw *mw) } int rxe_register_device(struct rxe_dev *rxe); -void rxe_unregister_device(struct rxe_dev *rxe); void rxe_mc_cleanup(struct rxe_pool_entry *arg); From patchwork Wed Feb 13 04:12:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 10809111 X-Patchwork-Delegate: jgg@ziepe.ca 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 E1B781390 for ; Wed, 13 Feb 2019 04:13:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C8EF42BFAF for ; Wed, 13 Feb 2019 04:13:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BD1342C06B; Wed, 13 Feb 2019 04:13:08 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 2EBE12BFE1 for ; Wed, 13 Feb 2019 04:13:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726902AbfBMENH (ORCPT ); Tue, 12 Feb 2019 23:13:07 -0500 Received: from mail-pl1-f193.google.com ([209.85.214.193]:35799 "EHLO mail-pl1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730431AbfBMENF (ORCPT ); Tue, 12 Feb 2019 23:13:05 -0500 Received: by mail-pl1-f193.google.com with SMTP id p8so549316plo.2 for ; Tue, 12 Feb 2019 20:13:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ziepe.ca; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=DhkZYOB0dd3ZnD0POvbXl6eCxkekf5bzjMa0QEm8y9U=; b=jgCbVjpfYysnT8Ciw/a2VLi4Q5nMpR/3sWsvkn1aswcuesdIfauHlHzquO6McWVfsw iipebmqvm92DMAAddUy13Gjw9DJKZpZzuxNeGSmrt22XULfaxDjWDErsRyBrF8AkZqDB ufmUcY5JOE7gK+uSQsKTO5PjoGVCPkQ0sT8rcWNrYk7c4Iv5JdewOnNPsdNMHCRM3tav l5rtn9MtIcCYN6otbsiZwjVqwe9ZUh9ecU0ab8MG90ye1Eo+29lJsI+AvH64XCLBHv1c KZtDX44+vvfUvued7injo/Nr+2CBQbq8oYViPUOmdN78qFBJQ6c9Azvpru2J6u8Gb+xe XDiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=DhkZYOB0dd3ZnD0POvbXl6eCxkekf5bzjMa0QEm8y9U=; b=BhK0XftjGRWWPQh0Ep7U8BdwH7BiNAUe3hC1KtR/fzR+cKUJjmDP6VoLvXTEyqC4ld 5x6G45TLJxSI8jMcAlo5yQ3td7wSE0c9tDaaMLxhIzuBmr4QVo7/xfExfhM/KbBEHCuo 2GEY0fvHtnidOaSCCXYeLP1a+pwfIzTGhYkoMBHT8vhRaE5d6tDVczKiHJu6sKHMPHo6 u4CQiFT+v67W/RxxYnldGaPN8qRMvNL7ewcIRBvSZU98kouJ4GntiptT29tEm28hr35i ptqEGmqPStRPm1KLsyO89/Rra+Tof8UpVs0R1WZZb9g7GIHs/vLcOwPYhZzeZGbcwK38 q7rw== X-Gm-Message-State: AHQUAuYl5tnVustP/MSJnx7Sq0NB8rZBweGThWz4nLMYyfFir1HE+9et A050IlM3ltuQlLfEeQ+6NcomKDAF130= X-Google-Smtp-Source: AHgI3IYsk8ENAuJMRh3jt2JVko5hyfNC5svtybhsUvo1kdO8EkSsUzZ6o50By0xjpyd2KzrHb2zuYw== X-Received: by 2002:a17:902:f096:: with SMTP id go22mr1280291plb.23.1550031184826; Tue, 12 Feb 2019 20:13:04 -0800 (PST) Received: from ziepe.ca (S010614cc2056d97f.ed.shawcable.net. [174.3.196.123]) by smtp.gmail.com with ESMTPSA id z62sm25877252pfi.4.2019.02.12.20.13.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 12 Feb 2019 20:13:03 -0800 (PST) Received: from jgg by mlx.ziepe.ca with local (Exim 4.90_1) (envelope-from ) id 1gtluu-0005sm-4c; Tue, 12 Feb 2019 21:13:00 -0700 From: Jason Gunthorpe To: linux-rdma@vger.kernel.org Cc: Jason Gunthorpe Subject: [PATCH 09/10] RDMA/rxe: Add ib_device_get_by_name() and use it in rxe Date: Tue, 12 Feb 2019 21:12:55 -0700 Message-Id: <20190213041256.22437-10-jgg@ziepe.ca> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190213041256.22437-1-jgg@ziepe.ca> References: <20190213041256.22437-1-jgg@ziepe.ca> MIME-Version: 1.0 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: Jason Gunthorpe rxe has an open coded version of this that is not as safe as the core version. This lets us eliminate the internal device list entirely from rxe. Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/device.c | 28 +++++++++++++++++++++++++++ drivers/infiniband/sw/rxe/rxe.c | 3 --- drivers/infiniband/sw/rxe/rxe.h | 2 -- drivers/infiniband/sw/rxe/rxe_net.c | 22 --------------------- drivers/infiniband/sw/rxe/rxe_sysfs.c | 9 ++++----- drivers/infiniband/sw/rxe/rxe_verbs.h | 1 - 6 files changed, 32 insertions(+), 33 deletions(-) diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index f6c755b675a86a..c8cacc19625708 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -239,6 +239,34 @@ static struct ib_device *__ib_device_get_by_name(const char *name) return NULL; } +/** + * ib_device_get_by_name - Find an IB device by name + * @name: The name to look for + * @driver_id: The driver ID that must match (RDMA_DRIVER_UNKNOWN matches all) + * + * Find and hold an ib_device by its name. The caller must call + * ib_device_put() on the returned pointer. + */ +struct ib_device *ib_device_get_by_name(const char *name, + enum rdma_driver_id driver_id) +{ + struct ib_device *device; + + down_read(&devices_rwsem); + device = __ib_device_get_by_name(name); + if (device && driver_id != RDMA_DRIVER_UNKNOWN && + device->driver_id != driver_id) + device = NULL; + + if (device) { + if (!ib_device_try_get(device)) + device = NULL; + } + up_read(&devices_rwsem); + return device; +} +EXPORT_SYMBOL(ib_device_get_by_name); + int ib_device_rename(struct ib_device *ibdev, const char *name) { int ret; diff --git a/drivers/infiniband/sw/rxe/rxe.c b/drivers/infiniband/sw/rxe/rxe.c index cd93c546c008cd..08a45ce9cab551 100644 --- a/drivers/infiniband/sw/rxe/rxe.c +++ b/drivers/infiniband/sw/rxe/rxe.c @@ -69,8 +69,6 @@ void rxe_dealloc(struct ib_device *ib_dev) if (rxe->tfm) crypto_free_shash(rxe->tfm); - - list_del(&rxe->list); } /* initialize rxe device parameters */ @@ -275,7 +273,6 @@ static int rxe_init(struct rxe_dev *rxe) spin_lock_init(&rxe->mmap_offset_lock); spin_lock_init(&rxe->pending_lock); INIT_LIST_HEAD(&rxe->pending_mmaps); - INIT_LIST_HEAD(&rxe->list); mutex_init(&rxe->usdev_lock); diff --git a/drivers/infiniband/sw/rxe/rxe.h b/drivers/infiniband/sw/rxe/rxe.h index ce4bf05cd85550..63b3b89b894a2e 100644 --- a/drivers/infiniband/sw/rxe/rxe.h +++ b/drivers/infiniband/sw/rxe/rxe.h @@ -99,8 +99,6 @@ int rxe_add(struct rxe_dev *rxe, unsigned int mtu); void rxe_rcv(struct sk_buff *skb); -struct rxe_dev *get_rxe_by_name(const char *name); - /* The caller must do a matching ib_device_put(&dev->ib_dev) */ static inline struct rxe_dev *rxe_get_dev_from_net(struct net_device *ndev) { diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c index d56a967ff90be2..d6dfbcf6a47e7b 100644 --- a/drivers/infiniband/sw/rxe/rxe_net.c +++ b/drivers/infiniband/sw/rxe/rxe_net.c @@ -45,25 +45,6 @@ #include "rxe_net.h" #include "rxe_loc.h" -static LIST_HEAD(rxe_dev_list); -static DEFINE_SPINLOCK(dev_list_lock); /* spinlock for device list */ - -struct rxe_dev *get_rxe_by_name(const char *name) -{ - struct rxe_dev *rxe; - struct rxe_dev *found = NULL; - - spin_lock_bh(&dev_list_lock); - list_for_each_entry(rxe, &rxe_dev_list, list) { - if (!strcmp(name, dev_name(&rxe->ib_dev.dev))) { - found = rxe; - break; - } - } - spin_unlock_bh(&dev_list_lock); - return found; -} - static struct rxe_recv_sockets recv_sockets; struct device *rxe_dma_device(struct rxe_dev *rxe) @@ -553,9 +534,6 @@ struct rxe_dev *rxe_net_add(struct net_device *ndev) return NULL; } - spin_lock_bh(&dev_list_lock); - list_add_tail(&rxe->list, &rxe_dev_list); - spin_unlock_bh(&dev_list_lock); return rxe; } diff --git a/drivers/infiniband/sw/rxe/rxe_sysfs.c b/drivers/infiniband/sw/rxe/rxe_sysfs.c index c8630638cd57ad..d51b55b0a311c5 100644 --- a/drivers/infiniband/sw/rxe/rxe_sysfs.c +++ b/drivers/infiniband/sw/rxe/rxe_sysfs.c @@ -101,7 +101,7 @@ static int rxe_param_set_remove(const char *val, const struct kernel_param *kp) { int len; char intf[32]; - struct rxe_dev *rxe; + struct ib_device *ib_dev; len = sanitize_arg(val, intf, sizeof(intf)); if (!len) { @@ -115,14 +115,13 @@ static int rxe_param_set_remove(const char *val, const struct kernel_param *kp) return 0; } - rxe = get_rxe_by_name(intf); - - if (!rxe) { + ib_dev = ib_device_get_by_name(intf, RDMA_DRIVER_RXE); + if (!ib_dev) { pr_err("not configured on %s\n", intf); return -EINVAL; } - ib_unregister_device(&rxe->ib_dev); + ib_unregister_device_and_put(ib_dev); return 0; } diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h index ad5574d8e8ba77..a22822526a62c6 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.h +++ b/drivers/infiniband/sw/rxe/rxe_verbs.h @@ -411,7 +411,6 @@ struct rxe_dev { atomic64_t stats_counters[RXE_NUM_OF_COUNTERS]; struct rxe_port port; - struct list_head list; struct crypto_shash *tfm; }; From patchwork Wed Feb 13 04:12:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 10809113 X-Patchwork-Delegate: jgg@ziepe.ca 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 DC98F1399 for ; Wed, 13 Feb 2019 04:13:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CA1AE2BFAF for ; Wed, 13 Feb 2019 04:13:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BE4D72C06B; Wed, 13 Feb 2019 04:13:09 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 3973E2BFAF for ; Wed, 13 Feb 2019 04:13:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730431AbfBMENI (ORCPT ); Tue, 12 Feb 2019 23:13:08 -0500 Received: from mail-pg1-f193.google.com ([209.85.215.193]:33879 "EHLO mail-pg1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730653AbfBMENG (ORCPT ); Tue, 12 Feb 2019 23:13:06 -0500 Received: by mail-pg1-f193.google.com with SMTP id i130so538814pgd.1 for ; Tue, 12 Feb 2019 20:13:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ziepe.ca; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9sM9lBb+MtiMI4FchVNo7/dMfEYmSMDOjs28zdeCPKk=; b=l/KKdd5mR+BcF7sSS7SA6wFQngKHJhk/fC+vUeQLWcm+ex4eg2iDyb1ighQNEccBtF 7MBhqxL4Km9ENeXZLy/Paz6l4zfEIyyJig1JlRQ9GisJFekfzXIzWaGv6Al30euKsbtJ WKHG2ss4Qx5MG+ynNNIAvZjqD0XLeCv4yKf7Omt1Vk/FayM3b0IpMztzu5T33DS1D6cr cjJX5vp2nN+V4qzejVEHqoLp3vKQKN5LDxadmcmElfSWb01iKLuNTm97hG89GVEZnPD9 /x1msPUh1APO1VAcs2UUpb8S2MkI+yQOuHkf0osHDatPDo60A9bLmaBdgGzZE85aROXF 8AVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9sM9lBb+MtiMI4FchVNo7/dMfEYmSMDOjs28zdeCPKk=; b=biYRzVvdaAcYdSUveioyIQVLqq3rtFU4Hg89rwrlQIvBhJ9yFGJLjWEbVgQDthOddb hmIGfke89rrA1hyWYGa63Z+A+j91gRnoGQzLB1glkHDNsToi9A0tpRH3DCzGEYaBPfgS 23xMRnHTxeBOapn1QV7aTCYdkJUWePuZnQkSumV+nyBzAwlKexZTASzMR+L5dILf7eQQ FSff0njVQ+YY3WUjrwyqPosLkfQGPOnXs/0FpbaSjwP/sD8ckdMUIKdyRlh8PDVqBRAc A+7VUDwvfx4f6A9bYvkTsoRRDNx6zgqjsrbOVLIdtbsG+rGPJQen2qtJmgWg+CMeJKby UpRQ== X-Gm-Message-State: AHQUAuZ5puyunfQ23MJkEPjtskZ7Ye/NBysEm64sQHbI+Li+vgbc7uYG U8GbACQM08tBXf+YRTwrEr69luHtryg= X-Google-Smtp-Source: AHgI3IYmEpcchvw40Rzt+kAH7S95JXTyelxzaK2dHjpo2S4sphBTE8xQrHH6nmTazJ/tgs4qjd6wCw== X-Received: by 2002:a65:6219:: with SMTP id d25mr7021664pgv.18.1550031185279; Tue, 12 Feb 2019 20:13:05 -0800 (PST) Received: from ziepe.ca (S010614cc2056d97f.ed.shawcable.net. [174.3.196.123]) by smtp.gmail.com with ESMTPSA id d13sm23908374pfd.58.2019.02.12.20.13.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 12 Feb 2019 20:13:03 -0800 (PST) Received: from jgg by mlx.ziepe.ca with local (Exim 4.90_1) (envelope-from ) id 1gtluu-0005ss-6m; Tue, 12 Feb 2019 21:13:00 -0700 From: Jason Gunthorpe To: linux-rdma@vger.kernel.org Cc: Jason Gunthorpe Subject: [PATCH 10/10] RDMA/rxe: Close a race after ib_register_device Date: Tue, 12 Feb 2019 21:12:56 -0700 Message-Id: <20190213041256.22437-11-jgg@ziepe.ca> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190213041256.22437-1-jgg@ziepe.ca> References: <20190213041256.22437-1-jgg@ziepe.ca> MIME-Version: 1.0 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: Jason Gunthorpe Since rxe allows unregistration from other threads the rxe pointer can become invalid any moment after ib_register_driver returns. This could cause a user triggered use after free. Add another driver callback to be called right after the device becomes registered to complete any device setup required post-registration. This callback has enough core locking to prevent the device from becoming unregistered. Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/device.c | 7 +++++++ drivers/infiniband/sw/rxe/rxe_net.c | 8 ++++---- drivers/infiniband/sw/rxe/rxe_net.h | 2 +- drivers/infiniband/sw/rxe/rxe_sysfs.c | 9 ++------- drivers/infiniband/sw/rxe/rxe_verbs.c | 14 ++++++++++++++ include/rdma/ib_verbs.h | 5 +++++ 6 files changed, 33 insertions(+), 12 deletions(-) diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index c8cacc19625708..e3f41557188b0f 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -796,6 +796,12 @@ static int enable_device_and_get(struct ib_device *device) */ downgrade_write(&devices_rwsem); + if (device->ops.enable_driver) { + ret = device->ops.enable_driver(device); + if (ret) + return ret; + } + down_read(&clients_rwsem); xa_for_each_marked (&clients, index, client, CLIENT_REGISTERED) { ret = add_client_context(device, client); @@ -1761,6 +1767,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops) SET_DEVICE_OP(dev_ops, disassociate_ucontext); SET_DEVICE_OP(dev_ops, drain_rq); SET_DEVICE_OP(dev_ops, drain_sq); + SET_DEVICE_OP(dev_ops, enable_driver); SET_DEVICE_OP(dev_ops, fill_res_entry); SET_DEVICE_OP(dev_ops, get_dev_fw_str); SET_DEVICE_OP(dev_ops, get_dma_mr); diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c index d6dfbcf6a47e7b..fb792f5bc0b7d4 100644 --- a/drivers/infiniband/sw/rxe/rxe_net.c +++ b/drivers/infiniband/sw/rxe/rxe_net.c @@ -517,24 +517,24 @@ enum rdma_link_layer rxe_link_layer(struct rxe_dev *rxe, unsigned int port_num) return IB_LINK_LAYER_ETHERNET; } -struct rxe_dev *rxe_net_add(struct net_device *ndev) +int rxe_net_add(struct net_device *ndev) { int err; struct rxe_dev *rxe = NULL; rxe = ib_alloc_device(rxe_dev, ib_dev); if (!rxe) - return NULL; + return -ENOMEM; rxe->ndev = ndev; err = rxe_add(rxe, ndev->mtu); if (err) { ib_dealloc_device(&rxe->ib_dev); - return NULL; + return err; } - return rxe; + return 0; } static void rxe_port_event(struct rxe_dev *rxe, diff --git a/drivers/infiniband/sw/rxe/rxe_net.h b/drivers/infiniband/sw/rxe/rxe_net.h index 106c586dbb2683..ad79514191bb9d 100644 --- a/drivers/infiniband/sw/rxe/rxe_net.h +++ b/drivers/infiniband/sw/rxe/rxe_net.h @@ -43,7 +43,7 @@ struct rxe_recv_sockets { struct socket *sk6; }; -struct rxe_dev *rxe_net_add(struct net_device *ndev); +int rxe_net_add(struct net_device *ndev); int rxe_net_init(void); void rxe_net_exit(void); diff --git a/drivers/infiniband/sw/rxe/rxe_sysfs.c b/drivers/infiniband/sw/rxe/rxe_sysfs.c index d51b55b0a311c5..46587eb0da0e63 100644 --- a/drivers/infiniband/sw/rxe/rxe_sysfs.c +++ b/drivers/infiniband/sw/rxe/rxe_sysfs.c @@ -60,7 +60,6 @@ static int rxe_param_set_add(const char *val, const struct kernel_param *kp) char intf[32]; struct net_device *ndev; struct rxe_dev *exists; - struct rxe_dev *rxe; len = sanitize_arg(val, intf, sizeof(intf)); if (!len) { @@ -82,16 +81,12 @@ static int rxe_param_set_add(const char *val, const struct kernel_param *kp) goto err; } - rxe = rxe_net_add(ndev); - if (!rxe) { + err = rxe_net_add(ndev); + if (err) { pr_err("failed to add %s\n", intf); - err = -EINVAL; goto err; } - rxe_set_port_state(rxe); - dev_info(&rxe->ib_dev.dev, "added %s\n", intf); - err: dev_put(ndev); return err; diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c index c7b7a59c0b2048..2834e16e704747 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.c +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c @@ -1123,6 +1123,15 @@ static const struct attribute_group rxe_attr_group = { .attrs = rxe_dev_attributes, }; +static int rxe_enable_driver(struct ib_device *ib_dev) +{ + struct rxe_dev *rxe = container_of(ib_dev, struct rxe_dev, ib_dev); + + rxe_set_port_state(rxe); + dev_info(&rxe->ib_dev.dev, "added %s\n", netdev_name(rxe->ndev)); + return 0; +} + static const struct ib_device_ops rxe_dev_ops = { .alloc_hw_stats = rxe_ib_alloc_hw_stats, .alloc_mr = rxe_alloc_mr, @@ -1142,6 +1151,7 @@ static const struct ib_device_ops rxe_dev_ops = { .destroy_qp = rxe_destroy_qp, .destroy_srq = rxe_destroy_srq, .detach_mcast = rxe_detach_mcast, + .enable_driver = rxe_enable_driver, .get_dma_mr = rxe_get_dma_mr, .get_hw_stats = rxe_ib_get_hw_stats, .get_link_layer = rxe_get_link_layer, @@ -1243,5 +1253,9 @@ int rxe_register_device(struct rxe_dev *rxe) if (err) pr_warn("%s failed with error %d\n", __func__, err); + /* + * Note that rxe may be invalid at this point if another thread + * unregistered it. + */ return err; } diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 282d2903e6d3cf..cde26abd16bb35 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -2539,6 +2539,11 @@ struct ib_device_ops { struct rdma_restrack_entry *entry); /* Device lifecycle callbacks */ + /* + * Called after the device becomes registered, before clients are + * attached + */ + int (*enable_driver)(struct ib_device *dev); /* * This is called as part of ib_dealloc_device(). */