diff options
| author | Vu Pham <vu@mellanox.com> | 2013-08-28 16:23:35 -0400 |
|---|---|---|
| committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-09-10 19:48:51 -0400 |
| commit | 59464ef4fbb567bcd3b160ae12c3eb087f4e7568 (patch) | |
| tree | dc9af410be7fae4c88a919e5190f4728fb3bfedb /drivers/infiniband | |
| parent | d40945d8c2fbbff8adb6f35cc3e268df4934eb2a (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.c | 367 | ||||
| -rw-r--r-- | drivers/infiniband/ulp/isert/ib_isert.h | 17 |
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); | |||
| 45 | static int | 45 | static int |
| 46 | isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | 46 | isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd, |
| 47 | struct isert_rdma_wr *wr); | 47 | struct isert_rdma_wr *wr); |
| 48 | static void | ||
| 49 | isert_unreg_rdma_frwr(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn); | ||
| 50 | static int | ||
| 51 | isert_reg_rdma_frwr(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | ||
| 52 | struct isert_rdma_wr *wr); | ||
| 48 | 53 | ||
| 49 | static void | 54 | static void |
| 50 | isert_qp_event_callback(struct ib_event *e, void *context) | 55 | isert_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 | ||
| 387 | static void | ||
| 388 | isert_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 | |||
| 412 | static int | ||
| 413 | isert_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 | |||
| 461 | err: | ||
| 462 | isert_conn_free_frwr_pool(isert_conn); | ||
| 463 | return ret; | ||
| 464 | } | ||
| 465 | |||
| 375 | static int | 466 | static int |
| 376 | isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) | 467 | isert_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) | |||
