aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/addr.c
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2006-10-31 14:12:59 -0500
committerRoland Dreier <rolandd@cisco.com>2006-11-02 17:26:04 -0500
commit7a118df3ea23820b9922a1b51cd2f24e464f4c17 (patch)
tree723e979c84263c52971494b7ba69cbee25f602bc /drivers/infiniband/core/addr.c
parent68586b67ab1a2fd618f79e29a06f10ae886f4b46 (diff)
RDMA/addr: Use client registration to fix module unload race
Require registration with ib_addr module to prevent caller from unloading while a callback is in progress. Signed-off-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/core/addr.c')
-rw-r--r--drivers/infiniband/core/addr.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 60d3fbdd216c..e11187ecc931 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{
@@ -229,6 +250,7 @@ static void process_req(void *data)
229 list_del(&req->list); 250 list_del(&req->list);
230 req->callback(req->status, &req->src_addr, req->addr, 251 req->callback(req->status, &req->src_addr, req->addr,
231 req->context); 252 req->context);
253 put_client(req->client);
232 kfree(req); 254 kfree(req);
233 } 255 }
234} 256}
@@ -264,7 +286,8 @@ static int addr_resolve_local(struct sockaddr_in *src_in,
264 return ret; 286 return ret;
265} 287}
266 288
267int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr, 289int rdma_resolve_ip(struct rdma_addr_client *client,
290 struct sockaddr *src_addr, struct sockaddr *dst_addr,
268 struct rdma_dev_addr *addr, int timeout_ms, 291 struct rdma_dev_addr *addr, int timeout_ms,
269 void (*callback)(int status, struct sockaddr *src_addr, 292 void (*callback)(int status, struct sockaddr *src_addr,
270 struct rdma_dev_addr *addr, void *context), 293 struct rdma_dev_addr *addr, void *context),
@@ -285,6 +308,8 @@ int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
285 req->addr = addr; 308 req->addr = addr;
286 req->callback = callback; 309 req->callback = callback;
287 req->context = context; 310 req->context = context;
311 req->client = client;
312 atomic_inc(&client->refcount);
288 313
289 src_in = (struct sockaddr_in *) &req->src_addr; 314 src_in = (struct sockaddr_in *) &req->src_addr;
290 dst_in = (struct sockaddr_in *) &req->dst_addr; 315 dst_in = (struct sockaddr_in *) &req->dst_addr;
@@ -305,6 +330,7 @@ int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
305 break; 330 break;
306 default: 331 default:
307 ret = req->status; 332 ret = req->status;
333 atomic_dec(&client->refcount);
308 kfree(req); 334 kfree(req);
309 break; 335 break;
310 } 336 }