diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 90 |
1 files changed, 38 insertions, 52 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 7e6e031cc41b..1a8cd20f484f 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -189,6 +189,7 @@ static void iscsi_complete_command(struct iscsi_session *session, | |||
189 | { | 189 | { |
190 | struct scsi_cmnd *sc = ctask->sc; | 190 | struct scsi_cmnd *sc = ctask->sc; |
191 | 191 | ||
192 | ctask->state = ISCSI_TASK_COMPLETED; | ||
192 | ctask->sc = NULL; | 193 | ctask->sc = NULL; |
193 | list_del_init(&ctask->running); | 194 | list_del_init(&ctask->running); |
194 | __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); | 195 | __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); |
@@ -568,20 +569,24 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |||
568 | } | 569 | } |
569 | 570 | ||
570 | /* process command queue */ | 571 | /* process command queue */ |
571 | while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask, | 572 | spin_lock_bh(&conn->session->lock); |
572 | sizeof(void*))) { | 573 | while (!list_empty(&conn->xmitqueue)) { |
573 | /* | 574 | /* |
574 | * iscsi tcp may readd the task to the xmitqueue to send | 575 | * iscsi tcp may readd the task to the xmitqueue to send |
575 | * write data | 576 | * write data |
576 | */ | 577 | */ |
577 | spin_lock_bh(&conn->session->lock); | 578 | conn->ctask = list_entry(conn->xmitqueue.next, |
578 | if (list_empty(&conn->ctask->running)) | 579 | struct iscsi_cmd_task, running); |
579 | list_add_tail(&conn->ctask->running, &conn->run_list); | 580 | conn->ctask->state = ISCSI_TASK_RUNNING; |
581 | list_move_tail(conn->xmitqueue.next, &conn->run_list); | ||
580 | spin_unlock_bh(&conn->session->lock); | 582 | spin_unlock_bh(&conn->session->lock); |
583 | |||
581 | rc = tt->xmit_cmd_task(conn, conn->ctask); | 584 | rc = tt->xmit_cmd_task(conn, conn->ctask); |
582 | if (rc) | 585 | if (rc) |
583 | goto again; | 586 | goto again; |
587 | spin_lock_bh(&conn->session->lock); | ||
584 | } | 588 | } |
589 | spin_unlock_bh(&conn->session->lock); | ||
585 | /* done with this ctask */ | 590 | /* done with this ctask */ |
586 | conn->ctask = NULL; | 591 | conn->ctask = NULL; |
587 | 592 | ||
@@ -691,6 +696,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
691 | sc->SCp.phase = session->age; | 696 | sc->SCp.phase = session->age; |
692 | sc->SCp.ptr = (char *)ctask; | 697 | sc->SCp.ptr = (char *)ctask; |
693 | 698 | ||
699 | ctask->state = ISCSI_TASK_PENDING; | ||
694 | ctask->mtask = NULL; | 700 | ctask->mtask = NULL; |
695 | ctask->conn = conn; | 701 | ctask->conn = conn; |
696 | ctask->sc = sc; | 702 | ctask->sc = sc; |
@@ -700,7 +706,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
700 | 706 | ||
701 | session->tt->init_cmd_task(ctask); | 707 | session->tt->init_cmd_task(ctask); |
702 | 708 | ||
703 | __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); | 709 | list_add_tail(&ctask->running, &conn->xmitqueue); |
704 | debug_scsi( | 710 | debug_scsi( |
705 | "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n", | 711 | "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n", |
706 | sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", | 712 | sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", |
@@ -977,31 +983,27 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, | |||
977 | /* | 983 | /* |
978 | * xmit mutex and session lock must be held | 984 | * xmit mutex and session lock must be held |
979 | */ | 985 | */ |
980 | #define iscsi_remove_task(tasktype) \ | 986 | static struct iscsi_mgmt_task * |
981 | static struct iscsi_##tasktype * \ | 987 | iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt) |
982 | iscsi_remove_##tasktype(struct kfifo *fifo, uint32_t itt) \ | 988 | { |
983 | { \ | 989 | int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*); |
984 | int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*); \ | 990 | struct iscsi_mgmt_task *task; |
985 | struct iscsi_##tasktype *task; \ | 991 | |
986 | \ | 992 | debug_scsi("searching %d tasks\n", nr_tasks); |
987 | debug_scsi("searching %d tasks\n", nr_tasks); \ | 993 | |
988 | \ | 994 | for (i = 0; i < nr_tasks; i++) { |
989 | for (i = 0; i < nr_tasks; i++) { \ | 995 | __kfifo_get(fifo, (void*)&task, sizeof(void*)); |
990 | __kfifo_get(fifo, (void*)&task, sizeof(void*)); \ | 996 | debug_scsi("check task %u\n", task->itt); |
991 | debug_scsi("check task %u\n", task->itt); \ | 997 | |
992 | \ | 998 | if (task->itt == itt) { |
993 | if (task->itt == itt) { \ | 999 | debug_scsi("matched task\n"); |
994 | debug_scsi("matched task\n"); \ | 1000 | return task; |
995 | return task; \ | 1001 | } |
996 | } \ | ||
997 | \ | ||
998 | __kfifo_put(fifo, (void*)&task, sizeof(void*)); \ | ||
999 | } \ | ||
1000 | return NULL; \ | ||
1001 | } | ||
1002 | 1002 | ||
1003 | iscsi_remove_task(mgmt_task); | 1003 | __kfifo_put(fifo, (void*)&task, sizeof(void*)); |
1004 | iscsi_remove_task(cmd_task); | 1004 | } |
1005 | return NULL; | ||
1006 | } | ||
1005 | 1007 | ||
1006 | static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) | 1008 | static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) |
1007 | { | 1009 | { |
@@ -1043,7 +1045,6 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1043 | struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; | 1045 | struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; |
1044 | struct iscsi_conn *conn = ctask->conn; | 1046 | struct iscsi_conn *conn = ctask->conn; |
1045 | struct iscsi_session *session = conn->session; | 1047 | struct iscsi_session *session = conn->session; |
1046 | struct iscsi_cmd_task *pending_ctask; | ||
1047 | int rc; | 1048 | int rc; |
1048 | 1049 | ||
1049 | conn->eh_abort_cnt++; | 1050 | conn->eh_abort_cnt++; |
@@ -1071,17 +1072,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1071 | goto failed; | 1072 | goto failed; |
1072 | } | 1073 | } |
1073 | 1074 | ||
1074 | /* check for the easy pending cmd abort */ | 1075 | if (ctask->state == ISCSI_TASK_PENDING) |
1075 | pending_ctask = iscsi_remove_cmd_task(conn->xmitqueue, ctask->itt); | 1076 | goto success; |
1076 | if (pending_ctask) { | ||
1077 | /* iscsi_tcp queues write transfers on the xmitqueue */ | ||
1078 | if (list_empty(&pending_ctask->running)) { | ||
1079 | debug_scsi("found pending task\n"); | ||
1080 | goto success; | ||
1081 | } else | ||
1082 | __kfifo_put(conn->xmitqueue, (void*)&pending_ctask, | ||
1083 | sizeof(void*)); | ||
1084 | } | ||
1085 | 1077 | ||
1086 | conn->tmabort_state = TMABORT_INITIAL; | 1078 | conn->tmabort_state = TMABORT_INITIAL; |
1087 | 1079 | ||
@@ -1263,6 +1255,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, | |||
1263 | if (cmd_task_size) | 1255 | if (cmd_task_size) |
1264 | ctask->dd_data = &ctask[1]; | 1256 | ctask->dd_data = &ctask[1]; |
1265 | ctask->itt = cmd_i; | 1257 | ctask->itt = cmd_i; |
1258 | INIT_LIST_HEAD(&ctask->running); | ||
1266 | } | 1259 | } |
1267 | 1260 | ||
1268 | spin_lock_init(&session->lock); | 1261 | spin_lock_init(&session->lock); |
@@ -1282,6 +1275,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, | |||
1282 | if (mgmt_task_size) | 1275 | if (mgmt_task_size) |
1283 | mtask->dd_data = &mtask[1]; | 1276 | mtask->dd_data = &mtask[1]; |
1284 | mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i; | 1277 | mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i; |
1278 | INIT_LIST_HEAD(&mtask->running); | ||
1285 | } | 1279 | } |
1286 | 1280 | ||
1287 | if (scsi_add_host(shost, NULL)) | 1281 | if (scsi_add_host(shost, NULL)) |
@@ -1361,12 +1355,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | |||
1361 | conn->tmabort_state = TMABORT_INITIAL; | 1355 | conn->tmabort_state = TMABORT_INITIAL; |
1362 | INIT_LIST_HEAD(&conn->run_list); | 1356 | INIT_LIST_HEAD(&conn->run_list); |
1363 | INIT_LIST_HEAD(&conn->mgmt_run_list); | 1357 | INIT_LIST_HEAD(&conn->mgmt_run_list); |
1364 | 1358 | INIT_LIST_HEAD(&conn->xmitqueue); | |
1365 | /* initialize general xmit PDU commands queue */ | ||
1366 | conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*), | ||
1367 | GFP_KERNEL, NULL); | ||
1368 | if (conn->xmitqueue == ERR_PTR(-ENOMEM)) | ||
1369 | goto xmitqueue_alloc_fail; | ||
1370 | 1359 | ||
1371 | /* initialize general immediate & non-immediate PDU commands queue */ | 1360 | /* initialize general immediate & non-immediate PDU commands queue */ |
1372 | conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), | 1361 | conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), |
@@ -1410,8 +1399,6 @@ login_mtask_alloc_fail: | |||
1410 | mgmtqueue_alloc_fail: | 1399 | mgmtqueue_alloc_fail: |
1411 | kfifo_free(conn->immqueue); | 1400 | kfifo_free(conn->immqueue); |
1412 | immqueue_alloc_fail: | 1401 | immqueue_alloc_fail: |
1413 | kfifo_free(conn->xmitqueue); | ||
1414 | xmitqueue_alloc_fail: | ||
1415 | iscsi_destroy_conn(cls_conn); | 1402 | iscsi_destroy_conn(cls_conn); |
1416 | return NULL; | 1403 | return NULL; |
1417 | } | 1404 | } |
@@ -1489,7 +1476,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
1489 | session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; | 1476 | session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; |
1490 | spin_unlock_bh(&session->lock); | 1477 | spin_unlock_bh(&session->lock); |
1491 | 1478 | ||
1492 | kfifo_free(conn->xmitqueue); | ||
1493 | kfifo_free(conn->immqueue); | 1479 | kfifo_free(conn->immqueue); |
1494 | kfifo_free(conn->mgmtqueue); | 1480 | kfifo_free(conn->mgmtqueue); |
1495 | 1481 | ||
@@ -1572,7 +1558,7 @@ static void fail_all_commands(struct iscsi_conn *conn) | |||
1572 | struct iscsi_cmd_task *ctask, *tmp; | 1558 | struct iscsi_cmd_task *ctask, *tmp; |
1573 | 1559 | ||
1574 | /* flush pending */ | 1560 | /* flush pending */ |
1575 | while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) { | 1561 | list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) { |
1576 | debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc, | 1562 | debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc, |
1577 | ctask->itt); | 1563 | ctask->itt); |
1578 | fail_command(conn, ctask, DID_BUS_BUSY << 16); | 1564 | fail_command(conn, ctask, DID_BUS_BUSY << 16); |