diff options
Diffstat (limited to 'drivers/infiniband/core/addr.c')
-rw-r--r-- | drivers/infiniband/core/addr.c | 47 |
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); | |||
61 | static DECLARE_WORK(work, process_req, NULL); | 62 | static DECLARE_WORK(work, process_req, NULL); |
62 | static struct workqueue_struct *addr_wq; | 63 | static struct workqueue_struct *addr_wq; |
63 | 64 | ||
65 | void rdma_addr_register_client(struct rdma_addr_client *client) | ||
66 | { | ||
67 | atomic_set(&client->refcount, 1); | ||
68 | init_completion(&client->comp); | ||
69 | } | ||
70 | EXPORT_SYMBOL(rdma_addr_register_client); | ||
71 | |||
72 | static inline void put_client(struct rdma_addr_client *client) | ||
73 | { | ||
74 | if (atomic_dec_and_test(&client->refcount)) | ||
75 | complete(&client->comp); | ||
76 | } | ||
77 | |||
78 | void rdma_addr_unregister_client(struct rdma_addr_client *client) | ||
79 | { | ||
80 | put_client(client); | ||
81 | wait_for_completion(&client->comp); | ||
82 | } | ||
83 | EXPORT_SYMBOL(rdma_addr_unregister_client); | ||
84 | |||
64 | int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, | 85 | int 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 | ||
267 | int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr, | 287 | int 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 | } |