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

[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
...@@ -295,6 +295,7 @@ struct iscsi_cid_queue { ...@@ -295,6 +295,7 @@ struct iscsi_cid_queue {
* @max_cqes: CQ size * @max_cqes: CQ size
* @num_ccell: number of command cells per connection * @num_ccell: number of command cells per connection
* @ofld_conns_active: active connection list * @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 * @max_active_conns: max offload connections supported by this device
* @cid_que: iscsi cid queue * @cid_que: iscsi cid queue
* @ep_rdwr_lock: read / write lock to synchronize various ep lists * @ep_rdwr_lock: read / write lock to synchronize various ep lists
...@@ -306,6 +307,7 @@ struct iscsi_cid_queue { ...@@ -306,6 +307,7 @@ struct iscsi_cid_queue {
* @dummy_buffer: Dummy buffer to be used with zero length scsicmd reqs * @dummy_buffer: Dummy buffer to be used with zero length scsicmd reqs
* @dummy_buf_dma: DMA address of 'dummy_buffer' memory buffer * @dummy_buf_dma: DMA address of 'dummy_buffer' memory buffer
* @lock: lock to synchonize access to hba structure * @lock: lock to synchonize access to hba structure
* @hba_shutdown_tmo: Timeout value to shutdown each connection
* @pci_did: PCI device ID * @pci_did: PCI device ID
* @pci_vid: PCI vendor ID * @pci_vid: PCI vendor ID
* @pci_sdid: PCI subsystem device ID * @pci_sdid: PCI subsystem device ID
...@@ -770,6 +772,8 @@ extern struct bnx2i_endpoint *bnx2i_find_ep_in_destroy_list( ...@@ -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 int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep);
extern void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action); 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 */ /* Debug related function prototypes */
extern void bnx2i_print_pend_cmd_queue(struct bnx2i_conn *conn); extern void bnx2i_print_pend_cmd_queue(struct bnx2i_conn *conn);
extern void bnx2i_print_active_cmd_queue(struct bnx2i_conn *conn); extern void bnx2i_print_active_cmd_queue(struct bnx2i_conn *conn);
......
...@@ -176,6 +176,9 @@ void bnx2i_start(void *handle) ...@@ -176,6 +176,9 @@ void bnx2i_start(void *handle)
void bnx2i_stop(void *handle) void bnx2i_stop(void *handle)
{ {
struct bnx2i_hba *hba = 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 */ /* check if cleanup happened in GOING_DOWN context */
if (!test_and_clear_bit(ADAPTER_STATE_GOING_DOWN, if (!test_and_clear_bit(ADAPTER_STATE_GOING_DOWN,
...@@ -187,9 +190,33 @@ void bnx2i_stop(void *handle) ...@@ -187,9 +190,33 @@ void bnx2i_stop(void *handle)
* control returns to network driver. So it is required to cleanup and * control returns to network driver. So it is required to cleanup and
* release all connection resources before returning from this routine. * release all connection resources before returning from this routine.
*/ */
wait_event_interruptible_timeout(hba->eh_wait, while (hba->ofld_conns_active) {
(hba->ofld_conns_active == 0), conns_active = hba->ofld_conns_active;
hba->hba_shutdown_tmo); wait_event_interruptible_timeout(hba->eh_wait,
(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 /* This flag should be cleared last so that ep_disconnect() gracefully
* cleans up connection context * cleans up connection context
*/ */
......
...@@ -708,7 +708,6 @@ bnx2i_find_ep_in_destroy_list(struct bnx2i_hba *hba, u32 iscsi_cid) ...@@ -708,7 +708,6 @@ bnx2i_find_ep_in_destroy_list(struct bnx2i_hba *hba, u32 iscsi_cid)
return ep; return ep;
} }
/** /**
* bnx2i_ep_active_list_add - add an entry to ep active list * bnx2i_ep_active_list_add - add an entry to ep active list
* @hba: pointer to adapter instance * @hba: pointer to adapter instance
...@@ -856,9 +855,9 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic) ...@@ -856,9 +855,9 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic)
mutex_init(&hba->net_dev_lock); mutex_init(&hba->net_dev_lock);
init_waitqueue_head(&hba->eh_wait); init_waitqueue_head(&hba->eh_wait);
if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) 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 */ else /* 5706/5708/5709 */
hba->hba_shutdown_tmo = 30 * HZ; hba->hba_shutdown_tmo = 20 * HZ;
if (iscsi_host_add(shost, &hba->pcidev->dev)) if (iscsi_host_add(shost, &hba->pcidev->dev))
goto free_dump_mem; goto free_dump_mem;
...@@ -1700,10 +1699,11 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, ...@@ -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)) { if (!hba || test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state)) {
rc = -EINVAL; rc = -EINVAL;
goto check_busy; goto nohba;
} }
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;
...@@ -1711,7 +1711,6 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, ...@@ -1711,7 +1711,6 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
} }
bnx2i_ep = ep->dd_data; bnx2i_ep = ep->dd_data;
mutex_lock(&hba->net_dev_lock);
if (bnx2i_adapter_ready(hba)) { if (bnx2i_adapter_ready(hba)) {
rc = -EPERM; rc = -EPERM;
goto net_if_down; goto net_if_down;
...@@ -1813,8 +1812,9 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, ...@@ -1813,8 +1812,9 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
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);
mutex_unlock(&hba->net_dev_lock);
check_busy: check_busy:
mutex_unlock(&hba->net_dev_lock);
nohba:
bnx2i_unreg_dev_all(); bnx2i_unreg_dev_all();
return ERR_PTR(rc); return ERR_PTR(rc);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment