1
0

[SCSI] bnx2i: Fixed the TCP graceful termination initiation

In compliance to RFC793, a TCP graceful termination will be used
instead of an abortive termination for the case where the remote
has initiated the close of the connection.
Additionally, a TCP abortive termination will be used to close the
connection when a logout response is not received in time after a
logout request has been initiated.

Signed-off-by: Eddie Wai <eddie.wai@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
Acked-by: Anil Veerabhadrappa <anilgv@broadcom.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
Eddie Wai
2010-07-01 15:34:54 -07:00
committed by James Bottomley
parent e37d2c4791
commit 2eefb20dbf
3 changed files with 40 additions and 19 deletions

View File

@@ -1890,6 +1890,8 @@ static int bnx2i_ep_tcp_conn_active(struct bnx2i_endpoint *bnx2i_ep)
case EP_STATE_ULP_UPDATE_START:
case EP_STATE_ULP_UPDATE_COMPL:
case EP_STATE_TCP_FIN_RCVD:
case EP_STATE_LOGOUT_SENT:
case EP_STATE_LOGOUT_RESP_RCVD:
case EP_STATE_ULP_UPDATE_FAILED:
ret = 1;
break;
@@ -1923,6 +1925,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
struct iscsi_session *session = NULL;
struct iscsi_conn *conn = NULL;
int ret = 0;
int close = 0;
int close_ret = 0;
if (!hba)
return 0;
@@ -1939,33 +1943,44 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
session = conn->session;
}
bnx2i_ep->state = EP_STATE_DISCONN_START;
init_timer(&bnx2i_ep->ofld_timer);
bnx2i_ep->ofld_timer.expires = hba->conn_teardown_tmo + jiffies;
bnx2i_ep->ofld_timer.function = bnx2i_ep_ofld_timer;
bnx2i_ep->ofld_timer.data = (unsigned long) bnx2i_ep;
add_timer(&bnx2i_ep->ofld_timer);
if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
int close = 0;
int close_ret = 0;
if (session) {
spin_lock_bh(&session->lock);
if (session->state == ISCSI_STATE_LOGGING_OUT)
close = 1;
spin_unlock_bh(&session->lock);
}
if (close)
close_ret = cnic->cm_close(bnx2i_ep->cm_sk);
else
close_ret = cnic->cm_abort(bnx2i_ep->cm_sk);
if (close_ret)
bnx2i_ep->state = EP_STATE_DISCONN_COMPL;
} else
if (!test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic))
goto out;
if (session) {
spin_lock_bh(&session->lock);
if (bnx2i_ep->state != EP_STATE_TCP_FIN_RCVD) {
if (session->state == ISCSI_STATE_LOGGING_OUT) {
if (bnx2i_ep->state == EP_STATE_LOGOUT_SENT) {
/* Logout sent, but no resp */
printk(KERN_ALERT "bnx2i - WARNING "
"logout response was not "
"received!\n");
} else if (bnx2i_ep->state ==
EP_STATE_LOGOUT_RESP_RCVD)
close = 1;
}
} else
close = 1;
spin_unlock_bh(&session->lock);
}
bnx2i_ep->state = EP_STATE_DISCONN_START;
if (close)
close_ret = cnic->cm_close(bnx2i_ep->cm_sk);
else
close_ret = cnic->cm_abort(bnx2i_ep->cm_sk);
if (close_ret)
bnx2i_ep->state = EP_STATE_DISCONN_COMPL;
/* wait for option-2 conn teardown */
wait_event_interruptible(bnx2i_ep->ofld_wait,
bnx2i_ep->state != EP_STATE_DISCONN_START);