diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index be0743dac3ff..594e7ee335f7 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -465,17 +465,32 @@ static int addr_resolve_neigh(const struct dst_entry *dst, return ret; } -static int copy_src_l2_addr(struct rdma_dev_addr *dev_addr, - const struct sockaddr *dst_in, - const struct dst_entry *dst, - const struct net_device *ndev) +static int rdma_set_src_addr_rcu(struct rdma_dev_addr *dev_addr, + unsigned int *ndev_flags, + const struct sockaddr *dst_in, + const struct dst_entry *dst) { - int ret = 0; + struct net_device *ndev = READ_ONCE(dst->dev); - if (dst->dev->flags & IFF_LOOPBACK) + *ndev_flags = ndev->flags; + /* A physical device must be the RDMA device to use */ + if (ndev->flags & IFF_LOOPBACK) { + int ret; + /* + * 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 (IS_ERR(ndev)) + return -ENODEV; ret = rdma_translate_ip(dst_in, dev_addr); - else + if (ret) + return ret; + } else { rdma_copy_src_l2_addr(dev_addr, dst->dev); + } /* * If there's a gateway and type of device not ARPHRD_INFINIBAND, @@ -490,31 +505,7 @@ static int copy_src_l2_addr(struct rdma_dev_addr *dev_addr, else dev_addr->network = RDMA_NETWORK_IB; - return ret; -} - -static int rdma_set_src_addr_rcu(struct rdma_dev_addr *dev_addr, - unsigned int *ndev_flags, - const struct sockaddr *dst_in, - const struct dst_entry *dst) -{ - struct net_device *ndev = READ_ONCE(dst->dev); - - *ndev_flags = ndev->flags; - /* A physical device must be the RDMA device to use */ - if (ndev->flags & 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 (IS_ERR(ndev)) - return -ENODEV; - } - - return copy_src_l2_addr(dev_addr, dst_in, dst, ndev); + return 0; } static int set_addr_netns_by_gid_rcu(struct rdma_dev_addr *addr)