diff options
author | Jitendra Bhivare <jitendra.bhivare@avagotech.com> | 2016-01-20 11:40:45 +0300 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2016-02-24 05:27:02 +0300 |
commit | 6ac999efeeff98f203eda8cf46d5016e99f58b0c (patch) | |
tree | 01af7f763c301355719201b7b531072c78bc5415 /drivers/scsi/be2iscsi/be_cmds.c | |
parent | 420eb6d7efc4591ef1968106cdaa980ea06fe00e (diff) | |
download | linux-6ac999efeeff98f203eda8cf46d5016e99f58b0c.tar.xz |
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: Jitendra Bhivare <jitendra.bhivare@avagotech.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/be2iscsi/be_cmds.c')
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.c | 60 |
1 files changed, 29 insertions, 31 deletions
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 2778089b01a5..cd50e3ce35a6 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -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) { -#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; struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); unsigned long timeout; - bool read_flag = false; - int ret = 0, i; u32 ready; - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(rdybit_check_q); - if (beiscsi_error(phba)) - return -EIO; + /* + * 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)) + return -EIO; - timeout = jiffies + (HZ * 110); + ready = ioread32(db); + if (ready == 0xffffffff) + return -EIO; - do { - for (i = 0; i < BEISCSI_MBX_RDY_BIT_TIMEOUT; i++) { - ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; - if (ready) { - read_flag = true; - break; - } - mdelay(1); - } + ready &= MPU_MAILBOX_DB_RDY_MASK; + if (ready) + return 0; - if (!read_flag) { - wait_event_timeout(rdybit_check_q, - (read_flag != true), - HZ * 5); - } - } while ((time_before(jiffies, timeout)) && !read_flag); + if (time_after(jiffies, timeout)) + break; + mdelay(1); + } while (!ready); - if (!read_flag) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : FW Timed Out\n"); - phba->fw_timeout = true; - beiscsi_ue_detect(phba); - ret = -EBUSY; - } + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : FW Timed Out\n"); - return ret; + phba->fw_timeout = true; + beiscsi_ue_detect(phba); + + return -EBUSY; } /* @@ -674,6 +669,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) if (status) return status; + /* RDY is set; small delay before CQE read. */ + udelay(1); + if (be_mcc_compl_is_new(compl)) { status = be_mcc_compl_process(ctrl, &mbox->compl); be_mcc_compl_use(compl); |