aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorVu Pham <vu@mellanox.com>2013-08-28 16:23:35 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2013-09-10 19:48:51 -0400
commit59464ef4fbb567bcd3b160ae12c3eb087f4e7568 (patch)
treedc9af410be7fae4c88a919e5190f4728fb3bfedb /drivers/infiniband
parentd40945d8c2fbbff8adb6f35cc3e268df4934eb2a (diff)
iser-target: introduce fast memory registration mode (FRWR)
This model was introduced in 00f7ec36c "RDMA/core: Add memory management extensions support" and works when the IB device supports the IB_DEVICE_MEM_MGT_EXTENSIONS capability. Upon creating the isert device, ib_isert will test whether the HCA supports FRWR. If supported then set the flag and assign function pointers that handle fast registration and deregistration of appropriate resources (fast_reg descriptors). When new connection coming in, ib_isert will check frwr flag and create frwr resouces, if fail to do it will switch back to old model of using global dma key and turn off the frwr support. Registration is done using posting IB_WR_FAST_REG_MR to the QP and invalidations using posting IB_WR_LOCAL_INV. Signed-off-by: Vu Pham <vu@mellanox.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.c367
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.h17
2 files changed, 371 insertions, 13 deletions
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 4c3d66009237..51c3bed6c12b 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -45,6 +45,11 @@ isert_unmap_cmd(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn);
45static int 45static int
46isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd, 46isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
47 struct isert_rdma_wr *wr); 47 struct isert_rdma_wr *wr);
48static void
49isert_unreg_rdma_frwr(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn);
50static int
51isert_reg_rdma_frwr(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
52 struct isert_rdma_wr *wr);
48 53
49static void 54static void
50isert_qp_event_callback(struct ib_event *e, void *context) 55isert_qp_event_callback(struct ib_event *e, void *context)
@@ -85,14 +90,8 @@ isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id)
85{ 90{
86 struct isert_device *device = isert_conn->conn_device; 91 struct isert_device *device = isert_conn->conn_device;
87 struct ib_qp_init_attr attr; 92 struct ib_qp_init_attr attr;
88 struct ib_device_attr devattr;
89 int ret, index, min_index = 0; 93 int ret, index, min_index = 0;
90 94
91 memset(&devattr, 0, sizeof(struct ib_device_attr));
92 ret = isert_query_device(cma_id->device, &devattr);
93 if (ret)
94 return ret;
95
96 mutex_lock(&device_list_mutex); 95 mutex_lock(&device_list_mutex);
97 for (index = 0; index < device->cqs_used; index++) 96 for (index = 0; index < device->cqs_used; index++)
98 if (device->cq_active_qps[index] < 97 if (device->cq_active_qps[index] <
@@ -113,7 +112,7 @@ isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id)
113 * FIXME: Use devattr.max_sge - 2 for max_send_sge as 112 * FIXME: Use devattr.max_sge - 2 for max_send_sge as
114 * work-around for RDMA_READ.. 113 * work-around for RDMA_READ..
115 */ 114 */
116 attr.cap.max_send_sge = devattr.max_sge - 2; 115 attr.cap.max_send_sge = device->dev_attr.max_sge - 2;
117 isert_conn->max_sge = attr.cap.max_send_sge; 116 isert_conn->max_sge = attr.cap.max_send_sge;
118 117
119 attr.cap.max_recv_sge = 1; 118 attr.cap.max_recv_sge = 1;
@@ -215,18 +214,31 @@ isert_create_device_ib_res(struct isert_device *device)
215{ 214{
216 struct ib_device *ib_dev = device->ib_device; 215 struct ib_device *ib_dev = device->ib_device;
217 struct isert_cq_desc *cq_desc; 216 struct isert_cq_desc *cq_desc;
217 struct ib_device_attr *dev_attr;
218 int ret = 0, i, j; 218 int ret = 0, i, j;
219 219
220 dev_attr = &device->dev_attr;
221 ret = isert_query_device(ib_dev, dev_attr);
222 if (ret)
223 return ret;
224
220 /* asign function handlers */ 225 /* asign function handlers */
221 device->reg_rdma_mem = isert_map_rdma; 226 if (dev_attr->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS) {
222 device->unreg_rdma_mem = isert_unmap_cmd; 227 device->use_frwr = 1;
228 device->reg_rdma_mem = isert_reg_rdma_frwr;
229 device->unreg_rdma_mem = isert_unreg_rdma_frwr;
230 } else {
231 device->use_frwr = 0;
232 device->reg_rdma_mem = isert_map_rdma;
233 device->unreg_rdma_mem = isert_unmap_cmd;
234 }
223 235
224 device->cqs_used = min_t(int, num_online_cpus(), 236 device->cqs_used = min_t(int, num_online_cpus(),
225 device->ib_device->num_comp_vectors); 237 device->ib_device->num_comp_vectors);
226 device->cqs_used = min(ISERT_MAX_CQ, device->cqs_used); 238 device->cqs_used = min(ISERT_MAX_CQ, device->cqs_used);
227 pr_debug("Using %d CQs, device %s supports %d vectors\n", 239 pr_debug("Using %d CQs, device %s supports %d vectors support FRWR %d\n",
228 device->cqs_used, device->ib_device->name, 240 device->cqs_used, device->ib_device->name,
229 device->ib_device->num_comp_vectors); 241 device->ib_device->num_comp_vectors, device->use_frwr);
230 device->cq_desc = kzalloc(sizeof(struct isert_cq_desc) * 242 device->cq_desc = kzalloc(sizeof(struct isert_cq_desc) *
231 device->cqs_used, GFP_KERNEL); 243 device->cqs_used, GFP_KERNEL);
232 if (!device->cq_desc) { 244 if (!device->cq_desc) {
@@ -372,6 +384,85 @@ isert_device_find_by_ib_dev(struct rdma_cm_id *cma_id)
372 return device; 384 return device;
373} 385}
374 386
387static void
388isert_conn_free_frwr_pool(struct isert_conn *isert_conn)
389{
390 struct fast_reg_descriptor *fr_desc, *tmp;
391 int i = 0;
392
393 if (list_empty(&isert_conn->conn_frwr_pool))
394 return;
395
396 pr_debug("Freeing conn %p frwr pool", isert_conn);
397
398 list_for_each_entry_safe(fr_desc, tmp,
399 &isert_conn->conn_frwr_pool, list) {
400 list_del(&fr_desc->list);
401 ib_free_fast_reg_page_list(fr_desc->data_frpl);
402 ib_dereg_mr(fr_desc->data_mr);
403 kfree(fr_desc);
404 ++i;
405 }
406
407 if (i < isert_conn->conn_frwr_pool_size)
408 pr_warn("Pool still has %d regions registered\n",
409 isert_conn->conn_frwr_pool_size - i);
410}
411
412static int
413isert_conn_create_frwr_pool(struct isert_conn *isert_conn)
414{
415 struct fast_reg_descriptor *fr_desc;
416 struct isert_device *device = isert_conn->conn_device;
417 int i, ret;
418
419 INIT_LIST_HEAD(&isert_conn->conn_frwr_pool);
420 isert_conn->conn_frwr_pool_size = 0;
421 for (i = 0; i < ISCSI_DEF_XMIT_CMDS_MAX; i++) {
422 fr_desc = kzalloc(sizeof(*fr_desc), GFP_KERNEL);
423 if (!fr_desc) {
424 pr_err("Failed to allocate fast_reg descriptor\n");
425 ret = -ENOMEM;
426 goto err;
427 }
428
429 fr_desc->data_frpl =
430 ib_alloc_fast_reg_page_list(device->ib_device,
431 ISCSI_ISER_SG_TABLESIZE);
432 if (IS_ERR(fr_desc->data_frpl)) {
433 pr_err("Failed to allocate fr_pg_list err=%ld\n",
434 PTR_ERR(fr_desc->data_frpl));
435 ret = PTR_ERR(fr_desc->data_frpl);
436 goto err;
437 }
438
439 fr_desc->data_mr = ib_alloc_fast_reg_mr(device->dev_pd,
440 ISCSI_ISER_SG_TABLESIZE);
441 if (IS_ERR(fr_desc->data_mr)) {
442 pr_err("Failed to allocate frmr err=%ld\n",
443 PTR_ERR(fr_desc->data_mr));
444 ret = PTR_ERR(fr_desc->data_mr);
445 ib_free_fast_reg_page_list(fr_desc->data_frpl);
446 goto err;
447 }
448 pr_debug("Create fr_desc %p page_list %p\n",
449 fr_desc, fr_desc->data_frpl->page_list);
450
451 fr_desc->valid = true;
452 list_add_tail(&fr_desc->list, &isert_conn->conn_frwr_pool);
453 isert_conn->conn_frwr_pool_size++;
454 }
455
456 pr_debug("Creating conn %p frwr pool size=%d",
457 isert_conn, isert_conn->conn_frwr_pool_size);
458
459 return 0;
460
461err:
462 isert_conn_free_frwr_pool(isert_conn);
463 return ret;
464}
465
375static int 466static int
376isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) 467isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
377{ 468{
@@ -398,6 +489,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)