]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
scsi: qla2xxx: Flush mailbox commands on chip reset
authorQuinn Tran <quinn.tran@cavium.com>
Thu, 2 Aug 2018 20:16:52 +0000 (13:16 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 2 Aug 2018 20:56:18 +0000 (16:56 -0400)
Flush pending mailbox commands on chip reset.  Wake up command that's
waiting for an interrupt and wait for mailbox counters to go to zero.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_os.c

index ee4d1f4fdf95207bd674972495aeffee3a0bb3d1..40bcf938cf4f03b5f746c59d3bd97bd8b6747b36 100644 (file)
@@ -3598,6 +3598,7 @@ struct qla_hw_data {
                uint32_t        detected_lr_sfp:1;
                uint32_t        using_lr_setting:1;
                uint32_t        rida_fmt2:1;
+               uint32_t        purge_mbox:1;
        } flags;
 
        uint16_t max_exchg;
@@ -3843,6 +3844,9 @@ struct qla_hw_data {
        int             port_down_retry_count;
        uint8_t         mbx_count;
        uint8_t         aen_mbx_count;
+       atomic_t        num_pend_mbx_stage1;
+       atomic_t        num_pend_mbx_stage2;
+       atomic_t        num_pend_mbx_stage3;
 
        uint32_t        login_retry_count;
        /* SNS command interfaces. */
@@ -4156,6 +4160,7 @@ struct qla_hw_data {
        struct work_struct board_disable;
 
        struct mr_data_fx00 mr;
+       uint32_t chip_reset;
 
        struct qlt_hw_data tgt;
        int     allow_cna_fw_dump;
index bb565f556c2f147ee2ba4a9f7fa21d6809f68f2a..a10a8bb895e9c7cdc6ccce88de1c604de104eeb7 100644 (file)
@@ -6283,6 +6283,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
        ql_log(ql_log_info, vha, 0x00af,
            "Performing ISP error recovery - ha=%p.\n", ha);
 
+       ha->flags.purge_mbox = 1;
        /* For ISP82XX, reset_chip is just disabling interrupts.
         * Driver waits for the completion of the commands.
         * the interrupts need to be enabled.
@@ -6297,13 +6298,31 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
        ha->current_topology = 0;
        ha->flags.fw_started = 0;
        ha->flags.fw_init_done = 0;
-       ha->base_qpair->chip_reset++;
+       ha->chip_reset++;
+       ha->base_qpair->chip_reset = ha->chip_reset;
        for (i = 0; i < ha->max_qpairs; i++) {
                if (ha->queue_pair_map[i])
                        ha->queue_pair_map[i]->chip_reset =
                                ha->base_qpair->chip_reset;
        }
 
+       /* purge MBox commands */
+       if (atomic_read(&ha->num_pend_mbx_stage3)) {
+               clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
+               complete(&ha->mbx_intr_comp);
+       }
+
+       i = 0;
+       while (atomic_read(&ha->num_pend_mbx_stage3) ||
+           atomic_read(&ha->num_pend_mbx_stage2) ||
+           atomic_read(&ha->num_pend_mbx_stage1)) {
+               msleep(20);
+               i++;
+               if (i > 50)
+                       break;
+       }
+       ha->flags.purge_mbox = 0;
+
        atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
        if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
                atomic_set(&vha->loop_state, LOOP_DOWN);
index 17537f0b3b54d17ab7e4c5e7c79835b07e6d8243..10847cdca0938a387b6c44c63ae8f3e8416bc04e 100644 (file)
@@ -110,6 +110,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
        unsigned long   wait_time;
        struct qla_hw_data *ha = vha->hw;
        scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
+       u32 chip_reset;
 
 
        ql_dbg(ql_dbg_mbx, vha, 0x1000, "Entered %s.\n", __func__);
@@ -140,7 +141,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 
        rval = QLA_SUCCESS;
        abort_active = test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
-
+       chip_reset = ha->chip_reset;
 
        if (ha->flags.pci_channel_io_perm_failure) {
                ql_log(ql_log_warn, vha, 0x1003,
@@ -167,6 +168,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                return QLA_FUNCTION_TIMEOUT;
        }
 
+       atomic_inc(&ha->num_pend_mbx_stage1);
        /*
         * Wait for active mailbox commands to finish by waiting at most tov
         * seconds. This is to serialize actual issuing of mailbox cmds during
@@ -177,8 +179,14 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                ql_log(ql_log_warn, vha, 0xd035,
                    "Cmd access timeout, cmd=0x%x, Exiting.\n",
                    mcp->mb[0]);
+               atomic_dec(&ha->num_pend_mbx_stage1);
                return QLA_FUNCTION_TIMEOUT;
        }
+       atomic_dec(&ha->num_pend_mbx_stage1);
+       if (ha->flags.purge_mbox || chip_reset != ha->chip_reset) {
+               rval = QLA_ABORTED;
+               goto premature_exit;
+       }
 
        ha->flags.mbox_busy = 1;
        /* Save mailbox command for debug */
@@ -189,6 +197,13 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
 
+       if (ha->flags.purge_mbox || chip_reset != ha->chip_reset) {
+               rval = QLA_ABORTED;
+               ha->flags.mbox_busy = 0;
+               spin_unlock_irqrestore(&ha->hardware_lock, flags);
+               goto premature_exit;
+       }
+
        /* Load mailbox registers. */
        if (IS_P3P_TYPE(ha))
                optr = (uint16_t __iomem *)&reg->isp82.mailbox_in[0];
@@ -231,7 +246,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
            "jiffies=%lx.\n", jiffies);
 
        /* Wait for mbx cmd completion until timeout */
-
+       atomic_inc(&ha->num_pend_mbx_stage2);
        if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) {
                set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
 
@@ -241,6 +256,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                                spin_unlock_irqrestore(&ha->hardware_lock,
                                        flags);
                                ha->flags.mbox_busy = 0;
+                               atomic_dec(&ha->num_pend_mbx_stage2);
                                ql_dbg(ql_dbg_mbx, vha, 0x1010,
                                    "Pending mailbox timeout, exiting.\n");
                                rval = QLA_FUNCTION_TIMEOUT;
@@ -254,6 +270,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
                wait_time = jiffies;
+               atomic_inc(&ha->num_pend_mbx_stage3);
                if (!wait_for_completion_timeout(&ha->mbx_intr_comp,
                    mcp->tov * HZ)) {
                        ql_dbg(ql_dbg_mbx, vha, 0x117a,
@@ -261,7 +278,17 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                        spin_lock_irqsave(&ha->hardware_lock, flags);
                        clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
                        spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+               } else if (ha->flags.purge_mbox ||
+                   chip_reset != ha->chip_reset) {
+                       ha->flags.mbox_busy = 0;
+                       atomic_dec(&ha->num_pend_mbx_stage2);
+                       atomic_dec(&ha->num_pend_mbx_stage3);
+                       rval = QLA_ABORTED;
+                       goto premature_exit;
                }
+               atomic_dec(&ha->num_pend_mbx_stage3);
+
                if (time_after(jiffies, wait_time + 5 * HZ))
                        ql_log(ql_log_warn, vha, 0x1015, "cmd=0x%x, waited %d msecs\n",
                            command, jiffies_to_msecs(jiffies - wait_time));
@@ -275,6 +302,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                                spin_unlock_irqrestore(&ha->hardware_lock,
                                        flags);
                                ha->flags.mbox_busy = 0;
+                               atomic_dec(&ha->num_pend_mbx_stage2);
                                ql_dbg(ql_dbg_mbx, vha, 0x1012,
                                    "Pending mailbox timeout, exiting.\n");
                                rval = QLA_FUNCTION_TIMEOUT;
@@ -289,6 +317,14 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 
                wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */
                while (!ha->flags.mbox_int) {
+                       if (ha->flags.purge_mbox ||
+                           chip_reset != ha->chip_reset) {
+                               ha->flags.mbox_busy = 0;
+                               atomic_dec(&ha->num_pend_mbx_stage2);
+                               rval = QLA_ABORTED;
+                               goto premature_exit;
+                       }
+
                        if (time_after(jiffies, wait_time))
                                break;
 
@@ -312,6 +348,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                    "Waited %d sec.\n",
                    (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ));
        }
+       atomic_dec(&ha->num_pend_mbx_stage2);
 
        /* Check whether we timed out */
        if (ha->flags.mbox_int) {
@@ -390,7 +427,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                /* Capture FW dump only, if PCI device active */
                if (!pci_channel_offline(vha->hw->pdev)) {
                        pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
-                       if (w == 0xffff || ictrl == 0xffffffff) {
+                       if (w == 0xffff || ictrl == 0xffffffff ||
+                           (chip_reset != ha->chip_reset)) {
                                /* This is special case if there is unload
                                 * of driver happening and if PCI device go
                                 * into bad state due to PCI error condition
@@ -497,7 +535,11 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
        complete(&ha->mbx_cmd_comp);
 
 mbx_done:
-       if (rval) {
+       if (rval == QLA_ABORTED) {
+               ql_log(ql_log_info, vha, 0xd035,
+                   "Chip Reset in progress. Purging Mbox cmd=0x%x.\n",
+                   mcp->mb[0]);
+       } else if (rval) {
                if (ql2xextended_error_logging & (ql_dbg_disc|ql_dbg_mbx)) {
                        pr_warn("%s [%s]-%04x:%ld: **** Failed", QL_MSGHDR,
                            dev_name(&ha->pdev->dev), 0x1020+0x800,
index e218d68de5329ae3e45a0677c96e882e8261dc66..04e0c7f51e68ee627a99c2378a5ab4e04a906e10 100644 (file)
@@ -2815,6 +2815,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        ha->link_data_rate = PORT_SPEED_UNKNOWN;
        ha->optrom_size = OPTROM_SIZE_2300;
        ha->max_exchg = FW_MAX_EXCHANGES_CNT;
+       atomic_set(&ha->num_pend_mbx_stage1, 0);
+       atomic_set(&ha->num_pend_mbx_stage2, 0);
+       atomic_set(&ha->num_pend_mbx_stage3, 0);
 
        /* Assign ISP specific operations. */
        if (IS_QLA2100(ha)) {