aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEddie Wai <eddie.wai@broadcom.com>2010-07-01 18:34:54 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-27 13:04:00 -0400
commit2eefb20dbf3032da1ad111c1ce178f899bc4859a (patch)
treec358114448f68bc7d3ffb9c79202fd42b2a68e35
parente37d2c4791480e27c2e2e4a556e4d2ba1d353ff8 (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>
-rw-r--r--drivers/scsi/bnx2i/bnx2i.h2
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c4
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c53
3 files changed, 40 insertions, 19 deletions
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index 69febb6f958..00c033511cb 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -639,6 +639,8 @@ enum {
639 EP_STATE_CLEANUP_CMPL = 0x800, 639 EP_STATE_CLEANUP_CMPL = 0x800,
640 EP_STATE_TCP_FIN_RCVD = 0x1000, 640 EP_STATE_TCP_FIN_RCVD = 0x1000,
641 EP_STATE_TCP_RST_RCVD = 0x2000, 641 EP_STATE_TCP_RST_RCVD = 0x2000,
642 EP_STATE_LOGOUT_SENT = 0x4000,
643 EP_STATE_LOGOUT_RESP_RCVD = 0x8000,
642 EP_STATE_PG_OFLD_FAILED = 0x1000000, 644 EP_STATE_PG_OFLD_FAILED = 0x1000000,
643 EP_STATE_ULP_UPDATE_FAILED = 0x2000000, 645 EP_STATE_ULP_UPDATE_FAILED = 0x2000000,
644 EP_STATE_CLEANUP_FAILED = 0x4000000, 646 EP_STATE_CLEANUP_FAILED = 0x4000000,
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 3a66ca24c7b..d23fc256d58 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -562,6 +562,8 @@ int bnx2i_send_iscsi_logout(struct bnx2i_conn *bnx2i_conn,
562 logout_wqe->num_bds = 1; 562 logout_wqe->num_bds = 1;
563 logout_wqe->cq_index = 0; /* CQ# used for completion, 5771x only */ 563 logout_wqe->cq_index = 0; /* CQ# used for completion, 5771x only */
564 564
565 bnx2i_conn->ep->state = EP_STATE_LOGOUT_SENT;
566
565 bnx2i_ring_dbell_update_sq_params(bnx2i_conn, 1); 567 bnx2i_ring_dbell_update_sq_params(bnx2i_conn, 1);
566 return 0; 568 return 0;
567} 569}
@@ -1482,6 +1484,8 @@ static int bnx2i_process_logout_resp(struct iscsi_session *session,
1482 resp_hdr->t2retain = cpu_to_be32(logout->time_to_retain); 1484 resp_hdr->t2retain = cpu_to_be32(logout->time_to_retain);
1483 1485
1484 __iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr, NULL, 0); 1486 __iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr, NULL, 0);
1487
1488 bnx2i_conn->ep->state = EP_STATE_LOGOUT_RESP_RCVD;
1485done: 1489done:
1486 spin_unlock(&session->lock); 1490 spin_unlock(&session->lock);
1487 return 0; 1491 return 0;
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index f6eebb39fe5..c66c5a45aa2 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);