提交 a91031a6 编写于 作者: E Eddie Wai 提交者: James Bottomley

[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: NEddie Wai <eddie.wai@broadcom.com>
Acked-by: NAnil Veerabhadrappa <anilgv@broadcom.com>
Reviewed-by: NMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: NJames Bottomley <James.Bottomley@suse.de>
上级 bee34877
...@@ -411,7 +411,9 @@ static void bnx2i_free_ep(struct iscsi_endpoint *ep) ...@@ -411,7 +411,9 @@ static void bnx2i_free_ep(struct iscsi_endpoint *ep)
bnx2i_ep->state = EP_STATE_IDLE; bnx2i_ep->state = EP_STATE_IDLE;
bnx2i_ep->hba->ofld_conns_active--; bnx2i_ep->hba->ofld_conns_active--;
bnx2i_free_iscsi_cid(bnx2i_ep->hba, bnx2i_ep->ep_iscsi_cid); if (bnx2i_ep->ep_iscsi_cid != (u16) -1)
bnx2i_free_iscsi_cid(bnx2i_ep->hba, bnx2i_ep->ep_iscsi_cid);
if (bnx2i_ep->conn) { if (bnx2i_ep->conn) {
bnx2i_ep->conn->ep = NULL; bnx2i_ep->conn->ep = NULL;
bnx2i_ep->conn = NULL; bnx2i_ep->conn = NULL;
...@@ -1738,13 +1740,17 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, ...@@ -1738,13 +1740,17 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
*/ */
hba = bnx2i_check_route(dst_addr); hba = bnx2i_check_route(dst_addr);
if (!hba || test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state)) { if (!hba) {
rc = -EINVAL; rc = -EINVAL;
goto nohba; goto nohba;
} }
mutex_lock(&hba->net_dev_lock);
if (bnx2i_adapter_ready(hba) || !hba->cid_que.cid_free_cnt) {
rc = -EPERM;
goto check_busy;
}
cnic = hba->cnic; cnic = hba->cnic;
mutex_lock(&hba->net_dev_lock);
ep = bnx2i_alloc_ep(hba); ep = bnx2i_alloc_ep(hba);
if (!ep) { if (!ep) {
rc = -ENOMEM; rc = -ENOMEM;
...@@ -1752,23 +1758,21 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, ...@@ -1752,23 +1758,21 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
} }
bnx2i_ep = ep->dd_data; bnx2i_ep = ep->dd_data;
if (bnx2i_adapter_ready(hba)) {
rc = -EPERM;
goto net_if_down;
}
bnx2i_ep->num_active_cmds = 0; bnx2i_ep->num_active_cmds = 0;
iscsi_cid = bnx2i_alloc_iscsi_cid(hba); iscsi_cid = bnx2i_alloc_iscsi_cid(hba);
if (iscsi_cid == -1) { if (iscsi_cid == -1) {
printk(KERN_ALERT "alloc_ep: unable to allocate iscsi cid\n"); printk(KERN_ALERT "bnx2i (%s): alloc_ep - unable to allocate "
"iscsi cid\n", hba->netdev->name);
rc = -ENOMEM; rc = -ENOMEM;
goto iscsi_cid_err; bnx2i_free_ep(ep);
goto check_busy;
} }
bnx2i_ep->hba_age = hba->age; bnx2i_ep->hba_age = hba->age;
rc = bnx2i_alloc_qp_resc(hba, bnx2i_ep); rc = bnx2i_alloc_qp_resc(hba, bnx2i_ep);
if (rc != 0) { if (rc != 0) {
printk(KERN_ALERT "bnx2i: ep_conn, alloc QP resc error\n"); printk(KERN_ALERT "bnx2i (%s): ep_conn - alloc QP resc error"
"\n", hba->netdev->name);
rc = -ENOMEM; rc = -ENOMEM;
goto qp_resc_err; goto qp_resc_err;
} }
...@@ -1807,7 +1811,12 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, ...@@ -1807,7 +1811,12 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
bnx2i_ep_ofld_list_del(hba, bnx2i_ep); bnx2i_ep_ofld_list_del(hba, bnx2i_ep);
if (bnx2i_ep->state != EP_STATE_OFLD_COMPL) { if (bnx2i_ep->state != EP_STATE_OFLD_COMPL) {
rc = -ENOSPC; if (bnx2i_ep->state == EP_STATE_OFLD_FAILED_CID_BUSY) {
printk(KERN_ALERT "bnx2i (%s): iscsi cid %d is busy\n",
hba->netdev->name, bnx2i_ep->ep_iscsi_cid);
rc = -EBUSY;
} else
rc = -ENOSPC;
goto conn_failed; goto conn_failed;
} }
...@@ -1815,7 +1824,8 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, ...@@ -1815,7 +1824,8 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
iscsi_cid, &bnx2i_ep->cm_sk, bnx2i_ep); iscsi_cid, &bnx2i_ep->cm_sk, bnx2i_ep);
if (rc) { if (rc) {
rc = -EINVAL; rc = -EINVAL;
goto conn_failed; /* Need to terminate and cleanup the connection */
goto release_ep;
} }
bnx2i_ep->cm_sk->rcv_buf = 256 * 1024; bnx2i_ep->cm_sk->rcv_buf = 256 * 1024;
...@@ -1859,8 +1869,6 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, ...@@ -1859,8 +1869,6 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
return ERR_PTR(rc); return ERR_PTR(rc);
} }
conn_failed: conn_failed:
net_if_down:
iscsi_cid_err:
bnx2i_free_qp_resc(hba, bnx2i_ep); bnx2i_free_qp_resc(hba, bnx2i_ep);
qp_resc_err: qp_resc_err:
bnx2i_free_ep(ep); bnx2i_free_ep(ep);
...@@ -1979,7 +1987,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) ...@@ -1979,7 +1987,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
if (!cnic) if (!cnic)
return 0; return 0;
if (bnx2i_ep->state == EP_STATE_IDLE) if (bnx2i_ep->state == EP_STATE_IDLE ||
bnx2i_ep->state == EP_STATE_DISCONN_TIMEDOUT)
return 0; return 0;
if (!bnx2i_ep_tcp_conn_active(bnx2i_ep)) if (!bnx2i_ep_tcp_conn_active(bnx2i_ep))
...@@ -2005,9 +2014,10 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) ...@@ -2005,9 +2014,10 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
if (session->state == ISCSI_STATE_LOGGING_OUT) { if (session->state == ISCSI_STATE_LOGGING_OUT) {
if (bnx2i_ep->state == EP_STATE_LOGOUT_SENT) { if (bnx2i_ep->state == EP_STATE_LOGOUT_SENT) {
/* Logout sent, but no resp */ /* Logout sent, but no resp */
printk(KERN_ALERT "bnx2i - WARNING " printk(KERN_ALERT "bnx2i (%s): WARNING"
"logout response was not " " logout response was not "
"received!\n"); "received!\n",
bnx2i_ep->hba->netdev->name);
} else if (bnx2i_ep->state == } else if (bnx2i_ep->state ==
EP_STATE_LOGOUT_RESP_RCVD) EP_STATE_LOGOUT_RESP_RCVD)
close = 1; close = 1;
...@@ -2025,9 +2035,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) ...@@ -2025,9 +2035,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
else else
close_ret = cnic->cm_abort(bnx2i_ep->cm_sk); close_ret = cnic->cm_abort(bnx2i_ep->cm_sk);
/* No longer allow CFC delete if cm_close/abort fails the request */
if (close_ret) if (close_ret)
printk(KERN_ALERT "bnx2i: %s close/abort(%d) returned %d\n", printk(KERN_ALERT "bnx2i (%s): close/abort(%d) returned %d\n",
bnx2i_ep->hba->netdev->name, close, close_ret); bnx2i_ep->hba->netdev->name, close, close_ret);
else else
/* wait for option-2 conn teardown */ /* wait for option-2 conn teardown */
...@@ -2041,7 +2050,7 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) ...@@ -2041,7 +2050,7 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
destroy_conn: destroy_conn:
bnx2i_ep_active_list_del(hba, bnx2i_ep); bnx2i_ep_active_list_del(hba, bnx2i_ep);
if (bnx2i_tear_down_conn(hba, bnx2i_ep)) if (bnx2i_tear_down_conn(hba, bnx2i_ep))
ret = -EINVAL; return -EINVAL;
out: out:
bnx2i_ep->state = EP_STATE_IDLE; bnx2i_ep->state = EP_STATE_IDLE;
return ret; return ret;
...@@ -2080,14 +2089,17 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) ...@@ -2080,14 +2089,17 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep)
mutex_lock(&hba->net_dev_lock); mutex_lock(&hba->net_dev_lock);
if (bnx2i_ep->state == EP_STATE_IDLE) if (bnx2i_ep->state == EP_STATE_DISCONN_TIMEDOUT)
goto return_bnx2i_ep; goto out;
if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state)) if (bnx2i_ep->state == EP_STATE_IDLE)
goto free_resc; goto free_resc;
if (bnx2i_ep->hba_age != hba->age) if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) ||
(bnx2i_ep->hba_age != hba->age)) {
bnx2i_ep_active_list_del(hba, bnx2i_ep);
goto free_resc; goto free_resc;
}
/* Do all chip cleanup here */ /* Do all chip cleanup here */
if (bnx2i_hw_ep_disconnect(bnx2i_ep)) { if (bnx2i_hw_ep_disconnect(bnx2i_ep)) {
...@@ -2096,11 +2108,12 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) ...@@ -2096,11 +2108,12 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep)
} }
free_resc: free_resc:
bnx2i_free_qp_resc(hba, bnx2i_ep); bnx2i_free_qp_resc(hba, bnx2i_ep);
return_bnx2i_ep:
if (bnx2i_conn) if (bnx2i_conn)
bnx2i_conn->ep = NULL; bnx2i_conn->ep = NULL;
bnx2i_free_ep(ep); bnx2i_free_ep(ep);
out:
mutex_unlock(&hba->net_dev_lock); mutex_unlock(&hba->net_dev_lock);
wake_up_interruptible(&hba->eh_wait); wake_up_interruptible(&hba->eh_wait);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册