Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb...
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / qla2xxx / qla_nx.c
index 7cfdf2bd8edb3f9eab7d940afcb7330b6d7355ca..14cd361742fa668259b1df795bec4616e7bd68d4 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2011 QLogic Corporation
+ * Copyright (c)  2003-2012 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
@@ -1612,23 +1612,6 @@ qla82xx_get_fw_offs(struct qla_hw_data *ha)
 }
 
 /* PCI related functions */
-char *
-qla82xx_pci_info_str(struct scsi_qla_host *vha, char *str)
-{
-       struct qla_hw_data *ha = vha->hw;
-       char lwstr[6];
-       uint16_t lnk;
-
-       pcie_capability_read_word(ha->pdev, PCI_EXP_LNKSTA, &lnk);
-       ha->link_width = (lnk >> 4) & 0x3f;
-
-       strcpy(str, "PCIe (");
-       strcat(str, "2.5Gb/s ");
-       snprintf(lwstr, sizeof(lwstr), "x%d)", ha->link_width);
-       strcat(str, lwstr);
-       return str;
-}
-
 int qla82xx_pci_region_offset(struct pci_dev *pdev, int region)
 {
        unsigned long val = 0;
@@ -2319,6 +2302,29 @@ void qla82xx_init_flags(struct qla_hw_data *ha)
        ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg;
 }
 
+inline void
+qla82xx_set_idc_version(scsi_qla_host_t *vha)
+{
+       int idc_ver;
+       uint32_t drv_active;
+       struct qla_hw_data *ha = vha->hw;
+
+       drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+       if (drv_active == (QLA82XX_DRV_ACTIVE << (ha->portnum * 4))) {
+               qla82xx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION,
+                   QLA82XX_IDC_VERSION);
+               ql_log(ql_log_info, vha, 0xb082,
+                   "IDC version updated to %d\n", QLA82XX_IDC_VERSION);
+       } else {
+               idc_ver = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_IDC_VERSION);
+               if (idc_ver != QLA82XX_IDC_VERSION)
+                       ql_log(ql_log_info, vha, 0xb083,
+                           "qla2xxx driver IDC version %d is not compatible "
+                           "with IDC version %d of the other drivers\n",
+                           QLA82XX_IDC_VERSION, idc_ver);
+       }
+}
+
 inline void
 qla82xx_set_drv_active(scsi_qla_host_t *vha)
 {
@@ -2353,7 +2359,7 @@ qla82xx_need_reset(struct qla_hw_data *ha)
        uint32_t drv_state;
        int rval;
 
-       if (ha->flags.isp82xx_reset_owner)
+       if (ha->flags.nic_core_reset_owner)
                return 1;
        else {
                drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
@@ -2860,7 +2866,7 @@ qla82xx_device_bootstrap(scsi_qla_host_t *vha)
                timeout = msleep_interruptible(200);
                if (timeout) {
                        qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
-                               QLA82XX_DEV_FAILED);
+                               QLA8XXX_DEV_FAILED);
                        return QLA_FUNCTION_FAILED;
                }
 
@@ -2891,10 +2897,7 @@ dev_initialize:
        /* set to DEV_INITIALIZING */
        ql_log(ql_log_info, vha, 0x009e,
            "HW State: INITIALIZING.\n");
-       qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_INITIALIZING);
-
-       /* Driver that sets device state to initializating sets IDC version */
-       qla82xx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, QLA82XX_IDC_VERSION);
+       qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA8XXX_DEV_INITIALIZING);
 
        qla82xx_idc_unlock(ha);
        rval = qla82xx_start_firmware(vha);
@@ -2904,14 +2907,14 @@ dev_initialize:
                ql_log(ql_log_fatal, vha, 0x00ad,
                    "HW State: FAILED.\n");
                qla82xx_clear_drv_active(ha);
-               qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_FAILED);
+               qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA8XXX_DEV_FAILED);
                return rval;
        }
 
 dev_ready:
        ql_log(ql_log_info, vha, 0x00ae,
            "HW State: READY.\n");
-       qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_READY);
+       qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA8XXX_DEV_READY);
 
        return QLA_SUCCESS;
 }
@@ -2935,7 +2938,7 @@ qla82xx_need_qsnt_handler(scsi_qla_host_t *vha)
 
        if (vha->flags.online) {
                /*Block any further I/O and wait for pending cmnds to complete*/
-               qla82xx_quiescent_state_cleanup(vha);
+               qla2x00_quiesce_io(vha);
        }
 
        /* Set the quiescence ready bit */
@@ -2960,7 +2963,7 @@ qla82xx_need_qsnt_handler(scsi_qla_host_t *vha)
                            "DRV_STATE:%d.\n", QLA2XXX_DRIVER_NAME,
                            drv_active, drv_state);
                        qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
-                           QLA82XX_DEV_READY);
+                           QLA8XXX_DEV_READY);
                        ql_log(ql_log_info, vha, 0xb025,
                            "HW State: DEV_READY.\n");
                        qla82xx_idc_unlock(ha);
@@ -2981,10 +2984,10 @@ qla82xx_need_qsnt_handler(scsi_qla_host_t *vha)
        }
        dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
        /* everyone acked so set the state to DEV_QUIESCENCE */
-       if (dev_state == QLA82XX_DEV_NEED_QUIESCENT) {
+       if (dev_state == QLA8XXX_DEV_NEED_QUIESCENT) {
                ql_log(ql_log_info, vha, 0xb026,
                    "HW State: DEV_QUIESCENT.\n");
-               qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_QUIESCENT);
+               qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA8XXX_DEV_QUIESCENT);
        }
 }
 
@@ -3014,8 +3017,8 @@ qla82xx_wait_for_state_change(scsi_qla_host_t *vha, uint32_t curr_state)
        return dev_state;
 }
 
-static void
-qla82xx_dev_failed_handler(scsi_qla_host_t *vha)
+void
+qla8xxx_dev_failed_handler(scsi_qla_host_t *vha)
 {
        struct qla_hw_data *ha = vha->hw;
 
@@ -3023,9 +3026,10 @@ qla82xx_dev_failed_handler(scsi_qla_host_t *vha)
        ql_log(ql_log_fatal, vha, 0x00b8,
            "Disabling the board.\n");
 
-       qla82xx_idc_lock(ha);
-       qla82xx_clear_drv_active(ha);
-       qla82xx_idc_unlock(ha);
+       if (IS_QLA82XX(ha)) {
+               qla82xx_clear_drv_active(ha);
+               qla82xx_idc_unlock(ha);
+       }
 
        /* Set DEV_FAILED flag to disable timer */
        vha->device_flags |= DFLG_DEV_FAILED;
@@ -3064,7 +3068,7 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
        }
 
        drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
-       if (!ha->flags.isp82xx_reset_owner) {
+       if (!ha->flags.nic_core_reset_owner) {
                ql_dbg(ql_dbg_p3p, vha, 0xb028,
                    "reset_acknowledged by 0x%x\n", ha->portnum);
                qla82xx_set_rst_ready(ha);
@@ -3076,7 +3080,7 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
        }
 
        /* wait for 10 seconds for reset ack from all functions */
-       reset_timeout = jiffies + (ha->nx_reset_timeout * HZ);
+       reset_timeout = jiffies + (ha->fcoe_reset_timeout * HZ);
 
        drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
        drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
@@ -3088,7 +3092,7 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
            drv_state, drv_active, dev_state, active_mask);
 
        while (drv_state != drv_active &&
-           dev_state != QLA82XX_DEV_INITIALIZING) {
+           dev_state != QLA8XXX_DEV_INITIALIZING) {
                if (time_after_eq(jiffies, reset_timeout)) {
                        ql_log(ql_log_warn, vha, 0x00b5,
                            "Reset timeout.\n");
@@ -3099,7 +3103,7 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
                qla82xx_idc_lock(ha);
                drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
                drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
-               if (ha->flags.isp82xx_reset_owner)
+               if (ha->flags.nic_core_reset_owner)
                        drv_active &= active_mask;
                dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
        }
@@ -3115,11 +3119,11 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
            dev_state < MAX_STATES ? qdev_state(dev_state) : "Unknown");
 
        /* Force to DEV_COLD unless someone else is starting a reset */
-       if (dev_state != QLA82XX_DEV_INITIALIZING &&
-           dev_state != QLA82XX_DEV_COLD) {
+       if (dev_state != QLA8XXX_DEV_INITIALIZING &&
+           dev_state != QLA8XXX_DEV_COLD) {
                ql_log(ql_log_info, vha, 0x00b7,
                    "HW State: COLD/RE-INIT.\n");
-               qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD);
+               qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA8XXX_DEV_COLD);
                qla82xx_set_rst_ready(ha);
                if (ql2xmdenable) {
                        if (qla82xx_md_collect(vha))
@@ -3226,8 +3230,10 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
        int loopcount = 0;
 
        qla82xx_idc_lock(ha);
-       if (!vha->flags.init_done)
+       if (!vha->flags.init_done) {
                qla82xx_set_drv_active(vha);
+               qla82xx_set_idc_version(vha);
+       }
 
        dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
        old_dev_state = dev_state;
@@ -3237,7 +3243,7 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
            dev_state < MAX_STATES ? qdev_state(dev_state) : "Unknown");
 
        /* wait for 30 seconds for device to go ready */
-       dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ);
+       dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout * HZ);
 
        while (1) {
 
@@ -3261,18 +3267,18 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
                }
 
                switch (dev_state) {
-               case QLA82XX_DEV_READY:
-                       ha->flags.isp82xx_reset_owner = 0;
-                       goto exit;
-               case QLA82XX_DEV_COLD:
+               case QLA8XXX_DEV_READY:
+                       ha->flags.nic_core_reset_owner = 0;
+                       goto rel_lock;
+               case QLA8XXX_DEV_COLD:
                        rval = qla82xx_device_bootstrap(vha);
                        break;
-               case QLA82XX_DEV_INITIALIZING:
+               case QLA8XXX_DEV_INITIALIZING:
                        qla82xx_idc_unlock(ha);
                        msleep(1000);
                        qla82xx_idc_lock(ha);
                        break;
-               case QLA82XX_DEV_NEED_RESET:
+               case QLA8XXX_DEV_NEED_RESET:
                        if (!ql2xdontresethba)
                                qla82xx_need_reset_handler(vha);
                        else {
@@ -3281,31 +3287,31 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
                                qla82xx_idc_lock(ha);
                        }
                        dev_init_timeout = jiffies +
-                           (ha->nx_dev_init_timeout * HZ);
+                           (ha->fcoe_dev_init_timeout * HZ);
                        break;
-               case QLA82XX_DEV_NEED_QUIESCENT:
+               case QLA8XXX_DEV_NEED_QUIESCENT:
                        qla82xx_need_qsnt_handler(vha);
                        /* Reset timeout value after quiescence handler */
-                       dev_init_timeout = jiffies + (ha->nx_dev_init_timeout\
+                       dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout\
                                                         * HZ);
                        break;
-               case QLA82XX_DEV_QUIESCENT:
+               case QLA8XXX_DEV_QUIESCENT:
                        /* Owner will exit and other will wait for the state
                         * to get changed
                         */
                        if (ha->flags.quiesce_owner)
-                               goto exit;
+                               goto rel_lock;
 
                        qla82xx_idc_unlock(ha);
                        msleep(1000);
                        qla82xx_idc_lock(ha);
 
                        /* Reset timeout value after quiescence handler */
-                       dev_init_timeout = jiffies + (ha->nx_dev_init_timeout\
+                       dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout\
                                                         * HZ);
                        break;
-               case QLA82XX_DEV_FAILED:
-                       qla82xx_dev_failed_handler(vha);
+               case QLA8XXX_DEV_FAILED:
+                       qla8xxx_dev_failed_handler(vha);
                        rval = QLA_FUNCTION_FAILED;
                        goto exit;
                default:
@@ -3315,8 +3321,9 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
                }
                loopcount++;
        }
-exit:
+rel_lock:
        qla82xx_idc_unlock(ha);
+exit:
        return rval;
 }
 
@@ -3364,22 +3371,30 @@ void qla82xx_watchdog(scsi_qla_host_t *vha)
        struct qla_hw_data *ha = vha->hw;
 
        /* don't poll if reset is going on */
-       if (!ha->flags.isp82xx_reset_hdlr_active) {
+       if (!ha->flags.nic_core_reset_hdlr_active) {
                dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
                if (qla82xx_check_temp(vha)) {
                        set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags);
                        ha->flags.isp82xx_fw_hung = 1;
                        qla82xx_clear_pending_mbx(vha);
-               } else if (dev_state == QLA82XX_DEV_NEED_RESET &&
+               } else if (dev_state == QLA8XXX_DEV_NEED_RESET &&
                    !test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) {
                        ql_log(ql_log_warn, vha, 0x6001,
                            "Adapter reset needed.\n");
                        set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
-               } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT &&
+               } else if (dev_state == QLA8XXX_DEV_NEED_QUIESCENT &&
                        !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) {
                        ql_log(ql_log_warn, vha, 0x6002,
                            "Quiescent needed.\n");
                        set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
+               } else if (dev_state == QLA8XXX_DEV_FAILED &&
+                       !test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) &&
+                       vha->flags.online == 1) {
+                       ql_log(ql_log_warn, vha, 0xb055,
+                           "Adapter state is failed. Offlining.\n");
+                       set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags);
+                       ha->flags.isp82xx_fw_hung = 1;
+                       qla82xx_clear_pending_mbx(vha);
                } else {
                        if (qla82xx_check_fw_alive(vha)) {
                                ql_dbg(ql_dbg_timer, vha, 0x6011,
@@ -3441,12 +3456,12 @@ qla82xx_set_reset_owner(scsi_qla_host_t *vha)
        uint32_t dev_state;
 
        dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
-       if (dev_state == QLA82XX_DEV_READY) {
+       if (dev_state == QLA8XXX_DEV_READY) {
                ql_log(ql_log_info, vha, 0xb02f,
                    "HW State: NEED RESET\n");
                qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
-                       QLA82XX_DEV_NEED_RESET);
-               ha->flags.isp82xx_reset_owner = 1;
+                       QLA8XXX_DEV_NEED_RESET);
+               ha->flags.nic_core_reset_owner = 1;
                ql_dbg(ql_dbg_p3p, vha, 0xb030,
                    "reset_owner is 0x%x\n", ha->portnum);
        } else
@@ -3477,7 +3492,7 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
                    "Device in failed state, exiting.\n");
                return QLA_SUCCESS;
        }
-       ha->flags.isp82xx_reset_hdlr_active = 1;
+       ha->flags.nic_core_reset_hdlr_active = 1;
 
        qla82xx_idc_lock(ha);
        qla82xx_set_reset_owner(vha);
@@ -3491,7 +3506,7 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
 
        if (rval == QLA_SUCCESS) {
                ha->flags.isp82xx_fw_hung = 0;
-               ha->flags.isp82xx_reset_hdlr_active = 0;
+               ha->flags.nic_core_reset_hdlr_active = 0;
                qla82xx_restart_isp(vha);
        }
 
@@ -4026,7 +4041,7 @@ qla82xx_minidump_process_rdmem(scsi_qla_host_t *vha,
 
        if (r_addr & 0xf) {
                ql_log(ql_log_warn, vha, 0xb033,
-                   "Read addr 0x%x not 16 bytes alligned\n", r_addr);
+                   "Read addr 0x%x not 16 bytes aligned\n", r_addr);
                return rval;
        }