Merge branch 'drm-prime-vmap' of git://people.freedesktop.org/~airlied/linux
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / qla2xxx / qla_init.c
index b9465643396b0c40e7fb7fbab19249f5c5cbded6..ca5084743135cf358c397dfccaa84fbbbbfece95 100644 (file)
@@ -17,6 +17,9 @@
 #include <asm/prom.h>
 #endif
 
+#include <target/target_core_base.h>
+#include "qla_target.h"
+
 /*
 *  QLogic ISP2x00 Hardware Support Function Prototypes.
 */
@@ -518,7 +521,10 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
                        return QLA_FUNCTION_FAILED;
                }
        }
-       rval = qla2x00_init_rings(vha);
+
+       if (qla_ini_mode_enabled(vha))
+               rval = qla2x00_init_rings(vha);
+
        ha->flags.chip_reset_done = 1;
 
        if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) {
@@ -1233,6 +1239,8 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
                        mq_size += ha->max_rsp_queues *
                            (rsp->length * sizeof(response_t));
                }
+               if (ha->tgt.atio_q_length)
+                       mq_size += ha->tgt.atio_q_length * sizeof(request_t);
                /* Allocate memory for Fibre Channel Event Buffer. */
                if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha))
                        goto try_eft;
@@ -1696,6 +1704,12 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
        icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma));
        icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma));
 
+       /* Setup ATIO queue dma pointers for target mode */
+       icb->atio_q_inpointer = __constant_cpu_to_le16(0);
+       icb->atio_q_length = cpu_to_le16(ha->tgt.atio_q_length);
+       icb->atio_q_address[0] = cpu_to_le32(LSD(ha->tgt.atio_dma));
+       icb->atio_q_address[1] = cpu_to_le32(MSD(ha->tgt.atio_dma));
+
        if (ha->mqenable || IS_QLA83XX(ha)) {
                icb->qos = __constant_cpu_to_le16(QLA_DEFAULT_QUE_QOS);
                icb->rid = __constant_cpu_to_le16(rid);
@@ -1739,6 +1753,8 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
                WRT_REG_DWORD(&reg->isp24.rsp_q_in, 0);
                WRT_REG_DWORD(&reg->isp24.rsp_q_out, 0);
        }
+       qlt_24xx_config_rings(vha, reg);
+
        /* PCI posting */
        RD_REG_DWORD(&ioreg->hccr);
 }
@@ -1794,6 +1810,11 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
 
        spin_unlock(&ha->vport_slock);
 
+       ha->tgt.atio_ring_ptr = ha->tgt.atio_ring;
+       ha->tgt.atio_ring_index = 0;
+       /* Initialize ATIO queue entries */
+       qlt_init_atio_q_entries(vha);
+
        ha->isp_ops->config_rings(vha);
 
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -2051,6 +2072,10 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
        vha->d_id.b.area = area;
        vha->d_id.b.al_pa = al_pa;
 
+       spin_lock(&ha->vport_slock);
+       qlt_update_vp_map(vha, SET_AL_PA);
+       spin_unlock(&ha->vport_slock);
+
        if (!vha->flags.init_done)
                ql_log(ql_log_info, vha, 0x2010,
                    "Topology - %s, Host Loop address 0x%x.\n",
@@ -2185,7 +2210,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
            nv->id[2] != 'P' || nv->id[3] != ' ' || nv->nvram_version < 1) {
                /* Reset NVRAM data. */
                ql_log(ql_log_warn, vha, 0x0064,
-                   "Inconisistent NVRAM "
+                   "Inconsistent NVRAM "
                    "detected: checksum=0x%x id=%c version=0x%x.\n",
                    chksum, nv->id[0], nv->nvram_version);
                ql_log(ql_log_warn, vha, 0x0065,
@@ -2270,7 +2295,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
        if (IS_QLA23XX(ha)) {
                nv->firmware_options[0] |= BIT_2;
                nv->firmware_options[0] &= ~BIT_3;
-               nv->firmware_options[0] &= ~BIT_6;
+               nv->special_options[0] &= ~BIT_6;
                nv->add_firmware_options[1] |= BIT_5 | BIT_4;
 
                if (IS_QLA2300(ha)) {
@@ -2467,14 +2492,21 @@ qla2x00_rport_del(void *data)
 {
        fc_port_t *fcport = data;
        struct fc_rport *rport;
+       scsi_qla_host_t *vha = fcport->vha;
        unsigned long flags;
 
        spin_lock_irqsave(fcport->vha->host->host_lock, flags);
        rport = fcport->drport ? fcport->drport: fcport->rport;
        fcport->drport = NULL;
        spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
-       if (rport)
+       if (rport) {
                fc_remote_port_delete(rport);
+               /*
+                * Release the target mode FC NEXUS in qla_target.c code
+                * if target mod is enabled.
+                */
+               qlt_fc_port_deleted(vha, fcport);
+       }
 }
 
 /**
@@ -2495,11 +2527,11 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
 
        /* Setup fcport template structure. */
        fcport->vha = vha;
-       fcport->vp_idx = vha->vp_idx;
        fcport->port_type = FCT_UNKNOWN;
        fcport->loop_id = FC_NO_LOOP_ID;
        qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED);
        fcport->supported_classes = FC_COS_UNSPECIFIED;
+       fcport->scan_state = QLA_FCPORT_SCAN_NONE;
 
        return fcport;
 }
@@ -2726,7 +2758,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
                new_fcport->d_id.b.area = area;
                new_fcport->d_id.b.al_pa = al_pa;
                new_fcport->loop_id = loop_id;
-               new_fcport->vp_idx = vha->vp_idx;
                rval2 = qla2x00_get_port_database(vha, new_fcport, 0);
                if (rval2 != QLA_SUCCESS) {
                        ql_dbg(ql_dbg_disc, vha, 0x201a,
@@ -2760,10 +2791,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
 
                if (!found) {
                        /* New device, add to fcports list. */
-                       if (vha->vp_idx) {
-                               new_fcport->vha = vha;
-                               new_fcport->vp_idx = vha->vp_idx;
-                       }
                        list_add_tail(&new_fcport->list, &vha->vp_fcports);
 
                        /* Allocate a new replacement fcport. */
@@ -2800,8 +2827,6 @@ cleanup_allocation:
 static void
 qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
 {
-#define LS_UNKNOWN      2
-       static char *link_speeds[] = { "1", "2", "?", "4", "8", "10" };
        char *link_speed;
        int rval;
        uint16_t mb[4];
@@ -2829,11 +2854,7 @@ qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
                    fcport->port_name[6], fcport->port_name[7], rval,
                    fcport->fp_speed, mb[0], mb[1]);
        } else {
-               link_speed = link_speeds[LS_UNKNOWN];
-               if (fcport->fp_speed < 5)
-                       link_speed = link_speeds[fcport->fp_speed];
-               else if (fcport->fp_speed == 0x13)
-                       link_speed = link_speeds[5];
+               link_speed = qla2x00_get_link_speed_str(ha);
                ql_dbg(ql_dbg_disc, vha, 0x2005,
                    "iIDMA adjusted to %s GB/s "
                    "on %02x%02x%02x%02x%02x%02x%02x%02x.\n", link_speed,
@@ -2864,6 +2885,12 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
                    "Unable to allocate fc remote port.\n");
                return;
        }
+       /*
+        * Create target mode FC NEXUS in qla_target.c if target mode is
+        * enabled..
+        */
+       qlt_fc_port_added(vha, fcport);
+
        spin_lock_irqsave(fcport->vha->host->host_lock, flags);
        *((fc_port_t **)rport->dd_data) = fcport;
        spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
@@ -2921,7 +2948,7 @@ static int
 qla2x00_configure_fabric(scsi_qla_host_t *vha)
 {
        int     rval;
-       fc_port_t       *fcport, *fcptemp;
+       fc_port_t       *fcport;
        uint16_t        next_loopid;
        uint16_t        mb[MAILBOX_REGISTER_COUNT];
        uint16_t        loop_id;
@@ -2959,7 +2986,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
                    0xfc, mb, BIT_1|BIT_0);
                if (rval != QLA_SUCCESS) {
                        set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
-                       return rval;
+                       break;
                }
                if (mb[0] != MBS_COMMAND_COMPLETE) {
                        ql_dbg(ql_dbg_disc, vha, 0x2042,
@@ -2991,21 +3018,16 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
                        }
                }
 
-#define QLA_FCPORT_SCAN                1
-#define QLA_FCPORT_FOUND       2
-
-               list_for_each_entry(fcport, &vha->vp_fcports, list) {
-                       fcport->scan_state = QLA_FCPORT_SCAN;
-               }
-
                rval = qla2x00_find_all_fabric_devs(vha, &new_fcports);
                if (rval != QLA_SUCCESS)
                        break;
 
-               /*
-                * Logout all previous fabric devices marked lost, except
-                * FCP2 devices.
-                */
+               /* Add new ports to existing port list */
+               list_splice_tail_init(&new_fcports, &vha->vp_fcports);
+
+               /* Starting free loop ID. */
+               next_loopid = ha->min_external_loopid;
+
                list_for_each_entry(fcport, &vha->vp_fcports, list) {
                        if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
                                break;
@@ -3013,7 +3035,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
                        if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
                                continue;
 
-                       if (fcport->scan_state == QLA_FCPORT_SCAN &&
+                       /* Logout lost/gone fabric devices (non-FCP2) */
+                       if (fcport->scan_state != QLA_FCPORT_SCAN_FOUND &&
                            atomic_read(&fcport->state) == FCS_ONLINE) {
                                qla2x00_mark_device_lost(vha, fcport,
                                    ql2xplogiabsentdevice, 0);
@@ -3026,78 +3049,30 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
                                            fcport->d_id.b.domain,
                                            fcport->d_id.b.area,
                                            fcport->d_id.b.al_pa);
-                                       fcport->loop_id = FC_NO_LOOP_ID;
                                }
-                       }
-               }
-
-               /* Starting free loop ID. */
-               next_loopid = ha->min_external_loopid;
-
-               /*
-                * Scan through our port list and login entries that need to be
-                * logged in.
-                */
-               list_for_each_entry(fcport, &vha->vp_fcports, list) {
-                       if (atomic_read(&vha->loop_down_timer) ||
-                           test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
-                               break;
-
-                       if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
-                           (fcport->flags & FCF_LOGIN_NEEDED) == 0)
                                continue;
-
-                       if (fcport->loop_id == FC_NO_LOOP_ID) {
-                               fcport->loop_id = next_loopid;
-                               rval = qla2x00_find_new_loop_id(
-                                   base_vha, fcport);
-                               if (rval != QLA_SUCCESS) {
-                                       /* Ran out of IDs to use */
-                                       break;
-                               }
                        }
-                       /* Login and update database */
-                       qla2x00_fabric_dev_login(vha, fcport, &next_loopid);
-               }
-
-               /* Exit if out of loop IDs. */
-               if (rval != QLA_SUCCESS) {
-                       break;
-               }
-
-               /*
-                * Login and add the new devices to our port list.
-                */
-               list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) {
-                       if (atomic_read(&vha->loop_down_timer) ||
-                           test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
-                               break;
-
-                       /* Find a new loop ID to use. */
-                       fcport->loop_id = next_loopid;
-                       rval = qla2x00_find_new_loop_id(base_vha, fcport);
-                       if (rval != QLA_SUCCESS) {
-                               /* Ran out of IDs to use */
-                               break;
+                       fcport->scan_state = QLA_FCPORT_SCAN_NONE;
+
+                       /* Login fabric devices that need a login */
+                       if ((fcport->flags & FCF_LOGIN_NEEDED) != 0 &&
+                           atomic_read(&vha->loop_down_timer) == 0) {
+                               if (fcport->loop_id == FC_NO_LOOP_ID) {
+                                       fcport->loop_id = next_loopid;
+                                       rval = qla2x00_find_new_loop_id(
+                                           base_vha, fcport);
+                                       if (rval != QLA_SUCCESS) {
+                                               /* Ran out of IDs to use */
+                                               continue;
+                                       }
+                               }
                        }
 
                        /* Login and update database */
                        qla2x00_fabric_dev_login(vha, fcport, &next_loopid);
-
-                       if (vha->vp_idx) {
-                               fcport->vha = vha;
-                               fcport->vp_idx = vha->vp_idx;
-                       }
-                       list_move_tail(&fcport->list, &vha->vp_fcports);
                }
        } while (0);
 
-       /* Free all new device structures not processed. */
-       list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) {
-               list_del(&fcport->list);
-               kfree(fcport);
-       }
-
        if (rval) {
                ql_dbg(ql_dbg_disc, vha, 0x2068,
                    "Configure fabric error exit rval=%d.\n", rval);
@@ -3287,7 +3262,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
                            WWN_SIZE))
                                continue;
 
-                       fcport->scan_state = QLA_FCPORT_FOUND;
+                       fcport->scan_state = QLA_FCPORT_SCAN_FOUND;
 
                        found++;
 
@@ -3595,6 +3570,12 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
                        if (mb[10] & BIT_1)
                                fcport->supported_classes |= FC_COS_CLASS3;
 
+                       if (IS_FWI2_CAPABLE(ha)) {
+                               if (mb[10] & BIT_7)
+                                       fcport->flags |=
+                                           FCF_CONF_COMP_SUPPORTED;
+                       }
+
                        rval = QLA_SUCCESS;
                        break;
                } else if (mb[0] == MBS_LOOP_ID_USED) {
@@ -3841,7 +3822,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
                vha->flags.online = 0;
        ha->flags.chip_reset_done = 0;
        clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
-       ha->qla_stats.total_isp_aborts++;
+       vha->qla_stats.total_isp_aborts++;
 
        ql_log(ql_log_info, vha, 0x00af,
            "Performing ISP error recovery - ha=%p.\n", ha);
@@ -4066,6 +4047,7 @@ qla2x00_restart_isp(scsi_qla_host_t *vha)
        struct qla_hw_data *ha = vha->hw;
        struct req_que *req = ha->req_q_map[0];
        struct rsp_que *rsp = ha->rsp_q_map[0];
+       unsigned long flags;
 
        /* If firmware needs to be loaded */
        if (qla2x00_isp_firmware(vha)) {
@@ -4090,6 +4072,16 @@ qla2x00_restart_isp(scsi_qla_host_t *vha)
                        qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
 
                        vha->flags.online = 1;
+
+                       /*
+                        * Process any ATIO queue entries that came in
+                        * while we weren't online.
+                        */
+                       spin_lock_irqsave(&ha->hardware_lock, flags);
+                       if (qla_tgt_mode_enabled(vha))
+                               qlt_24xx_process_atio_queue(vha);
+                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
                        /* Wait at most MAX_TARGET RSCNs for a stable link. */
                        wait_time = 256;
                        do {
@@ -4279,7 +4271,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
            nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) {
                /* Reset NVRAM data. */
                ql_log(ql_log_warn, vha, 0x006b,
-                   "Inconisistent NVRAM detected: checksum=0x%x id=%c "
+                   "Inconsistent NVRAM detected: checksum=0x%x id=%c "
                    "version=0x%x.\n", chksum, nv->id[0], nv->nvram_version);
                ql_log(ql_log_warn, vha, 0x006c,
                    "Falling back to functioning (yet invalid -- WWPN) "
@@ -4330,6 +4322,15 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
                rval = 1;
        }
 
+       if (!qla_ini_mode_enabled(vha)) {
+               /* Don't enable full login after initial LIP */
+               nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_13);
+               /* Don't enable LIP full login for initiator */
+               nv->host_p &= __constant_cpu_to_le32(~BIT_10);
+       }
+
+       qlt_24xx_config_nvram_stage1(vha, nv);
+
        /* Reset Initialization control block */
        memset(icb, 0, ha->init_cb_size);
 
@@ -4357,8 +4358,10 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
        qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name),
            "QLA2462");
 
-       /* Use alternate WWN? */
+       qlt_24xx_config_nvram_stage2(vha, icb);
+
        if (nv->host_p & __constant_cpu_to_le32(BIT_15)) {
+               /* Use alternate WWN? */
                memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
                memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
        }
@@ -5029,7 +5032,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
            nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) {
                /* Reset NVRAM data. */
                ql_log(ql_log_info, vha, 0x0073,
-                   "Inconisistent NVRAM detected: checksum=0x%x id=%c "
+                   "Inconsistent NVRAM detected: checksum=0x%x id=%c "
                    "version=0x%x.\n", chksum, nv->id[0],
                    le16_to_cpu(nv->nvram_version));
                ql_log(ql_log_info, vha, 0x0074,