diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2008-05-21 16:54:06 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-12 09:22:19 -0400 |
commit | 3e5c28ad0391389959ccae81c938c7533efb3490 (patch) | |
tree | bcfb02dc14afa91dd21fd59ec7c82f881be065c9 /drivers | |
parent | 052d014485d2ce5bb7fa8dd0df875dafd1db77df (diff) |
[SCSI] libiscsi: merge iscsi_mgmt_task and iscsi_cmd_task
There is no need to have the mgmt and cmd tasks separate
structs. It used to save a lot of memory when we overprealocated
memory for tasks, but the next patches will set up the
driver so in the future they can use a mempool or some other
common scsi command allocator and common tagging.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/libiscsi.c | 518 |
1 files changed, 246 insertions, 272 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 1e605de07cff..ef92b1b0f16e 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -197,7 +197,7 @@ static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask) | |||
197 | 197 | ||
198 | /** | 198 | /** |
199 | * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu | 199 | * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu |
200 | * @ctask: iscsi cmd task | 200 | * @ctask: iscsi task |
201 | * | 201 | * |
202 | * Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set | 202 | * Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set |
203 | * fields like dlength or final based on how much data it sends | 203 | * fields like dlength or final based on how much data it sends |
@@ -300,31 +300,31 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) | |||
300 | WARN_ON(hdrlength >= 256); | 300 | WARN_ON(hdrlength >= 256); |
301 | hdr->hlength = hdrlength & 0xFF; | 301 | hdr->hlength = hdrlength & 0xFF; |
302 | 302 | ||
303 | if (conn->session->tt->init_cmd_task && | 303 | if (conn->session->tt->init_task && |
304 | conn->session->tt->init_cmd_task(ctask)) | 304 | conn->session->tt->init_task(ctask)) |
305 | return -EIO; | 305 | return -EIO; |
306 | 306 | ||
307 | ctask->state = ISCSI_TASK_RUNNING; | 307 | ctask->state = ISCSI_TASK_RUNNING; |
308 | list_move_tail(&ctask->running, &conn->run_list); | 308 | list_move_tail(&ctask->running, &conn->run_list); |
309 | 309 | ||
310 | conn->scsicmd_pdus_cnt++; | 310 | conn->scsicmd_pdus_cnt++; |
311 | debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x " | 311 | debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d " |
312 | "len %d bidi_len %d cmdsn %d win %d]\n", | 312 | "bidi_len %d cmdsn %d win %d]\n", scsi_bidi_cmnd(sc) ? |
313 | scsi_bidi_cmnd(sc) ? "bidirectional" : | 313 | "bidirectional" : sc->sc_data_direction == DMA_TO_DEVICE ? |
314 | sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", | 314 | "write" : "read", conn->id, sc, sc->cmnd[0], ctask->itt, |
315 | conn->id, sc, sc->cmnd[0], ctask->itt, | 315 | scsi_bufflen(sc), |
316 | scsi_bufflen(sc), scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0, | 316 | scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0, |
317 | session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); | 317 | session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); |
318 | return 0; | 318 | return 0; |
319 | } | 319 | } |
320 | 320 | ||
321 | /** | 321 | /** |
322 | * iscsi_complete_command - return command back to scsi-ml | 322 | * iscsi_complete_command - finish a task |
323 | * @ctask: iscsi cmd task | 323 | * @ctask: iscsi cmd task |
324 | * | 324 | * |
325 | * Must be called with session lock. | 325 | * Must be called with session lock. |
326 | * This function returns the scsi command to scsi-ml and returns | 326 | * This function returns the scsi command to scsi-ml or cleans |
327 | * the cmd task to the pool of available cmd tasks. | 327 | * up mgmt tasks then returns the task to the pool. |
328 | */ | 328 | */ |
329 | static void iscsi_complete_command(struct iscsi_cmd_task *ctask) | 329 | static void iscsi_complete_command(struct iscsi_cmd_task *ctask) |
330 | { | 330 | { |
@@ -332,17 +332,34 @@ static void iscsi_complete_command(struct iscsi_cmd_task *ctask) | |||
332 | struct iscsi_session *session = conn->session; | 332 | struct iscsi_session *session = conn->session; |
333 | struct scsi_cmnd *sc = ctask->sc; | 333 | struct scsi_cmnd *sc = ctask->sc; |
334 | 334 | ||
335 | list_del_init(&ctask->running); | ||
335 | ctask->state = ISCSI_TASK_COMPLETED; | 336 | ctask->state = ISCSI_TASK_COMPLETED; |
336 | ctask->sc = NULL; | 337 | ctask->sc = NULL; |
337 | /* SCSI eh reuses commands to verify us */ | 338 | |
338 | sc->SCp.ptr = NULL; | ||
339 | if (conn->ctask == ctask) | 339 | if (conn->ctask == ctask) |
340 | conn->ctask = NULL; | 340 | conn->ctask = NULL; |
341 | list_del_init(&ctask->running); | 341 | /* |
342 | * login ctask is preallocated so do not free | ||
343 | */ | ||
344 | if (conn->login_ctask == ctask) | ||
345 | return; | ||
346 | |||
342 | __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); | 347 | __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); |
343 | 348 | ||
344 | if (sc->scsi_done) | 349 | if (conn->ping_ctask == ctask) |
345 | sc->scsi_done(sc); | 350 | conn->ping_ctask = NULL; |
351 | |||
352 | if (sc) { | ||
353 | ctask->sc = NULL; | ||
354 | /* SCSI eh reuses commands to verify us */ | ||
355 | sc->SCp.ptr = NULL; | ||
356 | /* | ||
357 | * queue command may call this to free the task, but | ||
358 | * not have setup the sc callback | ||
359 | */ | ||
360 | if (sc->scsi_done) | ||
361 | sc->scsi_done(sc); | ||
362 | } | ||
346 | } | 363 | } |
347 | 364 | ||
348 | static void __iscsi_get_ctask(struct iscsi_cmd_task *ctask) | 365 | static void __iscsi_get_ctask(struct iscsi_cmd_task *ctask) |
@@ -356,6 +373,16 @@ static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask) | |||
356 | iscsi_complete_command(ctask); | 373 | iscsi_complete_command(ctask); |
357 | } | 374 | } |
358 | 375 | ||
376 | void iscsi_put_ctask(struct iscsi_cmd_task *ctask) | ||
377 | { | ||
378 | struct iscsi_session *session = ctask->conn->session; | ||
379 | |||
380 | spin_lock_bh(&session->lock); | ||
381 | __iscsi_put_ctask(ctask); | ||
382 | spin_unlock_bh(&session->lock); | ||
383 | } | ||
384 | EXPORT_SYMBOL_GPL(iscsi_put_ctask); | ||
385 | |||
359 | /* | 386 | /* |
360 | * session lock must be held | 387 | * session lock must be held |
361 | */ | 388 | */ |
@@ -375,47 +402,28 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
375 | */ | 402 | */ |
376 | conn->session->queued_cmdsn--; | 403 | conn->session->queued_cmdsn--; |
377 | else | 404 | else |
378 | conn->session->tt->cleanup_cmd_task(conn, ctask); | 405 | conn->session->tt->cleanup_task(conn, ctask); |
379 | 406 | ||
380 | sc->result = err; | 407 | sc->result = err; |
408 | |||
381 | if (!scsi_bidi_cmnd(sc)) | 409 | if (!scsi_bidi_cmnd(sc)) |
382 | scsi_set_resid(sc, scsi_bufflen(sc)); | 410 | scsi_set_resid(sc, scsi_bufflen(sc)); |
383 | else { | 411 | else { |
384 | scsi_out(sc)->resid = scsi_out(sc)->length; | 412 | scsi_out(sc)->resid = scsi_out(sc)->length; |
385 | scsi_in(sc)->resid = scsi_in(sc)->length; | 413 | scsi_in(sc)->resid = scsi_in(sc)->length; |
386 | } | 414 | } |
415 | |||
387 | if (conn->ctask == ctask) | 416 | if (conn->ctask == ctask) |
388 | conn->ctask = NULL; | 417 | conn->ctask = NULL; |
389 | /* release ref from queuecommand */ | 418 | /* release ref from queuecommand */ |
390 | __iscsi_put_ctask(ctask); | 419 | __iscsi_put_ctask(ctask); |
391 | } | 420 | } |
392 | 421 | ||
393 | /** | 422 | static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, |
394 | * iscsi_free_mgmt_task - return mgmt task back to pool | 423 | struct iscsi_cmd_task *ctask) |
395 | * @conn: iscsi connection | ||
396 | * @mtask: mtask | ||
397 | * | ||
398 | * Must be called with session lock. | ||
399 | */ | ||
400 | void iscsi_free_mgmt_task(struct iscsi_conn *conn, | ||
401 | struct iscsi_mgmt_task *mtask) | ||
402 | { | ||
403 | list_del_init(&mtask->running); | ||
404 | if (conn->login_mtask == mtask) | ||
405 | return; | ||
406 | |||
407 | if (conn->ping_mtask == mtask) | ||
408 | conn->ping_mtask = NULL; | ||
409 | __kfifo_put(conn->session->mgmtpool.queue, | ||
410 | (void*)&mtask, sizeof(void*)); | ||
411 | } | ||
412 | EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task); | ||
413 | |||
414 | static int iscsi_prep_mtask(struct iscsi_conn *conn, | ||
415 | struct iscsi_mgmt_task *mtask) | ||
416 | { | 424 | { |
417 | struct iscsi_session *session = conn->session; | 425 | struct iscsi_session *session = conn->session; |
418 | struct iscsi_hdr *hdr = mtask->hdr; | 426 | struct iscsi_hdr *hdr = (struct iscsi_hdr *)ctask->hdr; |
419 | struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; | 427 | struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; |
420 | 428 | ||
421 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) | 429 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) |
@@ -429,7 +437,7 @@ static int iscsi_prep_mtask(struct iscsi_conn *conn, | |||
429 | */ | 437 | */ |
430 | nop->cmdsn = cpu_to_be32(session->cmdsn); | 438 | nop->cmdsn = cpu_to_be32(session->cmdsn); |
431 | if (hdr->itt != RESERVED_ITT) { | 439 | if (hdr->itt != RESERVED_ITT) { |
432 | hdr->itt = build_itt(mtask->itt, session->age); | 440 | hdr->itt = build_itt(ctask->itt, session->age); |
433 | /* | 441 | /* |
434 | * TODO: We always use immediate, so we never hit this. | 442 | * TODO: We always use immediate, so we never hit this. |
435 | * If we start to send tmfs or nops as non-immediate then | 443 | * If we start to send tmfs or nops as non-immediate then |
@@ -442,25 +450,25 @@ static int iscsi_prep_mtask(struct iscsi_conn *conn, | |||
442 | } | 450 | } |
443 | } | 451 | } |
444 | 452 | ||
445 | if (session->tt->init_mgmt_task) | 453 | if (session->tt->init_task) |
446 | session->tt->init_mgmt_task(conn, mtask); | 454 | session->tt->init_task(ctask); |
447 | 455 | ||
448 | if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) | 456 | if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) |
449 | session->state = ISCSI_STATE_LOGGING_OUT; | 457 | session->state = ISCSI_STATE_LOGGING_OUT; |
450 | 458 | ||
451 | list_move_tail(&mtask->running, &conn->mgmt_run_list); | 459 | list_move_tail(&ctask->running, &conn->mgmt_run_list); |
452 | debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", | 460 | debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", |
453 | hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, | 461 | hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, |
454 | mtask->data_count); | 462 | ctask->data_count); |
455 | return 0; | 463 | return 0; |
456 | } | 464 | } |
457 | 465 | ||
458 | static struct iscsi_mgmt_task * | 466 | static struct iscsi_cmd_task * |
459 | __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | 467 | __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, |
460 | char *data, uint32_t data_size) | 468 | char *data, uint32_t data_size) |
461 | { | 469 | { |
462 | struct iscsi_session *session = conn->session; | 470 | struct iscsi_session *session = conn->session; |
463 | struct iscsi_mgmt_task *mtask; | 471 | struct iscsi_cmd_task *ctask; |
464 | 472 | ||
465 | if (session->state == ISCSI_STATE_TERMINATE) | 473 | if (session->state == ISCSI_STATE_TERMINATE) |
466 | return NULL; | 474 | return NULL; |
@@ -470,48 +478,56 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
470 | /* | 478 | /* |
471 | * Login and Text are sent serially, in | 479 | * Login and Text are sent serially, in |
472 | * request-followed-by-response sequence. | 480 | * request-followed-by-response sequence. |
473 | * Same mtask can be used. Same ITT must be used. | 481 | * Same task can be used. Same ITT must be used. |
474 | * Note that login_mtask is preallocated at conn_create(). | 482 | * Note that login_task is preallocated at conn_create(). |
475 | */ | 483 | */ |
476 | mtask = conn->login_mtask; | 484 | ctask = conn->login_ctask; |
477 | else { | 485 | else { |
478 | BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); | 486 | BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); |
479 | BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); | 487 | BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); |
480 | 488 | ||
481 | if (!__kfifo_get(session->mgmtpool.queue, | 489 | if (!__kfifo_get(session->cmdpool.queue, |
482 | (void*)&mtask, sizeof(void*))) | 490 | (void*)&ctask, sizeof(void*))) |
483 | return NULL; | 491 | return NULL; |
484 | 492 | ||
485 | if ((hdr->opcode == (ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE)) && | 493 | if ((hdr->opcode == (ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE)) && |
486 | hdr->ttt == RESERVED_ITT) { | 494 | hdr->ttt == RESERVED_ITT) { |
487 | conn->ping_mtask = mtask; | 495 | conn->ping_ctask = ctask; |
488 | conn->last_ping = jiffies; | 496 | conn->last_ping = jiffies; |
489 | } | 497 | } |
490 | } | 498 | } |
499 | /* | ||
500 | * released in complete pdu for task we expect a response for, and | ||
501 | * released by the lld when it has transmitted the task for | ||
502 | * pdus we do not expect a response for. | ||
503 | */ | ||
504 | atomic_set(&ctask->refcount, 1); | ||
505 | ctask->conn = conn; | ||
506 | ctask->sc = NULL; | ||
491 | 507 | ||
492 | if (data_size) { | 508 | if (data_size) { |
493 | memcpy(mtask->data, data, data_size); | 509 | memcpy(ctask->data, data, data_size); |
494 | mtask->data_count = data_size; | 510 | ctask->data_count = data_size; |
495 | } else | 511 | } else |
496 | mtask->data_count = 0; | 512 | ctask->data_count = 0; |
497 | 513 | ||
498 | memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr)); | 514 | memcpy(ctask->hdr, hdr, sizeof(struct iscsi_hdr)); |
499 | INIT_LIST_HEAD(&mtask->running); | 515 | INIT_LIST_HEAD(&ctask->running); |
500 | list_add_tail(&mtask->running, &conn->mgmtqueue); | 516 | list_add_tail(&ctask->running, &conn->mgmtqueue); |
501 | 517 | ||
502 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { | 518 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { |
503 | if (iscsi_prep_mtask(conn, mtask)) { | 519 | if (iscsi_prep_mgmt_task(conn, ctask)) { |
504 | iscsi_free_mgmt_task(conn, mtask); | 520 | __iscsi_put_ctask(ctask); |
505 | return NULL; | 521 | return NULL; |
506 | } | 522 | } |
507 | 523 | ||
508 | if (session->tt->xmit_mgmt_task(conn, mtask)) | 524 | if (session->tt->xmit_task(ctask)) |
509 | mtask = NULL; | 525 | ctask = NULL; |
510 | 526 | ||
511 | } else | 527 | } else |
512 | scsi_queue_work(conn->session->host, &conn->xmitwork); | 528 | scsi_queue_work(conn->session->host, &conn->xmitwork); |
513 | 529 | ||
514 | return mtask; | 530 | return ctask; |
515 | } | 531 | } |
516 | 532 | ||
517 | int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, | 533 | int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, |
@@ -538,7 +554,7 @@ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); | |||
538 | * @datalen: len of buffer | 554 | * @datalen: len of buffer |
539 | * | 555 | * |
540 | * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and | 556 | * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and |
541 | * then completes the command and task. | 557 | * then completes the command and ctask. |
542 | **/ | 558 | **/ |
543 | static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | 559 | static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, |
544 | struct iscsi_cmd_task *ctask, char *data, | 560 | struct iscsi_cmd_task *ctask, char *data, |
@@ -634,9 +650,9 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | |||
634 | static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) | 650 | static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) |
635 | { | 651 | { |
636 | struct iscsi_nopout hdr; | 652 | struct iscsi_nopout hdr; |
637 | struct iscsi_mgmt_task *mtask; | 653 | struct iscsi_cmd_task *ctask; |
638 | 654 | ||
639 | if (!rhdr && conn->ping_mtask) | 655 | if (!rhdr && conn->ping_ctask) |
640 | return; | 656 | return; |
641 | 657 | ||
642 | memset(&hdr, 0, sizeof(struct iscsi_nopout)); | 658 | memset(&hdr, 0, sizeof(struct iscsi_nopout)); |
@@ -650,8 +666,8 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) | |||
650 | } else | 666 | } else |
651 | hdr.ttt = RESERVED_ITT; | 667 | hdr.ttt = RESERVED_ITT; |
652 | 668 | ||
653 | mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); | 669 | ctask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); |
654 | if (!mtask) | 670 | if (!ctask) |
655 | iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); | 671 | iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); |
656 | } | 672 | } |
657 | 673 | ||
@@ -697,7 +713,6 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
697 | struct iscsi_session *session = conn->session; | 713 | struct iscsi_session *session = conn->session; |
698 | int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0; | 714 | int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0; |
699 | struct iscsi_cmd_task *ctask; | 715 | struct iscsi_cmd_task *ctask; |
700 | struct iscsi_mgmt_task *mtask; | ||
701 | uint32_t itt; | 716 | uint32_t itt; |
702 | 717 | ||
703 | conn->last_recv = jiffies; | 718 | conn->last_recv = jiffies; |
@@ -710,93 +725,10 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
710 | else | 725 | else |
711 | itt = ~0U; | 726 | itt = ~0U; |
712 | 727 | ||
713 | if (itt < session->cmds_max) { | 728 | debug_scsi("[op 0x%x cid %d itt 0x%x len %d]\n", |
714 | ctask = session->cmds[itt]; | 729 | opcode, conn->id, itt, datalen); |
715 | |||
716 | debug_scsi("cmdrsp [op 0x%x cid %d itt 0x%x len %d]\n", | ||
717 | opcode, conn->id, ctask->itt, datalen); | ||
718 | |||
719 | switch(opcode) { | ||
720 | case ISCSI_OP_SCSI_CMD_RSP: | ||
721 | BUG_ON((void*)ctask != ctask->sc->SCp.ptr); | ||
722 | iscsi_scsi_cmd_rsp(conn, hdr, ctask, data, | ||
723 | datalen); | ||
724 | break; | ||
725 | case ISCSI_OP_SCSI_DATA_IN: | ||
726 | BUG_ON((void*)ctask != ctask->sc->SCp.ptr); | ||
727 | if (hdr->flags & ISCSI_FLAG_DATA_STATUS) { | ||
728 | conn->scsirsp_pdus_cnt++; | ||
729 | __iscsi_put_ctask(ctask); | ||
730 | } | ||
731 | break; | ||
732 | case ISCSI_OP_R2T: | ||
733 | /* LLD handles this for now */ | ||
734 | break; | ||
735 | default: | ||
736 | rc = ISCSI_ERR_BAD_OPCODE; | ||
737 | break; | ||
738 | } | ||
739 | } else if (itt >= ISCSI_MGMT_ITT_OFFSET && | ||
740 | itt < ISCSI_MGMT_ITT_OFFSET + session->mgmtpool_max) { | ||
741 | mtask = session->mgmt_cmds[itt - ISCSI_MGMT_ITT_OFFSET]; | ||
742 | |||
743 | debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n", | ||
744 | opcode, conn->id, mtask->itt, datalen); | ||
745 | 730 | ||
746 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | 731 | if (itt == ~0U) { |
747 | switch(opcode) { | ||
748 | case ISCSI_OP_LOGOUT_RSP: | ||
749 | if (datalen) { | ||
750 | rc = ISCSI_ERR_PROTO; | ||
751 | break; | ||
752 | } | ||
753 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | ||
754 | /* fall through */ | ||
755 | case ISCSI_OP_LOGIN_RSP: | ||
756 | case ISCSI_OP_TEXT_RSP: | ||
757 | /* | ||
758 | * login related PDU's exp_statsn is handled in | ||
759 | * userspace | ||
760 | */ | ||
761 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) | ||
762 | rc = ISCSI_ERR_CONN_FAILED; | ||
763 | iscsi_free_mgmt_task(conn, mtask); | ||
764 | break; | ||
765 | case ISCSI_OP_SCSI_TMFUNC_RSP: | ||
766 | if (datalen) { | ||
767 | rc = ISCSI_ERR_PROTO; | ||
768 | break; | ||
769 | } | ||
770 | |||
771 | iscsi_tmf_rsp(conn, hdr); | ||
772 | iscsi_free_mgmt_task(conn, mtask); | ||
773 | break; | ||
774 | case ISCSI_OP_NOOP_IN: | ||
775 | if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || | ||
776 | datalen) { | ||
777 | rc = ISCSI_ERR_PROTO; | ||
778 | break; | ||
779 | } | ||
780 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | ||
781 | |||
782 | if (conn->ping_mtask != mtask) { | ||
783 | /* | ||
784 | * If this is not in response to one of our | ||
785 | * nops then it must be from userspace. | ||
786 | */ | ||
787 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, | ||
788 | datalen)) | ||
789 | rc = ISCSI_ERR_CONN_FAILED; | ||
790 | } else | ||
791 | mod_timer(&conn->transport_timer, | ||
792 | jiffies + conn->recv_timeout); | ||
793 | iscsi_free_mgmt_task(conn, mtask); | ||
794 | break; | ||
795 | default: | ||
796 | rc = ISCSI_ERR_BAD_OPCODE; | ||
797 | break; | ||
798 | } | ||
799 | } else if (itt == ~0U) { | ||
800 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | 732 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); |
801 | 733 | ||
802 | switch(opcode) { | 734 | switch(opcode) { |
@@ -823,9 +755,88 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
823 | rc = ISCSI_ERR_BAD_OPCODE; | 755 | rc = ISCSI_ERR_BAD_OPCODE; |
824 | break; | 756 | break; |
825 | } | 757 | } |
826 | } else | 758 | goto out; |
827 | rc = ISCSI_ERR_BAD_ITT; | 759 | } |
760 | |||
761 | ctask = session->cmds[itt]; | ||
762 | switch(opcode) { | ||
763 | case ISCSI_OP_SCSI_CMD_RSP: | ||
764 | if (!ctask->sc) { | ||
765 | rc = ISCSI_ERR_NO_SCSI_CMD; | ||
766 | break; | ||
767 | } | ||
768 | BUG_ON((void*)ctask != ctask->sc->SCp.ptr); | ||
769 | iscsi_scsi_cmd_rsp(conn, hdr, ctask, data, datalen); | ||
770 | break; | ||
771 | case ISCSI_OP_SCSI_DATA_IN: | ||
772 | if (!ctask->sc) { | ||
773 | rc = ISCSI_ERR_NO_SCSI_CMD; | ||
774 | break; | ||
775 | } | ||
776 | BUG_ON((void*)ctask != ctask->sc->SCp.ptr); | ||
777 | if (hdr->flags & ISCSI_FLAG_DATA_STATUS) { | ||
778 | conn->scsirsp_pdus_cnt++; | ||
779 | iscsi_update_cmdsn(session, | ||
780 | (struct iscsi_nopin*) hdr); | ||
781 | __iscsi_put_ctask(ctask); | ||
782 | } | ||
783 | break; | ||
784 | case ISCSI_OP_R2T: | ||
785 | /* LLD handles this for now */ | ||
786 | break; | ||
787 | case ISCSI_OP_LOGOUT_RSP: | ||
788 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | ||
789 | if (datalen) { | ||
790 | rc = ISCSI_ERR_PROTO; | ||
791 | break; | ||
792 | } | ||
793 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | ||
794 | goto recv_pdu; | ||
795 | case ISCSI_OP_LOGIN_RSP: | ||
796 | case ISCSI_OP_TEXT_RSP: | ||
797 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | ||
798 | /* | ||
799 | * login related PDU's exp_statsn is handled in | ||
800 | * userspace | ||
801 | */ | ||
802 | goto recv_pdu; | ||
803 | case ISCSI_OP_SCSI_TMFUNC_RSP: | ||
804 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | ||
805 | if (datalen) { | ||
806 | rc = ISCSI_ERR_PROTO; | ||
807 | break; | ||
808 | } | ||
809 | |||
810 | iscsi_tmf_rsp(conn, hdr); | ||
811 | __iscsi_put_ctask(ctask); | ||
812 | break; | ||
813 | case ISCSI_OP_NOOP_IN: | ||
814 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | ||
815 | if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || datalen) { | ||
816 | rc = ISCSI_ERR_PROTO; | ||
817 | break; | ||
818 | } | ||
819 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | ||
820 | |||
821 | if (conn->ping_ctask != ctask) | ||
822 | /* | ||
823 | * If this is not in response to one of our | ||
824 | * nops then it must be from userspace. | ||
825 | */ | ||
826 | goto recv_pdu; | ||
827 | __iscsi_put_ctask(ctask); | ||
828 | break; | ||
829 | default: | ||
830 | rc = ISCSI_ERR_BAD_OPCODE; | ||
831 | break; | ||
832 | } | ||
828 | 833 | ||
834 | out: | ||
835 | return rc; | ||
836 | recv_pdu: | ||
837 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) | ||
838 | rc = ISCSI_ERR_CONN_FAILED; | ||
839 | __iscsi_put_ctask(ctask); | ||
829 | return rc; | 840 | return rc; |
830 | } | 841 | } |
831 | 842 | ||
@@ -845,6 +856,7 @@ int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt) | |||
845 | { | 856 | { |
846 | struct iscsi_session *session = conn->session; | 857 | struct iscsi_session *session = conn->session; |
847 | struct iscsi_cmd_task *ctask; | 858 | struct iscsi_cmd_task *ctask; |
859 | uint32_t i; | ||
848 | 860 | ||
849 | if (itt == RESERVED_ITT) | 861 | if (itt == RESERVED_ITT) |
850 | return 0; | 862 | return 0; |
@@ -858,25 +870,22 @@ int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt) | |||
858 | return ISCSI_ERR_BAD_ITT; | 870 | return ISCSI_ERR_BAD_ITT; |
859 | } | 871 | } |
860 | 872 | ||
861 | if (itt < session->cmds_max) { | 873 | i = get_itt(itt); |
862 | ctask = session->cmds[itt]; | 874 | if (i >= session->cmds_max) { |
863 | 875 | iscsi_conn_printk(KERN_ERR, conn, | |
864 | if (!ctask->sc) { | 876 | "received invalid itt index %u (max cmds " |
865 | iscsi_conn_printk(KERN_INFO, conn, "dropping ctask " | 877 | "%u.\n", i, session->cmds_max); |
866 | "with itt 0x%x\n", ctask->itt); | 878 | return ISCSI_ERR_BAD_ITT; |
867 | /* force drop */ | ||
868 | return ISCSI_ERR_NO_SCSI_CMD; | ||
869 | } | ||
870 | |||
871 | if (ctask->sc->SCp.phase != session->age) { | ||
872 | iscsi_conn_printk(KERN_ERR, conn, | ||
873 | "iscsi: ctask's session age %d, " | ||
874 | "expected %d\n", ctask->sc->SCp.phase, | ||
875 | session->age); | ||
876 | return ISCSI_ERR_SESSION_FAILED; | ||
877 | } | ||
878 | } | 879 | } |
879 | 880 | ||
881 | ctask = session->cmds[i]; | ||
882 | if (ctask->sc && ctask->sc->SCp.phase != session->age) { | ||
883 | iscsi_conn_printk(KERN_ERR, conn, | ||
884 | "iscsi: ctask's session age %d, " | ||
885 | "expected %d\n", ctask->sc->SCp.phase, | ||
886 | session->age); | ||
887 | return ISCSI_ERR_SESSION_FAILED; | ||
888 | } | ||
880 | return 0; | 889 | return 0; |
881 | } | 890 | } |
882 | EXPORT_SYMBOL_GPL(iscsi_verify_itt); | 891 | EXPORT_SYMBOL_GPL(iscsi_verify_itt); |
@@ -929,20 +938,6 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) | |||
929 | } | 938 | } |
930 | EXPORT_SYMBOL_GPL(iscsi_conn_failure); | 939 | EXPORT_SYMBOL_GPL(iscsi_conn_failure); |
931 | 940 | ||
932 | static int iscsi_xmit_mtask(struct iscsi_conn *conn) | ||
933 | { | ||
934 | int rc; | ||
935 | |||
936 | spin_unlock_bh(&conn->session->lock); | ||
937 | rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask); | ||
938 | spin_lock_bh(&conn->session->lock); | ||
939 | if (rc) | ||
940 | return rc; | ||
941 | /* done with this in-progress mtask */ | ||
942 | conn->mtask = NULL; | ||
943 | return 0; | ||
944 | } | ||
945 | |||
946 | static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) | 941 | static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) |
947 | { | 942 | { |
948 | struct iscsi_session *session = conn->session; | 943 | struct iscsi_session *session = conn->session; |
@@ -967,7 +962,7 @@ static int iscsi_xmit_ctask(struct iscsi_conn *conn) | |||
967 | 962 | ||
968 | __iscsi_get_ctask(ctask); | 963 | __iscsi_get_ctask(ctask); |
969 | spin_unlock_bh(&conn->session->lock); | 964 | spin_unlock_bh(&conn->session->lock); |
970 | rc = conn->session->tt->xmit_cmd_task(conn, ctask); | 965 | rc = conn->session->tt->xmit_task(ctask); |
971 | spin_lock_bh(&conn->session->lock); | 966 | spin_lock_bh(&conn->session->lock); |
972 | __iscsi_put_ctask(ctask); | 967 | __iscsi_put_ctask(ctask); |
973 | if (!rc) | 968 | if (!rc) |
@@ -1015,12 +1010,6 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |||
1015 | 1010 | ||
1016 | if (conn->ctask) { | 1011 | if (conn->ctask) { |
1017 | rc = iscsi_xmit_ctask(conn); | 1012 | rc = iscsi_xmit_ctask(conn); |
1018 | if (rc) | ||
1019 | goto again; | ||
1020 | } | ||
1021 | |||
1022 | if (conn->mtask) { | ||
1023 | rc = iscsi_xmit_mtask(conn); | ||
1024 | if (rc) | 1013 | if (rc) |
1025 | goto again; | 1014 | goto again; |
1026 | } | 1015 | } |
@@ -1032,14 +1021,14 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |||
1032 | */ | 1021 | */ |
1033 | check_mgmt: | 1022 | check_mgmt: |
1034 | while (!list_empty(&conn->mgmtqueue)) { | 1023 | while (!list_empty(&conn->mgmtqueue)) { |
1035 | conn->mtask = list_entry(conn->mgmtqueue.next, | 1024 | conn->ctask = list_entry(conn->mgmtqueue.next, |
1036 | struct iscsi_mgmt_task, running); | 1025 | struct iscsi_cmd_task, running); |
1037 | if (iscsi_prep_mtask(conn, conn->mtask)) { | 1026 | if (iscsi_prep_mgmt_task(conn, conn->ctask)) { |
1038 | iscsi_free_mgmt_task(conn, conn->mtask); | 1027 | __iscsi_put_ctask(conn->ctask); |
1039 | conn->mtask = NULL; | 1028 | conn->ctask = NULL; |
1040 | continue; | 1029 | continue; |
1041 | } | 1030 | } |
1042 | rc = iscsi_xmit_mtask(conn); | 1031 | rc = iscsi_xmit_ctask(conn); |
1043 | if (rc) | 1032 | if (rc) |
1044 | goto again; | 1033 | goto again; |
1045 | } | 1034 | } |
@@ -1224,7 +1213,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1224 | iscsi_complete_command(ctask); | 1213 | iscsi_complete_command(ctask); |
1225 | goto fault; | 1214 | goto fault; |
1226 | } | 1215 | } |
1227 | if (session->tt->xmit_cmd_task(conn, ctask)) { | 1216 | if (session->tt->xmit_task(ctask)) { |
1228 | sc->scsi_done = NULL; | 1217 | sc->scsi_done = NULL; |
1229 | iscsi_complete_command(ctask); | 1218 | iscsi_complete_command(ctask); |
1230 | reason = FAILURE_SESSION_NOT_READY; | 1219 | reason = FAILURE_SESSION_NOT_READY; |
@@ -1347,16 +1336,16 @@ static void iscsi_tmf_timedout(unsigned long data) | |||
1347 | spin_unlock(&session->lock); | 1336 | spin_unlock(&session->lock); |
1348 | } | 1337 | } |
1349 | 1338 | ||
1350 | static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, | 1339 | static int iscsi_exec_ctask_mgmt_fn(struct iscsi_conn *conn, |
1351 | struct iscsi_tm *hdr, int age, | 1340 | struct iscsi_tm *hdr, int age, |
1352 | int timeout) | 1341 | int timeout) |
1353 | { | 1342 | { |
1354 | struct iscsi_session *session = conn->session; | 1343 | struct iscsi_session *session = conn->session; |
1355 | struct iscsi_mgmt_task *mtask; | 1344 | struct iscsi_cmd_task *ctask; |
1356 | 1345 | ||
1357 | mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, | 1346 | ctask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, |
1358 | NULL, 0); | 1347 | NULL, 0); |
1359 | if (!mtask) { | 1348 | if (!ctask) { |
1360 | spin_unlock_bh(&session->lock); | 1349 | spin_unlock_bh(&session->lock); |
1361 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | 1350 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
1362 | spin_lock_bh(&session->lock); | 1351 | spin_lock_bh(&session->lock); |
@@ -1390,7 +1379,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, | |||
1390 | 1379 | ||
1391 | mutex_lock(&session->eh_mutex); | 1380 | mutex_lock(&session->eh_mutex); |
1392 | spin_lock_bh(&session->lock); | 1381 | spin_lock_bh(&session->lock); |
1393 | /* if the session drops it will clean up the mtask */ | 1382 | /* if the session drops it will clean up the ctask */ |
1394 | if (age != session->age || | 1383 | if (age != session->age || |
1395 | session->state != ISCSI_STATE_LOGGED_IN) | 1384 | session->state != ISCSI_STATE_LOGGED_IN) |
1396 | return -ENOTCONN; | 1385 | return -ENOTCONN; |
@@ -1497,7 +1486,7 @@ static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) | |||
1497 | jiffies)) | 1486 | jiffies)) |
1498 | rc = EH_RESET_TIMER; | 1487 | rc = EH_RESET_TIMER; |
1499 | /* if in the middle of checking the transport then give us more time */ | 1488 | /* if in the middle of checking the transport then give us more time */ |
1500 | if (conn->ping_mtask) | 1489 | if (conn->ping_ctask) |
1501 | rc = EH_RESET_TIMER; | 1490 | rc = EH_RESET_TIMER; |
1502 | done: | 1491 | done: |
1503 | spin_unlock(&session->lock); | 1492 | spin_unlock(&session->lock); |
@@ -1521,7 +1510,7 @@ static void iscsi_check_transport_timeouts(unsigned long data) | |||
1521 | 1510 | ||
1522 | recv_timeout *= HZ; | 1511 | recv_timeout *= HZ; |
1523 | last_recv = conn->last_recv; | 1512 | last_recv = conn->last_recv; |
1524 | if (conn->ping_mtask && | 1513 | if (conn->ping_ctask && |
1525 | time_before_eq(conn->last_ping + (conn->ping_timeout * HZ), | 1514 | time_before_eq(conn->last_ping + (conn->ping_timeout * HZ), |
1526 | jiffies)) { | 1515 | jiffies)) { |
1527 | iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " | 1516 | iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " |
@@ -1547,7 +1536,7 @@ done: | |||
1547 | spin_unlock(&session->lock); | 1536 | spin_unlock(&session->lock); |
1548 | } | 1537 | } |
1549 | 1538 | ||
1550 | static void iscsi_prep_abort_task_pdu(struct iscsi_cmd_task *ctask, | 1539 | static void iscsi_prep_abort_ctask_pdu(struct iscsi_cmd_task *ctask, |
1551 | struct iscsi_tm *hdr) | 1540 | struct iscsi_tm *hdr) |
1552 | { | 1541 | { |
1553 | memset(hdr, 0, sizeof(*hdr)); | 1542 | memset(hdr, 0, sizeof(*hdr)); |
@@ -1619,9 +1608,9 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1619 | conn->tmf_state = TMF_QUEUED; | 1608 | conn->tmf_state = TMF_QUEUED; |
1620 | 1609 | ||
1621 | hdr = &conn->tmhdr; | 1610 | hdr = &conn->tmhdr; |
1622 | iscsi_prep_abort_task_pdu(ctask, hdr); | 1611 | iscsi_prep_abort_ctask_pdu(ctask, hdr); |
1623 | 1612 | ||
1624 | if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) { | 1613 | if (iscsi_exec_ctask_mgmt_fn(conn, hdr, age, session->abort_timeout)) { |
1625 | rc = FAILED; | 1614 | rc = FAILED; |
1626 | goto failed; | 1615 | goto failed; |
1627 | } | 1616 | } |
@@ -1631,7 +1620,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1631 | spin_unlock_bh(&session->lock); | 1620 | spin_unlock_bh(&session->lock); |
1632 | iscsi_suspend_tx(conn); | 1621 | iscsi_suspend_tx(conn); |
1633 | /* | 1622 | /* |
1634 | * clean up task if aborted. grab the recv lock as a writer | 1623 | * clean up ctask if aborted. grab the recv lock as a writer |
1635 | */ | 1624 | */ |
1636 | write_lock_bh(conn->recv_lock); | 1625 | write_lock_bh(conn->recv_lock); |
1637 | spin_lock(&session->lock); | 1626 | spin_lock(&session->lock); |
@@ -1716,7 +1705,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) | |||
1716 | hdr = &conn->tmhdr; | 1705 | hdr = &conn->tmhdr; |
1717 | iscsi_prep_lun_reset_pdu(sc, hdr); | 1706 | iscsi_prep_lun_reset_pdu(sc, hdr); |
1718 | 1707 | ||
1719 | if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age, | 1708 | if (iscsi_exec_ctask_mgmt_fn(conn, hdr, session->age, |
1720 | session->lu_reset_timeout)) { | 1709 | session->lu_reset_timeout)) { |
1721 | rc = FAILED; | 1710 | rc = FAILED; |
1722 | goto unlock; | 1711 | goto unlock; |
@@ -1897,8 +1886,7 @@ EXPORT_SYMBOL_GPL(iscsi_host_free); | |||
1897 | * @iscsit: iscsi transport template | 1886 | * @iscsit: iscsi transport template |
1898 | * @shost: scsi host | 1887 | * @shost: scsi host |
1899 | * @cmds_max: session can queue | 1888 | * @cmds_max: session can queue |
1900 | * @cmd_task_size: LLD ctask private data size | 1889 | * @cmd_ctask_size: LLD ctask private data size |
1901 | * @mgmt_task_size: LLD mtask private data size | ||
1902 | * @initial_cmdsn: initial CmdSN | 1890 | * @initial_cmdsn: initial CmdSN |
1903 | * | 1891 | * |
1904 | * This can be used by software iscsi_transports that allocate | 1892 | * This can be used by software iscsi_transports that allocate |
@@ -1906,22 +1894,26 @@ EXPORT_SYMBOL_GPL(iscsi_host_free); | |||
1906 | */ | 1894 | */ |
1907 | struct iscsi_cls_session * | 1895 | struct iscsi_cls_session * |
1908 | iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | 1896 | iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, |
1909 | uint16_t cmds_max, int cmd_task_size, int mgmt_task_size, | 1897 | uint16_t scsi_cmds_max, int cmd_ctask_size, |
1910 | uint32_t initial_cmdsn) | 1898 | uint32_t initial_cmdsn) |
1911 | { | 1899 | { |
1912 | struct iscsi_session *session; | 1900 | struct iscsi_session *session; |
1913 | struct iscsi_cls_session *cls_session; | 1901 | struct iscsi_cls_session *cls_session; |
1914 | int cmd_i; | 1902 | int cmd_i, cmds_max; |
1915 | 1903 | ||
1916 | if (!is_power_of_2(cmds_max) || cmds_max >= ISCSI_MGMT_ITT_OFFSET || | 1904 | /* |
1917 | cmds_max < 2) { | 1905 | * The iscsi layer needs some ctasks for nop handling and tmfs. |
1918 | if (cmds_max != 0) | 1906 | */ |
1919 | printk(KERN_ERR "iscsi: invalid can_queue of %d. " | 1907 | if (scsi_cmds_max < 1) |
1920 | "can_queue must be a power of 2 and between " | 1908 | scsi_cmds_max = ISCSI_MGMT_CMDS_MAX; |
1921 | "2 and %d - setting to %d.\n", cmds_max, | 1909 | if ((scsi_cmds_max + ISCSI_MGMT_CMDS_MAX) >= ISCSI_MGMT_ITT_OFFSET) { |
1922 | ISCSI_MGMT_ITT_OFFSET, ISCSI_DEF_XMIT_CMDS_MAX); | 1910 | printk(KERN_ERR "iscsi: invalid can_queue of %d. " |
1923 | cmds_max = ISCSI_DEF_XMIT_CMDS_MAX; | 1911 | "can_queue must be less than %d.\n", |
1912 | scsi_cmds_max, | ||
1913 | ISCSI_MGMT_ITT_OFFSET - ISCSI_MGMT_CMDS_MAX); | ||
1914 | scsi_cmds_max = ISCSI_DEF_XMIT_CMDS_MAX; | ||
1924 | } | 1915 | } |
1916 | cmds_max = roundup_pow_of_two(scsi_cmds_max + ISCSI_MGMT_CMDS_MAX); | ||
1925 | 1917 | ||
1926 | cls_session = iscsi_alloc_session(shost, iscsit, | 1918 | cls_session = iscsi_alloc_session(shost, iscsit, |
1927 | sizeof(struct iscsi_session)); | 1919 | sizeof(struct iscsi_session)); |
@@ -1934,7 +1926,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | |||
1934 | session->fast_abort = 1; | 1926 | session->fast_abort = 1; |
1935 | session->lu_reset_timeout = 15; | 1927 | session->lu_reset_timeout = 15; |
1936 | session->abort_timeout = 10; | 1928 | session->abort_timeout = 10; |
1937 | session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; | 1929 | session->scsi_cmds_max = scsi_cmds_max; |
1938 | session->cmds_max = cmds_max; | 1930 | session->cmds_max = cmds_max; |
1939 | session->queued_cmdsn = session->cmdsn = initial_cmdsn; | 1931 | session->queued_cmdsn = session->cmdsn = initial_cmdsn; |
1940 | session->exp_cmdsn = initial_cmdsn + 1; | 1932 | session->exp_cmdsn = initial_cmdsn + 1; |
@@ -1947,36 +1939,19 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | |||
1947 | /* initialize SCSI PDU commands pool */ | 1939 | /* initialize SCSI PDU commands pool */ |
1948 | if (iscsi_pool_init(&session->cmdpool, session->cmds_max, | 1940 | if (iscsi_pool_init(&session->cmdpool, session->cmds_max, |
1949 | (void***)&session->cmds, | 1941 | (void***)&session->cmds, |
1950 | cmd_task_size + sizeof(struct iscsi_cmd_task))) | 1942 | cmd_ctask_size + sizeof(struct iscsi_cmd_task))) |
1951 | goto cmdpool_alloc_fail; | 1943 | goto cmdpool_alloc_fail; |
1952 | 1944 | ||
1953 | /* pre-format cmds pool with ITT */ | 1945 | /* pre-format cmds pool with ITT */ |
1954 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { | 1946 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { |
1955 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; | 1947 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; |
1956 | 1948 | ||
1957 | if (cmd_task_size) | 1949 | if (cmd_ctask_size) |
1958 | ctask->dd_data = &ctask[1]; | 1950 | ctask->dd_data = &ctask[1]; |
1959 | ctask->itt = cmd_i; | 1951 | ctask->itt = cmd_i; |
1960 | INIT_LIST_HEAD(&ctask->running); | 1952 | INIT_LIST_HEAD(&ctask->running); |
1961 | } | 1953 | } |
1962 | 1954 | ||
1963 | /* initialize immediate command pool */ | ||
1964 | if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max, | ||
1965 | (void***)&session->mgmt_cmds, | ||
1966 | mgmt_task_size + sizeof(struct iscsi_mgmt_task))) | ||
1967 | goto mgmtpool_alloc_fail; | ||
1968 | |||
1969 | |||
1970 | /* pre-format immediate cmds pool with ITT */ | ||
1971 | for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) { | ||
1972 | struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i]; | ||
1973 | |||
1974 | if (mgmt_task_size) | ||
1975 | mtask->dd_data = &mtask[1]; | ||
1976 | mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i; | ||
1977 | INIT_LIST_HEAD(&mtask->running); | ||
1978 | } | ||
1979 | |||
1980 | if (!try_module_get(iscsit->owner)) | 1955 | if (!try_module_get(iscsit->owner)) |
1981 | goto module_get_fail; | 1956 | goto module_get_fail; |
1982 | 1957 | ||
@@ -1987,8 +1962,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | |||
1987 | cls_session_fail: | 1962 | cls_session_fail: |
1988 | module_put(iscsit->owner); | 1963 | module_put(iscsit->owner); |
1989 | module_get_fail: | 1964 | module_get_fail: |
1990 | iscsi_pool_free(&session->mgmtpool); | ||
1991 | mgmtpool_alloc_fail: | ||
1992 | iscsi_pool_free(&session->cmdpool); | 1965 | iscsi_pool_free(&session->cmdpool); |
1993 | cmdpool_alloc_fail: | 1966 | cmdpool_alloc_fail: |
1994 | iscsi_free_session(cls_session); | 1967 | iscsi_free_session(cls_session); |
@@ -2008,7 +1981,6 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session) | |||
2008 | struct iscsi_session *session = cls_session->dd_data; | 1981 | struct iscsi_session *session = cls_session->dd_data; |
2009 | struct module *owner = cls_session->transport->owner; | 1982 | struct module *owner = cls_session->transport->owner; |
2010 | 1983 | ||
2011 | iscsi_pool_free(&session->mgmtpool); | ||
2012 | iscsi_pool_free(&session->cmdpool); | 1984 | iscsi_pool_free(&session->cmdpool); |
2013 | 1985 | ||
2014 | kfree(session->password); | 1986 | kfree(session->password); |
@@ -2063,30 +2035,30 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, | |||
2063 | INIT_LIST_HEAD(&conn->requeue); | 2035 | INIT_LIST_HEAD(&conn->requeue); |
2064 | INIT_WORK(&conn->xmitwork, iscsi_xmitworker); | 2036 | INIT_WORK(&conn->xmitwork, iscsi_xmitworker); |
2065 | 2037 | ||
2066 | /* allocate login_mtask used for the login/text sequences */ | 2038 | /* allocate login_ctask used for the login/text sequences */ |
2067 | spin_lock_bh(&session->lock); | 2039 | spin_lock_bh(&session->lock); |
2068 | if (!__kfifo_get(session->mgmtpool.queue, | 2040 | if (!__kfifo_get(session->cmdpool.queue, |
2069 | (void*)&conn->login_mtask, | 2041 | (void*)&conn->login_ctask, |
2070 | sizeof(void*))) { | 2042 | sizeof(void*))) { |
2071 | spin_unlock_bh(&session->lock); | 2043 | spin_unlock_bh(&session->lock); |
2072 | goto login_mtask_alloc_fail; | 2044 | goto login_ctask_alloc_fail; |
2073 | } | 2045 | } |
2074 | spin_unlock_bh(&session->lock); | 2046 | spin_unlock_bh(&session->lock); |
2075 | 2047 | ||
2076 | data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL); | 2048 | data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL); |
2077 | if (!data) | 2049 | if (!data) |
2078 | goto login_mtask_data_alloc_fail; | 2050 | goto login_ctask_data_alloc_fail; |
2079 | conn->login_mtask->data = conn->data = data; | 2051 | conn->login_ctask->data = conn->data = data; |
2080 | 2052 | ||
2081 | init_timer(&conn->tmf_timer); | 2053 | init_timer(&conn->tmf_timer); |
2082 | init_waitqueue_head(&conn->ehwait); | 2054 | init_waitqueue_head(&conn->ehwait); |
2083 | 2055 | ||
2084 | return cls_conn; | 2056 | return cls_conn; |
2085 | 2057 | ||
2086 | login_mtask_data_alloc_fail: | 2058 | login_ctask_data_alloc_fail: |
2087 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, | 2059 | __kfifo_put(session->cmdpool.queue, (void*)&conn->login_ctask, |
2088 | sizeof(void*)); | 2060 | sizeof(void*)); |
2089 | login_mtask_alloc_fail: | 2061 | login_ctask_alloc_fail: |
2090 | iscsi_destroy_conn(cls_conn); | 2062 | iscsi_destroy_conn(cls_conn); |
2091 | return NULL; | 2063 | return NULL; |
2092 | } | 2064 | } |
@@ -2146,7 +2118,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
2146 | spin_lock_bh(&session->lock); | 2118 | spin_lock_bh(&session->lock); |
2147 | kfree(conn->data); | 2119 | kfree(conn->data); |
2148 | kfree(conn->persistent_address); | 2120 | kfree(conn->persistent_address); |
2149 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, | 2121 | __kfifo_put(session->cmdpool.queue, (void*)&conn->login_ctask, |
2150 | sizeof(void*)); | 2122 | sizeof(void*)); |
2151 | if (session->leadconn == conn) | 2123 | if (session->leadconn == conn) |
2152 | session->leadconn = NULL; | 2124 | session->leadconn = NULL; |
@@ -2227,21 +2199,23 @@ EXPORT_SYMBOL_GPL(iscsi_conn_start); | |||
2227 | static void | 2199 | static void |
2228 | flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) | 2200 | flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) |
2229 | { | 2201 | { |
2230 | struct iscsi_mgmt_task *mtask, *tmp; | 2202 | struct iscsi_cmd_task *ctask, *tmp; |
2231 | 2203 | ||
2232 | /* handle pending */ | 2204 | /* handle pending */ |
2233 | list_for_each_entry_safe(mtask, tmp, &conn->mgmtqueue, running) { | 2205 | list_for_each_entry_safe(ctask, tmp, &conn->mgmtqueue, running) { |
2234 | debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt); | 2206 | debug_scsi("flushing pending mgmt ctask itt 0x%x\n", ctask->itt); |
2235 | iscsi_free_mgmt_task(conn, mtask); | 2207 | /* release ref from prep ctask */ |
2208 | __iscsi_put_ctask(ctask); | ||
2236 | } | 2209 | } |
2237 | 2210 | ||
2238 | /* handle running */ | 2211 | /* handle running */ |
2239 | list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) { | 2212 | list_for_each_entry_safe(ctask, tmp, &conn->mgmt_run_list, running) { |
2240 | debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt); | 2213 | debug_scsi("flushing running mgmt ctask itt 0x%x\n", ctask->itt); |
2241 | iscsi_free_mgmt_task(conn, mtask); | 2214 | /* release ref from prep ctask */ |
2215 | __iscsi_put_ctask(ctask); | ||
2242 | } | 2216 | } |
2243 | 2217 | ||
2244 | conn->mtask = NULL; | 2218 | conn->ctask = NULL; |
2245 | } | 2219 | } |
2246 | 2220 | ||
2247 | static void iscsi_start_session_recovery(struct iscsi_session *session, | 2221 | static void iscsi_start_session_recovery(struct iscsi_session *session, |
@@ -2272,7 +2246,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
2272 | 2246 | ||
2273 | /* | 2247 | /* |
2274 | * When this is called for the in_login state, we only want to clean | 2248 | * When this is called for the in_login state, we only want to clean |
2275 | * up the login task and connection. We do not need to block and set | 2249 | * up the login ctask and connection. We do not need to block and set |
2276 | * the recovery state again | 2250 | * the recovery state again |
2277 | */ | 2251 | */ |
2278 | if (flag == STOP_CONN_TERM) | 2252 | if (flag == STOP_CONN_TERM) |