diff options
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/ulp/iser/iscsi_iser.c | 87 | ||||
-rw-r--r-- | drivers/infiniband/ulp/iser/iscsi_iser.h | 4 | ||||
-rw-r--r-- | drivers/infiniband/ulp/iser/iser_verbs.c | 14 |
3 files changed, 43 insertions, 62 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 3a89039e9a96..42e95b833092 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c | |||
@@ -262,24 +262,6 @@ iscsi_iser_cleanup_task(struct iscsi_conn *conn, struct iscsi_task *task) | |||
262 | } | 262 | } |
263 | } | 263 | } |
264 | 264 | ||
265 | static struct iser_conn * | ||
266 | iscsi_iser_ib_conn_lookup(__u64 ep_handle) | ||
267 | { | ||
268 | struct iser_conn *ib_conn; | ||
269 | struct iser_conn *uib_conn = (struct iser_conn *)(unsigned long)ep_handle; | ||
270 | |||
271 | mutex_lock(&ig.connlist_mutex); | ||
272 | list_for_each_entry(ib_conn, &ig.connlist, conn_list) { | ||
273 | if (ib_conn == uib_conn) { | ||
274 | mutex_unlock(&ig.connlist_mutex); | ||
275 | return ib_conn; | ||
276 | } | ||
277 | } | ||
278 | mutex_unlock(&ig.connlist_mutex); | ||
279 | iser_err("no conn exists for eph %llx\n",(unsigned long long)ep_handle); | ||
280 | return NULL; | ||
281 | } | ||
282 | |||
283 | static struct iscsi_cls_conn * | 265 | static struct iscsi_cls_conn * |
284 | iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | 266 | iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) |
285 | { | 267 | { |
@@ -335,6 +317,7 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session, | |||
335 | struct iscsi_conn *conn = cls_conn->dd_data; | 317 | struct iscsi_conn *conn = cls_conn->dd_data; |
336 | struct iscsi_iser_conn *iser_conn; | 318 | struct iscsi_iser_conn *iser_conn; |
337 | struct iser_conn *ib_conn; | 319 | struct iser_conn *ib_conn; |
320 | struct iscsi_endpoint *ep; | ||
338 | int error; | 321 | int error; |
339 | 322 | ||
340 | error = iscsi_conn_bind(cls_session, cls_conn, is_leading); | 323 | error = iscsi_conn_bind(cls_session, cls_conn, is_leading); |
@@ -343,12 +326,14 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session, | |||
343 | 326 | ||
344 | /* the transport ep handle comes from user space so it must be | 327 | /* the transport ep handle comes from user space so it must be |
345 | * verified against the global ib connections list */ | 328 | * verified against the global ib connections list */ |
346 | ib_conn = iscsi_iser_ib_conn_lookup(transport_eph); | 329 | ep = iscsi_lookup_endpoint(transport_eph); |
347 | if (!ib_conn) { | 330 | if (!ep) { |
348 | iser_err("can't bind eph %llx\n", | 331 | iser_err("can't bind eph %llx\n", |
349 | (unsigned long long)transport_eph); | 332 | (unsigned long long)transport_eph); |
350 | return -EINVAL; | 333 | return -EINVAL; |
351 | } | 334 | } |
335 | ib_conn = ep->dd_data; | ||
336 | |||
352 | /* binds the iSER connection retrieved from the previously | 337 | /* binds the iSER connection retrieved from the previously |
353 | * connected ep_handle to the iSCSI layer connection. exchanges | 338 | * connected ep_handle to the iSCSI layer connection. exchanges |
354 | * connection pointers */ | 339 | * connection pointers */ |
@@ -401,21 +386,17 @@ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session) | |||
401 | } | 386 | } |
402 | 387 | ||
403 | static struct iscsi_cls_session * | 388 | static struct iscsi_cls_session * |
404 | iscsi_iser_session_create(struct Scsi_Host *shost, | 389 | iscsi_iser_session_create(struct iscsi_endpoint *ep, |
405 | uint16_t cmds_max, uint16_t qdepth, | 390 | uint16_t cmds_max, uint16_t qdepth, |
406 | uint32_t initial_cmdsn, uint32_t *hostno) | 391 | uint32_t initial_cmdsn, uint32_t *hostno) |
407 | { | 392 | { |
408 | struct iscsi_cls_session *cls_session; | 393 | struct iscsi_cls_session *cls_session; |
409 | struct iscsi_session *session; | 394 | struct iscsi_session *session; |
395 | struct Scsi_Host *shost; | ||
410 | int i; | 396 | int i; |
411 | struct iscsi_task *task; | 397 | struct iscsi_task *task; |
412 | struct iscsi_iser_task *iser_task; | 398 | struct iscsi_iser_task *iser_task; |
413 | 399 | struct iser_conn *ib_conn; | |
414 | if (shost) { | ||
415 | printk(KERN_ERR "iscsi_tcp: invalid shost %d.\n", | ||
416 | shost->host_no); | ||
417 | return NULL; | ||
418 | } | ||
419 | 400 | ||
420 | shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISCSI_MAX_CMD_PER_LUN); | 401 | shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISCSI_MAX_CMD_PER_LUN); |
421 | if (!shost) | 402 | if (!shost) |
@@ -426,7 +407,15 @@ iscsi_iser_session_create(struct Scsi_Host *shost, | |||
426 | shost->max_channel = 0; | 407 | shost->max_channel = 0; |
427 | shost->max_cmd_len = 16; | 408 | shost->max_cmd_len = 16; |
428 | 409 | ||
429 | if (iscsi_host_add(shost, NULL)) | 410 | /* |
411 | * older userspace tools (before 2.0-870) did not pass us | ||
412 | * the leading conn's ep so this will be NULL; | ||
413 | */ | ||
414 | if (ep) | ||
415 | ib_conn = ep->dd_data; | ||
416 | |||
417 | if (iscsi_host_add(shost, | ||
418 | ep ? ib_conn->device->ib_device->dma_device : NULL)) | ||
430 | goto free_host; | 419 | goto free_host; |
431 | *hostno = shost->host_no; | 420 | *hostno = shost->host_no; |
432 | 421 | ||
@@ -529,34 +518,37 @@ iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *s | |||
529 | stats->custom[3].value = conn->fmr_unalign_cnt; | 518 | stats->custom[3].value = conn->fmr_unalign_cnt; |
530 | } | 519 | } |
531 | 520 | ||
532 | static int | 521 | static struct iscsi_endpoint * |
533 | iscsi_iser_ep_connect(struct sockaddr *dst_addr, int non_blocking, | 522 | iscsi_iser_ep_connect(struct sockaddr *dst_addr, int non_blocking) |
534 | __u64 *ep_handle) | ||
535 | { | 523 | { |
536 | int err; | 524 | int err; |
537 | struct iser_conn *ib_conn; | 525 | struct iser_conn *ib_conn; |
526 | struct iscsi_endpoint *ep; | ||
538 | 527 | ||
539 | err = iser_conn_init(&ib_conn); | 528 | ep = iscsi_create_endpoint(sizeof(*ib_conn)); |
540 | if (err) | 529 | if (!ep) |
541 | goto out; | 530 | return ERR_PTR(-ENOMEM); |
542 | 531 | ||
543 | err = iser_connect(ib_conn, NULL, (struct sockaddr_in *)dst_addr, non_blocking); | 532 | ib_conn = ep->dd_data; |
544 | if (!err) | 533 | ib_conn->ep = ep; |
545 | *ep_handle = (__u64)(unsigned long)ib_conn; | 534 | iser_conn_init(ib_conn); |
546 | 535 | ||
547 | out: | 536 | err = iser_connect(ib_conn, NULL, (struct sockaddr_in *)dst_addr, |
548 | return err; | 537 | non_blocking); |
538 | if (err) { | ||
539 | iscsi_destroy_endpoint(ep); | ||
540 | return ERR_PTR(err); | ||
541 | } | ||
542 | return ep; | ||
549 | } | 543 | } |
550 | 544 | ||
551 | static int | 545 | static int |
552 | iscsi_iser_ep_poll(__u64 ep_handle, int timeout_ms) | 546 | iscsi_iser_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) |
553 | { | 547 | { |
554 | struct iser_conn *ib_conn = iscsi_iser_ib_conn_lookup(ep_handle); | 548 | struct iser_conn *ib_conn; |
555 | int rc; | 549 | int rc; |
556 | 550 | ||
557 | if (!ib_conn) | 551 | ib_conn = ep->dd_data; |
558 | return -EINVAL; | ||
559 | |||
560 | rc = wait_event_interruptible_timeout(ib_conn->wait, | 552 | rc = wait_event_interruptible_timeout(ib_conn->wait, |
561 | ib_conn->state == ISER_CONN_UP, | 553 | ib_conn->state == ISER_CONN_UP, |
562 | msecs_to_jiffies(timeout_ms)); | 554 | msecs_to_jiffies(timeout_ms)); |
@@ -578,14 +570,11 @@ iscsi_iser_ep_poll(__u64 ep_handle, int timeout_ms) | |||
578 | } | 570 | } |
579 | 571 | ||
580 | static void | 572 | static void |
581 | iscsi_iser_ep_disconnect(__u64 ep_handle) | 573 | iscsi_iser_ep_disconnect(struct iscsi_endpoint *ep) |
582 | { | 574 | { |
583 | struct iser_conn *ib_conn; | 575 | struct iser_conn *ib_conn; |
584 | 576 | ||
585 | ib_conn = iscsi_iser_ib_conn_lookup(ep_handle); | 577 | ib_conn = ep->dd_data; |
586 | if (!ib_conn) | ||
587 | return; | ||
588 | |||
589 | if (ib_conn->iser_conn) | 578 | if (ib_conn->iser_conn) |
590 | /* | 579 | /* |
591 | * Must suspend xmit path if the ep is bound to the | 580 | * Must suspend xmit path if the ep is bound to the |
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h index 05431f270fe8..cdf48763b082 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.h +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h | |||
@@ -174,6 +174,7 @@ struct iser_data_buf { | |||
174 | struct iser_device; | 174 | struct iser_device; |
175 | struct iscsi_iser_conn; | 175 | struct iscsi_iser_conn; |
176 | struct iscsi_iser_task; | 176 | struct iscsi_iser_task; |
177 | struct iscsi_endpoint; | ||
177 | 178 | ||
178 | struct iser_mem_reg { | 179 | struct iser_mem_reg { |
179 | u32 lkey; | 180 | u32 lkey; |
@@ -241,6 +242,7 @@ struct iser_device { | |||
241 | 242 | ||
242 | struct iser_conn { | 243 | struct iser_conn { |
243 | struct iscsi_iser_conn *iser_conn; /* iser conn for upcalls */ | 244 | struct iscsi_iser_conn *iser_conn; /* iser conn for upcalls */ |
245 | struct iscsi_endpoint *ep; | ||
244 | enum iser_ib_conn_state state; /* rdma connection state */ | 246 | enum iser_ib_conn_state state; /* rdma connection state */ |
245 | atomic_t refcount; | 247 | atomic_t refcount; |
246 | spinlock_t lock; /* used for state changes */ | 248 | spinlock_t lock; /* used for state changes */ |
@@ -313,7 +315,7 @@ void iscsi_iser_recv(struct iscsi_conn *conn, | |||
313 | char *rx_data, | 315 | char *rx_data, |
314 | int rx_data_len); | 316 | int rx_data_len); |
315 | 317 | ||
316 | int iser_conn_init(struct iser_conn **ib_conn); | 318 | void iser_conn_init(struct iser_conn *ib_conn); |
317 | 319 | ||
318 | void iser_conn_get(struct iser_conn *ib_conn); | 320 | void iser_conn_get(struct iser_conn *ib_conn); |
319 | 321 | ||
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 5daed2bd710e..81b45d4d9aa9 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c | |||
@@ -325,7 +325,7 @@ static void iser_conn_release(struct iser_conn *ib_conn) | |||
325 | iser_device_try_release(device); | 325 | iser_device_try_release(device); |
326 | if (ib_conn->iser_conn) | 326 | if (ib_conn->iser_conn) |
327 | ib_conn->iser_conn->ib_conn = NULL; | 327 | ib_conn->iser_conn->ib_conn = NULL; |
328 | kfree(ib_conn); | 328 | iscsi_destroy_endpoint(ib_conn->ep); |
329 | } | 329 | } |
330 | 330 | ||
331 | void iser_conn_get(struct iser_conn *ib_conn) | 331 | void iser_conn_get(struct iser_conn *ib_conn) |
@@ -494,15 +494,8 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve | |||
494 | return ret; | 494 | return ret; |
495 | } | 495 | } |
496 | 496 | ||
497 | int iser_conn_init(struct iser_conn **ibconn) | 497 | void iser_conn_init(struct iser_conn *ib_conn) |
498 | { | 498 | { |
499 | struct iser_conn *ib_conn; | ||
500 | |||
501 | ib_conn = kzalloc(sizeof *ib_conn, GFP_KERNEL); | ||
502 | if (!ib_conn) { | ||
503 | iser_err("can't alloc memory for struct iser_conn\n"); | ||
504 | return -ENOMEM; | ||
505 | } | ||
506 | ib_conn->state = ISER_CONN_INIT; | 499 | ib_conn->state = ISER_CONN_INIT; |
507 | init_waitqueue_head(&ib_conn->wait); | 500 | init_waitqueue_head(&ib_conn->wait); |
508 | atomic_set(&ib_conn->post_recv_buf_count, 0); | 501 | atomic_set(&ib_conn->post_recv_buf_count, 0); |
@@ -510,9 +503,6 @@ int iser_conn_init(struct iser_conn **ibconn) | |||
510 | atomic_set(&ib_conn->refcount, 1); | 503 | atomic_set(&ib_conn->refcount, 1); |
511 | INIT_LIST_HEAD(&ib_conn->conn_list); | 504 | INIT_LIST_HEAD(&ib_conn->conn_list); |
512 | spin_lock_init(&ib_conn->lock); | 505 | spin_lock_init(&ib_conn->lock); |
513 | |||
514 | *ibconn = ib_conn; | ||
515 | return 0; | ||
516 | } | 506 | } |
517 | 507 | ||
518 | /** | 508 | /** |