aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorRoi Dayan <roid@mellanox.com>2013-05-08 08:21:17 -0400
committerRoland Dreier <roland@purestorage.com>2013-06-04 20:03:11 -0400
commit5b61ff43a774b9843402fb280fec6d700e1fe583 (patch)
treeee988e3658ccadb4284d02af11275a8621d6f802 /drivers/infiniband
parentd683b96b072dc4680fc74964eca77e6a23d1fa6e (diff)
IB/iser: Fix device removal flow
Change the code to destroy the "last opened" rdma_cm id after making sure we released all other objects (QP, CQs, PD, etc) associated with the IB device. Since iser accesses the IB device using the rdma_cm id, we need to free any objects that are related to the device that is associated with the rdma_cm id prior to destroying that id. When this isn't done, the low level driver that created this device can be unloaded before iser has a chance to free all the objects and a such a call may invoke code segment which isn't valid any more and crash. Cc: Sean Hefty <sean.hefty@intel.com Signed-off-by: Roi Dayan <roid@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 5278916c3103..f13cc227eed7 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -292,10 +292,10 @@ out_err:
292} 292}
293 293
294/** 294/**
295 * releases the FMR pool, QP and CMA ID objects, returns 0 on success, 295 * releases the FMR pool and QP objects, returns 0 on success,
296 * -1 on failure 296 * -1 on failure
297 */ 297 */
298static int iser_free_ib_conn_res(struct iser_conn *ib_conn, int can_destroy_id) 298static int iser_free_ib_conn_res(struct iser_conn *ib_conn)
299{ 299{
300 int cq_index; 300 int cq_index;
301 BUG_ON(ib_conn == NULL); 301 BUG_ON(ib_conn == NULL);
@@ -314,13 +314,9 @@ static int iser_free_ib_conn_res(struct iser_conn *ib_conn, int can_destroy_id)
314 314
315 rdma_destroy_qp(ib_conn->cma_id); 315 rdma_destroy_qp(ib_conn->cma_id);
316 } 316 }
317 /* if cma handler context, the caller acts s.t the cma destroy the id */
318 if (ib_conn->cma_id != NULL && can_destroy_id)
319 rdma_destroy_id(ib_conn->cma_id);
320 317
321 ib_conn->fmr_pool = NULL; 318 ib_conn->fmr_pool = NULL;
322 ib_conn->qp = NULL; 319 ib_conn->qp = NULL;
323 ib_conn->cma_id = NULL;
324 kfree(ib_conn->page_vec); 320 kfree(ib_conn->page_vec);
325 321
326 if (ib_conn->login_buf) { 322 if (ib_conn->login_buf) {
@@ -415,11 +411,16 @@ static void iser_conn_release(struct iser_conn *ib_conn, int can_destroy_id)
415 list_del(&ib_conn->conn_list); 411 list_del(&ib_conn->conn_list);
416 mutex_unlock(&ig.connlist_mutex); 412 mutex_unlock(&ig.connlist_mutex);
417 iser_free_rx_descriptors(ib_conn); 413 iser_free_rx_descriptors(ib_conn);
418 iser_free_ib_conn_res(ib_conn, can_destroy_id); 414 iser_free_ib_conn_res(ib_conn);
419 ib_conn->device = NULL; 415 ib_conn->device = NULL;
420 /* on EVENT_ADDR_ERROR there's no device yet for this conn */ 416 /* on EVENT_ADDR_ERROR there's no device yet for this conn */
421 if (device != NULL) 417 if (device != NULL)
422 iser_device_try_release(device); 418 iser_device_try_release(device);
419 /* if cma handler context, the caller actually destroy the id */
420 if (ib_conn->cma_id != NULL && can_destroy_id) {
421 rdma_destroy_id(ib_conn->cma_id);
422 ib_conn->cma_id = NULL;
423 }
423 iscsi_destroy_endpoint(ib_conn->ep); 424 iscsi_destroy_endpoint(ib_conn->ep);
424} 425}
425 426