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

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

[SCSI] bnx2i: Optimized the bnx2i_stop connection clean up procedure



For cases where the iSCSI disconnection procedure times out due to
the iSCSI daemon being slow or unresponsive, the bnx2i_stop routine
will now perform hardware cleanup via bnx2i_hw_ep_disconnect on all
active endpoints so that subsequent operations will perform properly.
Also moved the mutex locks inside ep_connect and ep_disconnect so
that proper exclusivity can resolve simultaneous calls to the
ep_disconnect routine.

v2: Removed the unnecessary read lock in the bnx2i_stop

Signed-off-by: default avatarEddie Wai <eddie.wai@broadcom.com>
Reviewed-by: default avatarMichael Chan <mchan@broadcom.com>
Reviewed-by: default avatarBenjamin Li <benli@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 46012e8b
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -295,6 +295,7 @@ struct iscsi_cid_queue {
 * @max_cqes:              CQ size
 * @num_ccell:             number of command cells per connection
 * @ofld_conns_active:     active connection list
 * @eh_wait:               wait queue for the endpoint to shutdown
 * @max_active_conns:      max offload connections supported by this device
 * @cid_que:               iscsi cid queue
 * @ep_rdwr_lock:          read / write lock to synchronize various ep lists
@@ -306,6 +307,7 @@ struct iscsi_cid_queue {
 * @dummy_buffer:          Dummy buffer to be used with zero length scsicmd reqs
 * @dummy_buf_dma:         DMA address of 'dummy_buffer' memory buffer
 * @lock:              	   lock to synchonize access to hba structure
 * @hba_shutdown_tmo:      Timeout value to shutdown each connection
 * @pci_did:               PCI device ID
 * @pci_vid:               PCI vendor ID
 * @pci_sdid:              PCI subsystem device ID
@@ -770,6 +772,8 @@ extern struct bnx2i_endpoint *bnx2i_find_ep_in_destroy_list(
extern int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep);
extern void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action);

extern int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep);

/* Debug related function prototypes */
extern void bnx2i_print_pend_cmd_queue(struct bnx2i_conn *conn);
extern void bnx2i_print_active_cmd_queue(struct bnx2i_conn *conn);
+30 −3
Original line number Diff line number Diff line
@@ -176,6 +176,9 @@ void bnx2i_start(void *handle)
void bnx2i_stop(void *handle)
{
	struct bnx2i_hba *hba = handle;
	struct list_head *pos, *tmp;
	struct bnx2i_endpoint *bnx2i_ep;
	int conns_active;

	/* check if cleanup happened in GOING_DOWN context */
	if (!test_and_clear_bit(ADAPTER_STATE_GOING_DOWN,
@@ -187,9 +190,33 @@ void bnx2i_stop(void *handle)
	 *  control returns to network driver. So it is required to cleanup and
	 * release all connection resources before returning from this routine.
	 */
	while (hba->ofld_conns_active) {
		conns_active = hba->ofld_conns_active;
		wait_event_interruptible_timeout(hba->eh_wait,
					 (hba->ofld_conns_active == 0),
				(hba->ofld_conns_active != conns_active),
				hba->hba_shutdown_tmo);
		if (hba->ofld_conns_active == conns_active)
			break;
	}
	if (hba->ofld_conns_active) {
		/* Stage to force the disconnection
		 * This is the case where the daemon is either slow or
		 * not present
		 */
		printk(KERN_ALERT "bnx2i: Wait timeout, force all eps "
			"to disconnect (%d)\n", hba->ofld_conns_active);
		mutex_lock(&hba->net_dev_lock);
		list_for_each_safe(pos, tmp, &hba->ep_active_list) {
			bnx2i_ep = list_entry(pos, struct bnx2i_endpoint, link);
			/* Clean up the chip only */
			bnx2i_hw_ep_disconnect(bnx2i_ep);
		}
		mutex_unlock(&hba->net_dev_lock);
		if (hba->ofld_conns_active)
			printk(KERN_ERR "bnx2i: EP disconnect timeout (%d)!\n",
				hba->ofld_conns_active);
	}

	/* This flag should be cleared last so that ep_disconnect() gracefully
	 * cleans up connection context
	 */
+6 −6
Original line number Diff line number Diff line
@@ -708,7 +708,6 @@ bnx2i_find_ep_in_destroy_list(struct bnx2i_hba *hba, u32 iscsi_cid)
	return ep;
}


/**
 * bnx2i_ep_active_list_add - add an entry to ep active list
 * @hba:	pointer to adapter instance
@@ -856,9 +855,9 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic)
	mutex_init(&hba->net_dev_lock);
	init_waitqueue_head(&hba->eh_wait);
	if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type))
		hba->hba_shutdown_tmo = 240 * HZ;
		hba->hba_shutdown_tmo = 20 * HZ;
	else	/* 5706/5708/5709 */
		hba->hba_shutdown_tmo = 30 * HZ;
		hba->hba_shutdown_tmo = 20 * HZ;

	if (iscsi_host_add(shost, &hba->pcidev->dev))
		goto free_dump_mem;
@@ -1700,10 +1699,11 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,

	if (!hba || test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state)) {
		rc = -EINVAL;
		goto check_busy;
		goto nohba;
	}

	cnic = hba->cnic;
	mutex_lock(&hba->net_dev_lock);
	ep = bnx2i_alloc_ep(hba);
	if (!ep) {
		rc = -ENOMEM;
@@ -1711,7 +1711,6 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
	}
	bnx2i_ep = ep->dd_data;

	mutex_lock(&hba->net_dev_lock);
	if (bnx2i_adapter_ready(hba)) {
		rc = -EPERM;
		goto net_if_down;
@@ -1813,8 +1812,9 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
	bnx2i_free_qp_resc(hba, bnx2i_ep);
qp_resc_err:
	bnx2i_free_ep(ep);
	mutex_unlock(&hba->net_dev_lock);
check_busy:
	mutex_unlock(&hba->net_dev_lock);
nohba:
	bnx2i_unreg_dev_all();
	return ERR_PTR(rc);
}