aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c9
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h3
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c72
3 files changed, 46 insertions, 38 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 93399dff0c6..7b2fc98e2f2 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -325,7 +325,7 @@ iscsi_iser_conn_destroy(struct iscsi_cls_conn *cls_conn)
325 */ 325 */
326 if (ib_conn) { 326 if (ib_conn) {
327 ib_conn->iser_conn = NULL; 327 ib_conn->iser_conn = NULL;
328 iser_conn_put(ib_conn); 328 iser_conn_put(ib_conn, 1); /* deref iscsi/ib conn unbinding */
329 } 329 }
330} 330}
331 331
@@ -357,11 +357,12 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
357 /* binds the iSER connection retrieved from the previously 357 /* binds the iSER connection retrieved from the previously
358 * connected ep_handle to the iSCSI layer connection. exchanges 358 * connected ep_handle to the iSCSI layer connection. exchanges
359 * connection pointers */ 359 * connection pointers */
360 iser_err("binding iscsi conn %p to iser_conn %p\n",conn,ib_conn); 360 iser_err("binding iscsi/iser conn %p %p to ib_conn %p\n",
361 conn, conn->dd_data, ib_conn);
361 iser_conn = conn->dd_data; 362 iser_conn = conn->dd_data;
362 ib_conn->iser_conn = iser_conn; 363 ib_conn->iser_conn = iser_conn;
363 iser_conn->ib_conn = ib_conn; 364 iser_conn->ib_conn = ib_conn;
364 iser_conn_get(ib_conn); 365 iser_conn_get(ib_conn); /* ref iscsi/ib conn binding */
365 return 0; 366 return 0;
366} 367}
367 368
@@ -382,7 +383,7 @@ iscsi_iser_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
382 * There is no unbind event so the stop callback 383 * There is no unbind event so the stop callback
383 * must release the ref from the bind. 384 * must release the ref from the bind.
384 */ 385 */
385 iser_conn_put(ib_conn); 386 iser_conn_put(ib_conn, 1); /* deref iscsi/ib conn unbinding */
386 } 387 }
387 iser_conn->ib_conn = NULL; 388 iser_conn->ib_conn = NULL;
388} 389}
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index 53da74b45c7..f1df01567bb 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -247,7 +247,6 @@ struct iser_conn {
247 struct rdma_cm_id *cma_id; /* CMA ID */ 247 struct rdma_cm_id *cma_id; /* CMA ID */
248 struct ib_qp *qp; /* QP */ 248 struct ib_qp *qp; /* QP */
249 struct ib_fmr_pool *fmr_pool; /* pool of IB FMRs */ 249 struct ib_fmr_pool *fmr_pool; /* pool of IB FMRs */
250 int disc_evt_flag; /* disconn event delivered */
251 wait_queue_head_t wait; /* waitq for conn/disconn */ 250 wait_queue_head_t wait; /* waitq for conn/disconn */
252 int post_recv_buf_count; /* posted rx count */ 251 int post_recv_buf_count; /* posted rx count */
253 atomic_t post_send_buf_count; /* posted tx count */ 252 atomic_t post_send_buf_count; /* posted tx count */
@@ -321,7 +320,7 @@ void iser_conn_init(struct iser_conn *ib_conn);
321 320
322void iser_conn_get(struct iser_conn *ib_conn); 321void iser_conn_get(struct iser_conn *ib_conn);
323 322
324void iser_conn_put(struct iser_conn *ib_conn); 323int iser_conn_put(struct iser_conn *ib_conn, int destroy_cma_id_allowed);
325 324
326void iser_conn_terminate(struct iser_conn *ib_conn); 325void iser_conn_terminate(struct iser_conn *ib_conn);
327 326
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index ed7c9013541..78fdecacea3 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -238,7 +238,7 @@ alloc_err:
238 * releases the FMR pool, QP and CMA ID objects, returns 0 on success, 238 * releases the FMR pool, QP and CMA ID objects, returns 0 on success,
239 * -1 on failure 239 * -1 on failure
240 */ 240 */
241static int iser_free_ib_conn_res(struct iser_conn *ib_conn) 241static int iser_free_ib_conn_res(struct iser_conn *ib_conn, int can_destroy_id)
242{ 242{
243 BUG_ON(ib_conn == NULL); 243 BUG_ON(ib_conn == NULL);
244 244
@@ -253,7 +253,8 @@ static int iser_free_ib_conn_res(struct iser_conn *ib_conn)
253 if (ib_conn->qp != NULL) 253 if (ib_conn->qp != NULL)
254 rdma_destroy_qp(ib_conn->cma_id); 254 rdma_destroy_qp(ib_conn->cma_id);
255 255
256 if (ib_conn->cma_id != NULL) 256 /* if cma handler context, the caller acts s.t the cma destroy the id */
257 if (ib_conn->cma_id != NULL && can_destroy_id)
257 rdma_destroy_id(ib_conn->cma_id); 258 rdma_destroy_id(ib_conn->cma_id);
258 259
259 ib_conn->fmr_pool = NULL; 260 ib_conn->fmr_pool = NULL;
@@ -331,7 +332,7 @@ static int iser_conn_state_comp_exch(struct iser_conn *ib_conn,
331/** 332/**
332 * Frees all conn objects and deallocs conn descriptor 333 * Frees all conn objects and deallocs conn descriptor
333 */ 334 */
334static void iser_conn_release(struct iser_conn *ib_conn) 335static void iser_conn_release(struct iser_conn *ib_conn, int can_destroy_id)
335{ 336{
336 struct iser_device *device = ib_conn->device; 337 struct iser_device *device = ib_conn->device;
337 338
@@ -341,7 +342,7 @@ static void iser_conn_release(struct iser_conn *ib_conn)
341 list_del(&ib_conn->conn_list); 342 list_del(&ib_conn->conn_list);
342 mutex_unlock(&ig.connlist_mutex); 343 mutex_unlock(&ig.connlist_mutex);
343 iser_free_rx_descriptors(ib_conn); 344 iser_free_rx_descriptors(ib_conn);
344 iser_free_ib_conn_res(ib_conn); 345 iser_free_ib_conn_res(ib_conn, can_destroy_id);
345 ib_conn->device = NULL; 346 ib_conn->device = NULL;
346 /* on EVENT_ADDR_ERROR there's no device yet for this conn */ 347 /* on EVENT_ADDR_ERROR there's no device yet for this conn */
347 if (device != NULL) 348 if (device != NULL)
@@ -354,10 +355,13 @@ void iser_conn_get(struct iser_conn *ib_conn)
354 atomic_inc(&ib_conn->refcount); 355 atomic_inc(&ib_conn->refcount);
355} 356}
356 357
357void iser_conn_put(struct iser_conn *ib_conn) 358int iser_conn_put(struct iser_conn *ib_conn, int can_destroy_id)
358{ 359{
359 if (atomic_dec_and_test(&ib_conn->refcount)) 360 if (atomic_dec_and_test(&ib_conn->refcount)) {
360 iser_conn_release(ib_conn); 361 iser_conn_release(ib_conn, can_destroy_id);
362 return 1;
363 }
364 return 0;
361} 365}
362 366
363/** 367/**
@@ -381,19 +385,20 @@ void iser_conn_terminate(struct iser_conn *ib_conn)
381 wait_event_interruptible(ib_conn->wait, 385 wait_event_interruptible(ib_conn->wait,
382 ib_conn->state == ISER_CONN_DOWN); 386 ib_conn->state == ISER_CONN_DOWN);
383 387
384 iser_conn_put(ib_conn); 388 iser_conn_put(ib_conn, 1); /* deref ib conn deallocate */
385} 389}
386 390
387static void iser_connect_error(struct rdma_cm_id *cma_id) 391static int iser_connect_error(struct rdma_cm_id *cma_id)
388{ 392{
389 struct iser_conn *ib_conn; 393 struct iser_conn *ib_conn;
390 ib_conn = (struct iser_conn *)cma_id->context; 394 ib_conn = (struct iser_conn *)cma_id->context;
391 395
392 ib_conn->state = ISER_CONN_DOWN; 396 ib_conn->state = ISER_CONN_DOWN;
393 wake_up_interruptible(&ib_conn->wait); 397 wake_up_interruptible(&ib_conn->wait);
398 return iser_conn_put(ib_conn, 0); /* deref ib conn's cma id */
394} 399}
395 400
396static void iser_addr_handler(struct rdma_cm_id *cma_id) 401static int iser_addr_handler(struct rdma_cm_id *cma_id)
397{ 402{
398 struct iser_device *device; 403 struct iser_device *device;
399 struct iser_conn *ib_conn; 404 struct iser_conn *ib_conn;
@@ -402,8 +407,7 @@ static void iser_addr_handler(struct rdma_cm_id *cma_id)
402 device = iser_device_find_by_ib_device(cma_id); 407 device = iser_device_find_by_ib_device(cma_id);
403 if (!device) { 408 if (!device) {
404 iser_err("device lookup/creation failed\n"); 409 iser_err("device lookup/creation failed\n");
405 iser_connect_error(cma_id); 410 return iser_connect_error(cma_id);
406 return;
407 } 411 }
408 412
409 ib_conn = (struct iser_conn *)cma_id->context; 413 ib_conn = (struct iser_conn *)cma_id->context;
@@ -412,11 +416,13 @@ static void iser_addr_handler(struct rdma_cm_id *cma_id)
412 ret = rdma_resolve_route(cma_id, 1000); 416 ret = rdma_resolve_route(cma_id, 1000);
413 if (ret) { 417 if (ret) {
414 iser_err("resolve route failed: %d\n", ret); 418 iser_err("resolve route failed: %d\n", ret);
415 iser_connect_error(cma_id); 419 return iser_connect_error(cma_id);
416 } 420 }
421
422 return 0;
417} 423}
418 424
419static void iser_route_handler(struct rdma_cm_id *cma_id) 425static int iser_route_handler(struct rdma_cm_id *cma_id)
420{ 426{
421 struct rdma_conn_param conn_param; 427 struct rdma_conn_param conn_param;
422 int ret; 428 int ret;
@@ -437,9 +443,9 @@ static void iser_route_handler(struct rdma_cm_id *cma_id)
437 goto failure; 443 goto failure;
438 } 444 }
439 445
440 return; 446 return 0;
441failure: 447failure:
442 iser_connect_error(cma_id); 448 return iser_connect_error(cma_id);
443} 449}
444 450
445static void iser_connected_handler(struct rdma_cm_id *cma_id) 451static void iser_connected_handler(struct rdma_cm_id *cma_id)
@@ -451,12 +457,12 @@ static void iser_connected_handler(struct rdma_cm_id *cma_id)
451 wake_up_interruptible(&ib_conn->wait); 457 wake_up_interruptible(&ib_conn->wait);
452} 458}
453 459
454static void iser_disconnected_handler(struct rdma_cm_id *cma_id) 460static int iser_disconnected_handler(struct rdma_cm_id *cma_id)
455{ 461{
456 struct iser_conn *ib_conn; 462 struct iser_conn *ib_conn;
463 int ret;
457 464
458 ib_conn = (struct iser_conn *)cma_id->context; 465 ib_conn = (struct iser_conn *)cma_id->context;
459 ib_conn->disc_evt_flag = 1;
460 466
461 /* getting here when the state is UP means that the conn is being * 467 /* getting here when the state is UP means that the conn is being *
462 * terminated asynchronously from the iSCSI layer's perspective. */ 468 * terminated asynchronously from the iSCSI layer's perspective. */
@@ -471,20 +477,24 @@ static void iser_disconnected_handler(struct rdma_cm_id *cma_id)
471 ib_conn->state = ISER_CONN_DOWN; 477 ib_conn->state = ISER_CONN_DOWN;
472 wake_up_interruptible(&ib_conn->wait); 478 wake_up_interruptible(&ib_conn->wait);
473 } 479 }
480
481 ret = iser_conn_put(ib_conn, 0); /* deref ib conn's cma id */
482 return ret;
474} 483}
475 484
476static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) 485static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
477{ 486{
478 int ret = 0; 487 int ret = 0;
479 488
480 iser_err("event %d conn %p id %p\n",event->event,cma_id->context,cma_id); 489 iser_err("event %d status %d conn %p id %p\n",
490 event->event, event->status, cma_id->context, cma_id);
481 491
482 switch (event->event) { 492 switch (event->event) {
483 case RDMA_CM_EVENT_ADDR_RESOLVED: 493 case RDMA_CM_EVENT_ADDR_RESOLVED:
484 iser_addr_handler(cma_id); 494 ret = iser_addr_handler(cma_id);
485 break; 495 break;
486 case RDMA_CM_EVENT_ROUTE_RESOLVED: 496 case RDMA_CM_EVENT_ROUTE_RESOLVED:
487 iser_route_handler(cma_id); 497 ret = iser_route_handler(cma_id);
488 break; 498 break;
489 case RDMA_CM_EVENT_ESTABLISHED: 499 case RDMA_CM_EVENT_ESTABLISHED:
490 iser_connected_handler(cma_id); 500 iser_connected_handler(cma_id);
@@ -494,13 +504,12 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve
494 case RDMA_CM_EVENT_CONNECT_ERROR: 504 case RDMA_CM_EVENT_CONNECT_ERROR:
495 case RDMA_CM_EVENT_UNREACHABLE: 505 case RDMA_CM_EVENT_UNREACHABLE:
496 case RDMA_CM_EVENT_REJECTED: 506 case RDMA_CM_EVENT_REJECTED:
497 iser_err("event: %d, error: %d\n", event->event, event->status); 507 ret = iser_connect_error(cma_id);
498 iser_connect_error(cma_id);
499 break; 508 break;
500 case RDMA_CM_EVENT_DISCONNECTED: 509 case RDMA_CM_EVENT_DISCONNECTED:
501 case RDMA_CM_EVENT_DEVICE_REMOVAL: 510 case RDMA_CM_EVENT_DEVICE_REMOVAL:
502 case RDMA_CM_EVENT_ADDR_CHANGE: 511 case RDMA_CM_EVENT_ADDR_CHANGE:
503 iser_disconnected_handler(cma_id); 512 ret = iser_disconnected_handler(cma_id);
504 break; 513 break;
505 default: 514 default:
506 iser_err("Unexpected RDMA CM event (%d)\n", event->event); 515 iser_err("Unexpected RDMA CM event (%d)\n", event->event);
@@ -515,7 +524,7 @@ void iser_conn_init(struct iser_conn *ib_conn)
515 init_waitqueue_head(&ib_conn->wait); 524 init_waitqueue_head(&ib_conn->wait);
516 ib_conn->post_recv_buf_count = 0; 525 ib_conn->post_recv_buf_count = 0;
517 atomic_set(&ib_conn->post_send_buf_count, 0); 526 atomic_set(&ib_conn->post_send_buf_count, 0);
518 atomic_set(&ib_conn->refcount, 1); 527 atomic_set(&ib_conn->refcount, 1); /* ref ib conn allocation */
519 INIT_LIST_HEAD(&ib_conn->conn_list); 528 INIT_LIST_HEAD(&ib_conn->conn_list);
520 spin_lock_init(&ib_conn->lock); 529 spin_lock_init(&ib_conn->lock);
521} 530}
@@ -543,6 +552,7 @@ int iser_connect(struct iser_conn *ib_conn,
543 552
544 ib_conn->state = ISER_CONN_PENDING; 553 ib_conn->state = ISER_CONN_PENDING;
545 554
555 iser_conn_get(ib_conn); /* ref ib conn's cma id */
546 ib_conn->cma_id = rdma_create_id(iser_cma_handler, 556 ib_conn->cma_id = rdma_create_id(iser_cma_handler,
547 (void *)ib_conn, 557 (void *)ib_conn,
548 RDMA_PS_TCP); 558 RDMA_PS_TCP);
@@ -580,7 +590,7 @@ id_failure:
580addr_failure: 590addr_failure:
581 ib_conn->state = ISER_CONN_DOWN; 591 ib_conn->state = ISER_CONN_DOWN;
582connect_failure: 592connect_failure:
583 iser_conn_release(ib_conn); 593 iser_conn_release(ib_conn, 1);
584 return err; 594 return err;
585} 595}
586 596
@@ -749,12 +759,10 @@ static void iser_handle_comp_error(struct iser_tx_desc *desc,
749 iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn, 759 iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn,
750 ISCSI_ERR_CONN_FAILED); 760 ISCSI_ERR_CONN_FAILED);
751 761
752 /* complete the termination process if disconnect event was delivered * 762 /* no more non completed posts to the QP, complete the
753 * note there are no more non completed posts to the QP */ 763 * termination process w.o worrying on disconnect event */
754 if (ib_conn->disc_evt_flag) { 764 ib_conn->state = ISER_CONN_DOWN;
755 ib_conn->state = ISER_CONN_DOWN; 765 wake_up_interruptible(&ib_conn->wait);
756 wake_up_interruptible(&ib_conn->wait);
757 }
758 } 766 }
759} 767}
760 768