--- zzzz-none-000/linux-2.6.19.2/drivers/scsi/libiscsi.c 2007-01-10 19:10:37.000000000 +0000 +++ davinci-8020-5505/linux-2.6.19.2/drivers/scsi/libiscsi.c 2007-01-11 07:38:19.000000000 +0000 @@ -481,8 +481,8 @@ break; case ISCSI_OP_ASYNC_EVENT: conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; - if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) - rc = ISCSI_ERR_CONN_FAILED; + /* we need sth like iscsi_async_event_rsp() */ + rc = ISCSI_ERR_BAD_OPCODE; break; default: rc = ISCSI_ERR_BAD_OPCODE; @@ -578,27 +578,6 @@ } EXPORT_SYMBOL_GPL(iscsi_conn_failure); -static int iscsi_xmit_imm_task(struct iscsi_conn *conn) -{ - struct iscsi_hdr *hdr = conn->mtask->hdr; - int rc, was_logout = 0; - - if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) { - conn->session->state = ISCSI_STATE_IN_RECOVERY; - iscsi_block_session(session_to_cls(conn->session)); - was_logout = 1; - } - rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask); - if (rc) - return rc; - - if (was_logout) { - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); - return -ENODATA; - } - return 0; -} - /** * iscsi_data_xmit - xmit any command into the scheduled connection * @conn: iscsi connection @@ -644,7 +623,7 @@ conn->ctask = NULL; } if (conn->mtask) { - rc = iscsi_xmit_imm_task(conn); + rc = tt->xmit_mgmt_task(conn, conn->mtask); if (rc) goto again; /* done with this in-progress mtask */ @@ -659,7 +638,7 @@ list_add_tail(&conn->mtask->running, &conn->mgmt_run_list); spin_unlock_bh(&conn->session->lock); - rc = iscsi_xmit_imm_task(conn); + rc = tt->xmit_mgmt_task(conn, conn->mtask); if (rc) goto again; } @@ -682,6 +661,8 @@ spin_unlock_bh(&conn->session->lock); rc = tt->xmit_cmd_task(conn, conn->ctask); + if (rc) + goto again; spin_lock_bh(&conn->session->lock); __iscsi_put_ctask(conn->ctask); @@ -797,10 +778,6 @@ } conn = session->leadconn; - if (!conn) { - reason = FAILURE_SESSION_FREED; - goto fault; - } if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask, sizeof(void*))) { @@ -975,13 +952,13 @@ if (session->state == ISCSI_STATE_TERMINATE) { failed: debug_scsi("failing host reset: session terminated " - "[CID %d age %d]\n", conn->id, session->age); + "[CID %d age %d]", conn->id, session->age); spin_unlock_bh(&session->lock); return FAILED; } if (sc->SCp.phase == session->age) { - debug_scsi("failing connection CID %d due to SCSI host reset\n", + debug_scsi("failing connection CID %d due to SCSI host reset", conn->id); fail_session = 1; } @@ -1054,8 +1031,7 @@ NULL, 0); if (rc) { iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - debug_scsi("abort sent failure [itt 0x%x] %d\n", ctask->itt, - rc); + debug_scsi("abort sent failure [itt 0x%x] %d", ctask->itt, rc); return rc; } @@ -1072,7 +1048,7 @@ conn->tmabort_timer.function = iscsi_tmabort_timedout; conn->tmabort_timer.data = (unsigned long)ctask; add_timer(&conn->tmabort_timer); - debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt); + debug_scsi("abort set timeout [itt 0x%x]", ctask->itt); } spin_unlock_bh(&session->lock); mutex_unlock(&conn->xmitmutex); @@ -1401,6 +1377,7 @@ } spin_lock_init(&session->lock); + INIT_LIST_HEAD(&session->connections); /* initialize immediate command pool */ if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max, @@ -1603,11 +1580,16 @@ kfree(conn->persistent_address); __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, sizeof(void*)); - if (session->leadconn == conn) { + list_del(&conn->item); + if (list_empty(&session->connections)) session->leadconn = NULL; + if (session->leadconn && session->leadconn == conn) + session->leadconn = container_of(session->connections.next, + struct iscsi_conn, item); + + if (session->leadconn == NULL) /* no connections exits.. reset sequencing */ session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; - } spin_unlock_bh(&session->lock); kfifo_free(conn->immqueue); @@ -1795,12 +1777,32 @@ struct iscsi_cls_conn *cls_conn, int is_leading) { struct iscsi_session *session = class_to_transport_session(cls_session); - struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data; + /* lookup for existing connection */ spin_lock_bh(&session->lock); + list_for_each_entry(tmp, &session->connections, item) { + if (tmp == conn) { + if (conn->c_stage != ISCSI_CONN_STOPPED || + conn->stop_stage == STOP_CONN_TERM) { + printk(KERN_ERR "iscsi: can't bind " + "non-stopped connection (%d:%d)\n", + conn->c_stage, conn->stop_stage); + spin_unlock_bh(&session->lock); + return -EIO; + } + break; + } + } + if (tmp != conn) { + /* bind new iSCSI connection to session */ + conn->session = session; + list_add(&conn->item, &session->connections); + } + spin_unlock_bh(&session->lock); + if (is_leading) session->leadconn = conn; - spin_unlock_bh(&session->lock); /* * Unblock xmitworker(), Login Phase will pass through.