diff options
author | Eddie Wai <eddie.wai@broadcom.com> | 2010-07-02 02:34:50 +0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-07-27 21:03:56 +0400 |
commit | 6447f286326690a936c35f9f913499307f869934 (patch) | |
tree | 5232176f4fef9d62fdab968e43fca18bacefc4de /drivers/scsi/bnx2i/bnx2i_iscsi.c | |
parent | 9ab98f57b3e1d73cd0720d29c21b687ba609cde9 (diff) | |
download | linux-6447f286326690a936c35f9f913499307f869934.tar.xz |
[SCSI] bnx2i: Separated the hardware's cleanup procedure from ep_disconnect
This patch introduces a new bnx2i_hw_ep_disconnect routine which
contains all chip related disconnect and clean up procedure of
iSCSI offload connections. This separation is intended as a
preparation for the subsequent bnx2i_stop patch.
Signed-off-by: Eddie Wai <eddie.wai@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Acked-by: Anil Veerabhadrappa <anilgv@broadcom.com>
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 | 119 |
1 files changed, 76 insertions, 43 deletions
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index fa68ab34b998..6edfde5f2e09 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1866,54 +1866,35 @@ static int bnx2i_ep_tcp_conn_active(struct bnx2i_endpoint *bnx2i_ep) } -/** - * bnx2i_ep_disconnect - executes TCP connection teardown process - * @ep: TCP connection (endpoint) handle +/* + * bnx2i_hw_ep_disconnect - executes TCP connection teardown process in the hw + * @ep: TCP connection (bnx2i endpoint) handle * * executes TCP connection teardown process */ -static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) +int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) { - struct bnx2i_endpoint *bnx2i_ep; - struct bnx2i_conn *bnx2i_conn = NULL; - struct iscsi_session *session = NULL; - struct iscsi_conn *conn; + struct bnx2i_hba *hba = bnx2i_ep->hba; struct cnic_dev *cnic; - struct bnx2i_hba *hba; + struct iscsi_session *session = NULL; + struct iscsi_conn *conn = NULL; + int ret = 0; - bnx2i_ep = ep->dd_data; + if (!hba) + return 0; - /* driver should not attempt connection cleanup until TCP_CONNECT - * completes either successfully or fails. Timeout is 9-secs, so - * wait for it to complete - */ - while ((bnx2i_ep->state == EP_STATE_CONNECT_START) && - !time_after(jiffies, bnx2i_ep->timestamp + (12 * HZ))) - msleep(250); + cnic = hba->cnic; + if (!cnic) + return 0; + + if (!bnx2i_ep_tcp_conn_active(bnx2i_ep)) + goto destroy_conn; if (bnx2i_ep->conn) { - bnx2i_conn = bnx2i_ep->conn; - conn = bnx2i_conn->cls_conn->dd_data; + conn = bnx2i_ep->conn->cls_conn->dd_data; session = conn->session; - - iscsi_suspend_queue(conn); } - hba = bnx2i_ep->hba; - if (bnx2i_ep->state == EP_STATE_IDLE) - goto return_bnx2i_ep; - cnic = hba->cnic; - - mutex_lock(&hba->net_dev_lock); - - if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state)) - goto free_resc; - if (bnx2i_ep->hba_age != hba->age) - goto free_resc; - - if (!bnx2i_ep_tcp_conn_active(bnx2i_ep)) - goto destory_conn; - bnx2i_ep->state = EP_STATE_DISCONN_START; init_timer(&bnx2i_ep->ofld_timer); @@ -1924,6 +1905,7 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { int close = 0; + int close_ret = 0; if (session) { spin_lock_bh(&session->lock); @@ -1932,11 +1914,13 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) spin_unlock_bh(&session->lock); } if (close) - cnic->cm_close(bnx2i_ep->cm_sk); + close_ret = cnic->cm_close(bnx2i_ep->cm_sk); else - cnic->cm_abort(bnx2i_ep->cm_sk); + close_ret = cnic->cm_abort(bnx2i_ep->cm_sk); + if (close_ret) + bnx2i_ep->state = EP_STATE_DISCONN_COMPL; } else - goto free_resc; + goto out; /* wait for option-2 conn teardown */ wait_event_interruptible(bnx2i_ep->ofld_wait, @@ -1946,20 +1930,69 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) flush_signals(current); del_timer_sync(&bnx2i_ep->ofld_timer); -destory_conn: - if (bnx2i_tear_down_conn(hba, bnx2i_ep)) { +destroy_conn: + if (bnx2i_tear_down_conn(hba, bnx2i_ep)) + ret = -EINVAL; +out: + bnx2i_ep->state = EP_STATE_IDLE; + return ret; +} + + +/** + * bnx2i_ep_disconnect - executes TCP connection teardown process + * @ep: TCP connection (iscsi endpoint) handle + * + * executes TCP connection teardown process + */ +static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) +{ + struct bnx2i_endpoint *bnx2i_ep; + struct bnx2i_conn *bnx2i_conn = NULL; + struct iscsi_conn *conn = NULL; + struct bnx2i_hba *hba; + + bnx2i_ep = ep->dd_data; + + /* driver should not attempt connection cleanup until TCP_CONNECT + * completes either successfully or fails. Timeout is 9-secs, so + * wait for it to complete + */ + while ((bnx2i_ep->state == EP_STATE_CONNECT_START) && + !time_after(jiffies, bnx2i_ep->timestamp + (12 * HZ))) + msleep(250); + + if (bnx2i_ep->conn) { + bnx2i_conn = bnx2i_ep->conn; + conn = bnx2i_conn->cls_conn->dd_data; + iscsi_suspend_queue(conn); + } + hba = bnx2i_ep->hba; + + mutex_lock(&hba->net_dev_lock); + + if (bnx2i_ep->state == EP_STATE_IDLE) + goto return_bnx2i_ep; + + if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state)) + goto free_resc; + + if (bnx2i_ep->hba_age != hba->age) + goto free_resc; + + /* Do all chip cleanup here */ + if (bnx2i_hw_ep_disconnect(bnx2i_ep)) { mutex_unlock(&hba->net_dev_lock); return; } free_resc: - mutex_unlock(&hba->net_dev_lock); bnx2i_free_qp_resc(hba, bnx2i_ep); return_bnx2i_ep: if (bnx2i_conn) bnx2i_conn->ep = NULL; bnx2i_free_ep(ep); - + mutex_unlock(&hba->net_dev_lock); if (!hba->ofld_conns_active) bnx2i_unreg_dev_all(); |