diff options
author | Eddie Wai <eddie.wai@broadcom.com> | 2010-07-01 18:34:54 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-07-27 13:04:00 -0400 |
commit | 2eefb20dbf3032da1ad111c1ce178f899bc4859a (patch) | |
tree | c358114448f68bc7d3ffb9c79202fd42b2a68e35 /drivers/scsi/bnx2i/bnx2i_iscsi.c | |
parent | e37d2c4791480e27c2e2e4a556e4d2ba1d353ff8 (diff) |
[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>
Diffstat (limited to 'drivers/scsi/bnx2i/bnx2i_iscsi.c')
-rw-r--r-- | drivers/scsi/bnx2i/bnx2i_iscsi.c | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index f6eebb39fe54..c66c5a45aa27 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c | |||
@@ -1890,6 +1890,8 @@ static int bnx2i_ep_tcp_conn_active(struct bnx2i_endpoint *bnx2i_ep) | |||
1890 | case EP_STATE_ULP_UPDATE_START: | 1890 | case EP_STATE_ULP_UPDATE_START: |
1891 | case EP_STATE_ULP_UPDATE_COMPL: | 1891 | case EP_STATE_ULP_UPDATE_COMPL: |
1892 | case EP_STATE_TCP_FIN_RCVD: | 1892 | case EP_STATE_TCP_FIN_RCVD: |
1893 | case EP_STATE_LOGOUT_SENT: | ||
1894 | case EP_STATE_LOGOUT_RESP_RCVD: | ||
1893 | case EP_STATE_ULP_UPDATE_FAILED: | 1895 | case EP_STATE_ULP_UPDATE_FAILED: |
1894 | ret = 1; | 1896 | ret = 1; |
1895 | break; | 1897 | break; |
@@ -1923,6 +1925,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) | |||
1923 | struct iscsi_session *session = NULL; | 1925 | struct iscsi_session *session = NULL; |
1924 | struct iscsi_conn *conn = NULL; | 1926 | struct iscsi_conn *conn = NULL; |
1925 | int ret = 0; | 1927 | int ret = 0; |
1928 | int close = 0; | ||
1929 | int close_ret = 0; | ||
1926 | 1930 | ||
1927 | if (!hba) | 1931 | if (!hba) |
1928 | return 0; | 1932 | return 0; |
@@ -1939,33 +1943,44 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) | |||
1939 | session = conn->session; | 1943 | session = conn->session; |
1940 | } | 1944 | } |
1941 | 1945 | ||
1942 | bnx2i_ep->state = EP_STATE_DISCONN_START; | ||
1943 | |||
1944 | init_timer(&bnx2i_ep->ofld_timer); | 1946 | init_timer(&bnx2i_ep->ofld_timer); |
1945 | bnx2i_ep->ofld_timer.expires = hba->conn_teardown_tmo + jiffies; | 1947 | bnx2i_ep->ofld_timer.expires = hba->conn_teardown_tmo + jiffies; |
1946 | bnx2i_ep->ofld_timer.function = bnx2i_ep_ofld_timer; | 1948 | bnx2i_ep->ofld_timer.function = bnx2i_ep_ofld_timer; |
1947 | bnx2i_ep->ofld_timer.data = (unsigned long) bnx2i_ep; | 1949 | bnx2i_ep->ofld_timer.data = (unsigned long) bnx2i_ep; |
1948 | add_timer(&bnx2i_ep->ofld_timer); | 1950 | add_timer(&bnx2i_ep->ofld_timer); |
1949 | 1951 | ||
1950 | if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { | 1952 | if (!test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) |
1951 | int close = 0; | ||
1952 | int close_ret = 0; | ||
1953 | |||
1954 | if (session) { | ||
1955 | spin_lock_bh(&session->lock); | ||
1956 | if (session->state == ISCSI_STATE_LOGGING_OUT) | ||
1957 | close = 1; | ||
1958 | spin_unlock_bh(&session->lock); | ||
1959 | } | ||
1960 | if (close) | ||
1961 | close_ret = cnic->cm_close(bnx2i_ep->cm_sk); | ||
1962 | else | ||
1963 | close_ret = cnic->cm_abort(bnx2i_ep->cm_sk); | ||
1964 | if (close_ret) | ||
1965 | bnx2i_ep->state = EP_STATE_DISCONN_COMPL; | ||
1966 | } else | ||
1967 | goto out; | 1953 | goto out; |
1968 | 1954 | ||
1955 | if (session) { | ||
1956 | spin_lock_bh(&session->lock); | ||
1957 | if (bnx2i_ep->state != EP_STATE_TCP_FIN_RCVD) { | ||
1958 | if (session->state == ISCSI_STATE_LOGGING_OUT) { | ||
1959 | if (bnx2i_ep->state == EP_STATE_LOGOUT_SENT) { | ||
1960 | /* Logout sent, but no resp */ | ||
1961 | printk(KERN_ALERT "bnx2i - WARNING " | ||
1962 | "logout response was not " | ||
1963 | "received!\n"); | ||
1964 | } else if (bnx2i_ep->state == | ||
1965 | EP_STATE_LOGOUT_RESP_RCVD) | ||
1966 | close = 1; | ||
1967 | } | ||
1968 | } else | ||
1969 | close = 1; | ||
1970 | |||
1971 | spin_unlock_bh(&session->lock); | ||
1972 | } | ||
1973 | |||
1974 | bnx2i_ep->state = EP_STATE_DISCONN_START; | ||
1975 | |||
1976 | if (close) | ||
1977 | close_ret = cnic->cm_close(bnx2i_ep->cm_sk); | ||
1978 | else | ||
1979 | close_ret = cnic->cm_abort(bnx2i_ep->cm_sk); | ||
1980 | |||
1981 | if (close_ret) | ||
1982 | bnx2i_ep->state = EP_STATE_DISCONN_COMPL; | ||
1983 | |||
1969 | /* wait for option-2 conn teardown */ | 1984 | /* wait for option-2 conn teardown */ |
1970 | wait_event_interruptible(bnx2i_ep->ofld_wait, | 1985 | wait_event_interruptible(bnx2i_ep->ofld_wait, |
1971 | bnx2i_ep->state != EP_STATE_DISCONN_START); | 1986 | bnx2i_ep->state != EP_STATE_DISCONN_START); |