aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/addr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/core/addr.c')
-rw-r--r--drivers/infiniband/core/addr.c47
1 files changed, 35 insertions, 12 deletions
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 60d3fbdd216c..7767a11b6890 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -47,6 +47,7 @@ struct addr_req {
47 struct sockaddr src_addr; 47 struct sockaddr src_addr;
48 struct sockaddr dst_addr; 48 struct sockaddr dst_addr;
49 struct rdma_dev_addr *addr; 49 struct rdma_dev_addr *addr;
50 struct rdma_addr_client *client;
50 void *context; 51 void *context;
51 void (*callback)(int status, struct sockaddr *src_addr, 52 void (*callback)(int status, struct sockaddr *src_addr,
52 struct rdma_dev_addr *addr, void *context); 53 struct rdma_dev_addr *addr, void *context);
@@ -61,6 +62,26 @@ static LIST_HEAD(req_list);
61static DECLARE_WORK(work, process_req, NULL); 62static DECLARE_WORK(work, process_req, NULL);
62static struct workqueue_struct *addr_wq; 63static struct workqueue_struct *addr_wq;
63 64
65void rdma_addr_register_client(struct rdma_addr_client *client)
66{
67 atomic_set(&client->refcount, 1);
68 init_completion(&client->comp);
69}
70EXPORT_SYMBOL(rdma_addr_register_client);
71
72static inline void put_client(struct rdma_addr_client *client)
73{
74 if (atomic_dec_and_test(&client->refcount))
75 complete(&client->comp);
76}
77
78void rdma_addr_unregister_client(struct rdma_addr_client *client)
79{
80 put_client(client);
81 wait_for_completion(&client->comp);
82}
83EXPORT_SYMBOL(rdma_addr_unregister_client);
84
64int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, 85int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
65 const unsigned char *dst_dev_addr) 86 const unsigned char *dst_dev_addr)
66{ 87{
@@ -118,7 +139,7 @@ static void queue_req(struct addr_req *req)
118 139
119 mutex_lock(&lock); 140 mutex_lock(&lock);
120 list_for_each_entry_reverse(temp_req, &req_list, list) { 141 list_for_each_entry_reverse(temp_req, &req_list, list) {
121 if (time_after(req->timeout, temp_req->timeout)) 142 if (time_after_eq(req->timeout, temp_req->timeout))
122 break; 143 break;
123 } 144 }
124 145
@@ -204,19 +225,17 @@ static void process_req(void *data)
204 225
205 mutex_lock(&lock); 226 mutex_lock(&lock);
206 list_for_each_entry_safe(req, temp_req, &req_list, list) { 227 list_for_each_entry_safe(req, temp_req, &req_list, list) {
207 if (req->status) { 228 if (req->status == -ENODATA) {
208 src_in = (struct sockaddr_in *) &req->src_addr; 229 src_in = (struct sockaddr_in *) &req->src_addr;
209 dst_in = (struct sockaddr_in *) &req->dst_addr; 230 dst_in = (struct sockaddr_in *) &req->dst_addr;
210 req->status = addr_resolve_remote(src_in, dst_in, 231 req->status = addr_resolve_remote(src_in, dst_in,
211 req->addr); 232 req->addr);
233 if (req->status && time_after_eq(jiffies, req->timeout))
234 req->status = -ETIMEDOUT;
235 else if (req->status == -ENODATA)
236 continue;
212 } 237 }
213 if (req->status && time_after(jiffies, req->timeout)) 238 list_move_tail(&req->list, &done_list);
214 req->status = -ETIMEDOUT;
215 else if (req->status == -ENODATA)
216 continue;
217
218 list_del(&req->list);
219 list_add_tail(&req->list, &done_list);
220 } 239 }
221 240
222 if (!list_empty(&req_list)) { 241 if (!list_empty(&req_list)) {
@@ -229,6 +248,7 @@ static void process_req(void *data)
229 list_del(&req->list); 248 list_del(&req->list);
230 req->callback(req->status, &req->src_addr, req->addr, 249 req->callback(req->status, &req->src_addr, req->addr,
231 req->context); 250 req->context);
251 put_client(req->client);
232 kfree(req); 252 kfree(req);
233 } 253 }
234} 254}
@@ -264,7 +284,8 @@ static int addr_resolve_local(struct sockaddr_in *src_in,
264 return ret; 284 return ret;
265} 285}
266 286
267int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr, 287int rdma_resolve_ip(struct rdma_addr_client *client,
288 struct sockaddr *src_addr, struct sockaddr *dst_addr,
268 struct rdma_dev_addr *addr, int timeout_ms, 289 struct rdma_dev_addr *addr, int timeout_ms,
269 void (*callback)(int status, struct sockaddr *src_addr, 290 void (*callback)(int status, struct sockaddr *src_addr,
270 struct rdma_dev_addr *addr, void *context), 291 struct rdma_dev_addr *addr, void *context),
@@ -285,6 +306,8 @@ int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
285 req->addr = addr; 306 req->addr = addr;
286 req->callback = callback; 307 req->callback = callback;
287 req->context = context; 308 req->context = context;
309 req->client = client;
310 atomic_inc(&client->refcount);
288 311
289 src_in = (struct sockaddr_in *) &req->src_addr; 312 src_in = (struct sockaddr_in *) &req->src_addr;
290 dst_in = (struct sockaddr_in *) &req->dst_addr; 313 dst_in = (struct sockaddr_in *) &req->dst_addr;
@@ -305,6 +328,7 @@ int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
305 break; 328 break;
306 default: 329 default:
307 ret = req->status; 330 ret = req->status;
331 atomic_dec(&client->refcount);
308 kfree(req); 332 kfree(req);
309 break; 333 break;
310 } 334 }
@@ -321,8 +345,7 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr)
321 if (req->addr == addr) { 345 if (req->addr == addr) {
322 req->status = -ECANCELED; 346 req->status = -ECANCELED;
323 req->timeout = jiffies; 347 req->timeout = jiffies;
324 list_del(&req->list); 348 list_move(&req->list, &req_list);
325 list_add(&req->list, &req_list);
326 set_timeout(req->timeout); 349 set_timeout(req->timeout);
327 break; 350 break;
328 } 351 }