Date: Wed, 24 Jun 2026 19:51:21 +0000 From: John Baldwin <jhb@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 4726b80d9379 - main - OFED: Various changes from Linux 4.20 Message-ID: <6a3c3539.452a4.3b65f13f@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=4726b80d9379cdefd00ae77d0b91973bde573790 commit 4726b80d9379cdefd00ae77d0b91973bde573790 Author: John Baldwin <jhb@FreeBSD.org> AuthorDate: 2026-06-24 19:30:56 +0000 Commit: John Baldwin <jhb@FreeBSD.org> CommitDate: 2026-06-24 19:30:56 +0000 OFED: Various changes from Linux 4.20 This contains changes from the following Linux commits: 627212c9d49b RDMA/core: Replace open-coded variant of get_device adee9f3f3bbb RDMA/core: Depend on device_add() to add device attributes 954a8e3aea87 RDMA/cma: Protect cma dev list with lock 722c7b2bfead RDMA/{cma, core}: Avoid callback on rdma_addr_cancel() f9d08f1e1939 RDMA/core: Rate limit MAD error messages e1f540c3ed0e RDMA/core: Define client_data_lock as rwlock instead of spinlock 2d65f49ff961 RDMA/core: Use simpler spin lock irq API from blocking context 4512acd0d34c RDMA/core: Remove context entries from list while unregistering device f7b65d9bf2db RDMA/core: Use simplified list_for_each 93688ddbe1da RDMA/core: No need to protect kfree with spin lock and semaphore 50704e039ab1 RDMA/umem: Restore lockdep check while downgrading lock eb93c82ed8c7 RDMA/core: Document QP @event_handler function 4269024639f6 RDMA/core: Document CM @event_handler function 77addc524473 RDMA/core: Rename rdma_copy_addr to rdma_copy_src_l2_addr a362ea1d9e1a RDMA/core: Introduce and use rdma_set_src_addr() between IPv4 and IPv6 89c5691cdd95 RDMA/core: Let protocol specific function typecast sockaddr structure caf1e3ae9fa6 RDMA/core Introduce and use rdma_find_ndev_for_src_ip_rcu c31d4b2ddf07 RDMA/core: Protect against changing dst->dev during destination resolve 0e9d2c19bff1 RDMA/core: Consider net ns of gid attribute for RoCE d6b1764a8c5a RDMA/core: Introduce rdma_read_gid_attr_ndev_rcu() to check GID attribute 6aaecd385685 RDMA/core: Simplify roce_resolve_route_from_path() 0965cc953a23 RDMA/core: Properly return the error code of rdma_set_src_addr_rcu d4b4dd1b9706 RDMA/umem: Do not use current->tgid to track the mm_struct c9990ab39b6e RDMA/umem: Move all the ODP related stuff out of ucontext and into per_mm 597ecc5a0954 RDMA/umem: Get rid of struct ib_umem.odp_data 41b4deeaa123 RDMA/umem: Make ib_umem_odp into a sub structure of ib_umem b5231b019d76 RDMA/umem: Use ib_umem_odp in all function signatures connected to ODP 56ac9dd9177c RDMA/umem: Avoid synchronize_srcu in the ODP MR destruction path be7a57b41ad8 RDMA/umem: Handle a half-complete start/end sequence ca748c39ea3f RDMA/umem: Get rid of per_mm->notifier_count f27a0d50a4bc RDMA/umem: Use umem->owning_mm inside ODP Tested by: Wafa Hamzah <wafah@nvidia.com> (mlx5_ib) Tested by: John Baldwin <jhb@FreeBSD.org> (iw_cxgbe) Sponsored by: Chelsio Communications --- sys/ofed/drivers/infiniband/core/core_priv.h | 10 +- sys/ofed/drivers/infiniband/core/ib_addr.c | 307 +++++++---- sys/ofed/drivers/infiniband/core/ib_cache.c | 33 ++ sys/ofed/drivers/infiniband/core/ib_cma.c | 27 +- sys/ofed/drivers/infiniband/core/ib_device.c | 51 +- sys/ofed/drivers/infiniband/core/ib_mad.c | 72 +-- sys/ofed/drivers/infiniband/core/ib_sa_query.c | 36 -- sys/ofed/drivers/infiniband/core/ib_sysfs.c | 65 ++- sys/ofed/drivers/infiniband/core/ib_umem.c | 100 ++-- sys/ofed/drivers/infiniband/core/ib_umem_odp.c | 619 +++++++++++------------ sys/ofed/drivers/infiniband/core/ib_uverbs_cmd.c | 8 + sys/ofed/drivers/infiniband/core/ib_verbs.c | 2 +- sys/ofed/include/rdma/ib_addr.h | 7 +- sys/ofed/include/rdma/ib_umem.h | 9 +- sys/ofed/include/rdma/ib_umem_odp.h | 75 +-- sys/ofed/include/rdma/ib_verbs.h | 17 +- sys/ofed/include/rdma/rdma_cm.h | 6 +- 17 files changed, 776 insertions(+), 668 deletions(-) diff --git a/sys/ofed/drivers/infiniband/core/core_priv.h b/sys/ofed/drivers/infiniband/core/core_priv.h index 198dac54cdf0..db0a7a0046b8 100644 --- a/sys/ofed/drivers/infiniband/core/core_priv.h +++ b/sys/ofed/drivers/infiniband/core/core_priv.h @@ -190,8 +190,16 @@ int rdma_resolve_ip_route(struct sockaddr *src_addr, int rdma_addr_find_l2_eth_by_grh(const union ib_gid *sgid, const union ib_gid *dgid, - u8 *dmac, if_t ndev, + u8 *dmac, const struct ib_gid_attr *sgid_attr, int *hoplimit); +void rdma_copy_src_l2_addr(struct rdma_dev_addr *dev_addr, + const if_t dev); + +struct sa_path_rec; +int roce_resolve_route_from_path(struct sa_path_rec *rec, + const struct ib_gid_attr *attr); + +if_t rdma_read_gid_attr_ndev_rcu(const struct ib_gid_attr *attr); struct rdma_umap_priv { struct vm_area_struct *vma; diff --git a/sys/ofed/drivers/infiniband/core/ib_addr.c b/sys/ofed/drivers/infiniband/core/ib_addr.c index 1810230c34f5..87370f4aba99 100644 --- a/sys/ofed/drivers/infiniband/core/ib_addr.c +++ b/sys/ofed/drivers/infiniband/core/ib_addr.c @@ -45,6 +45,7 @@ #include <net/route/nhop.h> #include <net/netevent.h> #include <rdma/ib_addr.h> +#include <rdma/ib_sa.h> #include <rdma/ib.h> #include <netinet/in_fib.h> @@ -66,6 +67,7 @@ struct addr_req { struct rdma_dev_addr *addr, void *context); unsigned long timeout; struct delayed_work work; + bool resolve_by_gid_attr; /* Consider gid attr in resolve phase */ int status; }; @@ -113,9 +115,17 @@ rdma_copy_addr_sub(u8 *dst, const u8 *src, unsigned min, unsigned max) memset(dst + min, 0, max - min); } -void rdma_copy_addr(struct rdma_dev_addr *dev_addr, - const if_t dev, - const unsigned char *dst_dev_addr) +/** + * rdma_copy_src_l2_addr - Copy netdevice source addresses + * @dev_addr: Destination address pointer where to copy the addresses + * @dev: Netdevice whose source addresses to copy + * + * rdma_copy_src_l2_addr() copies source addresses from the specified netdevice. + * This includes unicast address, broadcast address, device type and + * interface index. + */ +void rdma_copy_src_l2_addr(struct rdma_dev_addr *dev_addr, + const if_t dev) { int dev_type = if_gettype(dev); @@ -137,50 +147,61 @@ void rdma_copy_addr(struct rdma_dev_addr *dev_addr, if_getaddrlen(dev), MAX_ADDR_LEN); rdma_copy_addr_sub(dev_addr->broadcast, if_getbroadcastaddr(dev), if_getaddrlen(dev), MAX_ADDR_LEN); - if (dst_dev_addr != NULL) { - rdma_copy_addr_sub(dev_addr->dst_dev_addr, dst_dev_addr, - if_getaddrlen(dev), MAX_ADDR_LEN); - } dev_addr->bound_dev_if = if_getindex(dev); } -EXPORT_SYMBOL(rdma_copy_addr); +EXPORT_SYMBOL(rdma_copy_src_l2_addr); -int rdma_translate_ip(const struct sockaddr *addr, - struct rdma_dev_addr *dev_addr) +static if_t +rdma_find_ndev_for_src_ip_rcu(struct vnet *net, const struct sockaddr *src_in) { - if_t dev; - int ret = 0; + if_t dev = NULL; + int ret = -EADDRNOTAVAIL; - if (dev_addr->bound_dev_if) { - dev = dev_get_by_index(dev_addr->net, dev_addr->bound_dev_if); - } else switch (addr->sa_family) { + switch (src_in->sa_family) { #ifdef INET case AF_INET: - dev = ip_ifp_find(dev_addr->net, - ((const struct sockaddr_in *)addr)->sin_addr.s_addr); + dev = ip_ifp_find(net, + ((const struct sockaddr_in *)src_in)->sin_addr.s_addr); + if (dev) + ret = 0; break; #endif #ifdef INET6 case AF_INET6: - dev = ip6_ifp_find(dev_addr->net, - ((const struct sockaddr_in6 *)addr)->sin6_addr, 0); + dev = ip6_ifp_find(net, + ((const struct sockaddr_in6 *)src_in)->sin6_addr, 0); + if (dev) + ret = 0; break; #endif - default: - dev = NULL; - break; } + return ret ? ERR_PTR(ret) : dev; +} - if (dev != NULL) { - /* disallow connections through 127.0.0.1 itself */ - if (if_getflags(dev) & IFF_LOOPBACK) - ret = -EINVAL; - else - rdma_copy_addr(dev_addr, dev, NULL); - dev_put(dev); +int rdma_translate_ip(const struct sockaddr *addr, + struct rdma_dev_addr *dev_addr) +{ + if_t dev; + int ret = 0; + + if (dev_addr->bound_dev_if) { + dev = dev_get_by_index(dev_addr->net, dev_addr->bound_dev_if); + if (!dev) + return -ENODEV; } else { - ret = -ENODEV; + rcu_read_lock(); + dev = rdma_find_ndev_for_src_ip_rcu(dev_addr->net, addr); + rcu_read_unlock(); + if (IS_ERR(dev)) + return PTR_ERR(dev); } + + /* disallow connections through 127.0.0.1 itself */ + if (if_getflags(dev) & IFF_LOOPBACK) + ret = -EINVAL; + else + rdma_copy_src_l2_addr(dev_addr, dev); + dev_put(dev); return ret; } EXPORT_SYMBOL(rdma_translate_ip); @@ -226,12 +247,15 @@ static int addr_resolve_multi(u8 *edst, if_t ifp, struct sockaddr *dst_in) #endif #ifdef INET -static int addr4_resolve(struct sockaddr_in *src_in, - const struct sockaddr_in *dst_in, +static int addr4_resolve(struct sockaddr *src_sock, + const struct sockaddr *dst_sock, struct rdma_dev_addr *addr, u8 *edst, if_t *ifpp) { + struct sockaddr_in *src_in = (struct sockaddr_in *)src_sock; + const struct sockaddr_in *dst_in = + (const struct sockaddr_in *)dst_sock; enum { ADDR_VALID = 0, ADDR_SRC_ANY = 1, @@ -398,8 +422,8 @@ done: return (-error); } #else -static int addr4_resolve(struct sockaddr_in *src_in, - const struct sockaddr_in *dst_in, +static int addr4_resolve(struct sockaddr *src_sock, + const struct sockaddr *dst_sock, struct rdma_dev_addr *addr, u8 *edst, if_t *ifpp) @@ -409,12 +433,15 @@ static int addr4_resolve(struct sockaddr_in *src_in, #endif #ifdef INET6 -static int addr6_resolve(struct sockaddr_in6 *src_in, - const struct sockaddr_in6 *dst_in, +static int addr6_resolve(struct sockaddr *src_sock, + const struct sockaddr *dst_sock, struct rdma_dev_addr *addr, u8 *edst, if_t *ifpp) { + struct sockaddr_in6 *src_in = (struct sockaddr_in6 *)src_sock; + const struct sockaddr_in6 *dst_in = + (const struct sockaddr_in6 *)dst_sock; enum { ADDR_VALID = 0, ADDR_SRC_ANY = 1, @@ -586,8 +613,8 @@ done: return (-error); } #else -static int addr6_resolve(struct sockaddr_in6 *src_in, - const struct sockaddr_in6 *dst_in, +static int addr6_resolve(struct sockaddr *src_sock, + const struct sockaddr *dst_sock, struct rdma_dev_addr *addr, u8 *edst, if_t *ifpp) @@ -599,11 +626,12 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, static int addr_resolve_neigh(if_t dev, const struct sockaddr *dst_in, u8 *edst, - struct rdma_dev_addr *addr) + struct rdma_dev_addr *addr, + unsigned int ndev_flags) { - if (if_getflags(dev) & IFF_LOOPBACK) { - int ret; + int ret = 0; + if (ndev_flags & IFF_LOOPBACK) { /* * Binding to a loopback device is not allowed. Make * sure the destination device address is global by @@ -612,66 +640,143 @@ static int addr_resolve_neigh(if_t dev, if (addr->bound_dev_if == if_getindex(dev)) addr->bound_dev_if = 0; - ret = rdma_translate_ip(dst_in, addr); - if (ret == 0) { - memcpy(addr->dst_dev_addr, addr->src_dev_addr, - MAX_ADDR_LEN); + memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN); + } else { + if (!(ndev_flags & IFF_NOARP)) { + /* If the device doesn't do ARP internally */ + memcpy(addr->dst_dev_addr, edst, MAX_ADDR_LEN); } - return ret; + } + + return ret; +} + +static int copy_src_l2_addr(struct rdma_dev_addr *dev_addr, + const struct sockaddr *dst_in, + if_t ndev) +{ + int ret = 0; + + if (if_getflags(ndev) & IFF_LOOPBACK) + ret = rdma_translate_ip(dst_in, dev_addr); + else + rdma_copy_src_l2_addr(dev_addr, ndev); + + return ret; +} + +static int rdma_set_src_addr_rcu(struct rdma_dev_addr *dev_addr, + unsigned int *ndev_flags, + const struct sockaddr *dst_in, + if_t ndev) +{ + *ndev_flags = if_getflags(ndev); + /* A physical device must be the RDMA device to use */ + if (if_getflags(ndev) & IFF_LOOPBACK) { + /* + * RDMA (IB/RoCE, iWarp) doesn't run on lo interface or + * loopback IP address. So if route is resolved to loopback + * interface, translate that to a real ndev based on non + * loopback IP address. + */ + ndev = rdma_find_ndev_for_src_ip_rcu(dev_net(ndev), dst_in); + if (!ndev) + return -ENODEV; } - /* If the device doesn't do ARP internally */ - if (!(if_getflags(dev) & IFF_NOARP)) { - rdma_copy_addr(addr, dev, edst); - return 0; - } + return copy_src_l2_addr(dev_addr, dst_in, ndev); +} + +static int set_addr_netns_by_gid_rcu(struct rdma_dev_addr *addr) +{ + if_t ndev; - rdma_copy_addr(addr, dev, NULL); + ndev = rdma_read_gid_attr_ndev_rcu(addr->sgid_attr); + if (IS_ERR(ndev)) + return PTR_ERR(ndev); + /* + * Since we are holding the rcu, reading net and ifindex + * are safe without any additional reference; because + * change_net_namespace() in net/core/ib_dev.c does rcu sync + * after it changes the state to IFF_DOWN and before + * updating netdev fields {net, ifindex}. + */ + addr->net = dev_net(ndev); + addr->bound_dev_if = if_getindex(ndev); return 0; } +static void rdma_addr_set_net_defaults(struct rdma_dev_addr *addr) +{ + addr->net = &init_net; + addr->bound_dev_if = 0; +} + static int addr_resolve(struct sockaddr *src_in, const struct sockaddr *dst_in, - struct rdma_dev_addr *addr) + struct rdma_dev_addr *addr, + bool resolve_by_gid_attr) { struct epoch_tracker et; if_t ndev = NULL; u8 edst[MAX_ADDR_LEN]; + unsigned int ndev_flags = 0; int ret; if (dst_in->sa_family != src_in->sa_family) return -EINVAL; NET_EPOCH_ENTER(et); + if (resolve_by_gid_attr) { + if (!addr->sgid_attr) { + NET_EPOCH_ENTER(et); + pr_warn_ratelimited("%s: missing gid_attr\n", __func__); + return -EINVAL; + } + /* + * If the request is for a specific gid attribute of the + * rdma_dev_addr, derive net from the netdevice of the + * GID attribute. + */ + ret = set_addr_netns_by_gid_rcu(addr); + if (ret) { + NET_EPOCH_ENTER(et); + return ret; + } + } switch (src_in->sa_family) { case AF_INET: - ret = addr4_resolve((struct sockaddr_in *)src_in, - (const struct sockaddr_in *)dst_in, - addr, edst, &ndev); + ret = addr4_resolve(src_in, dst_in, addr, edst, &ndev); break; case AF_INET6: - ret = addr6_resolve((struct sockaddr_in6 *)src_in, - (const struct sockaddr_in6 *)dst_in, addr, - edst, &ndev); + ret = addr6_resolve(src_in, dst_in, addr, edst, &ndev); break; default: ret = -EADDRNOTAVAIL; break; } + if (ret) { + NET_EPOCH_EXIT(et); + goto done; + } + ret = rdma_set_src_addr_rcu(addr, &ndev_flags, dst_in, ndev); NET_EPOCH_EXIT(et); - /* check for error */ - if (ret != 0) - return ret; - /* store MAC addresses and check for loopback */ - ret = addr_resolve_neigh(ndev, dst_in, edst, addr); + if (!ret) + ret = addr_resolve_neigh(ndev, dst_in, edst, addr, ndev_flags); /* set belonging VNET, if any */ addr->net = dev_net(ndev); dev_put(ndev); - +done: + /* + * Clear the addr net to go back to its original state, only if it was + * derived from GID attribute in this context. + */ + if (resolve_by_gid_attr) + rdma_addr_set_net_defaults(addr); return ret; } @@ -685,7 +790,8 @@ static void process_one_req(struct work_struct *_work) if (req->status == -ENODATA) { src_in = (struct sockaddr *)&req->src_addr; dst_in = (struct sockaddr *)&req->dst_addr; - req->status = addr_resolve(src_in, dst_in, req->addr); + req->status = addr_resolve(src_in, dst_in, req->addr, + req->resolve_by_gid_attr); if (req->status && time_after_eq(jiffies, req->timeout)) { req->status = -ETIMEDOUT; } else if (req->status == -ENODATA) { @@ -720,6 +826,7 @@ int rdma_resolve_ip(struct sockaddr *src_addr, const struct sockaddr *dst_addr, struct rdma_dev_addr *addr, int timeout_ms, void (*callback)(int status, struct sockaddr *src_addr, struct rdma_dev_addr *addr, void *context), + bool resolve_by_gid_attr, void *context) { struct sockaddr *src_in, *dst_in; @@ -748,9 +855,11 @@ int rdma_resolve_ip(struct sockaddr *src_addr, const struct sockaddr *dst_addr, req->addr = addr; req->callback = callback; req->context = context; + req->resolve_by_gid_attr = resolve_by_gid_attr; INIT_DELAYED_WORK(&req->work, process_one_req); - req->status = addr_resolve(src_in, dst_in, addr); + req->status = addr_resolve(src_in, dst_in, addr, + req->resolve_by_gid_attr); switch (req->status) { case 0: req->timeout = jiffies; @@ -771,25 +880,49 @@ err: } EXPORT_SYMBOL(rdma_resolve_ip); -int rdma_resolve_ip_route(struct sockaddr *src_addr, - const struct sockaddr *dst_addr, - struct rdma_dev_addr *addr) +int roce_resolve_route_from_path(struct sa_path_rec *rec, + const struct ib_gid_attr *attr) { - struct sockaddr_storage ssrc_addr = {}; - struct sockaddr *src_in = (struct sockaddr *)&ssrc_addr; + union rdma_sockaddr sgid, dgid; + struct rdma_dev_addr dev_addr = {}; + int ret; - if (src_addr) { - if (src_addr->sa_family != dst_addr->sa_family) - return -EINVAL; + if (rec->roce.route_resolved) + return 0; - memcpy(src_in, src_addr, rdma_addr_size(src_addr)); - } else { - src_in->sa_family = dst_addr->sa_family; - } + rdma_gid2ip(&sgid._sockaddr, &rec->sgid); + rdma_gid2ip(&dgid._sockaddr, &rec->dgid); + + if (sgid._sockaddr.sa_family != dgid._sockaddr.sa_family) + return -EINVAL; + + if (!attr || !attr->ndev) + return -EINVAL; - return addr_resolve(src_in, dst_addr, addr); + dev_addr.net = &init_net; + dev_addr.sgid_attr = attr; + + ret = addr_resolve(&sgid._sockaddr, &dgid._sockaddr, + &dev_addr, true); + if (ret) + return ret; + + if ((dev_addr.network == RDMA_NETWORK_IPV4 || + dev_addr.network == RDMA_NETWORK_IPV6) && + rec->rec_type != SA_PATH_REC_TYPE_ROCE_V2) + return -EINVAL; + + rec->roce.route_resolved = true; + return 0; } +/** + * rdma_addr_cancel - Cancel resolve ip request + * @addr: Pointer to address structure given previously + * during rdma_resolve_ip(). + * rdma_addr_cancel() is synchronous function which cancels any pending + * request if there is any. + */ void rdma_addr_cancel(struct rdma_dev_addr *addr) { struct addr_req *req, *temp_req; @@ -817,11 +950,6 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr) * guarentees no work is running and none will be started. */ cancel_delayed_work_sync(&found->work); - - if (found->callback) - found->callback(-ECANCELED, (struct sockaddr *)&found->src_addr, - found->addr, found->context); - kfree(found); } EXPORT_SYMBOL(rdma_addr_cancel); @@ -840,7 +968,7 @@ static void resolve_cb(int status, struct sockaddr *src_addr, int rdma_addr_find_l2_eth_by_grh(const union ib_gid *sgid, const union ib_gid *dgid, - u8 *dmac, if_t ndev, + u8 *dmac, const struct ib_gid_attr *sgid_attr, int *hoplimit) { struct rdma_dev_addr dev_addr; @@ -852,13 +980,12 @@ int rdma_addr_find_l2_eth_by_grh(const union ib_gid *sgid, rdma_gid2ip(&dgid_addr._sockaddr, dgid); memset(&dev_addr, 0, sizeof(dev_addr)); - - dev_addr.bound_dev_if = if_getindex(ndev); - dev_addr.net = dev_net(ndev); + dev_addr.net = &init_net; + dev_addr.sgid_attr = sgid_attr; init_completion(&ctx.comp); ret = rdma_resolve_ip(&sgid_addr._sockaddr, &dgid_addr._sockaddr, - &dev_addr, 1000, resolve_cb, &ctx); + &dev_addr, 1000, resolve_cb, true, &ctx); if (ret) return ret; diff --git a/sys/ofed/drivers/infiniband/core/ib_cache.c b/sys/ofed/drivers/infiniband/core/ib_cache.c index 7bf3213140ff..1ad577ff4b83 100644 --- a/sys/ofed/drivers/infiniband/core/ib_cache.c +++ b/sys/ofed/drivers/infiniband/core/ib_cache.c @@ -1265,6 +1265,39 @@ void rdma_hold_gid_attr(const struct ib_gid_attr *attr) } EXPORT_SYMBOL(rdma_hold_gid_attr); +/** + * rdma_read_gid_attr_ndev_rcu - Read GID attribute netdevice + * which must be in UP state. + * + * @attr:Pointer to the GID attribute + * + * Returns pointer to netdevice if the netdevice was attached to GID and + * netdevice is in UP state. Caller must hold RCU lock as this API + * reads the netdev flags which can change while netdevice migrates to + * different net namespace. Returns ERR_PTR with error code otherwise. + * + */ +if_t rdma_read_gid_attr_ndev_rcu(const struct ib_gid_attr *attr) +{ + struct ib_gid_table_entry *entry = + container_of(attr, struct ib_gid_table_entry, attr); + struct ib_device *device = entry->attr.device; + if_t ndev = ERR_PTR(-ENODEV); + u8 port_num = entry->attr.port_num; + struct ib_gid_table *table; + unsigned long flags; + bool valid; + + table = rdma_gid_table(device, port_num); + + read_lock_irqsave(&table->rwlock, flags); + valid = is_gid_entry_valid(table->data_vec[attr->index]); + if (valid && attr->ndev && (if_getflags(attr->ndev) & IFF_UP)) + ndev = attr->ndev; + read_unlock_irqrestore(&table->rwlock, flags); + return ndev; +} + static int config_non_roce_gid_cache(struct ib_device *device, u8 port, int gid_tbl_len) { diff --git a/sys/ofed/drivers/infiniband/core/ib_cma.c b/sys/ofed/drivers/infiniband/core/ib_cma.c index 426c7ae80143..a16e31df6752 100644 --- a/sys/ofed/drivers/infiniband/core/ib_cma.c +++ b/sys/ofed/drivers/infiniband/core/ib_cma.c @@ -729,6 +729,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) dgid = (union ib_gid *) &addr->sib_addr; pkey = ntohs(addr->sib_pkey); + mutex_lock(&lock); list_for_each_entry(cur_dev, &dev_list, list) { for (p = 1; p <= cur_dev->device->phys_port_cnt; ++p) { if (!rdma_cap_af_ib(cur_dev->device, p)) @@ -755,18 +756,19 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) cma_dev = cur_dev; sgid = gid; id_priv->id.port_num = p; + goto found; } } } } - - if (!cma_dev) - return -ENODEV; + mutex_unlock(&lock); + return -ENODEV; found: cma_attach_to_dev(id_priv, cma_dev); - addr = (struct sockaddr_ib *) cma_src_addr(id_priv); - memcpy(&addr->sib_addr, &sgid, sizeof sgid); + mutex_unlock(&lock); + addr = (struct sockaddr_ib *)cma_src_addr(id_priv); + memcpy(&addr->sib_addr, &sgid, sizeof(sgid)); cma_translate_ib(addr, &id_priv->id.route.addr.dev_addr); return 0; } @@ -2104,7 +2106,7 @@ cma_ib_new_conn_id(const struct rdma_cm_id *listen_id, rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path; if (net_dev) { - rdma_copy_addr(&rt->addr.dev_addr, net_dev, NULL); + rdma_copy_src_l2_addr(&rt->addr.dev_addr, net_dev); } else { if (!cma_protocol_roce(listen_id) && cma_any_addr(vnet, cma_src_addr(id_priv))) { @@ -2151,7 +2153,7 @@ cma_ib_new_udp_id(const struct rdma_cm_id *listen_id, goto err; if (net_dev) { - rdma_copy_addr(&id->route.addr.dev_addr, net_dev, NULL); + rdma_copy_src_l2_addr(&id->route.addr.dev_addr, net_dev); } else { if (!cma_any_addr(vnet, cma_src_addr(id_priv))) { ret = cma_translate_addr(cma_src_addr(id_priv), @@ -3067,13 +3069,11 @@ static void addr_handler(int status, struct sockaddr *src_addr, if (id_priv->id.event_handler(&id_priv->id, &event)) { cma_exch(id_priv, RDMA_CM_DESTROYING); mutex_unlock(&id_priv->handler_mutex); - cma_deref_id(id_priv); rdma_destroy_id(&id_priv->id); return; } out: mutex_unlock(&id_priv->handler_mutex); - cma_deref_id(id_priv); } static int cma_resolve_loopback(struct rdma_id_private *id_priv) @@ -3171,7 +3171,6 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, return -EINVAL; memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr)); - atomic_inc(&id_priv->refcount); if (cma_any_addr(vnet, dst_addr)) { ret = cma_resolve_loopback(id_priv); } else { @@ -3182,9 +3181,10 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, if (ret) goto err; - ret = rdma_resolve_ip(cma_src_addr(id_priv), - dst_addr, &id->route.addr.dev_addr, - timeout_ms, addr_handler, id_priv); + ret = rdma_resolve_ip(cma_src_addr(id_priv), dst_addr, + &id->route.addr.dev_addr, + timeout_ms, addr_handler, + false, id_priv); } } if (ret) @@ -3193,7 +3193,6 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, return 0; err: cma_comp_exch(id_priv, RDMA_CM_ADDR_QUERY, RDMA_CM_ADDR_BOUND); - cma_deref_id(id_priv); return ret; } EXPORT_SYMBOL(rdma_resolve_addr); diff --git a/sys/ofed/drivers/infiniband/core/ib_device.c b/sys/ofed/drivers/infiniband/core/ib_device.c index 204466ea5a76..eddb0ac5885f 100644 --- a/sys/ofed/drivers/infiniband/core/ib_device.c +++ b/sys/ofed/drivers/infiniband/core/ib_device.c @@ -217,7 +217,7 @@ struct ib_device *ib_alloc_device(size_t size) INIT_LIST_HEAD(&device->event_handler_list); spin_lock_init(&device->event_handler_lock); - spin_lock_init(&device->client_data_lock); + rwlock_init(&device->client_data_lock); INIT_LIST_HEAD(&device->client_data_list); INIT_LIST_HEAD(&device->port_list); @@ -233,6 +233,7 @@ EXPORT_SYMBOL(ib_alloc_device); */ void ib_dealloc_device(struct ib_device *device) { + WARN_ON(!list_empty(&device->client_data_list)); WARN_ON(device->reg_state != IB_DEV_UNREGISTERED && device->reg_state != IB_DEV_UNINITIALIZED); kobject_put(&device->dev.kobj); @@ -242,9 +243,8 @@ EXPORT_SYMBOL(ib_dealloc_device); static int add_client_context(struct ib_device *device, struct ib_client *client) { struct ib_client_data *context; - unsigned long flags; - context = kmalloc(sizeof *context, GFP_KERNEL); + context = kmalloc(sizeof(*context), GFP_KERNEL); if (!context) return -ENOMEM; @@ -253,9 +253,9 @@ static int add_client_context(struct ib_device *device, struct ib_client *client context->going_down = false; down_write(&lists_rwsem); - spin_lock_irqsave(&device->client_data_lock, flags); + write_lock_irq(&device->client_data_lock); list_add(&context->list, &device->client_data_list); - spin_unlock_irqrestore(&device->client_data_lock, flags); + write_unlock_irq(&device->client_data_lock); up_write(&lists_rwsem); return 0; @@ -403,14 +403,13 @@ void ib_unregister_device(struct ib_device *device) down_write(&lists_rwsem); list_del(&device->core_list); - spin_lock_irqsave(&device->client_data_lock, flags); - list_for_each_entry_safe(context, tmp, &device->client_data_list, list) + write_lock_irq(&device->client_data_lock); + list_for_each_entry(context, &device->client_data_list, list) context->going_down = true; - spin_unlock_irqrestore(&device->client_data_lock, flags); + write_unlock_irq(&device->client_data_lock); downgrade_write(&lists_rwsem); - list_for_each_entry_safe(context, tmp, &device->client_data_list, - list) { + list_for_each_entry(context, &device->client_data_list, list) { if (context->client->remove) context->client->remove(device, context->data); } @@ -423,10 +422,13 @@ void ib_unregister_device(struct ib_device *device) ib_cache_cleanup_one(device); down_write(&lists_rwsem); - spin_lock_irqsave(&device->client_data_lock, flags); - list_for_each_entry_safe(context, tmp, &device->client_data_list, list) + write_lock_irqsave(&device->client_data_lock, flags); + list_for_each_entry_safe(context, tmp, &device->client_data_list, + list) { + list_del(&context->list); kfree(context); - spin_unlock_irqrestore(&device->client_data_lock, flags); + } + write_unlock_irqrestore(&device->client_data_lock, flags); up_write(&lists_rwsem); device->reg_state = IB_DEV_UNREGISTERED; @@ -476,9 +478,8 @@ EXPORT_SYMBOL(ib_register_client); */ void ib_unregister_client(struct ib_client *client) { - struct ib_client_data *context, *tmp; + struct ib_client_data *context; struct ib_device *device; - unsigned long flags; mutex_lock(&device_mutex); @@ -490,14 +491,14 @@ void ib_unregister_client(struct ib_client *client) struct ib_client_data *found_context = NULL; down_write(&lists_rwsem); - spin_lock_irqsave(&device->client_data_lock, flags); - list_for_each_entry_safe(context, tmp, &device->client_data_list, list) + write_lock_irq(&device->client_data_lock); + list_for_each_entry(context, &device->client_data_list, list) if (context->client == client) { context->going_down = true; found_context = context; break; } - spin_unlock_irqrestore(&device->client_data_lock, flags); + write_unlock_irq(&device->client_data_lock); up_write(&lists_rwsem); if (client->remove) @@ -511,11 +512,11 @@ void ib_unregister_client(struct ib_client *client) } down_write(&lists_rwsem); - spin_lock_irqsave(&device->client_data_lock, flags); + write_lock_irq(&device->client_data_lock); list_del(&found_context->list); - kfree(found_context); - spin_unlock_irqrestore(&device->client_data_lock, flags); + write_unlock_irq(&device->client_data_lock); up_write(&lists_rwsem); + kfree(found_context); } mutex_unlock(&device_mutex); @@ -536,13 +537,13 @@ void *ib_get_client_data(struct ib_device *device, struct ib_client *client) void *ret = NULL; unsigned long flags; - spin_lock_irqsave(&device->client_data_lock, flags); + read_lock_irqsave(&device->client_data_lock, flags); list_for_each_entry(context, &device->client_data_list, list) if (context->client == client) { ret = context->data; break; } - spin_unlock_irqrestore(&device->client_data_lock, flags); + read_unlock_irqrestore(&device->client_data_lock, flags); return ret; } @@ -563,7 +564,7 @@ void ib_set_client_data(struct ib_device *device, struct ib_client *client, struct ib_client_data *context; unsigned long flags; - spin_lock_irqsave(&device->client_data_lock, flags); + write_lock_irqsave(&device->client_data_lock, flags); list_for_each_entry(context, &device->client_data_list, list) if (context->client == client) { context->data = data; @@ -574,7 +575,7 @@ void ib_set_client_data(struct ib_device *device, struct ib_client *client, device->name, client->name); out: - spin_unlock_irqrestore(&device->client_data_lock, flags); + write_unlock_irqrestore(&device->client_data_lock, flags); } EXPORT_SYMBOL(ib_set_client_data); diff --git a/sys/ofed/drivers/infiniband/core/ib_mad.c b/sys/ofed/drivers/infiniband/core/ib_mad.c index 94739f6f96a4..a0040749d854 100644 --- a/sys/ofed/drivers/infiniband/core/ib_mad.c +++ b/sys/ofed/drivers/infiniband/core/ib_mad.c @@ -224,30 +224,30 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, /* Validate parameters */ qpn = get_spl_qp_index(qp_type); if (qpn == -1) { - dev_notice(&device->dev, - "ib_register_mad_agent: invalid QP Type %d\n", - qp_type); + dev_dbg_ratelimited(&device->dev, "%s: invalid QP Type %d\n", + __func__, qp_type); goto error1; } if (rmpp_version && rmpp_version != IB_MGMT_RMPP_VERSION) { - dev_notice(&device->dev, - "ib_register_mad_agent: invalid RMPP Version %u\n", - rmpp_version); + dev_dbg_ratelimited(&device->dev, + "%s: invalid RMPP Version %u\n", + __func__, rmpp_version); goto error1; } /* Validate MAD registration request if supplied */ if (mad_reg_req) { if (mad_reg_req->mgmt_class_version >= MAX_MGMT_VERSION) { - dev_notice(&device->dev, - "ib_register_mad_agent: invalid Class Version %u\n", - mad_reg_req->mgmt_class_version); + dev_dbg_ratelimited(&device->dev, + "%s: invalid Class Version %u\n", + __func__, + mad_reg_req->mgmt_class_version); goto error1; } if (!recv_handler) { - dev_notice(&device->dev, - "ib_register_mad_agent: no recv_handler\n"); + dev_dbg_ratelimited(&device->dev, + "%s: no recv_handler\n", __func__); goto error1; } if (mad_reg_req->mgmt_class >= MAX_MGMT_CLASS) { @@ -257,9 +257,9 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, */ if (mad_reg_req->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) { - dev_notice(&device->dev, - "ib_register_mad_agent: Invalid Mgmt Class 0x%x\n", - mad_reg_req->mgmt_class); + dev_dbg_ratelimited(&device->dev, + "%s: Invalid Mgmt Class 0x%x\n", + __func__, mad_reg_req->mgmt_class); goto error1; } } else if (mad_reg_req->mgmt_class == 0) { @@ -267,8 +267,9 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, * Class 0 is reserved in IBA and is used for * aliasing of IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE */ - dev_notice(&device->dev, - "ib_register_mad_agent: Invalid Mgmt Class 0\n"); + dev_dbg_ratelimited(&device->dev, + "%s: Invalid Mgmt Class 0\n", + __func__); goto error1; } else if (is_vendor_class(mad_reg_req->mgmt_class)) { /* @@ -276,18 +277,19 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, * ensure supplied OUI is not zero */ if (!is_vendor_oui(mad_reg_req->oui)) { - dev_notice(&device->dev, - "ib_register_mad_agent: No OUI specified for class 0x%x\n", - mad_reg_req->mgmt_class); + dev_dbg_ratelimited(&device->dev, + "%s: No OUI specified for class 0x%x\n", + __func__, + mad_reg_req->mgmt_class); goto error1; } } /* Make sure class supplied is consistent with RMPP */ if (!ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) { if (rmpp_version) { - dev_notice(&device->dev, - "ib_register_mad_agent: RMPP version for non-RMPP class 0x%x\n", - mad_reg_req->mgmt_class); *** 1680 LINES SKIPPED ***home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a3c3539.452a4.3b65f13f>
