struct sockaddr src_addr;
struct sockaddr dst_addr;
struct rdma_dev_addr *addr;
+ struct rdma_addr_client *client;
void *context;
void (*callback)(int status, struct sockaddr *src_addr,
struct rdma_dev_addr *addr, void *context);
static DECLARE_WORK(work, process_req, NULL);
static struct workqueue_struct *addr_wq;
-static int copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
- unsigned char *dst_dev_addr)
+void rdma_addr_register_client(struct rdma_addr_client *client)
+{
+ atomic_set(&client->refcount, 1);
+ init_completion(&client->comp);
+}
+EXPORT_SYMBOL(rdma_addr_register_client);
+
+static inline void put_client(struct rdma_addr_client *client)
+{
+ if (atomic_dec_and_test(&client->refcount))
+ complete(&client->comp);
+}
+
+void rdma_addr_unregister_client(struct rdma_addr_client *client)
+{
+ put_client(client);
+ wait_for_completion(&client->comp);
+}
+EXPORT_SYMBOL(rdma_addr_unregister_client);
+
+int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
+ const unsigned char *dst_dev_addr)
{
switch (dev->type) {
case ARPHRD_INFINIBAND:
- dev_addr->dev_type = IB_NODE_CA;
+ dev_addr->dev_type = RDMA_NODE_IB_CA;
+ break;
+ case ARPHRD_ETHER:
+ dev_addr->dev_type = RDMA_NODE_RNIC;
break;
default:
return -EADDRNOTAVAIL;
memcpy(dev_addr->dst_dev_addr, dst_dev_addr, MAX_ADDR_LEN);
return 0;
}
+EXPORT_SYMBOL(rdma_copy_addr);
int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
{
struct net_device *dev;
- u32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+ __be32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
int ret;
dev = ip_dev_find(ip);
if (!dev)
return -EADDRNOTAVAIL;
- ret = copy_addr(dev_addr, dev, NULL);
+ ret = rdma_copy_addr(dev_addr, dev, NULL);
dev_put(dev);
return ret;
}
mutex_lock(&lock);
list_for_each_entry_reverse(temp_req, &req_list, list) {
- if (time_after(req->timeout, temp_req->timeout))
+ if (time_after_eq(req->timeout, temp_req->timeout))
break;
}
/* If the device does ARP internally, return 'done' */
if (rt->idev->dev->flags & IFF_NOARP) {
- copy_addr(addr, rt->idev->dev, NULL);
+ rdma_copy_addr(addr, rt->idev->dev, NULL);
goto put;
}
src_in->sin_addr.s_addr = rt->rt_src;
}
- ret = copy_addr(addr, neigh->dev, neigh->ha);
+ ret = rdma_copy_addr(addr, neigh->dev, neigh->ha);
release:
neigh_release(neigh);
put:
list_del(&req->list);
req->callback(req->status, &req->src_addr, req->addr,
req->context);
+ put_client(req->client);
kfree(req);
}
}
{
struct net_device *dev;
u32 src_ip = src_in->sin_addr.s_addr;
- u32 dst_ip = dst_in->sin_addr.s_addr;
+ __be32 dst_ip = dst_in->sin_addr.s_addr;
int ret;
dev = ip_dev_find(dst_ip);
if (ZERONET(src_ip)) {
src_in->sin_family = dst_in->sin_family;
src_in->sin_addr.s_addr = dst_ip;
- ret = copy_addr(addr, dev, dev->dev_addr);
+ ret = rdma_copy_addr(addr, dev, dev->dev_addr);
} else if (LOOPBACK(src_ip)) {
ret = rdma_translate_ip((struct sockaddr *)dst_in, addr);
if (!ret)
return ret;
}
-int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
+int rdma_resolve_ip(struct rdma_addr_client *client,
+ struct sockaddr *src_addr, 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),
req->addr = addr;
req->callback = callback;
req->context = context;
+ req->client = client;
+ atomic_inc(&client->refcount);
src_in = (struct sockaddr_in *) &req->src_addr;
dst_in = (struct sockaddr_in *) &req->dst_addr;
break;
default:
ret = req->status;
+ atomic_dec(&client->refcount);
kfree(req);
break;
}