Commit 6ac999ef authored by Jitendra Bhivare's avatar Jitendra Bhivare Committed by Martin K. Petersen

be2iscsi: Fix soft lockup in mgmt_get_all_if_id path using bmbx

We are taking mbox_lock spinlock which disables pre-emption before we
poll for mbox completion. Waiting there with spinlock held in excess of
20s will cause soft lockup.

Actual fix is to change mbox_lock to mutex. The changes are done in
phases. This is the first part.

1. Changed mgmt_get_all_if_id to use MCC where after posting lock is
released.

2. Changed be_mbox_db_ready_wait to busy wait for 12s max and removed
wait_event_timeout. Added error handling code for IO reads.
OPCODE_COMMON_QUERY_FIRMWARE_CONFIG mbox command takes 8s time when
unreachable boot targets configured.
Signed-off-by: default avatarJitendra Bhivare <jitendra.bhivare@avagotech.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 420eb6d7
...@@ -587,47 +587,42 @@ int be_mcc_notify_wait(struct beiscsi_hba *phba) ...@@ -587,47 +587,42 @@ int be_mcc_notify_wait(struct beiscsi_hba *phba)
**/ **/
static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
{ {
#define BEISCSI_MBX_RDY_BIT_TIMEOUT 4000 /* 4sec */ #define BEISCSI_MBX_RDY_BIT_TIMEOUT 12000 /* 12sec */
void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
unsigned long timeout; unsigned long timeout;
bool read_flag = false;
int ret = 0, i;
u32 ready; u32 ready;
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(rdybit_check_q);
/*
* This BMBX busy wait path is used during init only.
* For the commands executed during init, 5s should suffice.
*/
timeout = jiffies + msecs_to_jiffies(BEISCSI_MBX_RDY_BIT_TIMEOUT);
do {
if (beiscsi_error(phba)) if (beiscsi_error(phba))
return -EIO; return -EIO;
timeout = jiffies + (HZ * 110); ready = ioread32(db);
if (ready == 0xffffffff)
return -EIO;
do { ready &= MPU_MAILBOX_DB_RDY_MASK;
for (i = 0; i < BEISCSI_MBX_RDY_BIT_TIMEOUT; i++) { if (ready)
ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; return 0;
if (ready) {
read_flag = true; if (time_after(jiffies, timeout))
break; break;
}
mdelay(1); mdelay(1);
} } while (!ready);
if (!read_flag) {
wait_event_timeout(rdybit_check_q,
(read_flag != true),
HZ * 5);
}
} while ((time_before(jiffies, timeout)) && !read_flag);
if (!read_flag) {
beiscsi_log(phba, KERN_ERR, beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BC_%d : FW Timed Out\n"); "BC_%d : FW Timed Out\n");
phba->fw_timeout = true; phba->fw_timeout = true;
beiscsi_ue_detect(phba); beiscsi_ue_detect(phba);
ret = -EBUSY;
}
return ret; return -EBUSY;
} }
/* /*
...@@ -674,6 +669,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) ...@@ -674,6 +669,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl)
if (status) if (status)
return status; return status;
/* RDY is set; small delay before CQE read. */
udelay(1);
if (be_mcc_compl_is_new(compl)) { if (be_mcc_compl_is_new(compl)) {
status = be_mcc_compl_process(ctrl, &mbox->compl); status = be_mcc_compl_process(ctrl, &mbox->compl);
be_mcc_compl_use(compl); be_mcc_compl_use(compl);
......
...@@ -809,27 +809,39 @@ int mgmt_open_connection(struct beiscsi_hba *phba, ...@@ -809,27 +809,39 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba) unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba)
{ {
struct be_ctrl_info *ctrl = &phba->ctrl; struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); struct be_mcc_wrb *wrb;
struct be_cmd_get_all_if_id_req *req = embedded_payload(wrb); struct be_cmd_get_all_if_id_req *req;
struct be_cmd_get_all_if_id_req *pbe_allid = req; struct be_cmd_get_all_if_id_req *pbe_allid;
unsigned int tag;
int status = 0; int status = 0;
memset(wrb, 0, sizeof(*wrb));
spin_lock(&ctrl->mbox_lock); spin_lock(&ctrl->mbox_lock);
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
return -ENOMEM;
}
wrb = wrb_from_mccq(phba);
req = embedded_payload(wrb);
wrb->tag0 |= tag;
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID, OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID,
sizeof(*req)); sizeof(*req));
status = be_mbox_notify(ctrl); be_mcc_notify(phba);
if (!status) spin_unlock(&ctrl->mbox_lock);
phba->interface_handle = pbe_allid->if_hndl_list[0];
else { status = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
if (status) {
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
"BG_%d : Failed in mgmt_get_all_if_id\n"); "BG_%d : Failed in mgmt_get_all_if_id\n");
return -EBUSY;
} }
spin_unlock(&ctrl->mbox_lock);
pbe_allid = embedded_payload(wrb);
phba->interface_handle = pbe_allid->if_hndl_list[0];
return status; return status;
} }
......
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