aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2005-09-01 12:28:03 -0400
committerRoland Dreier <rolandd@cisco.com>2005-09-07 12:48:52 -0400
commit0b2b35f68140ceeb1b78ef85680198e63ebc8649 (patch)
tree342c13bd8a1e1c071389df8ef9951a723cb4b270
parent1d6801f9dd3ebb054ae685153a01b1a4ec817f46 (diff)
[PATCH] IB: Add user-supplied context to userspace CM ABI
- Add user specified context to all uCM events. Users will not retrieve any events associated with the context after destroying the corresponding cm_id. - Provide the ib_cm_init_qp_attr() call to userspace clients of the CM. This call may be used to set QP attributes properly before modifying the QP. - Fixes some error handling synchonization and cleanup issues. - Performs some minor code cleanup. Signed-off-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/infiniband/core/ucm.c287
-rw-r--r--drivers/infiniband/core/ucm.h11
-rw-r--r--include/rdma/ib_user_cm.h72
3 files changed, 261 insertions, 109 deletions
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 79595826ccc7..d0f0b0a2edd3 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -72,7 +72,6 @@ enum {
72 72
73static struct semaphore ctx_id_mutex; 73static struct semaphore ctx_id_mutex;
74static struct idr ctx_id_table; 74static struct idr ctx_id_table;
75static int ctx_id_rover = 0;
76 75
77static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id) 76static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
78{ 77{
@@ -97,33 +96,16 @@ static void ib_ucm_ctx_put(struct ib_ucm_context *ctx)
97 wake_up(&ctx->wait); 96 wake_up(&ctx->wait);
98} 97}
99 98
100static ssize_t ib_ucm_destroy_ctx(struct ib_ucm_file *file, int id) 99static inline int ib_ucm_new_cm_id(int event)
101{ 100{
102 struct ib_ucm_context *ctx; 101 return event == IB_CM_REQ_RECEIVED || event == IB_CM_SIDR_REQ_RECEIVED;
103 struct ib_ucm_event *uevent; 102}
104
105 down(&ctx_id_mutex);
106 ctx = idr_find(&ctx_id_table, id);
107 if (!ctx)
108 ctx = ERR_PTR(-ENOENT);
109 else if (ctx->file != file)
110 ctx = ERR_PTR(-EINVAL);
111 else
112 idr_remove(&ctx_id_table, ctx->id);
113 up(&ctx_id_mutex);
114
115 if (IS_ERR(ctx))
116 return PTR_ERR(ctx);
117
118 atomic_dec(&ctx->ref);
119 wait_event(ctx->wait, !atomic_read(&ctx->ref));
120 103
121 /* No new events will be generated after destroying the cm_id. */ 104static void ib_ucm_cleanup_events(struct ib_ucm_context *ctx)
122 if (!IS_ERR(ctx->cm_id)) 105{
123 ib_destroy_cm_id(ctx->cm_id); 106 struct ib_ucm_event *uevent;
124 107
125 /* Cleanup events not yet reported to the user. */ 108 down(&ctx->file->mutex);
126 down(&file->mutex);
127 list_del(&ctx->file_list); 109 list_del(&ctx->file_list);
128 while (!list_empty(&ctx->events)) { 110 while (!list_empty(&ctx->events)) {
129 111
@@ -133,15 +115,12 @@ static ssize_t ib_ucm_destroy_ctx(struct ib_ucm_file *file, int id)
133 list_del(&uevent->ctx_list); 115 list_del(&uevent->ctx_list);
134 116
135 /* clear incoming connections. */ 117 /* clear incoming connections. */
136 if (uevent->cm_id) 118 if (ib_ucm_new_cm_id(uevent->resp.event))
137 ib_destroy_cm_id(uevent->cm_id); 119 ib_destroy_cm_id(uevent->cm_id);
138 120
139 kfree(uevent); 121 kfree(uevent);
140 } 122 }
141 up(&file->mutex); 123 up(&ctx->file->mutex);
142
143 kfree(ctx);
144 return 0;
145} 124}
146 125
147static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) 126static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
@@ -153,36 +132,31 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
153 if (!ctx) 132 if (!ctx)
154 return NULL; 133 return NULL;
155 134
135 memset(ctx, 0, sizeof *ctx);
156 atomic_set(&ctx->ref, 1); 136 atomic_set(&ctx->ref, 1);
157 init_waitqueue_head(&ctx->wait); 137 init_waitqueue_head(&ctx->wait);
158 ctx->file = file; 138 ctx->file = file;
159
160 INIT_LIST_HEAD(&ctx->events); 139 INIT_LIST_HEAD(&ctx->events);
161 140
162 list_add_tail(&ctx->file_list, &file->ctxs); 141 do {
163 142 result = idr_pre_get(&ctx_id_table, GFP_KERNEL);
164 ctx_id_rover = (ctx_id_rover + 1) & INT_MAX; 143 if (!result)
165retry: 144 goto error;
166 result = idr_pre_get(&ctx_id_table, GFP_KERNEL);
167 if (!result)
168 goto error;
169 145
170 down(&ctx_id_mutex); 146 down(&ctx_id_mutex);
171 result = idr_get_new_above(&ctx_id_table, ctx, ctx_id_rover, &ctx->id); 147 result = idr_get_new(&ctx_id_table, ctx, &ctx->id);
172 up(&ctx_id_mutex); 148 up(&ctx_id_mutex);
149 } while (result == -EAGAIN);
173 150
174 if (result == -EAGAIN)
175 goto retry;
176 if (result) 151 if (result)
177 goto error; 152 goto error;
178 153
154 list_add_tail(&ctx->file_list, &file->ctxs);
179 ucm_dbg("Allocated CM ID <%d>\n", ctx->id); 155 ucm_dbg("Allocated CM ID <%d>\n", ctx->id);
180
181 return ctx; 156 return ctx;
157
182error: 158error:
183 list_del(&ctx->file_list);
184 kfree(ctx); 159 kfree(ctx);
185
186 return NULL; 160 return NULL;
187} 161}
188/* 162/*
@@ -219,12 +193,9 @@ static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
219 kpath->packet_life_time_selector; 193 kpath->packet_life_time_selector;
220} 194}
221 195
222static void ib_ucm_event_req_get(struct ib_ucm_context *ctx, 196static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq,
223 struct ib_ucm_req_event_resp *ureq,
224 struct ib_cm_req_event_param *kreq) 197 struct ib_cm_req_event_param *kreq)
225{ 198{
226 ureq->listen_id = ctx->id;
227
228 ureq->remote_ca_guid = kreq->remote_ca_guid; 199 ureq->remote_ca_guid = kreq->remote_ca_guid;
229 ureq->remote_qkey = kreq->remote_qkey; 200 ureq->remote_qkey = kreq->remote_qkey;
230 ureq->remote_qpn = kreq->remote_qpn; 201 ureq->remote_qpn = kreq->remote_qpn;
@@ -259,14 +230,6 @@ static void ib_ucm_event_rep_get(struct ib_ucm_rep_event_resp *urep,
259 urep->srq = krep->srq; 230 urep->srq = krep->srq;
260} 231}
261 232
262static void ib_ucm_event_sidr_req_get(struct ib_ucm_context *ctx,
263 struct ib_ucm_sidr_req_event_resp *ureq,
264 struct ib_cm_sidr_req_event_param *kreq)
265{
266 ureq->listen_id = ctx->id;
267 ureq->pkey = kreq->pkey;
268}
269
270static void ib_ucm_event_sidr_rep_get(struct ib_ucm_sidr_rep_event_resp *urep, 233static void ib_ucm_event_sidr_rep_get(struct ib_ucm_sidr_rep_event_resp *urep,
271 struct ib_cm_sidr_rep_event_param *krep) 234 struct ib_cm_sidr_rep_event_param *krep)
272{ 235{
@@ -275,15 +238,14 @@ static void ib_ucm_event_sidr_rep_get(struct ib_ucm_sidr_rep_event_resp *urep,
275 urep->qpn = krep->qpn; 238 urep->qpn = krep->qpn;
276}; 239};
277 240
278static int ib_ucm_event_process(struct ib_ucm_context *ctx, 241static int ib_ucm_event_process(struct ib_cm_event *evt,
279 struct ib_cm_event *evt,
280 struct ib_ucm_event *uvt) 242 struct ib_ucm_event *uvt)
281{ 243{
282 void *info = NULL; 244 void *info = NULL;
283 245
284 switch (evt->event) { 246 switch (evt->event) {
285 case IB_CM_REQ_RECEIVED: 247 case IB_CM_REQ_RECEIVED:
286 ib_ucm_event_req_get(ctx, &uvt->resp.u.req_resp, 248 ib_ucm_event_req_get(&uvt->resp.u.req_resp,