aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/Kconfig25
-rw-r--r--drivers/infiniband/core/Makefile5
-rw-r--r--drivers/infiniband/core/cm.c5
-rw-r--r--drivers/infiniband/core/mad_rmpp.c4
-rw-r--r--drivers/infiniband/core/sa_query.c30
-rw-r--r--drivers/infiniband/core/ucm.c287
-rw-r--r--drivers/infiniband/core/ucm.h11
-rw-r--r--drivers/infiniband/core/uverbs.h26
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c155
-rw-r--r--drivers/infiniband/core/uverbs_main.c98
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c45
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c2
-rw-r--r--include/rdma/ib_cm.h1
-rw-r--r--include/rdma/ib_mad.h21
-rw-r--r--include/rdma/ib_sa.h31
-rw-r--r--include/rdma/ib_user_cm.h72
-rw-r--r--include/rdma/ib_user_verbs.h21
17 files changed, 589 insertions, 250 deletions
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index 32cdfb30e9b4..325d502e25cd 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -8,15 +8,26 @@ config INFINIBAND
8 any protocols you wish to use as well as drivers for your 8 any protocols you wish to use as well as drivers for your
9 InfiniBand hardware. 9 InfiniBand hardware.
10 10
11config INFINIBAND_USER_VERBS 11config INFINIBAND_USER_MAD
12 tristate "InfiniBand userspace verbs support" 12 tristate "InfiniBand userspace MAD support"
13 depends on INFINIBAND 13 depends on INFINIBAND
14 ---help--- 14 ---help---
15 Userspace InfiniBand verbs support. This is the kernel side 15 Userspace InfiniBand Management Datagram (MAD) support. This
16 of userspace verbs, which allows userspace processes to 16 is the kernel side of the userspace MAD support, which allows
17 directly access InfiniBand hardware for fast-path 17 userspace processes to send and receive MADs. You will also
18 operations. You will also need libibverbs and a hardware 18 need libibumad from <http://www.openib.org>.
19 driver library from <http://www.openib.org>. 19
20config INFINIBAND_USER_ACCESS
21 tristate "InfiniBand userspace access (verbs and CM)"
22 depends on INFINIBAND
23 ---help---
24 Userspace InfiniBand access support. This enables the
25 kernel side of userspace verbs and the userspace
26 communication manager (CM). This allows userspace processes
27 to set up connections and directly access InfiniBand
28 hardware for fast-path operations. You will also need
29 libibverbs, libibcm and a hardware driver library from
30 <http://www.openib.org>.
20 31
21source "drivers/infiniband/hw/mthca/Kconfig" 32source "drivers/infiniband/hw/mthca/Kconfig"
22 33
diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
index 678a7e097f32..ec3353f24b27 100644
--- a/drivers/infiniband/core/Makefile
+++ b/drivers/infiniband/core/Makefile
@@ -1,6 +1,7 @@
1obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_sa.o \ 1obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_sa.o \
2 ib_cm.o ib_umad.o ib_ucm.o 2 ib_cm.o
3obj-$(CONFIG_INFINIBAND_USER_VERBS) += ib_uverbs.o 3obj-$(CONFIG_INFINIBAND_USER_MAD) += ib_umad.o
4obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o
4 5
5ib_core-y := packer.o ud_header.o verbs.o sysfs.o \ 6ib_core-y := packer.o ud_header.o verbs.o sysfs.o \
6 device.o fmr_pool.o cache.o 7 device.o fmr_pool.o cache.o
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 4de93ba274a6..54db6d4831f1 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -173,7 +173,8 @@ static int cm_alloc_msg(struct cm_id_private *cm_id_priv,
173 if (IS_ERR(ah)) 173 if (IS_ERR(ah))
174 return PTR_ERR(ah); 174 return PTR_ERR(ah);
175 175
176 m = ib_create_send_mad(mad_agent, 1, cm_id_priv->av.pkey_index, 176 m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn,
177 cm_id_priv->av.pkey_index,
177 ah, 0, sizeof(struct ib_mad_hdr), 178 ah, 0, sizeof(struct ib_mad_hdr),
178 sizeof(struct ib_mad)-sizeof(struct ib_mad_hdr), 179 sizeof(struct ib_mad)-sizeof(struct ib_mad_hdr),
179 GFP_ATOMIC); 180 GFP_ATOMIC);
@@ -536,6 +537,7 @@ struct ib_cm_id *ib_create_cm_id(ib_cm_handler cm_handler,
536 cm_id_priv->id.state = IB_CM_IDLE; 537 cm_id_priv->id.state = IB_CM_IDLE;
537 cm_id_priv->id.cm_handler = cm_handler; 538 cm_id_priv->id.cm_handler = cm_handler;
538 cm_id_priv->id.context = context; 539 cm_id_priv->id.context = context;
540 cm_id_priv->id.remote_cm_qpn = 1;
539 ret = cm_alloc_id(cm_id_priv); 541 ret = cm_alloc_id(cm_id_priv);
540 if (ret) 542 if (ret)
541 goto error; 543 goto error;
@@ -1313,6 +1315,7 @@ error3: atomic_dec(&cm_id_priv->refcount);
1313 cm_deref_id(listen_cm_id_priv); 1315 cm_deref_id(listen_cm_id_priv);
1314 cm_cleanup_timewait(cm_id_priv->timewait_info); 1316 cm_cleanup_timewait(cm_id_priv->timewait_info);
1315error2: kfree(cm_id_priv->timewait_info); 1317error2: kfree(cm_id_priv->timewait_info);
1318 cm_id_priv->timewait_info = NULL;
1316error1: ib_destroy_cm_id(&cm_id_priv->id); 1319error1: ib_destroy_cm_id(&cm_id_priv->id);
1317 return ret; 1320 return ret;
1318} 1321}
diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c
index 43fd805e0265..2bd8b1cc57c4 100644
--- a/drivers/infiniband/core/mad_rmpp.c
+++ b/drivers/infiniband/core/mad_rmpp.c
@@ -593,7 +593,8 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
593 rmpp_mad->rmpp_hdr.paylen_newwin = 593 rmpp_mad->rmpp_hdr.paylen_newwin =
594 cpu_to_be32(mad_send_wr->total_seg * 594 cpu_to_be32(mad_send_wr->total_seg *
595 (sizeof(struct ib_rmpp_mad) - 595 (sizeof(struct ib_rmpp_mad) -
596 offsetof(struct ib_rmpp_mad, data))); 596 offsetof(struct ib_rmpp_mad, data)) -
597 mad_send_wr->pad);
597 mad_send_wr->sg_list[0].length = sizeof(struct ib_rmpp_mad); 598 mad_send_wr->sg_list[0].length = sizeof(struct ib_rmpp_mad);
598 } else { 599 } else {
599 mad_send_wr->send_wr.num_sge = 2; 600 mad_send_wr->send_wr.num_sge = 2;
@@ -602,6 +603,7 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
602 mad_send_wr->sg_list[1].length = sizeof(struct ib_rmpp_mad) - 603 mad_send_wr->sg_list[1].length = sizeof(struct ib_rmpp_mad) -
603 mad_send_wr->data_offset; 604 mad_send_wr->data_offset;
604 mad_send_wr->sg_list[1].lkey = mad_send_wr->sg_list[0].lkey; 605 mad_send_wr->sg_list[1].lkey = mad_send_wr->sg_list[0].lkey;
606 rmpp_mad->rmpp_hdr.paylen_newwin = 0;
605 } 607 }
606 608
607 if (mad_send_wr->seg_num == mad_send_wr->total_seg) { 609 if (mad_send_wr->seg_num == mad_send_wr->total_seg) {
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 126ac80db7b8..78de2dd1a4f2 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -113,32 +113,6 @@ static DEFINE_IDR(query_idr);
113static spinlock_t tid_lock; 113static spinlock_t tid_lock;
114static u32 tid; 114static u32 tid;
115 115
116enum {
117 IB_SA_ATTR_CLASS_PORTINFO = 0x01,
118 IB_SA_ATTR_NOTICE = 0x02,
119 IB_SA_ATTR_INFORM_INFO = 0x03,
120 IB_SA_ATTR_NODE_REC = 0x11,
121 IB_SA_ATTR_PORT_INFO_REC = 0x12,
122 IB_SA_ATTR_SL2VL_REC = 0x13,
123 IB_SA_ATTR_SWITCH_REC = 0x14,
124 IB_SA_ATTR_LINEAR_FDB_REC = 0x15,
125 IB_SA_ATTR_RANDOM_FDB_REC = 0x16,
126 IB_SA_ATTR_MCAST_FDB_REC = 0x17,
127 IB_SA_ATTR_SM_INFO_REC = 0x18,
128 IB_SA_ATTR_LINK_REC = 0x20,
129 IB_SA_ATTR_GUID_INFO_REC = 0x30,
130 IB_SA_ATTR_SERVICE_REC = 0x31,
131 IB_SA_ATTR_PARTITION_REC = 0x33,
132 IB_SA_ATTR_RANGE_REC = 0x34,
133 IB_SA_ATTR_PATH_REC = 0x35,
134 IB_SA_ATTR_VL_ARB_REC = 0x36,
135 IB_SA_ATTR_MC_GROUP_REC = 0x37,
136 IB_SA_ATTR_MC_MEMBER_REC = 0x38,
137 IB_SA_ATTR_TRACE_REC = 0x39,
138 IB_SA_ATTR_MULTI_PATH_REC = 0x3a,
139 IB_SA_ATTR_SERVICE_ASSOC_REC = 0x3b
140};
141
142#define PATH_REC_FIELD(field) \ 116#define PATH_REC_FIELD(field) \
143 .struct_offset_bytes = offsetof(struct ib_sa_path_rec, field), \ 117 .struct_offset_bytes = offsetof(struct ib_sa_path_rec, field), \
144 .struct_size_bytes = sizeof ((struct ib_sa_path_rec *) 0)->field, \ 118 .struct_size_bytes = sizeof ((struct ib_sa_path_rec *) 0)->field, \
@@ -431,8 +405,8 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event
431 event->event == IB_EVENT_LID_CHANGE || 405 event->event == IB_EVENT_LID_CHANGE ||
432 event->event == IB_EVENT_PKEY_CHANGE || 406 event->event == IB_EVENT_PKEY_CHANGE ||
433 event->event == IB_EVENT_SM_CHANGE) { 407 event->event == IB_EVENT_SM_CHANGE) {
434 struct ib_sa_device *sa_dev = 408 struct ib_sa_device *sa_dev;
435 ib_get_client_data(event->device, &sa_client); 409 sa_dev = container_of(handler, typeof(*sa_dev), event_handler);
436 410
437 schedule_work(&sa_dev->port[event->element.port_num - 411 schedule_work(&sa_dev->port[event->element.port_num -
438 sa_dev->start_port].update_task); 412 sa_dev->start_port].update_task);
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,
287 &evt->param.req_rcvd); 249 &evt->param.req_rcvd);
288 uvt->data_len = IB_CM_REQ_PRIVATE_DATA_SIZE; 250 uvt->data_len = IB_CM_REQ_PRIVATE_DATA_SIZE;
289 uvt->resp.present = IB_UCM_PRES_PRIMARY; 251 uvt->resp.present = IB_UCM_PRES_PRIMARY;
@@ -331,8 +293,8 @@ static int ib_ucm_event_process(struct ib_ucm_context *ctx,
331 info = evt->param.apr_rcvd.apr_info; 293 info = evt->param.apr_rcvd.apr_info;
332 break; 294 break;
333 case IB_CM_SIDR_REQ_RECEIVED: 295 case IB_CM_SIDR_REQ_RECEIVED:
334 ib_ucm_event_sidr_req_get(ctx, &uvt->resp.u.sidr_req_resp, 296 uvt->resp.u.sidr_req_resp.pkey =
335 &evt->param.sidr_req_rcvd); 297 evt->param.sidr_req_rcvd.pkey;
336 uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE; 298 uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE;
337 break; 299 break;
338 case IB_CM_SIDR_REP_RECEIVED: 300 case IB_CM_SIDR_REP_RECEIVED:
@@ -378,31 +340,24 @@ static int ib_ucm_event_handler(struct ib_cm_id *cm_id,
378 struct ib_ucm_event *uevent; 340 struct ib_ucm_event *uevent;
379 struct ib_ucm_context *ctx; 341 struct ib_ucm_context *ctx;
380 int result = 0; 342 int result = 0;
381 int id;
382 343
383 ctx = cm_id->context; 344 ctx = cm_id->context;
384 345
385 if (event->event == IB_CM_REQ_RECEIVED ||
386 event->event == IB_CM_SIDR_REQ_RECEIVED)
387 id = IB_UCM_CM_ID_INVALID;
388 else
389 id = ctx->id;
390
391 uevent = kmalloc(sizeof(*uevent), GFP_KERNEL); 346 uevent = kmalloc(sizeof(*uevent), GFP_KERNEL);
392 if (!uevent) 347 if (!uevent)
393 goto err1; 348 goto err1;
394 349
395 memset(uevent, 0, sizeof(*uevent)); 350 memset(uevent, 0, sizeof(*uevent));
396 uevent->resp.id = id; 351 uevent->ctx = ctx;
352 uevent->cm_id = cm_id;
353 uevent->resp.uid = ctx->uid;
354 uevent->resp.id = ctx->id;
397 uevent->resp.event = event->event; 355 uevent->resp.event = event->event;
398 356
399 result = ib_ucm_event_process(ctx, event, uevent); 357 result = ib_ucm_event_process(event, uevent);
400 if (result) 358 if (result)
401 goto err2; 359 goto err2;
402 360
403 uevent->ctx = ctx;
404 uevent->cm_id = (id == IB_UCM_CM_ID_INVALID) ? cm_id : NULL;
405
406 down(&ctx->file->mutex); 361 down(&ctx->file->mutex);
407 list_add_tail(&uevent->file_list, &ctx->file->events); 362 list_add_tail(&uevent->file_list, &ctx->file->events);
408 list_add_tail(&uevent->ctx_list, &ctx->events); 363 list_add_tail(&uevent->ctx_list, &ctx->events);
@@ -414,7 +369,7 @@ err2:
414 kfree(uevent); 369 kfree(uevent);
415err1: 370err1:
416 /* Destroy new cm_id's */ 371 /* Destroy new cm_id's */
417 return (id == IB_UCM_CM_ID_INVALID); 372 return ib_ucm_new_cm_id(event->event);
418} 373}
419 374
420static ssize_t ib_ucm_event(struct ib_ucm_file *file, 375static ssize_t ib_ucm_event(struct ib_ucm_file *file,
@@ -423,7 +378,7 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
423{ 378{
424 struct ib_ucm_context *ctx; 379 struct ib_ucm_context *ctx;
425 struct ib_ucm_event_get cmd; 380 struct ib_ucm_event_get cmd;
426 struct ib_ucm_event *uevent = NULL; 381 struct ib_ucm_event *uevent;
427 int result = 0; 382 int result = 0;
428 DEFINE_WAIT(wait); 383 DEFINE_WAIT(wait);
429 384
@@ -436,7 +391,6 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
436 * wait 391 * wait
437 */ 392 */
438 down(&file->mutex); 393 down(&file->mutex);
439
440 while (list_empty(&file->events)) { 394 while (list_empty(&file->events)) {
441 395
442 if (file->filp->f_flags & O_NONBLOCK) { 396 if (file->filp->f_flags & O_NONBLOCK) {
@@ -463,21 +417,18 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
463 417
464 uevent = list_entry(file->events.next, struct ib_ucm_event, file_list); 418 uevent = list_entry(file->events.next, struct ib_ucm_event, file_list);
465 419
466 if (!uevent->cm_id) 420 if (ib_ucm_new_cm_id(uevent->resp.event)) {
467 goto user; 421 ctx = ib_ucm_ctx_alloc(file);
422 if (!ctx) {
423 result = -ENOMEM;
424 goto done;
425 }
468 426
469 ctx = ib_ucm_ctx_alloc(file); 427 ctx->cm_id = uevent->cm_id;
470 if (!ctx) { 428 ctx->cm_id->context = ctx;
471 result = -ENOMEM; 429 uevent->resp.id = ctx->id;
472 goto done;
473 } 430 }
474 431
475 ctx->cm_id = uevent->cm_id;
476 ctx->cm_id->context = ctx;
477
478 uevent->resp.id = ctx->id;
479
480user:
481 if (copy_to_user((void __user *)(unsigned long)cmd.response, 432 if (copy_to_user((void __user *)(unsigned long)cmd.response,
482 &uevent->resp, sizeof(uevent->resp))) { 433 &uevent->resp, sizeof(uevent->resp))) {
483 result = -EFAULT; 434 result = -EFAULT;
@@ -485,12 +436,10 @@ user:
485 } 436 }
486 437
487 if (uevent->data) { 438 if (uevent->data) {
488
489 if (cmd.data_len < uevent->data_len) { 439 if (cmd.data_len < uevent->data_len) {
490 result = -ENOMEM; 440 result = -ENOMEM;
491 goto done; 441 goto done;
492 } 442 }
493
494 if (copy_to_user((void __user *)(unsigned long)cmd.data, 443 if (copy_to_user((void __user *)(unsigned long)cmd.data,
495 uevent->data, uevent->data_len)) { 444 uevent->data, uevent->data_len)) {
496 result = -EFAULT; 445 result = -EFAULT;
@@ -499,12 +448,10 @@ user:
499 } 448 }
500 449
501 if (uevent->info) { 450 if (uevent->info) {
502
503 if (cmd.info_len < uevent->info_len) { 451 if (cmd.info_len < uevent->info_len) {
504 result = -ENOMEM; 452 result = -ENOMEM;
505 goto done; 453 goto done;
506 } 454 }
507
508 if (copy_to_user((void __user *)(unsigned long)cmd.info, 455 if (copy_to_user((void __user *)(unsigned long)cmd.info,
509 uevent->info, uevent->info_len)) { 456 uevent->info, uevent->info_len)) {
510 result = -EFAULT; 457 result = -EFAULT;
@@ -514,6 +461,7 @@ user:
514 461
515 list_del(&uevent->file_list); 462 list_del(&uevent->file_list);
516 list_del(&uevent->ctx_list); 463 list_del(&uevent->ctx_list);
464 uevent->ctx->events_reported++;
517 465
518 kfree(uevent->data); 466 kfree(uevent->data);
519 kfree(uevent->info); 467 kfree(uevent->info);
@@ -545,6 +493,7 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
545 if (!ctx) 493 if (!ctx)
546 return -ENOMEM; 494 return -ENOMEM;
547 495
496 ctx->uid = cmd.uid;
548 ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler, ctx); 497 ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler, ctx);
549 if (IS_ERR(ctx->cm_id)) { 498 if (IS_ERR(ctx->cm_id)) {
550 result = PTR_ERR(ctx->cm_id); 499 result = PTR_ERR(ctx->cm_id);
@@ -561,7 +510,14 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
561 return 0; 510 return 0;
562 511
563err: 512err:
564 ib_ucm_destroy_ctx(file, ctx->id); 513 down(&ctx_id_mutex);
514 idr_remove(&ctx_id_table, ctx->id);
515 up(&ctx_id_mutex);
516
517 if (!IS_ERR(ctx->cm_id))
518 ib_destroy_cm_id(ctx->cm_id);
519
520 kfree(ctx);
565 return result; 521 return result;
566} 522}
567 523
@@ -570,11 +526,44 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
570 int in_len, int out_len) 526 int in_len, int out_len)
571{ 527{
572 struct ib_ucm_destroy_id cmd; 528 struct ib_ucm_destroy_id cmd;
529 struct ib_ucm_destroy_id_resp resp;
530 struct ib_ucm_context *ctx;
531 int result = 0;
532
533 if (out_len < sizeof(resp))
534 return -ENOSPC;
573 535
574 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 536 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
575 return -EFAULT; 537 return -EFAULT;
576 538
577 return ib_ucm_destroy_ctx(file, cmd.id); 539 down(&ctx_id_mutex);
540 ctx = idr_find(&ctx_id_table, cmd.id);
541 if (!ctx)
542 ctx = ERR_PTR(-ENOENT);
543 else if (ctx->file != file)
544 ctx = ERR_PTR(-EINVAL);
545 else
546 idr_remove(&ctx_id_table, ctx->id);
547 up(&ctx_id_mutex);
548
549 if (IS_ERR(ctx))
550 return PTR_ERR(ctx);
551
552 atomic_dec(&ctx->ref);
553 wait_event(ctx->wait, !atomic_read(&ctx->ref));
554
555 /* No new events will be generated after destroying the cm_id. */
556 ib_destroy_cm_id(ctx->cm_id);
557 /* Cleanup events not yet reported to the user. */
558 ib_ucm_cleanup_events(ctx);
559
560 resp.events_reported = ctx->events_reported;
561 if (copy_to_user((void __user *)(unsigned long)cmd.response,
562 &resp, sizeof(resp)))
563 result = -EFAULT;
564
565 kfree(ctx);
566 return result;
578} 567}
579 568
580static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file, 569static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
@@ -609,6 +598,98 @@ static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
609 return result; 598 return result;
610} 599}
611 600
601static void ib_ucm_copy_ah_attr(struct ib_ucm_ah_attr *dest_attr,
602 struct ib_ah_attr *src_attr)
603{
604 memcpy(dest_attr->grh_dgid, src_attr->grh.dgid.raw,
605 sizeof src_attr->grh.dgid);
606 dest_attr->grh_flow_label = src_attr->grh.flow_label;
607 dest_attr->grh_sgid_index = src_attr->grh.sgid_index;
608 dest_attr->grh_hop_limit = src_attr->grh.hop_limit;
609 dest_attr->grh_traffic_class = src_attr->grh.traffic_class;
610
611 dest_attr->dlid = src_attr->dlid;
612 dest_attr->sl = src_attr->sl;
613 dest_attr->src_path_bits = src_attr->src_path_bits;
614 dest_attr->static_rate = src_attr->static_rate;
615 dest_attr->is_global = (src_attr->ah_flags & IB_AH_GRH);
616 dest_attr->port_num = src_attr->port_num;
617}
618
619static void ib_ucm_copy_qp_attr(struct ib_ucm_init_qp_attr_resp *dest_attr,
620 struct ib_qp_attr *src_attr)
621{
622 dest_attr->cur_qp_state = src_attr->cur_qp_state;
623 dest_attr->path_mtu = src_attr->path_mtu;
624 dest_attr->path_mig_state = src_attr->path_mig_state;
625 dest_attr->qkey = src_attr->qkey;
626 dest_attr->rq_psn = src_attr->rq_psn;
627 dest_attr->sq_psn = src_attr->sq_psn;
628 dest_attr->dest_qp_num = src_attr->dest_qp_num;
629 dest_attr->qp_access_flags = src_attr->qp_access_flags;
630
631 dest_attr->max_send_wr = src_attr->cap.max_send_wr;
632 dest_attr->max_recv_wr = src_attr->cap.max_recv_wr;
633 dest_attr->max_send_sge = src_attr->cap.max_send_sge;
634 dest_attr->max_recv_sge = src_attr->cap.max_recv_sge;
635 dest_attr->max_inline_data = src_attr->cap.max_inline_data;
636
637 ib_ucm_copy_ah_attr(&dest_attr->ah_attr, &src_attr->ah_attr);
638 ib_ucm_copy_ah_attr(&dest_attr->alt_ah_attr, &src_attr->alt_ah_attr);
639
640 dest_attr->pkey_index = src_attr->pkey_index;
641 dest_attr->alt_pkey_index = src_attr->alt_pkey_index;
642 dest_attr->en_sqd_async_notify = src_attr->en_sqd_async_notify;
643 dest_attr->sq_draining = src_attr->sq_draining;
644 dest_attr->max_rd_atomic = src_attr->max_rd_atomic;
645 dest_attr->max_dest_rd_atomic = src_attr->max_dest_rd_atomic;
646 dest_attr->min_rnr_timer = src_attr->min_rnr_timer;
647 dest_attr->port_num = src_attr->port_num;
648 dest_attr->timeout = src_attr->timeout;
649 dest_attr->retry_cnt = src_attr->retry_cnt;
650 dest_attr->rnr_retry = src_attr->rnr_retry;
651 dest_attr->alt_port_num = src_attr->alt_port_num;
652 dest_attr->alt_timeout = src_attr->alt_timeout;
653}
654
655static ssize_t ib_ucm_init_qp_attr(struct ib_ucm_file *file,
656 const char __user *inbuf,
657 int in_len, int out_len)
658{
659 struct ib_ucm_init_qp_attr_resp resp;
660 struct ib_ucm_init_qp_attr cmd;
661 struct ib_ucm_context *ctx;
662 struct ib_qp_attr qp_attr;
663 int result = 0;
664
665 if (out_len < sizeof(resp))
666 return -ENOSPC;
667
668 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
669 return -EFAULT;
670
671 ctx = ib_ucm_ctx_get(file, cmd.id);
672 if (IS_ERR(ctx))
673 return PTR_ERR(ctx);
674
675 resp.qp_attr_mask = 0;
676 memset(&qp_attr, 0, sizeof qp_attr);
677 qp_attr.qp_state = cmd.qp_state;
678 result = ib_cm_init_qp_attr(ctx->cm_id, &qp_attr, &resp.qp_attr_mask);
679 if (result)
680 goto out;
681
682 ib_ucm_copy_qp_attr(&resp, &qp_attr);
683
684 if (copy_to_user((void __user *)(unsigned long)cmd.response,
685 &resp, sizeof(resp)))
686 result = -EFAULT;
687
688out:
689 ib_ucm_ctx_put(ctx);
690 return result;
691}
692
612static ssize_t ib_ucm_listen(struct ib_ucm_file *file, 693static ssize_t ib_ucm_listen(struct ib_ucm_file *file,
613 const char __user *inbuf, 694 const char __user *inbuf,
614 int in_len, int out_len) 695 int in_len, int out_len)
@@ -808,6 +889,7 @@ static ssize_t ib_ucm_send_rep(struct ib_ucm_file *file,
808 889
809 ctx = ib_ucm_ctx_get(file, cmd.id); 890 ctx = ib_ucm_ctx_get(file, cmd.id);
810 if (!IS_ERR(ctx)) { 891 if (!IS_ERR(ctx)) {
892 ctx->uid = cmd.uid;
811 result = ib_send_cm_rep(ctx->cm_id, &param); 893 result = ib_send_cm_rep(ctx->cm_id, &param);
812 ib_ucm_ctx_put(ctx); 894 ib_ucm_ctx_put(ctx);
813 } else 895 } else
@@ -1086,6 +1168,7 @@ static ssize_t (*ucm_cmd_table[])(struct ib_ucm_file *file,
1086 [IB_USER_CM_CMD_SEND_SIDR_REQ] = ib_ucm_send_sidr_req, 1168 [IB_USER_CM_CMD_SEND_SIDR_REQ] = ib_ucm_send_sidr_req,
1087 [IB_USER_CM_CMD_SEND_SIDR_REP] = ib_ucm_send_sidr_rep, 1169 [IB_USER_CM_CMD_SEND_SIDR_REP] = ib_ucm_send_sidr_rep,
1088 [IB_USER_CM_CMD_EVENT] = ib_ucm_event, 1170 [IB_USER_CM_CMD_EVENT] = ib_ucm_event,
1171 [IB_USER_CM_CMD_INIT_QP_ATTR] = ib_ucm_init_qp_attr,
1089}; 1172};
1090 1173
1091static ssize_t ib_ucm_write(struct file *filp, const char __user *buf, 1174static ssize_t ib_ucm_write(struct file *filp, const char __user *buf,
@@ -1161,12 +1244,18 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
1161 1244
1162 down(&file->mutex); 1245 down(&file->mutex);
1163 while (!list_empty(&file->ctxs)) { 1246 while (!list_empty(&file->ctxs)) {
1164
1165 ctx = list_entry(file->ctxs.next, 1247 ctx = list_entry(file->ctxs.next,
1166 struct ib_ucm_context, file_list); 1248 struct ib_ucm_context, file_list);
1167
1168 up(&file->mutex); 1249 up(&file->mutex);
1169 ib_ucm_destroy_ctx(file, ctx->id); 1250
1251 down(&ctx_id_mutex);
1252 idr_remove(&ctx_id_table, ctx->id);
1253 up(&ctx_id_mutex);
1254
1255 ib_destroy_cm_id(ctx->cm_id);
1256 ib_ucm_cleanup_events(ctx);
1257 kfree(ctx);
1258
1170 down(&file->mutex); 1259 down(&file->mutex);
1171 } 1260 }
1172 up(&file->mutex); 1261 up(&file->mutex);
diff --git a/drivers/infiniband/core/ucm.h b/drivers/infiniband/core/ucm.h
index c8819b928a1b..f46f37bc1201 100644
--- a/drivers/infiniband/core/ucm.h
+++ b/drivers/infiniband/core/ucm.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2005 Topspin Communications. All rights reserved. 2 * Copyright (c) 2005 Topspin Communications. All rights reserved.
3 * Copyright (c) 2005 Intel Corporation. All rights reserved.
3 * 4 *
4 * This software is available to you under a choice of one of two 5 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU 6 * licenses. You may choose to be licensed under the terms of the GNU
@@ -43,8 +44,6 @@
43#include <rdma/ib_cm.h> 44#include <rdma/ib_cm.h>
44#include <rdma/ib_user_cm.h> 45#include <rdma/ib_user_cm.h>
45 46
46#define IB_UCM_CM_ID_INVALID 0xffffffff
47
48struct ib_ucm_file { 47struct ib_ucm_file {
49 struct semaphore mutex; 48 struct semaphore mutex;
50 struct file *filp; 49 struct file *filp;
@@ -58,9 +57,11 @@ struct ib_ucm_context {
58 int id; 57 int id;
59 wait_queue_head_t wait; 58 wait_queue_head_t wait;
60 atomic_t ref; 59 atomic_t ref;
60 int events_reported;
61 61
62 struct ib_ucm_file *file; 62 struct ib_ucm_file *file;
63 struct ib_cm_id *cm_id; 63 struct ib_cm_id *cm_id;
64 __u64 uid;
64 65
65 struct list_head events; /* list of pending events. */ 66 struct list_head events; /* list of pending events. */
66 struct list_head file_list; /* member in file ctx list */ 67 struct list_head file_list; /* member in file ctx list */
@@ -71,16 +72,12 @@ struct ib_ucm_event {
71 struct list_head file_list; /* member in file event list */ 72 struct list_head file_list; /* member in file event list */
72 struct list_head ctx_list; /* member in ctx event list */ 73 struct list_head ctx_list; /* member in ctx event list */
73 74
75 struct ib_cm_id *cm_id;
74 struct ib_ucm_event_resp resp; 76 struct ib_ucm_event_resp resp;
75 void *data; 77 void *data;
76 void *info; 78 void *info;
77 int data_len; 79 int data_len;
78 int info_len; 80 int info_len;
79 /*
80 * new connection identifiers needs to be saved until
81 * userspace can get a handle on them.
82 */
83 struct ib_cm_id *cm_id;
84}; 81};
85 82
86#endif /* UCM_H */ 83#endif /* UCM_H */
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 180b3d4765e4..b1897bed14ad 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -76,20 +76,28 @@ struct ib_uverbs_file {
76 struct ib_uverbs_event_file comp_file[1]; 76 struct ib_uverbs_event_file comp_file[1];
77}; 77};
78 78
79struct ib_uverbs_async_event { 79struct ib_uverbs_event {
80 struct ib_uverbs_async_event_desc desc; 80 union {
81 struct ib_uverbs_async_event_desc async;
82 struct ib_uverbs_comp_event_desc comp;
83 } desc;
81 struct list_head list; 84 struct list_head list;
85 struct list_head obj_list;
86 u32 *counter;
82}; 87};
83 88
84struct ib_uverbs_comp_event { 89struct ib_uevent_object {
85 struct ib_uverbs_comp_event_desc desc; 90 struct ib_uobject uobject;
86 struct list_head list; 91 struct list_head event_list;
92 u32 events_reported;
87}; 93};
88 94
89struct ib_uobject_mr { 95struct ib_ucq_object {
90 struct ib_uobject uobj; 96 struct ib_uobject uobject;
91 struct page *page_list; 97 struct list_head comp_list;
92 struct scatterlist *sg_list; 98 struct list_head async_list;
99 u32 comp_events_reported;
100 u32 async_events_reported;
93}; 101};
94 102
95extern struct semaphore ib_uverbs_idr_mutex; 103extern struct semaphore ib_uverbs_idr_mutex;
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index ebccf9f38af9..e91ebde46481 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -590,7 +590,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
590 struct ib_uverbs_create_cq cmd; 590 struct ib_uverbs_create_cq cmd;
591 struct ib_uverbs_create_cq_resp resp; 591 struct ib_uverbs_create_cq_resp resp;
592 struct ib_udata udata; 592 struct ib_udata udata;
593 struct ib_uobject *uobj; 593 struct ib_ucq_object *uobj;
594 struct ib_cq *cq; 594 struct ib_cq *cq;
595 int ret; 595 int ret;
596 596
@@ -611,8 +611,12 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
611 if (!uobj) 611 if (!uobj)
612 return -ENOMEM; 612 return -ENOMEM;
613 613
614 uobj->user_handle = cmd.user_handle; 614 uobj->uobject.user_handle = cmd.user_handle;
615 uobj->context = file->ucontext; 615 uobj->uobject.context = file->ucontext;
616 uobj->comp_events_reported = 0;
617 uobj->async_events_reported = 0;
618 INIT_LIST_HEAD(&uobj->comp_list);
619 INIT_LIST_HEAD(&uobj->async_list);
616 620
617 cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe, 621 cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe,
618 file->ucontext, &udata); 622 file->ucontext, &udata);
@@ -622,7 +626,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
622 } 626 }
623 627
624 cq->device = file->device->ib_dev; 628 cq->device = file->device->ib_dev;
625 cq->uobject = uobj; 629 cq->uobject = &uobj->uobject;
626 cq->comp_handler = ib_uverbs_comp_handler; 630 cq->comp_handler = ib_uverbs_comp_handler;
627 cq->event_handler = ib_uverbs_cq_event_handler; 631 cq->event_handler = ib_uverbs_cq_event_handler;
628 cq->cq_context = file; 632 cq->cq_context = file;
@@ -635,7 +639,7 @@ retry:
635 } 639 }
636 640
637 down(&ib_uverbs_idr_mutex); 641 down(&ib_uverbs_idr_mutex);
638 ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->id); 642 ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id);
639 up(&ib_uverbs_idr_mutex); 643 up(&ib_uverbs_idr_mutex);
640 644
641 if (ret == -EAGAIN) 645 if (ret == -EAGAIN)
@@ -644,11 +648,11 @@ retry:
644 goto err_cq; 648 goto err_cq;
645 649
646 spin_lock_irq(&file->ucontext->lock); 650 spin_lock_irq(&file->ucontext->lock);
647 list_add_tail(&uobj->list, &file->ucontext->cq_list); 651 list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
648 spin_unlock_irq(&file->ucontext->lock); 652 spin_unlock_irq(&file->ucontext->lock);
649 653
650 memset(&resp, 0, sizeof resp); 654 memset(&resp, 0, sizeof resp);
651 resp.cq_handle = uobj->id; 655 resp.cq_handle = uobj->uobject.id;
652 resp.cqe = cq->cqe; 656 resp.cqe = cq->cqe;
653 657
654 if (copy_to_user((void __user *) (unsigned long) cmd.response, 658 if (copy_to_user((void __user *) (unsigned long) cmd.response,
@@ -661,11 +665,11 @@ retry:
661 665
662err_list: 666err_list:
663 spin_lock_irq(&file->ucontext->lock); 667 spin_lock_irq(&file->ucontext->lock);
664 list_del(&uobj->list); 668 list_del(&uobj->uobject.list);
665 spin_unlock_irq(&file->ucontext->lock); 669 spin_unlock_irq(&file->ucontext->lock);
666 670
667 down(&ib_uverbs_idr_mutex); 671 down(&ib_uverbs_idr_mutex);
668 idr_remove(&ib_uverbs_cq_idr, uobj->id); 672 idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
669 up(&ib_uverbs_idr_mutex); 673 up(&ib_uverbs_idr_mutex);
670 674
671err_cq: 675err_cq:
@@ -680,21 +684,27 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
680 const char __user *buf, int in_len, 684 const char __user *buf, int in_len,
681 int out_len) 685 int out_len)
682{ 686{
683 struct ib_uverbs_destroy_cq cmd; 687 struct ib_uverbs_destroy_cq cmd;
684 struct ib_cq *cq; 688 struct ib_uverbs_destroy_cq_resp resp;
685 struct ib_uobject *uobj; 689 struct ib_cq *cq;
686 int ret = -EINVAL; 690 struct ib_ucq_object *uobj;
691 struct ib_uverbs_event *evt, *tmp;
692 u64 user_handle;
693 int ret = -EINVAL;
687 694
688 if (copy_from_user(&cmd, buf, sizeof cmd)) 695 if (copy_from_user(&cmd, buf, sizeof cmd))
689 return -EFAULT; 696 return -EFAULT;
690 697
698 memset(&resp, 0, sizeof resp);
699
691 down(&ib_uverbs_idr_mutex); 700 down(&ib_uverbs_idr_mutex);
692 701
693 cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); 702 cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
694 if (!cq || cq->uobject->context != file->ucontext) 703 if (!cq || cq->uobject->context != file->ucontext)
695 goto out; 704 goto out;
696 705
697 uobj = cq->uobject; 706 user_handle = cq->uobject->user_handle;
707 uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
698 708
699 ret = ib_destroy_cq(cq); 709 ret = ib_destroy_cq(cq);
700 if (ret) 710 if (ret)
@@ -703,11 +713,32 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
703 idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); 713 idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
704 714
705 spin_lock_irq(&file->ucontext->lock); 715 spin_lock_irq(&file->ucontext->lock);
706 list_del(&uobj->list); 716 list_del(&uobj->uobject.list);
707 spin_unlock_irq(&file->ucontext->lock); 717 spin_unlock_irq(&file->ucontext->lock);
708 718
719 spin_lock_irq(&file->comp_file[0].lock);
720 list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
721 list_del(&evt->list);
722 kfree(evt);
723 }
724 spin_unlock_irq(&file->comp_file[0].lock);
725
726 spin_lock_irq(&file->async_file.lock);
727 list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {
728 list_del(&evt->list);
729 kfree(evt);
730 }
731 spin_unlock_irq(&file->async_file.lock);
732
733 resp.comp_events_reported = uobj->comp_events_reported;
734 resp.async_events_reported = uobj->async_events_reported;
735
709 kfree(uobj); 736 kfree(uobj);
710 737
738 if (copy_to_user((void __user *) (unsigned long) cmd.response,
739 &resp, sizeof resp))
740 ret = -EFAULT;
741
711out: 742out:
712 up(&ib_uverbs_idr_mutex); 743 up(&ib_uverbs_idr_mutex);
713 744
@@ -721,7 +752,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
721 struct ib_uverbs_create_qp cmd; 752 struct ib_uverbs_create_qp cmd;
722 struct ib_uverbs_create_qp_resp resp; 753 struct ib_uverbs_create_qp_resp resp;
723 struct ib_udata udata; 754 struct ib_udata udata;
724 struct ib_uobject *uobj; 755 struct ib_uevent_object *uobj;
725 struct ib_pd *pd; 756 struct ib_pd *pd;
726 struct ib_cq *scq, *rcq; 757 struct ib_cq *scq, *rcq;
727 struct ib_srq *srq; 758 struct ib_srq *srq;
@@ -772,8 +803,10 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
772 attr.cap.max_recv_sge = cmd.max_recv_sge; 803 attr.cap.max_recv_sge = cmd.max_recv_sge;
773 attr.cap.max_inline_data = cmd.max_inline_data; 804 attr.cap.max_inline_data = cmd.max_inline_data;
774 805
775 uobj->user_handle = cmd.user_handle; 806 uobj->uobject.user_handle = cmd.user_handle;
776 uobj->context = file->ucontext; 807 uobj->uobject.context = file->ucontext;
808 uobj->events_reported = 0;
809 INIT_LIST_HEAD(&uobj->event_list);
777 810
778 qp = pd->device->create_qp(pd, &attr, &udata); 811 qp = pd->device->create_qp(pd, &attr, &udata);
779 if (IS_ERR(qp)) { 812 if (IS_ERR(qp)) {
@@ -786,7 +819,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
786 qp->send_cq = attr.send_cq; 819 qp->send_cq = attr.send_cq;
787 qp->recv_cq = attr.recv_cq; 820 qp->recv_cq = attr.recv_cq;
788 qp->srq = attr.srq; 821 qp->srq = attr.srq;
789 qp->uobject = uobj; 822 qp->uobject = &uobj->uobject;
790 qp->event_handler = attr.event_handler; 823 qp->event_handler = attr.event_handler;
791 qp->qp_context = attr.qp_context; 824 qp->qp_context = attr.qp_context;
792 qp->qp_type = attr.qp_type; 825 qp->qp_type = attr.qp_type;
@@ -805,17 +838,17 @@ retry:
805 goto err_destroy; 838 goto err_destroy;
806 } 839 }
807 840
808 ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->id); 841 ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uobject.id);
809 842
810 if (ret == -EAGAIN) 843 if (ret == -EAGAIN)
811 goto retry; 844 goto retry;
812 if (ret) 845 if (ret)
813 goto err_destroy; 846 goto err_destroy;
814 847
815 resp.qp_handle = uobj->id; 848 resp.qp_handle = uobj->uobject.id;
816 849
817 spin_lock_irq(&file->ucontext->lock); 850 spin_lock_irq(&file->ucontext->lock);
818 list_add_tail(&uobj->list, &file->ucontext->qp_list); 851 list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
819 spin_unlock_irq(&file->ucontext->lock); 852 spin_unlock_irq(&file->ucontext->lock);
820 853
821 if (copy_to_user((void __user *) (unsigned long) cmd.response, 854 if (copy_to_user((void __user *) (unsigned long) cmd.response,
@@ -830,7 +863,7 @@ retry:
830 863
831err_list: 864err_list:
832 spin_lock_irq(&file->ucontext->lock); 865 spin_lock_irq(&file->ucontext->lock);
833 list_del(&uobj->list); 866 list_del(&uobj->uobject.list);
834 spin_unlock_irq(&file->ucontext->lock); 867 spin_unlock_irq(&file->ucontext->lock);
835 868
836err_destroy: 869err_destroy:
@@ -930,21 +963,25 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
930 const char __user *buf, int in_len, 963 const char __user *buf, int in_len,
931 int out_len) 964 int out_len)
932{ 965{
933 struct ib_uverbs_destroy_qp cmd; 966 struct ib_uverbs_destroy_qp cmd;
934 struct ib_qp *qp; 967 struct ib_uverbs_destroy_qp_resp resp;
935 struct ib_uobject *uobj; 968 struct ib_qp *qp;
936 int ret = -EINVAL; 969 struct ib_uevent_object *uobj;
970 struct ib_uverbs_event *evt, *tmp;
971 int ret = -EINVAL;
937 972
938 if (copy_from_user(&cmd, buf, sizeof cmd)) 973 if (copy_from_user(&cmd, buf, sizeof cmd))
939 return -EFAULT; 974 return -EFAULT;
940 975
976 memset(&resp, 0, sizeof resp);
977
941 down(&ib_uverbs_idr_mutex); 978 down(&ib_uverbs_idr_mutex);
942 979
943 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 980 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
944 if (!qp || qp->uobject->context != file->ucontext) 981 if (!qp || qp->uobject->context != file->ucontext)
945 goto out; 982 goto out;
946 983
947 uobj = qp->uobject; 984 uobj = container_of(qp->uobject, struct ib_uevent_object, uobject);
948 985
949 ret = ib_destroy_qp(qp); 986 ret = ib_destroy_qp(qp);
950 if (ret) 987 if (ret)
@@ -953,11 +990,24 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
953 idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); 990 idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
954 991
955 spin_lock_irq(&file->ucontext->lock); 992 spin_lock_irq(&file->ucontext->lock);
956 list_del(&uobj->list); 993 list_del(&uobj->uobject.list);
957 spin_unlock_irq(&file->ucontext->lock); 994 spin_unlock_irq(&file->ucontext->lock);
958 995
996 spin_lock_irq(&file->async_file.lock);
997 list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
998 list_del(&evt->list);
999 kfree(evt);
1000 }
1001 spin_unlock_irq(&file->async_file.lock);
1002
1003 resp.events_reported = uobj->events_reported;
1004
959 kfree(uobj); 1005 kfree(uobj);
960 1006
1007 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1008 &resp, sizeof resp))
1009 ret = -EFAULT;
1010
961out: 1011out:
962 up(&ib_uverbs_idr_mutex); 1012 up(&ib_uverbs_idr_mutex);
963 1013
@@ -1015,7 +1065,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
1015 struct ib_uverbs_create_srq cmd; 1065 struct ib_uverbs_create_srq cmd;
1016 struct ib_uverbs_create_srq_resp resp; 1066 struct ib_uverbs_create_srq_resp resp;
1017 struct ib_udata udata; 1067 struct ib_udata udata;
1018 struct ib_uobject *uobj; 1068 struct ib_uevent_object *uobj;
1019 struct ib_pd *pd; 1069 struct ib_pd *pd;
1020 struct ib_srq *srq; 1070 struct ib_srq *srq;
1021 struct ib_srq_init_attr attr; 1071 struct ib_srq_init_attr attr;
@@ -1050,8 +1100,10 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
1050 attr.attr.max_sge = cmd.max_sge; 1100 attr.attr.max_sge = cmd.max_sge;
1051 attr.attr.srq_limit = cmd.srq_limit; 1101 attr.attr.srq_limit = cmd.srq_limit;
1052 1102
1053 uobj->user_handle = cmd.user_handle; 1103 uobj->uobject.user_handle = cmd.user_handle;
1054 uobj->context = file->ucontext; 1104 uobj->uobject.context = file->ucontext;
1105 uobj->events_reported = 0;
1106 INIT_LIST_HEAD(&uobj->event_list);
1055 1107
1056 srq = pd->device->create_srq(pd, &attr, &udata); 1108 srq = pd->device->create_srq(pd, &attr, &udata);
1057 if (IS_ERR(srq)) { 1109 if (IS_ERR(srq)) {
@@ -1061,7 +1113,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
1061 1113
1062 srq->device = pd->device; 1114 srq->device = pd->device;
1063 srq->pd = pd; 1115 srq->pd = pd;
1064 srq->uobject = uobj; 1116 srq->uobject = &uobj->uobject;
1065 srq->event_handler = attr.event_handler; 1117 srq->event_handler = attr.event_handler;
1066 srq->srq_context = attr.srq_context; 1118 srq->srq_context = attr.srq_context;
1067 atomic_inc(&pd->usecnt); 1119 atomic_inc(&pd->usecnt);
@@ -1075,17 +1127,17 @@ retry:
1075 goto err_destroy; 1127 goto err_destroy;
1076 } 1128 }
1077 1129
1078 ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->id); 1130 ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->uobject.id);
1079 1131
1080 if (ret == -EAGAIN) 1132 if (ret == -EAGAIN)
1081 goto retry; 1133 goto retry;
1082 if (ret) 1134 if (ret)
1083 goto err_destroy; 1135 goto err_destroy;
1084 1136
1085 resp.srq_handle = uobj->id; 1137 resp.srq_handle = uobj->uobject.id;
1086 1138
1087 spin_lock_irq(&file->ucontext->lock); 1139 spin_lock_irq(&file->ucontext->lock);
1088 list_add_tail(&uobj->list, &file->ucontext->srq_list); 1140 list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
1089 spin_unlock_irq(&file->ucontext->lock); 1141 spin_unlock_irq(&file->ucontext->lock);
1090 1142
1091 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1143 if (copy_to_user((void __user *) (unsigned long) cmd.response,
@@ -1100,7 +1152,7 @@ retry:
1100 1152
1101err_list: 1153err_list:
1102 spin_lock_irq(&file->ucontext->lock); 1154 spin_lock_irq(&file->ucontext->lock);
1103 list_del(&uobj->list); 1155 list_del(&uobj->uobject.list);
1104 spin_unlock_irq(&file->ucontext->lock); 1156 spin_unlock_irq(&file->ucontext->lock);
1105 1157
1106err_destroy: 1158err_destroy:
@@ -1149,21 +1201,25 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
1149 const char __user *buf, int in_len, 1201 const char __user *buf, int in_len,
1150 int out_len) 1202 int out_len)
1151{ 1203{
1152 struct ib_uverbs_destroy_srq cmd; 1204 struct ib_uverbs_destroy_srq cmd;
1153 struct ib_srq *srq; 1205 struct ib_uverbs_destroy_srq_resp resp;
1154 struct ib_uobject *uobj; 1206 struct ib_srq *srq;
1155 int ret = -EINVAL; 1207 struct ib_uevent_object *uobj;
1208 struct ib_uverbs_event *evt, *tmp;
1209 int ret = -EINVAL;
1156 1210
1157 if (copy_from_user(&cmd, buf, sizeof cmd)) 1211 if (copy_from_user(&cmd, buf, sizeof cmd))
1158 return -EFAULT; 1212 return -EFAULT;
1159 1213
1160 down(&ib_uverbs_idr_mutex); 1214 down(&ib_uverbs_idr_mutex);
1161 1215
1216 memset(&resp, 0, sizeof resp);
1217
1162 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); 1218 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
1163 if (!srq || srq->uobject->context != file->ucontext) 1219 if (!srq || srq->uobject->context != file->ucontext)
1164 goto out; 1220 goto out;
1165 1221
1166 uobj = srq->uobject; 1222 uobj = container_of(srq->uobject, struct ib_uevent_object, uobject);
1167 1223
1168 ret = ib_destroy_srq(srq); 1224 ret = ib_destroy_srq(srq);
1169 if (ret) 1225 if (ret)
@@ -1172,11 +1228,24 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
1172 idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); 1228 idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
1173 1229
1174 spin_lock_irq(&file->ucontext->lock); 1230 spin_lock_irq(&file->ucontext->lock);
1175 list_del(&uobj->list); 1231 list_del(&uobj->uobject.list);
1176 spin_unlock_irq(&file->ucontext->lock); 1232 spin_unlock_irq(&file->ucontext->lock);
1177 1233
1234 spin_lock_irq(&file->async_file.lock);
1235 list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
1236 list_del(&evt->list);
1237 kfree(evt);
1238 }
1239 spin_unlock_irq(&file->async_file.lock);
1240
1241 resp.events_reported = uobj->events_reported;
1242
1178 kfree(uobj); 1243 kfree(uobj);
1179 1244
1245 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1246 &resp, sizeof resp))
1247 ret = -EFAULT;
1248
1180out: 1249out:
1181 up(&ib_uverbs_idr_mutex); 1250 up(&ib_uverbs_idr_mutex);
1182 1251
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 09caf5b1ef36..ce5bdb7af306 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -120,7 +120,7 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
120 idr_remove(&ib_uverbs_qp_idr, uobj->id); 120 idr_remove(&ib_uverbs_qp_idr, uobj->id);
121 ib_destroy_qp(qp); 121 ib_destroy_qp(qp);
122 list_del(&uobj->list); 122 list_del(&uobj->list);
123 kfree(uobj); 123 kfree(container_of(uobj, struct ib_uevent_object, uobject));
124 } 124 }
125 125
126 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) { 126 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
@@ -128,7 +128,7 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
128 idr_remove(&ib_uverbs_cq_idr, uobj->id); 128 idr_remove(&ib_uverbs_cq_idr, uobj->id);
129 ib_destroy_cq(cq); 129 ib_destroy_cq(cq);
130 list_del(&uobj->list); 130 list_del(&uobj->list);
131 kfree(uobj); 131 kfree(container_of(uobj, struct ib_ucq_object, uobject));
132 } 132 }
133 133
134 list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) { 134 list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
@@ -136,7 +136,7 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
136 idr_remove(&ib_uverbs_srq_idr, uobj->id); 136 idr_remove(&ib_uverbs_srq_idr, uobj->id);
137 ib_destroy_srq(srq); 137 ib_destroy_srq(srq);
138 list_del(&uobj->list); 138 list_del(&uobj->list);
139 kfree(uobj); 139 kfree(container_of(uobj, struct ib_uevent_object, uobject));
140 } 140 }
141 141
142 /* XXX Free MWs */ 142 /* XXX Free MWs */
@@ -182,7 +182,7 @@ static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
182 size_t count, loff_t *pos) 182 size_t count, loff_t *pos)
183{ 183{
184 struct ib_uverbs_event_file *file = filp->private_data; 184 struct ib_uverbs_event_file *file = filp->private_data;
185 void *event; 185 struct ib_uverbs_event *event;
186 int eventsz; 186 int eventsz;
187 int ret = 0; 187 int ret = 0;
188 188
@@ -207,21 +207,23 @@ static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
207 return -ENODEV; 207 return -ENODEV;
208 } 208 }
209 209
210 if (file->is_async) { 210 event = list_entry(file->event_list.next, struct ib_uverbs_event, list);
211 event = list_entry(file->event_list.next, 211
212 struct ib_uverbs_async_event, list); 212 if (file->is_async)
213 eventsz = sizeof (struct ib_uverbs_async_event_desc); 213 eventsz = sizeof (struct ib_uverbs_async_event_desc);
214 } else { 214 else
215 event = list_entry(file->event_list.next,
216 struct ib_uverbs_comp_event, list);
217 eventsz = sizeof (struct ib_uverbs_comp_event_desc); 215 eventsz = sizeof (struct ib_uverbs_comp_event_desc);
218 }
219 216
220 if (eventsz > count) { 217 if (eventsz > count) {
221 ret = -EINVAL; 218 ret = -EINVAL;
222 event = NULL; 219 event = NULL;
223 } else 220 } else {
224 list_del(file->event_list.next); 221 list_del(file->event_list.next);
222 if (event->counter) {
223 ++(*event->counter);
224 list_del(&event->obj_list);
225 }
226 }
225 227
226 spin_unlock_irq(&file->lock); 228 spin_unlock_irq(&file->lock);
227 229
@@ -257,16 +259,13 @@ static unsigned int ib_uverbs_event_poll(struct file *filp,
257 259
258static void ib_uverbs_event_release(struct ib_uverbs_event_file *file) 260static void ib_uverbs_event_release(struct ib_uverbs_event_file *file)
259{ 261{
260 struct list_head *entry, *tmp; 262 struct ib_uverbs_event *entry, *tmp;
261 263
262 spin_lock_irq(&file->lock); 264 spin_lock_irq(&file->lock);
263 if (file->fd != -1) { 265 if (file->fd != -1) {
264 file->fd = -1; 266 file->fd = -1;
265 list_for_each_safe(entry, tmp, &file->event_list) 267 list_for_each_entry_safe(entry, tmp, &file->event_list, list)
266 if (file->is_async) 268 kfree(entry);
267 kfree(list_entry(entry, struct ib_uverbs_async_event, list));
268 else
269 kfree(list_entry(entry, struct ib_uverbs_comp_event, list));
270 } 269 }
271 spin_unlock_irq(&file->lock); 270 spin_unlock_irq(&file->lock);
272} 271}
@@ -304,18 +303,23 @@ static struct file_operations uverbs_event_fops = {
304 303
305void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context) 304void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
306{ 305{
307 struct ib_uverbs_file *file = cq_context; 306 struct ib_uverbs_file *file = cq_context;
308 struct ib_uverbs_comp_event *entry; 307 struct ib_ucq_object *uobj;
309 unsigned long flags; 308 struct ib_uverbs_event *entry;
309 unsigned long flags;
310 310
311 entry = kmalloc(sizeof *entry, GFP_ATOMIC); 311 entry = kmalloc(sizeof *entry, GFP_ATOMIC);
312 if (!entry) 312 if (!entry)
313 return; 313 return;
314 314
315 entry->desc.cq_handle = cq->uobject->user_handle; 315 uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
316
317 entry->desc.comp.cq_handle = cq->uobject->user_handle;
318 entry->counter = &uobj->comp_events_reported;
316 319
317 spin_lock_irqsave(&file->comp_file[0].lock, flags); 320 spin_lock_irqsave(&file->comp_file[0].lock, flags);
318 list_add_tail(&entry->list, &file->comp_file[0].event_list); 321 list_add_tail(&entry->list, &file->comp_file[0].event_list);
322 list_add_tail(&entry->obj_list, &uobj->comp_list);
319 spin_unlock_irqrestore(&file->comp_file[0].lock, flags); 323 spin_unlock_irqrestore(&file->comp_file[0].lock, flags);
320 324
321 wake_up_interruptible(&file->comp_file[0].poll_wait); 325 wake_up_interruptible(&file->comp_file[0].poll_wait);
@@ -323,20 +327,25 @@ void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
323} 327}
324 328
325static void ib_uverbs_async_handler(struct ib_uverbs_file *file, 329static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
326 __u64 element, __u64 event) 330 __u64 element, __u64 event,
331 struct list_head *obj_list,
332 u32 *counter)
327{ 333{
328 struct ib_uverbs_async_event *entry; 334 struct ib_uverbs_event *entry;
329 unsigned long flags; 335 unsigned long flags;
330 336
331 entry = kmalloc(sizeof *entry, GFP_ATOMIC); 337 entry = kmalloc(sizeof *entry, GFP_ATOMIC);
332 if (!entry) 338 if (!entry)
333 return; 339 return;
334 340
335 entry->desc.element = element; 341 entry->desc.async.element = element;
336 entry->desc.event_type = event; 342 entry->desc.async.event_type = event;
343 entry->counter = counter;
337 344
338 spin_lock_irqsave(&file->async_file.lock, flags); 345 spin_lock_irqsave(&file->async_file.lock, flags);
339 list_add_tail(&entry->list, &file->async_file.event_list); 346 list_add_tail(&entry->list, &file->async_file.event_list);
347 if (obj_list)
348 list_add_tail(&entry->obj_list, obj_list);
340 spin_unlock_irqrestore(&file->async_file.lock, flags); 349 spin_unlock_irqrestore(&file->async_file.lock, flags);
341 350
342 wake_up_interruptible(&file->async_file.poll_wait); 351 wake_up_interruptible(&file->async_file.poll_wait);
@@ -345,23 +354,39 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
345 354
346void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr) 355void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr)
347{ 356{
348 ib_uverbs_async_handler(context_ptr, 357 struct ib_ucq_object *uobj;
349 event->element.cq->uobject->user_handle, 358
350 event->event); 359 uobj = container_of(event->element.cq->uobject,
360 struct ib_ucq_object, uobject);
361
362 ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
363 event->event, &uobj->async_list,
364 &uobj->async_events_reported);
365
351} 366}
352 367
353void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr) 368void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
354{ 369{
355 ib_uverbs_async_handler(context_ptr, 370 struct ib_uevent_object *uobj;
356 event->element.qp->uobject->user_handle, 371
357 event->event); 372 uobj = container_of(event->element.qp->uobject,
373 struct ib_uevent_object, uobject);
374
375 ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
376 event->event, &uobj->event_list,
377 &uobj->events_reported);
358} 378}
359 379
360void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr) 380void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
361{ 381{
362 ib_uverbs_async_handler(context_ptr, 382 struct ib_uevent_object *uobj;
363 event->element.srq->uobject->user_handle, 383
364 event->event); 384 uobj = container_of(event->element.srq->uobject,
385 struct ib_uevent_object, uobject);
386
387 ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
388 event->event, &uobj->event_list,
389 &uobj->events_reported);
365} 390}
366 391
367static void ib_uverbs_event_handler(struct ib_event_handler *handler, 392static void ib_uverbs_event_handler(struct ib_event_handler *handler,
@@ -370,7 +395,8 @@ static void ib_uverbs_event_handler(struct ib_event_handler *handler,
370 struct ib_uverbs_file *file = 395 struct ib_uverbs_file *file =
371 container_of(handler, struct ib_uverbs_file, event_handler); 396 container_of(handler, struct ib_uverbs_file, event_handler);
372 397
373 ib_uverbs_async_handler(file, event->element.port_num, event->event); 398 ib_uverbs_async_handler(file, event->element.port_num, event->event,
399 NULL, NULL);
374} 400}
375 401
376static int ib_uverbs_event_init(struct ib_uverbs_event_file *file, 402static int ib_uverbs_event_init(struct ib_uverbs_event_file *file,
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 0164b84d4ec6..bcef06bf15e7 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -220,6 +220,16 @@ static void *get_send_wqe(struct mthca_qp *qp, int n)
220 (PAGE_SIZE - 1)); 220 (PAGE_SIZE - 1));
221} 221}
222 222
223static void mthca_wq_init(struct mthca_wq *wq)
224{
225 spin_lock_init(&wq->lock);
226 wq->next_ind = 0;
227 wq->last_comp = wq->max - 1;
228 wq->head = 0;
229 wq->tail = 0;
230 wq->last = NULL;
231}
232
223void mthca_qp_event(struct mthca_dev *dev, u32 qpn, 233void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
224 enum ib_event_type event_type) 234 enum ib_event_type event_type)
225{ 235{
@@ -833,8 +843,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
833 store_attrs(to_msqp(qp), attr, attr_mask); 843 store_attrs(to_msqp(qp), attr, attr_mask);
834 844
835 /* 845 /*
836 * If we are moving QP0 to RTR, bring the IB link up; if we 846 * If we moved QP0 to RTR, bring the IB link up; if we moved
837 * are moving QP0 to RESET or ERROR, bring the link back down. 847 * QP0 to RESET or ERROR, bring the link back down.
838 */ 848 */
839 if (is_qp0(dev, qp)) { 849 if (is_qp0(dev, qp)) {
840 if (cur_state != IB_QPS_RTR && 850 if (cur_state != IB_QPS_RTR &&
@@ -848,6 +858,26 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
848 mthca_CLOSE_IB(dev, to_msqp(qp)->port, &status); 858 mthca_CLOSE_IB(dev, to_msqp(qp)->port, &status);
849 } 859 }
850 860
861 /*
862 * If we moved a kernel QP to RESET, clean up all old CQ
863 * entries and reinitialize the QP.
864 */
865 if (!err && new_state == IB_QPS_RESET && !qp->ibqp.uobject) {
866 mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn,
867 qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
868 if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
869 mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn,
870 qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
871
872 mthca_wq_init(&qp->sq);
873 mthca_wq_init(&qp->rq);
874
875 if (mthca_is_memfree(dev)) {
876 *qp->sq.db = 0;
877 *qp->rq.db = 0;
878 }
879 }
880
851 return err; 881 return err;
852} 882}
853 883
@@ -1003,16 +1033,6 @@ static void mthca_free_memfree(struct mthca_dev *dev,
1003 } 1033 }
1004} 1034}
1005 1035
1006static void mthca_wq_init(struct mthca_wq* wq)
1007{
1008 spin_lock_init(&wq->lock);
1009 wq->next_ind = 0;
1010 wq->last_comp = wq->max - 1;
1011 wq->head = 0;
1012 wq->tail = 0;
1013 wq->last = NULL;
1014}
1015
1016static int mthca_alloc_qp_common(struct mthca_dev *dev, 1036static int mthca_alloc_qp_common(struct mthca_dev *dev,
1017 struct mthca_pd *pd, 1037 struct mthca_pd *pd,
1018 struct mthca_cq *send_cq, 1038 struct mthca_cq *send_cq,
@@ -1024,6 +1044,7 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
1024 int i; 1044 int i;
1025 1045
1026 atomic_set(&qp->refcount, 1); 1046 atomic_set(&qp->refcount, 1);
1047 init_waitqueue_head(&qp->wait);
1027 qp->state = IB_QPS_RESET; 1048 qp->state = IB_QPS_RESET;
1028 qp->atomic_rd_en = 0; 1049 qp->atomic_rd_en = 0;
1029 qp->resp_depth = 0; 1050 qp->resp_depth = 0;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 0e8ac138e355..49d120d2b92c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1062,6 +1062,8 @@ static void ipoib_remove_one(struct ib_device *device)
1062 ipoib_dev_cleanup(priv->dev); 1062 ipoib_dev_cleanup(priv->dev);
1063 free_netdev(priv->dev); 1063 free_netdev(priv->dev);
1064 } 1064 }
1065
1066 kfree(dev_list);
1065} 1067}
1066 1068
1067static int __init ipoib_init_module(void) 1069static int __init ipoib_init_module(void)
diff --git a/include/rdma/ib_cm.h b/include/rdma/ib_cm.h
index 77fe9039209b..5308683c8c41 100644
--- a/include/rdma/ib_cm.h
+++ b/include/rdma/ib_cm.h
@@ -290,6 +290,7 @@ struct ib_cm_id {
290 enum ib_cm_lap_state lap_state; /* internal CM/debug use */ 290 enum ib_cm_lap_state lap_state; /* internal CM/debug use */
291 __be32 local_id; 291 __be32 local_id;
292 __be32 remote_id; 292 __be32 remote_id;
293 u32 remote_cm_qpn; /* 1 unless redirected */
293}; 294};
294 295
295/** 296/**
diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
index fc6b1c18ffc6..53184a38fdf6 100644
--- a/include/rdma/ib_mad.h
+++ b/include/rdma/ib_mad.h
@@ -173,6 +173,27 @@ struct ib_vendor_mad {
173 u8 data[216]; 173 u8 data[216];
174}; 174};
175 175
176struct ib_class_port_info
177{
178 u8 base_version;
179 u8 class_version;
180 __be16 capability_mask;
181 u8 reserved[3];
182 u8 resp_time_value;
183 u8 redirect_gid[16];
184 __be32 redirect_tcslfl;
185 __be16 redirect_lid;
186 __be16 redirect_pkey;
187 __be32 redirect_qp;
188 __be32 redirect_qkey;
189 u8 trap_gid[16];
190 __be32 trap_tcslfl;
191 __be16 trap_lid;
192 __be16 trap_pkey;
193 __be32 trap_hlqp;
194 __be32 trap_qkey;
195};
196
176/** 197/**
177 * ib_mad_send_buf - MAD data buffer and work request for sends. 198 * ib_mad_send_buf - MAD data buffer and work request for sends.
178 * @mad: References an allocated MAD data buffer. The size of the data 199 * @mad: References an allocated MAD data buffer. The size of the data
diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h
index c022edfc49da..a7555c800ecf 100644
--- a/include/rdma/ib_sa.h
+++ b/include/rdma/ib_sa.h
@@ -46,7 +46,36 @@ enum {
46 46
47 IB_SA_METHOD_GET_TABLE = 0x12, 47 IB_SA_METHOD_GET_TABLE = 0x12,
48 IB_SA_METHOD_GET_TABLE_RESP = 0x92, 48 IB_SA_METHOD_GET_TABLE_RESP = 0x92,
49 IB_SA_METHOD_DELETE = 0x15 49 IB_SA_METHOD_DELETE = 0x15,
50 IB_SA_METHOD_DELETE_RESP = 0x95,
51 IB_SA_METHOD_GET_MULTI = 0x14,
52 IB_SA_METHOD_GET_MULTI_RESP = 0x94,
53 IB_SA_METHOD_GET_TRACE_TBL = 0x13
54};
55
56enum {
57 IB_SA_ATTR_CLASS_PORTINFO = 0x01,
58 IB_SA_ATTR_NOTICE = 0x02,
59 IB_SA_ATTR_INFORM_INFO = 0x03,
60 IB_SA_ATTR_NODE_REC = 0x11,
61 IB_SA_ATTR_PORT_INFO_REC = 0x12,
62 IB_SA_ATTR_SL2VL_REC = 0x13,
63 IB_SA_ATTR_SWITCH_REC = 0x14,
64 IB_SA_ATTR_LINEAR_FDB_REC = 0x15,
65 IB_SA_ATTR_RANDOM_FDB_REC = 0x16,
66 IB_SA_ATTR_MCAST_FDB_REC = 0x17,
67 IB_SA_ATTR_SM_INFO_REC = 0x18,
68 IB_SA_ATTR_LINK_REC = 0x20,
69 IB_SA_ATTR_GUID_INFO_REC = 0x30,
70 IB_SA_ATTR_SERVICE_REC = 0x31,
71 IB_SA_ATTR_PARTITION_REC = 0x33,
72 IB_SA_ATTR_PATH_REC = 0x35,
73 IB_SA_ATTR_VL_ARB_REC = 0x36,
74 IB_SA_ATTR_MC_MEMBER_REC = 0x38,
75 IB_SA_ATTR_TRACE_REC = 0x39,
76 IB_SA_ATTR_MULTI_PATH_REC = 0x3a,
77 IB_SA_ATTR_SERVICE_ASSOC_REC = 0x3b,
78 IB_SA_ATTR_INFORM_INFO_REC = 0xf3
50}; 79};
51 80
52enum ib_sa_selector { 81enum ib_sa_selector {
diff --git a/include/rdma/ib_user_cm.h b/include/rdma/ib_user_cm.h
index 72182d16778b..e4d1654276ad 100644
--- a/include/rdma/ib_user_cm.h
+++ b/include/rdma/ib_user_cm.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2005 Topspin Communications. All rights reserved. 2 * Copyright (c) 2005 Topspin Communications. All rights reserved.
3 * Copyright (c) 2005 Intel Corporation. All rights reserved.
3 * 4 *
4 * This software is available to you under a choice of one of two 5 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU 6 * licenses. You may choose to be licensed under the terms of the GNU
@@ -37,7 +38,7 @@
37 38
38#include <linux/types.h> 39#include <linux/types.h>
39 40
40#define IB_USER_CM_ABI_VERSION 1 41#define IB_USER_CM_ABI_VERSION 2
41 42
42enum { 43enum {
43 IB_USER_CM_CMD_CREATE_ID, 44 IB_USER_CM_CMD_CREATE_ID,
@@ -60,6 +61,7 @@ enum {
60 IB_USER_CM_CMD_SEND_SIDR_REP, 61 IB_USER_CM_CMD_SEND_SIDR_REP,
61 62
62 IB_USER_CM_CMD_EVENT, 63 IB_USER_CM_CMD_EVENT,
64 IB_USER_CM_CMD_INIT_QP_ATTR,
63}; 65};
64/* 66/*
65 * command ABI structures. 67 * command ABI structures.
@@ -71,6 +73,7 @@ struct ib_ucm_cmd_hdr {
71}; 73};
72 74
73struct ib_ucm_create_id { 75struct ib_ucm_create_id {
76 __u64 uid;
74 __u64 response; 77 __u64 response;
75}; 78};
76 79
@@ -79,9 +82,14 @@ struct ib_ucm_create_id_resp {
79}; 82};
80 83
81struct ib_ucm_destroy_id { 84struct ib_ucm_destroy_id {
85 __u64 response;
82 __u32 id; 86 __u32 id;
83}; 87};
84 88
89struct ib_ucm_destroy_id_resp {
90 __u32 events_reported;
91};
92
85struct ib_ucm_attr_id { 93struct ib_ucm_attr_id {
86 __u64 response; 94 __u64 response;
87 __u32 id; 95 __u32 id;
@@ -94,6 +102,64 @@ struct ib_ucm_attr_id_resp {
94 __be32 remote_id; 102 __be32 remote_id;
95}; 103};
96 104
105struct ib_ucm_init_qp_attr {
106 __u64 response;
107 __u32 id;
108 __u32 qp_state;
109};
110
111struct ib_ucm_ah_attr {
112 __u8 grh_dgid[16];
113 __u32 grh_flow_label;
114 __u16 dlid;
115 __u16 reserved;
116 __u8 grh_sgid_index;
117 __u8 grh_hop_limit;
118 __u8 grh_traffic_class;
119 __u8 sl;
120 __u8 src_path_bits;
121 __u8 static_rate;
122 __u8 is_global;
123 __u8 port_num;
124};
125
126struct ib_ucm_init_qp_attr_resp {
127 __u32 qp_attr_mask;
128 __u32 qp_state;
129 __u32 cur_qp_state;
130 __u32 path_mtu;
131 __u32 path_mig_state;
132 __u32 qkey;
133 __u32 rq_psn;
134 __u32 sq_psn;
135 __u32 dest_qp_num;
136 __u32 qp_access_flags;
137
138 struct ib_ucm_ah_attr ah_attr;
139 struct ib_ucm_ah_attr alt_ah_attr;
140
141 /* ib_qp_cap */
142 __u32 max_send_wr;
143 __u32 max_recv_wr;
144 __u32 max_send_sge;
145 __u32 max_recv_sge;
146 __u32 max_inline_data;
147
148 __u16 pkey_index;
149 __u16 alt_pkey_index;
150 __u8 en_sqd_async_notify;
151 __u8 sq_draining;
152 __u8 max_rd_atomic;
153 __u8 max_dest_rd_atomic;
154 __u8 min_rnr_timer;
155 __u8 port_num;
156 __u8 timeout;
157 __u8 retry_cnt;
158 __u8 rnr_retry;
159 __u8 alt_port_num;
160 __u8 alt_timeout;
161};
162
97struct ib_ucm_listen { 163struct ib_ucm_listen {
98 __be64 service_id; 164 __be64 service_id;
99 __be64 service_mask; 165 __be64 service_mask;
@@ -157,6 +223,7 @@ struct ib_ucm_req {
157}; 223};
158 224
159struct ib_ucm_rep { 225struct ib_ucm_rep {
226 __u64 uid;
160 __u64 data; 227 __u64 data;
161 __u32 id; 228 __u32 id;
162 __u32 qpn; 229 __u32 qpn;
@@ -232,7 +299,6 @@ struct ib_ucm_event_get {
232}; 299};
233 300
234struct ib_ucm_req_event_resp { 301struct ib_ucm_req_event_resp {
235 __u32 listen_id;
236 /* device */ 302 /* device */
237 /* port */ 303 /* port */
238 struct ib_ucm_path_rec primary_path; 304 struct ib_ucm_path_rec primary_path;
@@ -287,7 +353,6 @@ struct ib_ucm_apr_event_resp {
287}; 353};
288 354
289struct ib_ucm_sidr_req_event_resp { 355struct ib_ucm_sidr_req_event_resp {
290 __u32 listen_id;
291 /* device */ 356 /* device */
292 /* port */ 357 /* port */
293 __u16 pkey; 358 __u16 pkey;
@@ -307,6 +372,7 @@ struct ib_ucm_sidr_rep_event_resp {
307#define IB_UCM_PRES_ALTERNATE 0x08 372#define IB_UCM_PRES_ALTERNATE 0x08
308 373
309struct ib_ucm_event_resp { 374struct ib_ucm_event_resp {
375 __u64 uid;
310 __u32 id; 376 __u32 id;
311 __u32 event; 377 __u32 event;
312 __u32 present; 378 __u32 present;
diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h
index 7ebb01c8f996..fd85725391a4 100644
--- a/include/rdma/ib_user_verbs.h
+++ b/include/rdma/ib_user_verbs.h
@@ -42,7 +42,7 @@
42 * Increment this value if any changes that break userspace ABI 42 * Increment this value if any changes that break userspace ABI
43 * compatibility are made. 43 * compatibility are made.
44 */ 44 */
45#define IB_USER_VERBS_ABI_VERSION 1 45#define IB_USER_VERBS_ABI_VERSION 2
46 46
47enum { 47enum {
48 IB_USER_VERBS_CMD_QUERY_PARAMS, 48 IB_USER_VERBS_CMD_QUERY_PARAMS,
@@ -292,7 +292,14 @@ struct ib_uverbs_create_cq_resp {
292}; 292};
293 293
294struct ib_uverbs_destroy_cq { 294struct ib_uverbs_destroy_cq {
295 __u64 response;
295 __u32 cq_handle; 296 __u32 cq_handle;
297 __u32 reserved;
298};
299
300struct ib_uverbs_destroy_cq_resp {
301 __u32 comp_events_reported;
302 __u32 async_events_reported;
296}; 303};
297 304
298struct ib_uverbs_create_qp { 305struct ib_uverbs_create_qp {
@@ -372,7 +379,13 @@ struct ib_uverbs_modify_qp_resp {
372}; 379};
373 380
374struct ib_uverbs_destroy_qp { 381struct ib_uverbs_destroy_qp {
382 __u64 response;
375 __u32 qp_handle; 383 __u32 qp_handle;
384 __u32 reserved;
385};
386
387struct ib_uverbs_destroy_qp_resp {
388 __u32 events_reported;
376}; 389};
377 390
378struct ib_uverbs_attach_mcast { 391struct ib_uverbs_attach_mcast {
@@ -416,7 +429,13 @@ struct ib_uverbs_modify_srq {
416}; 429};
417 430
418struct ib_uverbs_destroy_srq { 431struct ib_uverbs_destroy_srq {
432 __u64 response;
419 __u32 srq_handle; 433 __u32 srq_handle;
434 __u32 reserved;
435};
436
437struct ib_uverbs_destroy_srq_resp {
438 __u32 events_reported;
420}; 439};
421 440
422#endif /* IB_USER_VERBS_H */ 441#endif /* IB_USER_VERBS_H */