Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a91031a6 authored by Eddie Wai's avatar Eddie Wai Committed by James Bottomley
Browse files

[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: default avatarEddie Wai <eddie.wai@broadcom.com>
Acked-by: default avatarAnil Veerabhadrappa <anilgv@broadcom.com>
Reviewed-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent bee34877
Loading
Loading
Loading
Loading
+40 −27
Original line number Diff line number Diff line
@@ -411,7 +411,9 @@ static void bnx2i_free_ep(struct iscsi_endpoint *ep)
	bnx2i_ep->state = EP_STATE_IDLE;
	bnx2i_ep->hba->ofld_conns_active--;

	if (bnx2i_ep->ep_iscsi_cid != (u16) -1)
		bnx2i_free_iscsi_cid(bnx2i_ep->hba, bnx2i_ep->ep_iscsi_cid);

	if (bnx2i_ep->conn) {
		bnx2i_ep->conn->ep = NULL;
		bnx2i_ep->conn = NULL;
@@ -1738,13 +1740,17 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
		 */
		hba = bnx2i_check_route(dst_addr);

	if (!hba || test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state)) {
	if (!hba) {
		rc = -EINVAL;
		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;
	mutex_lock(&hba->net_dev_lock);
	ep = bnx2i_alloc_ep(hba);
	if (!ep) {
		rc = -ENOMEM;
@@ -1752,23 +1758,21 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
	}
	bnx2i_ep = ep->dd_data;

	if (bnx2i_adapter_ready(hba)) {
		rc = -EPERM;
		goto net_if_down;
	}

	bnx2i_ep->num_active_cmds = 0;
	iscsi_cid = bnx2i_alloc_iscsi_cid(hba);
	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;
		goto iscsi_cid_err;
		bnx2i_free_ep(ep);
		goto check_busy;
	}
	bnx2i_ep->hba_age = hba->age;

	rc = bnx2i_alloc_qp_resc(hba, bnx2i_ep);
	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;
		goto qp_resc_err;
	}
@@ -1807,6 +1811,11 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
	bnx2i_ep_ofld_list_del(hba, bnx2i_ep);

	if (bnx2i_ep->state != EP_STATE_OFLD_COMPL) {
		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;
	}
@@ -1815,7 +1824,8 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
			     iscsi_cid, &bnx2i_ep->cm_sk, bnx2i_ep);
	if (rc) {
		rc = -EINVAL;
		goto conn_failed;
		/* Need to terminate and cleanup the connection */
		goto release_ep;
	}

	bnx2i_ep->cm_sk->rcv_buf = 256 * 1024;
@@ -1859,8 +1869,6 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
		return ERR_PTR(rc);
	}
conn_failed:
net_if_down:
iscsi_cid_err:
	bnx2i_free_qp_resc(hba, bnx2i_ep);
qp_resc_err:
	bnx2i_free_ep(ep);
@@ -1979,7 +1987,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
	if (!cnic)
		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;

	if (!bnx2i_ep_tcp_conn_active(bnx2i_ep))
@@ -2005,9 +2014,10 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
			if (session->state == ISCSI_STATE_LOGGING_OUT) {
				if (bnx2i_ep->state == EP_STATE_LOGOUT_SENT) {
					/* Logout sent, but no resp */
					printk(KERN_ALERT "bnx2i - WARNING "
					printk(KERN_ALERT "bnx2i (%s): WARNING"
						" logout response was not "
						"received!\n");
						"received!\n",
						bnx2i_ep->hba->netdev->name);
				} else if (bnx2i_ep->state ==
					   EP_STATE_LOGOUT_RESP_RCVD)
					close = 1;
@@ -2025,9 +2035,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
	else
		close_ret = cnic->cm_abort(bnx2i_ep->cm_sk);

	/* No longer allow CFC delete if cm_close/abort fails the request */
	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);
	else
		/* wait for option-2 conn teardown */
@@ -2041,7 +2050,7 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep)
destroy_conn:
	bnx2i_ep_active_list_del(hba, bnx2i_ep);
	if (bnx2i_tear_down_conn(hba, bnx2i_ep))
		ret = -EINVAL;
		return -EINVAL;
out:
	bnx2i_ep->state = EP_STATE_IDLE;
	return ret;
@@ -2080,14 +2089,17 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep)

	mutex_lock(&hba->net_dev_lock);

	if (bnx2i_ep->state == EP_STATE_IDLE)
		goto return_bnx2i_ep;
	if (bnx2i_ep->state == EP_STATE_DISCONN_TIMEDOUT)
		goto out;

	if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state))
	if (bnx2i_ep->state == EP_STATE_IDLE)
		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;
	}

	/* Do all chip cleanup here */
	if (bnx2i_hw_ep_disconnect(bnx2i_ep)) {
@@ -2096,11 +2108,12 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep)
	}
free_resc:
	bnx2i_free_qp_resc(hba, bnx2i_ep);
return_bnx2i_ep:

	if (bnx2i_conn)
		bnx2i_conn->ep = NULL;

	bnx2i_free_ep(ep);
out:
	mutex_unlock(&hba->net_dev_lock);

	wake_up_interruptible(&hba->eh_wait);