diff options
Diffstat (limited to 'drivers/infiniband/core/addr.c')
| -rw-r--r-- | drivers/infiniband/core/addr.c | 53 | 
1 files changed, 24 insertions, 29 deletions
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index e9cf51b1343..1612cfd50f3 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -178,6 +178,25 @@ static void queue_req(struct addr_req *req)  	mutex_unlock(&lock);  } +static int dst_fetch_ha(struct dst_entry *dst, struct rdma_dev_addr *addr) +{ +	struct neighbour *n; +	int ret; + +	rcu_read_lock(); +	n = dst_get_neighbour_noref(dst); +	if (!n || !(n->nud_state & NUD_VALID)) { +		if (n) +			neigh_event_send(n, NULL); +		ret = -ENODATA; +	} else { +		ret = rdma_copy_addr(addr, dst->dev, n->ha); +	} +	rcu_read_unlock(); + +	return ret; +} +  static int addr4_resolve(struct sockaddr_in *src_in,  			 struct sockaddr_in *dst_in,  			 struct rdma_dev_addr *addr) @@ -185,7 +204,6 @@ static int addr4_resolve(struct sockaddr_in *src_in,  	__be32 src_ip = src_in->sin_addr.s_addr;  	__be32 dst_ip = dst_in->sin_addr.s_addr;  	struct rtable *rt; -	struct neighbour *neigh;  	struct flowi4 fl4;  	int ret; @@ -214,20 +232,7 @@ static int addr4_resolve(struct sockaddr_in *src_in,  		goto put;  	} -	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev); -	if (!neigh || !(neigh->nud_state & NUD_VALID)) { -		rcu_read_lock(); -		neigh_event_send(dst_get_neighbour(&rt->dst), NULL); -		rcu_read_unlock(); -		ret = -ENODATA; -		if (neigh) -			goto release; -		goto put; -	} - -	ret = rdma_copy_addr(addr, neigh->dev, neigh->ha); -release: -	neigh_release(neigh); +	ret = dst_fetch_ha(&rt->dst, addr);  put:  	ip_rt_put(rt);  out: @@ -240,13 +245,12 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,  			 struct rdma_dev_addr *addr)  {  	struct flowi6 fl6; -	struct neighbour *neigh;  	struct dst_entry *dst;  	int ret;  	memset(&fl6, 0, sizeof fl6); -	ipv6_addr_copy(&fl6.daddr, &dst_in->sin6_addr); -	ipv6_addr_copy(&fl6.saddr, &src_in->sin6_addr); +	fl6.daddr = dst_in->sin6_addr; +	fl6.saddr = src_in->sin6_addr;  	fl6.flowi6_oif = addr->bound_dev_if;  	dst = ip6_route_output(&init_net, NULL, &fl6); @@ -260,7 +264,7 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,  			goto put;  		src_in->sin6_family = AF_INET6; -		ipv6_addr_copy(&src_in->sin6_addr, &fl6.saddr); +		src_in->sin6_addr = fl6.saddr;  	}  	if (dst->dev->flags & IFF_LOOPBACK) { @@ -276,16 +280,7 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,  		goto put;  	} -	rcu_read_lock(); -	neigh = dst_get_neighbour(dst); -	if (!neigh || !(neigh->nud_state & NUD_VALID)) { -		if (neigh) -			neigh_event_send(neigh, NULL); -		ret = -ENODATA; -	} else { -		ret = rdma_copy_addr(addr, dst->dev, neigh->ha); -	} -	rcu_read_unlock(); +	ret = dst_fetch_ha(dst, addr);  put:  	dst_release(dst);  	return ret;  |