diff options
author | Eddie Wai <eddie.wai@broadcom.com> | 2010-11-23 18:29:30 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-12-21 13:24:15 -0500 |
commit | a91031a6526441ff36552d53363037c3bbca0c5b (patch) | |
tree | aa1e70b241807bf19a78dffda99420bfe3ed60ed /drivers/scsi/bnx2i | |
parent | bee348770dcaeafa57bbd32129ce0cb16a4342d6 (diff) |
[SCSI] bnx2i: Cleaned up various error conditions in ep_connect/disconnect
Various error conditions inside ep_connect and ep_disconnect were
either not being handled or not being handled correctly. This patch
fixes all those issues.
Signed-off-by: Eddie Wai <eddie.wai@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')
-rw-r--r-- | drivers/scsi/bnx2i/bnx2i_iscsi.c | 67 |
1 files changed, 40 insertions, 27 deletions
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index f622e89041cd..24997c679f3c 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c | |||
@@ -411,7 +411,9 @@ static void bnx2i_free_ep(struct iscsi_endpoint *ep) | |||
411 | bnx2i_ep->state = EP_STATE_IDLE; | 411 | bnx2i_ep->state = EP_STATE_IDLE; |
412 | bnx2i_ep->hba->ofld_conns_active--; | 412 | bnx2i_ep->hba->ofld_conns_active--; |
413 | 413 | ||
414 | bnx2i_free_iscsi_cid(bnx2i_ep->hba, bnx2i_ep->ep_iscsi_cid); | 414 | if (bnx2i_ep->ep_iscsi_cid != (u16) -1) |
415 | bnx2i_free_iscsi_cid(bnx2i_ep->hba, bnx2i_ep->ep_iscsi_cid); | ||
416 | |||
415 | if (bnx2i_ep->conn) { | 417 | if (bnx2i_ep->conn) { |
416 | bnx2i_ep->conn->ep = NULL; | 418 | bnx2i_ep->conn->ep = NULL; |
417 | bnx2i_ep->conn = NULL; | 419 | bnx2i_ep->conn = NULL; |
@@ -1738,13 +1740,17 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, | |||
1738 | */ | 1740 | */ |
1739 | hba = bnx2i_check_route(dst_addr); | 1741 | hba = bnx2i_check_route(dst_addr); |
1740 | 1742 | ||
1741 | if (!hba || test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state)) { | 1743 | if (!hba) { |
1742 | rc = -EINVAL; | 1744 | rc = -EINVAL; |
1743 | goto nohba; | 1745 | goto nohba; |
1744 | } | 1746 | } |
1747 | mutex_lock(&hba->net_dev_lock); | ||
1745 | 1748 | ||
1749 | if (bnx2i_adapter_ready(hba) || !hba->cid_que.cid_free_cnt) { | ||
1750 | rc = -EPERM; | ||
1751 | goto check_busy; | ||
1752 | } | ||
1746 | cnic = hba->cnic; | 1753 | cnic = hba->cnic; |
1747 | mutex_lock(&hba->net_dev_lock); | ||
1748 | ep = bnx2i_alloc_ep(hba); | 1754 | ep = bnx2i_alloc_ep(hba); |
1749 | if (!ep) { | 1755 | if (!ep) { |
1750 | rc = -ENOMEM; | 1756 | rc = -ENOMEM; |
@@ -1752,23 +1758,21 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, | |||
1752 | } | 1758 | } |
1753 | bnx2i_ep = ep->dd_data; | 1759 | bnx2i_ep = ep->dd_data; |
1754 | 1760 | ||
1755 | if (bnx2i_adapter_ready(hba)) { | ||
1756 | rc = -EPERM; | ||
1757 | goto net_if_down; | ||
1758 | } | ||
1759 | |||
1760 | bnx2i_ep->num_active_cmds = 0; | 1761 | bnx2i_ep->num_active_cmds = 0; |
1761 | iscsi_cid = bnx2i_alloc_iscsi_cid(hba); | 1762 | iscsi_cid = bnx2i_alloc_iscsi_cid(hba); |
1762 | if (iscsi_cid == -1) { | 1763 | if (iscsi_cid == -1) { |
1763 | printk(KERN_ALERT "alloc_ep: unable to allocate iscsi cid\n"); | 1764 | printk(KERN_ALERT "bnx2i (%s): alloc_ep - unable to allocate " |
1765 | "iscsi cid\n", hba->netdev->name); | ||
1764 | rc = -ENOMEM; | 1766 | rc = -ENOMEM; |
1765 | goto iscsi_cid_err; | 1767 | bnx2i_free_ep(ep); |
1768 | goto check_busy; | ||
1766 | } | 1769 | } |
1767 | bnx2i_ep->hba_age = hba->age; | 1770 | bnx2i_ep->hba_age = hba->age; |
1768 | 1771 | ||
1769 | rc = bnx2i_alloc_qp_resc(hba, bnx2i_ep); | 1772 | rc = bnx2i_alloc_qp_resc(hba, bnx2i_ep); |
1770 | if (rc != 0) { | 1773 | if (rc != 0) { |
1771 | printk(KERN_ALERT "bnx2i: ep_conn, alloc QP resc error\n"); | 1774 | printk(KERN_ALERT "bnx2i (%s): ep_conn - alloc QP resc error" |
1775 | "\n", hba->netdev->name); | ||
1772 | rc = -ENOMEM; | 1776 | rc = -ENOMEM; |
1773 | goto qp_resc_err; | 1777 | goto qp_resc_err; |
1774 | } | 1778 | } |
@@ -1807,7 +1811,12 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, | |||
1807 | bnx2i_ep_ofld_list_del(hba, bnx2i_ep); | 1811 | bnx2i_ep_ofld_list_del(hba, bnx2i_ep); |
1808 | 1812 | ||
1809 | if (bnx2i_ep->state != EP_STATE_OFLD_COMPL) { | 1813 | if (bnx2i_ep->state != EP_STATE_OFLD_COMPL) { |
1810 | rc = -ENOSPC; | 1814 | if (bnx2i_ep->state == EP_STATE_OFLD_FAILED_CID_BUSY) { |
1815 | printk(KERN_ALERT "bnx2i (%s): iscsi cid %d is busy\n", | ||
1816 | hba->netdev->name, bnx2i_ep->ep_iscsi_cid); | ||
1817 | rc = -EBUSY; | ||
1818 | } else | ||
1819 | rc = -ENOSPC; | ||
1811 | goto conn_failed; | 1820 | goto conn_failed; |
1812 | } | 1821 | } |
1813 | 1822 | ||
@@ -1815,7 +1824,8 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, | |||
1815 | iscsi_cid, &bnx2i_ep->cm_sk, bnx2i_ep); | 1824 | iscsi_cid, &bnx2i_ep->cm_sk, bnx2i_ep); |
1816 | if (rc) { | 1825 | if (rc) { |
1817 | rc = -EINVAL; | 1826 | rc = -EINVAL; |
1818 | goto conn_failed; | 1827 | /* Need to terminate and cleanup the connection */ |
1828 | goto release_ep; | ||
1819 | } | 1829 | } |
1820 | 1830 | ||
1821 | bnx2i_ep->cm_sk->rcv_buf = 256 * 1024; | 1831 | bnx2i_ep->cm_sk->rcv_buf = 256 * 1024; |
@@ -1859,8 +1869,6 @@ release_ep: | |||
1859 | return ERR_PTR(rc); | 1869 | return ERR_PTR(rc); |
1860 | } | 1870 | } |
1861 | conn_failed: | 1871 | conn_failed: |
1862 | net_if_down: | ||
1863 | iscsi_cid_err: | ||
1864 | bnx2i_free_qp_resc(hba, bnx2i_ep); | 1872 | bnx2i_free_qp_resc(hba, bnx2i_ep); |
1865 | qp_resc_err: | 1873 | qp_resc_err: |
1866 | bnx2i_free_ep(ep); | 1874 | bnx2i_free_ep(ep); |
@@ -1979,7 +1987,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) | |||
1979 | if (!cnic) | 1987 | if (!cnic) |
1980 | return 0; | 1988 | return 0; |
1981 | 1989 | ||
1982 | if (bnx2i_ep->state == EP_STATE_IDLE) | 1990 | if (bnx2i_ep->state == EP_STATE_IDLE || |
1991 | bnx2i_ep->state == EP_STATE_DISCONN_TIMEDOUT) | ||
1983 | return 0; | 1992 | return 0; |
1984 | 1993 | ||
1985 | if (!bnx2i_ep_tcp_conn_active(bnx2i_ep)) | 1994 | if (!bnx2i_ep_tcp_conn_active(bnx2i_ep)) |
@@ -2005,9 +2014,10 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) | |||
2005 | if (session->state == ISCSI_STATE_LOGGING_OUT) { | 2014 | if (session->state == ISCSI_STATE_LOGGING_OUT) { |
2006 | if (bnx2i_ep->state == EP_STATE_LOGOUT_SENT) { | 2015 | if (bnx2i_ep->state == EP_STATE_LOGOUT_SENT) { |
2007 | /* Logout sent, but no resp */ | 2016 | /* Logout sent, but no resp */ |
2008 | printk(KERN_ALERT "bnx2i - WARNING " | 2017 | printk(KERN_ALERT "bnx2i (%s): WARNING" |
2009 | "logout response was not " | 2018 | " logout response was not " |
2010 | "received!\n"); | 2019 | "received!\n", |
2020 | bnx2i_ep->hba->netdev->name); | ||
2011 | } else if (bnx2i_ep->state == | 2021 | } else if (bnx2i_ep->state == |
2012 | EP_STATE_LOGOUT_RESP_RCVD) | 2022 | EP_STATE_LOGOUT_RESP_RCVD) |
2013 | close = 1; | 2023 | close = 1; |
@@ -2025,9 +2035,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) | |||
2025 | else | 2035 | else |
2026 | close_ret = cnic->cm_abort(bnx2i_ep->cm_sk); | 2036 | close_ret = cnic->cm_abort(bnx2i_ep->cm_sk); |
2027 | 2037 | ||
2028 | /* No longer allow CFC delete if cm_close/abort fails the request */ | ||
2029 | if (close_ret) | 2038 | if (close_ret) |
2030 | printk(KERN_ALERT "bnx2i: %s close/abort(%d) returned %d\n", | 2039 | printk(KERN_ALERT "bnx2i (%s): close/abort(%d) returned %d\n", |
2031 | bnx2i_ep->hba->netdev->name, close, close_ret); | 2040 | bnx2i_ep->hba->netdev->name, close, close_ret); |
2032 | else | 2041 | else |
2033 | /* wait for option-2 conn teardown */ | 2042 | /* wait for option-2 conn teardown */ |
@@ -2041,7 +2050,7 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) | |||
2041 | destroy_conn: | 2050 | destroy_conn: |
2042 | bnx2i_ep_active_list_del(hba, bnx2i_ep); | 2051 | bnx2i_ep_active_list_del(hba, bnx2i_ep); |
2043 | if (bnx2i_tear_down_conn(hba, bnx2i_ep)) | 2052 | if (bnx2i_tear_down_conn(hba, bnx2i_ep)) |
2044 | ret = -EINVAL; | 2053 | return -EINVAL; |
2045 | out: | 2054 | out: |
2046 | bnx2i_ep->state = EP_STATE_IDLE; | 2055 | bnx2i_ep->state = EP_STATE_IDLE; |
2047 | return ret; | 2056 | return ret; |
@@ -2080,14 +2089,17 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) | |||
2080 | 2089 | ||
2081 | mutex_lock(&hba->net_dev_lock); | 2090 | mutex_lock(&hba->net_dev_lock); |
2082 | 2091 | ||
2083 | if (bnx2i_ep->state == EP_STATE_IDLE) | 2092 | if (bnx2i_ep->state == EP_STATE_DISCONN_TIMEDOUT) |
2084 | goto return_bnx2i_ep; | 2093 | goto out; |
2085 | 2094 | ||
2086 | if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state)) | 2095 | if (bnx2i_ep->state == EP_STATE_IDLE) |
2087 | goto free_resc; | 2096 | goto free_resc; |
2088 | 2097 | ||
2089 | if (bnx2i_ep->hba_age != hba->age) | 2098 | if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) || |
2099 | (bnx2i_ep->hba_age != hba->age)) { | ||
2100 | bnx2i_ep_active_list_del(hba, bnx2i_ep); | ||
2090 | goto free_resc; | 2101 | goto free_resc; |
2102 | } | ||
2091 | 2103 | ||
2092 | /* Do all chip cleanup here */ | 2104 | /* Do all chip cleanup here */ |
2093 | if (bnx2i_hw_ep_disconnect(bnx2i_ep)) { | 2105 | if (bnx2i_hw_ep_disconnect(bnx2i_ep)) { |
@@ -2096,11 +2108,12 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) | |||
2096 | } | 2108 | } |
2097 | free_resc: | 2109 | free_resc: |
2098 | bnx2i_free_qp_resc(hba, bnx2i_ep); | 2110 | bnx2i_free_qp_resc(hba, bnx2i_ep); |
2099 | return_bnx2i_ep: | 2111 | |
2100 | if (bnx2i_conn) | 2112 | if (bnx2i_conn) |
2101 | bnx2i_conn->ep = NULL; | 2113 | bnx2i_conn->ep = NULL; |
2102 | 2114 | ||
2103 | bnx2i_free_ep(ep); | 2115 | bnx2i_free_ep(ep); |
2116 | out: | ||
2104 | mutex_unlock(&hba->net_dev_lock); | 2117 | mutex_unlock(&hba->net_dev_lock); |
2105 | 2118 | ||
2106 | wake_up_interruptible(&hba->eh_wait); | 2119 | wake_up_interruptible(&hba->eh_wait); |