diff options
| author | Sean Hefty <sean.hefty@intel.com> | 2005-09-01 12:28:03 -0400 |
|---|---|---|
| committer | Roland Dreier <rolandd@cisco.com> | 2005-09-07 12:48:52 -0400 |
| commit | 0b2b35f68140ceeb1b78ef85680198e63ebc8649 (patch) | |
| tree | 342c13bd8a1e1c071389df8ef9951a723cb4b270 | |
| parent | 1d6801f9dd3ebb054ae685153a01b1a4ec817f46 (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.c | 287 | ||||
| -rw-r--r-- | drivers/infiniband/core/ucm.h | 11 | ||||
| -rw-r--r-- | include/rdma/ib_user_cm.h | 72 |
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 | ||
| 73 | static struct semaphore ctx_id_mutex; | 73 | static struct semaphore ctx_id_mutex; |
| 74 | static struct idr ctx_id_table; | 74 | static struct idr ctx_id_table; |
| 75 | static int ctx_id_rover = 0; | ||
| 76 | 75 | ||
| 77 | static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id) | 76 | static 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 | ||
| 100 | static ssize_t ib_ucm_destroy_ctx(struct ib_ucm_file *file, int id) | 99 | static 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. */ | 104 | static 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 | ||
| 147 | static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) | 126 | static 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) |
| 165 | retry: | 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 | |||
| 182 | error: | 158 | error: |
| 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 | ||
| 222 | static void ib_ucm_event_req_get(struct ib_ucm_context *ctx, | 196 | static 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 | ||
| 262 | static 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 | |||
| 270 | static void ib_ucm_event_sidr_rep_get(struct ib_ucm_sidr_rep_event_resp *urep, | 233 | static 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 | ||
| 278 | static int ib_ucm_event_process(struct ib_ucm_context *ctx, | 241 | static 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, |
