Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[deliverable/linux.git] / drivers / scsi / qla2xxx / qla_os.c
index ccb5e6404d09a85a026ac2c03c1470433b2937ba..5307bf86d5e08d453be2f8d3bd3ca781607b640c 100644 (file)
@@ -47,6 +47,7 @@ MODULE_PARM_DESC(ql2xenableclass2,
                "Specify if Class 2 operations are supported from the very "
                "beginning. Default is 0 - class 2 not supported.");
 
+
 int ql2xlogintimeout = 20;
 module_param(ql2xlogintimeout, int, S_IRUGO);
 MODULE_PARM_DESC(ql2xlogintimeout,
@@ -354,7 +355,12 @@ fail_req_map:
 
 static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
 {
-       if (req && req->ring)
+       if (IS_QLAFX00(ha)) {
+               if (req && req->ring_fx00)
+                       dma_free_coherent(&ha->pdev->dev,
+                           (req->length_fx00 + 1) * sizeof(request_t),
+                           req->ring_fx00, req->dma_fx00);
+       } else if (req && req->ring)
                dma_free_coherent(&ha->pdev->dev,
                (req->length + 1) * sizeof(request_t),
                req->ring, req->dma);
@@ -368,11 +374,16 @@ static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
 
 static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)
 {
-       if (rsp && rsp->ring)
+       if (IS_QLAFX00(ha)) {
+               if (rsp && rsp->ring)
+                       dma_free_coherent(&ha->pdev->dev,
+                           (rsp->length_fx00 + 1) * sizeof(request_t),
+                           rsp->ring_fx00, rsp->dma_fx00);
+       } else if (rsp && rsp->ring) {
                dma_free_coherent(&ha->pdev->dev,
                (rsp->length + 1) * sizeof(response_t),
                rsp->ring, rsp->dma);
-
+       }
        kfree(rsp);
        rsp = NULL;
 }
@@ -633,7 +644,7 @@ qla2x00_sp_free_dma(void *vha, void *ptr)
        qla2x00_rel_sp(sp->fcport->vha, sp);
 }
 
-static void
+void
 qla2x00_sp_compl(void *data, void *ptr, int res)
 {
        struct qla_hw_data *ha = (struct qla_hw_data *)data;
@@ -657,6 +668,9 @@ qla2x00_sp_compl(void *data, void *ptr, int res)
        cmd->scsi_done(cmd);
 }
 
+/* If we are SP1 here, we need to still take and release the host_lock as SP1
+ * does not have the changes necessary to avoid taking host->host_lock.
+ */
 static int
 qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 {
@@ -1304,6 +1318,9 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
                }
        }
 
+       if (IS_QLAFX00(ha))
+               return QLA_SUCCESS;
+
        if (ha->flags.enable_lip_full_login && !IS_CNA_CAPABLE(ha)) {
                atomic_set(&vha->loop_state, LOOP_DOWN);
                atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
@@ -1858,6 +1875,7 @@ static struct isp_operations qla2100_isp_ops = {
        .start_scsi             = qla2x00_start_scsi,
        .abort_isp              = qla2x00_abort_isp,
        .iospace_config         = qla2x00_iospace_config,
+       .initialize_adapter     = qla2x00_initialize_adapter,
 };
 
 static struct isp_operations qla2300_isp_ops = {
@@ -1895,6 +1913,7 @@ static struct isp_operations qla2300_isp_ops = {
        .start_scsi             = qla2x00_start_scsi,
        .abort_isp              = qla2x00_abort_isp,
        .iospace_config         = qla2x00_iospace_config,
+       .initialize_adapter     = qla2x00_initialize_adapter,
 };
 
 static struct isp_operations qla24xx_isp_ops = {
@@ -1932,6 +1951,7 @@ static struct isp_operations qla24xx_isp_ops = {
        .start_scsi             = qla24xx_start_scsi,
        .abort_isp              = qla2x00_abort_isp,
        .iospace_config         = qla2x00_iospace_config,
+       .initialize_adapter     = qla2x00_initialize_adapter,
 };
 
 static struct isp_operations qla25xx_isp_ops = {
@@ -1969,6 +1989,7 @@ static struct isp_operations qla25xx_isp_ops = {
        .start_scsi             = qla24xx_dif_start_scsi,
        .abort_isp              = qla2x00_abort_isp,
        .iospace_config         = qla2x00_iospace_config,
+       .initialize_adapter     = qla2x00_initialize_adapter,
 };
 
 static struct isp_operations qla81xx_isp_ops = {
@@ -2006,6 +2027,7 @@ static struct isp_operations qla81xx_isp_ops = {
        .start_scsi             = qla24xx_dif_start_scsi,
        .abort_isp              = qla2x00_abort_isp,
        .iospace_config         = qla2x00_iospace_config,
+       .initialize_adapter     = qla2x00_initialize_adapter,
 };
 
 static struct isp_operations qla82xx_isp_ops = {
@@ -2043,6 +2065,7 @@ static struct isp_operations qla82xx_isp_ops = {
        .start_scsi             = qla82xx_start_scsi,
        .abort_isp              = qla82xx_abort_isp,
        .iospace_config         = qla82xx_iospace_config,
+       .initialize_adapter     = qla2x00_initialize_adapter,
 };
 
 static struct isp_operations qla83xx_isp_ops = {
@@ -2080,6 +2103,45 @@ static struct isp_operations qla83xx_isp_ops = {
        .start_scsi             = qla24xx_dif_start_scsi,
        .abort_isp              = qla2x00_abort_isp,
        .iospace_config         = qla83xx_iospace_config,
+       .initialize_adapter     = qla2x00_initialize_adapter,
+};
+
+static struct isp_operations qlafx00_isp_ops = {
+       .pci_config             = qlafx00_pci_config,
+       .reset_chip             = qlafx00_soft_reset,
+       .chip_diag              = qlafx00_chip_diag,
+       .config_rings           = qlafx00_config_rings,
+       .reset_adapter          = qlafx00_soft_reset,
+       .nvram_config           = NULL,
+       .update_fw_options      = NULL,
+       .load_risc              = NULL,
+       .pci_info_str           = qlafx00_pci_info_str,
+       .fw_version_str         = qlafx00_fw_version_str,
+       .intr_handler           = qlafx00_intr_handler,
+       .enable_intrs           = qlafx00_enable_intrs,
+       .disable_intrs          = qlafx00_disable_intrs,
+       .abort_command          = qlafx00_abort_command,
+       .target_reset           = qlafx00_abort_target,
+       .lun_reset              = qlafx00_lun_reset,
+       .fabric_login           = NULL,
+       .fabric_logout          = NULL,
+       .calc_req_entries       = NULL,
+       .build_iocbs            = NULL,
+       .prep_ms_iocb           = qla24xx_prep_ms_iocb,
+       .prep_ms_fdmi_iocb      = qla24xx_prep_ms_fdmi_iocb,
+       .read_nvram             = qla24xx_read_nvram_data,
+       .write_nvram            = qla24xx_write_nvram_data,
+       .fw_dump                = NULL,
+       .beacon_on              = qla24xx_beacon_on,
+       .beacon_off             = qla24xx_beacon_off,
+       .beacon_blink           = NULL,
+       .read_optrom            = qla24xx_read_optrom_data,
+       .write_optrom           = qla24xx_write_optrom_data,
+       .get_flash_version      = qla24xx_get_flash_version,
+       .start_scsi             = qlafx00_start_scsi,
+       .abort_isp              = qlafx00_abort_isp,
+       .iospace_config         = qlafx00_iospace_config,
+       .initialize_adapter     = qlafx00_initialize_adapter,
 };
 
 static inline void
@@ -2192,6 +2254,9 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
                ha->device_type |= DT_T10_PI;
                ha->fw_srisc_address = RISC_START_ADDRESS_2400;
                break;
+       case PCI_DEVICE_ID_QLOGIC_ISPF001:
+               ha->device_type |= DT_ISPFX00;
+               break;
        }
 
        if (IS_QLA82XX(ha))
@@ -2265,7 +2330,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8021 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2031 ||
-           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8031) {
+           pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8031 ||
+           pdev->device == PCI_DEVICE_ID_QLOGIC_ISPF001) {
                bars = pci_select_bars(pdev, IORESOURCE_MEM);
                mem_only = 1;
                ql_dbg_pci(ql_dbg_init, pdev, 0x0007,
@@ -2436,6 +2502,18 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX;
                ha->nvram_conf_off = ~0;
                ha->nvram_data_off = ~0;
+       }  else if (IS_QLAFX00(ha)) {
+               ha->max_fibre_devices = MAX_FIBRE_DEVICES_FX00;
+               ha->mbx_count = MAILBOX_REGISTER_COUNT_FX00;
+               ha->aen_mbx_count = AEN_MAILBOX_REGISTER_COUNT_FX00;
+               req_length = REQUEST_ENTRY_CNT_FX00;
+               rsp_length = RESPONSE_ENTRY_CNT_FX00;
+               ha->init_cb_size = sizeof(struct init_cb_fx);
+               ha->isp_ops = &qlafx00_isp_ops;
+               ha->port_down_retry_count = 30; /* default value */
+               ha->mr.fw_hbt_cnt = QLAFX00_HEARTBEAT_INTERVAL;
+               ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL;
+               ha->mr.fw_hbt_en = 1;
        }
 
        ql_dbg_pci(ql_dbg_init, pdev, 0x001e,
@@ -2500,13 +2578,24 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        host = base_vha->host;
        base_vha->req = req;
-       host->can_queue = req->length + 128;
+       if (IS_QLAFX00(ha))
+               host->can_queue = 1024;
+       else
+               host->can_queue = req->length + 128;
        if (IS_QLA2XXX_MIDTYPE(ha))
                base_vha->mgmt_svr_loop_id = 10 + base_vha->vp_idx;
        else
                base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER +
                                                base_vha->vp_idx;
 
+       /* Setup fcport template structure. */
+       ha->mr.fcport.vha = base_vha;
+       ha->mr.fcport.port_type = FCT_UNKNOWN;
+       ha->mr.fcport.loop_id = FC_NO_LOOP_ID;
+       qla2x00_set_fcport_state(&ha->mr.fcport, FCS_UNCONFIGURED);
+       ha->mr.fcport.supported_classes = FC_COS_UNSPECIFIED;
+       ha->mr.fcport.scan_state = 1;
+
        /* Set the SG table size based on ISP type */
        if (!IS_FWI2_CAPABLE(ha)) {
                if (IS_QLA2100(ha))
@@ -2562,6 +2651,13 @@ que_init:
        rsp->req = req;
        req->rsp = rsp;
 
+       if (IS_QLAFX00(ha)) {
+               ha->rsp_q_map[0] = rsp;
+               ha->req_q_map[0] = req;
+               set_bit(0, ha->req_qid_map);
+               set_bit(0, ha->rsp_qid_map);
+       }
+
        /* FWI2-capable only. */
        req->req_q_in = &ha->iobase->isp24.req_q_in;
        req->req_q_out = &ha->iobase->isp24.req_q_out;
@@ -2574,6 +2670,13 @@ que_init:
                rsp->rsp_q_out =  &ha->mqiobase->isp25mq.rsp_q_out;
        }
 
+       if (IS_QLAFX00(ha)) {
+               req->req_q_in = &ha->iobase->ispfx00.req_q_in;
+               req->req_q_out = &ha->iobase->ispfx00.req_q_out;
+               rsp->rsp_q_in = &ha->iobase->ispfx00.rsp_q_in;
+               rsp->rsp_q_out = &ha->iobase->ispfx00.rsp_q_out;
+       }
+
        if (IS_QLA82XX(ha)) {
                req->req_q_out = &ha->iobase->isp82.req_q_out[0];
                rsp->rsp_q_in = &ha->iobase->isp82.rsp_q_in[0];
@@ -2595,7 +2698,7 @@ que_init:
            "req->req_q_in=%p req->req_q_out=%p rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n",
            req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out);
 
-       if (qla2x00_initialize_adapter(base_vha)) {
+       if (ha->isp_ops->initialize_adapter(base_vha)) {
                ql_log(ql_log_fatal, base_vha, 0x00d6,
                    "Failed to initialize adapter - Adapter flags %x.\n",
                    base_vha->device_flags);
@@ -2720,6 +2823,18 @@ skip_dpc:
 
        qla2x00_alloc_sysfs_attr(base_vha);
 
+       if (IS_QLAFX00(ha)) {
+               ret = qlafx00_fx_disc(base_vha,
+                       &base_vha->hw->mr.fcport, FXDISC_GET_CONFIG_INFO);
+
+               ret = qlafx00_fx_disc(base_vha,
+                       &base_vha->hw->mr.fcport, FXDISC_GET_PORT_INFO);
+
+               /* Register system information */
+               ret =  qlafx00_fx_disc(base_vha,
+                       &base_vha->hw->mr.fcport, FXDISC_REG_HOST_INFO);
+       }
+
        qla2x00_init_host_attr(base_vha);
 
        qla2x00_dfs_setup(base_vha);
@@ -2777,6 +2892,8 @@ iospace_config_failed:
        } else {
                if (ha->iobase)
                        iounmap(ha->iobase);
+               if (ha->cregbase)
+                       iounmap(ha->cregbase);
        }
        pci_release_selected_regions(ha->pdev, ha->bars);
        kfree(ha);
@@ -2960,6 +3077,9 @@ qla2x00_remove_one(struct pci_dev *pdev)
                if (ha->iobase)
                        iounmap(ha->iobase);
 
+               if (ha->cregbase)
+                       iounmap(ha->cregbase);
+
                if (ha->mqiobase)
                        iounmap(ha->mqiobase);
 
@@ -3068,6 +3188,12 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
 void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
     int do_login, int defer)
 {
+       if (IS_QLAFX00(vha->hw)) {
+               qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
+               qla2x00_schedule_rport_del(vha, fcport, defer);
+               return;
+       }
+
        if (atomic_read(&fcport->state) == FCS_ONLINE &&
            vha->vp_idx == fcport->vha->vp_idx) {
                qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
@@ -3710,6 +3836,22 @@ qla2x00_uevent_emit(struct scsi_qla_host *vha, u32 code)
        kobject_uevent_env(&vha->hw->pdev->dev.kobj, KOBJ_CHANGE, envp);
 }
 
+int
+qlafx00_post_aenfx_work(struct scsi_qla_host *vha,  uint32_t evtcode,
+                       uint32_t *data, int cnt)
+{
+       struct qla_work_evt *e;
+
+       e = qla2x00_alloc_work(vha, QLA_EVT_AENFX);
+       if (!e)
+               return QLA_FUNCTION_FAILED;
+
+       e->u.aenfx.evtcode = evtcode;
+       e->u.aenfx.count = cnt;
+       memcpy(e->u.aenfx.mbx, data, sizeof(*data) * cnt);
+       return qla2x00_post_work(vha, e);
+}
+
 void
 qla2x00_do_work(struct scsi_qla_host *vha)
 {
@@ -3758,6 +3900,9 @@ qla2x00_do_work(struct scsi_qla_host *vha)
                case QLA_EVT_UEVENT:
                        qla2x00_uevent_emit(vha, e->u.uevent.code);
                        break;
+               case QLA_EVT_AENFX:
+                       qlafx00_process_aen(vha, e);
+                       break;
                }
                if (e->flags & QLA_EVT_FLAG_FREE)
                        kfree(e);
@@ -4592,6 +4737,38 @@ qla2x00_do_dpc(void *data)
                                ql_dbg(ql_dbg_dpc, base_vha, 0x4006,
                                    "FCoE context reset end.\n");
                        }
+               } else if (IS_QLAFX00(ha)) {
+                       if (test_and_clear_bit(ISP_UNRECOVERABLE,
+                               &base_vha->dpc_flags)) {
+                               ql_dbg(ql_dbg_dpc, base_vha, 0x4020,
+                                   "Firmware Reset Recovery\n");
+                               if (qlafx00_reset_initialize(base_vha)) {
+                                       /* Failed. Abort isp later. */
+                                       if (!test_bit(UNLOADING,
+                                           &base_vha->dpc_flags))
+                                               set_bit(ISP_UNRECOVERABLE,
+                                                   &base_vha->dpc_flags);
+                                               ql_dbg(ql_dbg_dpc, base_vha,
+                                                   0x4021,
+                                                   "Reset Recovery Failed\n");
+                               }
+                       }
+
+                       if (test_and_clear_bit(FX00_TARGET_SCAN,
+                               &base_vha->dpc_flags)) {
+                               ql_dbg(ql_dbg_dpc, base_vha, 0x4022,
+                                   "ISPFx00 Target Scan scheduled\n");
+                               if (qlafx00_rescan_isp(base_vha)) {
+                                       if (!test_bit(UNLOADING,
+                                           &base_vha->dpc_flags))
+                                               set_bit(ISP_UNRECOVERABLE,
+                                                   &base_vha->dpc_flags);
+                                       ql_dbg(ql_dbg_dpc, base_vha, 0x401e,
+                                           "ISPFx00 Target Scan Failed\n");
+                               }
+                               ql_dbg(ql_dbg_dpc, base_vha, 0x401f,
+                                   "ISPFx00 Target Scan End\n");
+                       }
                }
 
                if (test_and_clear_bit(ISP_ABORT_NEEDED,
@@ -4630,6 +4807,9 @@ qla2x00_do_dpc(void *data)
                        clear_bit(SCR_PENDING, &base_vha->dpc_flags);
                }
 
+               if (IS_QLAFX00(ha))
+                       goto loop_resync_check;
+
                if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) {
                        ql_dbg(ql_dbg_dpc, base_vha, 0x4009,
                            "Quiescence mode scheduled.\n");
@@ -4654,7 +4834,7 @@ qla2x00_do_dpc(void *data)
                }
 
                if (test_and_clear_bit(RESET_MARKER_NEEDED,
-                                                       &base_vha->dpc_flags) &&
+                               &base_vha->dpc_flags) &&
                    (!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) {
 
                        ql_dbg(ql_dbg_dpc, base_vha, 0x400b,
@@ -4677,9 +4857,9 @@ qla2x00_do_dpc(void *data)
                        ql_dbg(ql_dbg_dpc, base_vha, 0x400e,
                            "Relogin end.\n");
                }
-
+loop_resync_check:
                if (test_and_clear_bit(LOOP_RESYNC_NEEDED,
-                                                       &base_vha->dpc_flags)) {
+                   &base_vha->dpc_flags)) {
 
                        ql_dbg(ql_dbg_dpc, base_vha, 0x400f,
                            "Loop resync scheduled.\n");
@@ -4697,6 +4877,9 @@ qla2x00_do_dpc(void *data)
                            "Loop resync end.\n");
                }
 
+               if (IS_QLAFX00(ha))
+                       goto intr_on_check;
+
                if (test_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags) &&
                    atomic_read(&base_vha->loop_state) == LOOP_READY) {
                        clear_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags);
@@ -4714,7 +4897,7 @@ qla2x00_do_dpc(void *data)
                if (test_and_clear_bit(HOST_RAMP_UP_QUEUE_DEPTH,
                    &base_vha->dpc_flags))
                        qla2x00_host_ramp_up_queuedepth(base_vha);
-
+intr_on_check:
                if (!ha->interrupts_on)
                        ha->isp_ops->enable_intrs(ha);
 
@@ -4722,7 +4905,8 @@ qla2x00_do_dpc(void *data)
                                        &base_vha->dpc_flags))
                        ha->isp_ops->beacon_blink(base_vha);
 
-               qla2x00_do_dpc_all_vps(base_vha);
+               if (!IS_QLAFX00(ha))
+                       qla2x00_do_dpc_all_vps(base_vha);
 
                ha->dpc_active = 0;
 end_loop:
@@ -4818,6 +5002,9 @@ qla2x00_timer(scsi_qla_host_t *vha)
                qla82xx_watchdog(vha);
        }
 
+       if (!vha->vp_idx && IS_QLAFX00(ha))
+               qlafx00_timer_routine(vha);
+
        /* Loop down handler. */
        if (atomic_read(&vha->loop_down_timer) > 0 &&
            !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) &&
@@ -5335,6 +5522,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8001) },
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8021) },
        { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8031) },
+       { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISPF001) },
        { 0 },
 };
 MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
This page took 0.034034 seconds and 5 git commands to generate.