]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/qla2xxx/qla_os.c
Merge branch 'omap-pool'
[linux-2.6-omap-h63xx.git] / drivers / scsi / qla2xxx / qla_os.c
index 3ddfa889e94936205cb145278302b9ad144cd7c3..e4fdcdad80d0b7c12c1be44b0eb75a834ef37d49 100644 (file)
@@ -104,9 +104,7 @@ static int qla2xxx_slave_alloc(struct scsi_device *);
 static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time);
 static void qla2xxx_scan_start(struct Scsi_Host *);
 static void qla2xxx_slave_destroy(struct scsi_device *);
-static int qla2x00_queuecommand(struct scsi_cmnd *cmd,
-               void (*fn)(struct scsi_cmnd *));
-static int qla24xx_queuecommand(struct scsi_cmnd *cmd,
+static int qla2xxx_queuecommand(struct scsi_cmnd *cmd,
                void (*fn)(struct scsi_cmnd *));
 static int qla2xxx_eh_abort(struct scsi_cmnd *);
 static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
@@ -117,42 +115,10 @@ static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
 static int qla2x00_change_queue_depth(struct scsi_device *, int);
 static int qla2x00_change_queue_type(struct scsi_device *, int);
 
-static struct scsi_host_template qla2x00_driver_template = {
+struct scsi_host_template qla2xxx_driver_template = {
        .module                 = THIS_MODULE,
        .name                   = QLA2XXX_DRIVER_NAME,
-       .queuecommand           = qla2x00_queuecommand,
-
-       .eh_abort_handler       = qla2xxx_eh_abort,
-       .eh_device_reset_handler = qla2xxx_eh_device_reset,
-       .eh_target_reset_handler = qla2xxx_eh_target_reset,
-       .eh_bus_reset_handler   = qla2xxx_eh_bus_reset,
-       .eh_host_reset_handler  = qla2xxx_eh_host_reset,
-
-       .slave_configure        = qla2xxx_slave_configure,
-
-       .slave_alloc            = qla2xxx_slave_alloc,
-       .slave_destroy          = qla2xxx_slave_destroy,
-       .scan_finished          = qla2xxx_scan_finished,
-       .scan_start             = qla2xxx_scan_start,
-       .change_queue_depth     = qla2x00_change_queue_depth,
-       .change_queue_type      = qla2x00_change_queue_type,
-       .this_id                = -1,
-       .cmd_per_lun            = 3,
-       .use_clustering         = ENABLE_CLUSTERING,
-       .sg_tablesize           = SG_ALL,
-
-       /*
-        * The RISC allows for each command to transfer (2^32-1) bytes of data,
-        * which equates to 0x800000 sectors.
-        */
-       .max_sectors            = 0xFFFF,
-       .shost_attrs            = qla2x00_host_attrs,
-};
-
-struct scsi_host_template qla24xx_driver_template = {
-       .module                 = THIS_MODULE,
-       .name                   = QLA2XXX_DRIVER_NAME,
-       .queuecommand           = qla24xx_queuecommand,
+       .queuecommand           = qla2xxx_queuecommand,
 
        .eh_abort_handler       = qla2xxx_eh_abort,
        .eh_device_reset_handler = qla2xxx_eh_device_reset,
@@ -430,73 +396,7 @@ qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
 }
 
 static int
-qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
-{
-       scsi_qla_host_t *vha = shost_priv(cmd->device->host);
-       fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
-       struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
-       struct qla_hw_data *ha = vha->hw;
-       srb_t *sp;
-       int rval;
-
-       if (unlikely(pci_channel_offline(ha->pdev))) {
-               cmd->result = DID_REQUEUE << 16;
-               goto qc_fail_command;
-       }
-
-       rval = fc_remote_port_chkready(rport);
-       if (rval) {
-               cmd->result = rval;
-               goto qc_fail_command;
-       }
-
-       /* Close window on fcport/rport state-transitioning. */
-       if (fcport->drport)
-               goto qc_target_busy;
-
-       if (atomic_read(&fcport->state) != FCS_ONLINE) {
-               if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
-                   atomic_read(&vha->loop_state) == LOOP_DEAD) {
-                       cmd->result = DID_NO_CONNECT << 16;
-                       goto qc_fail_command;
-               }
-               goto qc_target_busy;
-       }
-
-       spin_unlock_irq(vha->host->host_lock);
-
-       sp = qla2x00_get_new_sp(vha, fcport, cmd, done);
-       if (!sp)
-               goto qc_host_busy_lock;
-
-       rval = ha->isp_ops->start_scsi(sp);
-       if (rval != QLA_SUCCESS)
-               goto qc_host_busy_free_sp;
-
-       spin_lock_irq(vha->host->host_lock);
-
-       return 0;
-
-qc_host_busy_free_sp:
-       qla2x00_sp_free_dma(sp);
-       mempool_free(sp, ha->srb_mempool);
-
-qc_host_busy_lock:
-       spin_lock_irq(vha->host->host_lock);
-       return SCSI_MLQUEUE_HOST_BUSY;
-
-qc_target_busy:
-       return SCSI_MLQUEUE_TARGET_BUSY;
-
-qc_fail_command:
-       done(cmd);
-
-       return 0;
-}
-
-
-static int
-qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
        scsi_qla_host_t *vha = shost_priv(cmd->device->host);
        fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
@@ -507,7 +407,10 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
        int rval;
 
        if (unlikely(pci_channel_offline(ha->pdev))) {
-               cmd->result = DID_REQUEUE << 16;
+               if (ha->pdev->error_state == pci_channel_io_frozen)
+                       cmd->result = DID_REQUEUE << 16;
+               else
+                       cmd->result = DID_NO_CONNECT << 16;
                goto qc24_fail_command;
        }
 
@@ -635,6 +538,34 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
        return (return_status);
 }
 
+int
+qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha)
+{
+       int             return_status;
+       unsigned long   wait_reset;
+       struct qla_hw_data *ha = vha->hw;
+       scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
+
+       wait_reset = jiffies + (MAX_LOOP_TIMEOUT * HZ);
+       while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) ||
+           test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
+           test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
+           ha->dpc_active) && time_before(jiffies, wait_reset)) {
+
+               msleep(1000);
+
+               if (!test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags) &&
+                   ha->flags.chip_reset_done)
+                       break;
+       }
+       if (ha->flags.chip_reset_done)
+               return_status = QLA_SUCCESS;
+       else
+               return_status = QLA_FUNCTION_FAILED;
+
+       return return_status;
+}
+
 /*
  * qla2x00_wait_for_loop_ready
  *    Wait for MAX_LOOP_TIMEOUT(5 min) value for loop
@@ -1163,7 +1094,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
                        continue;
                for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
                        sp = req->outstanding_cmds[cnt];
-                       if (sp && sp->fcport->vha == vha) {
+                       if (sp) {
                                req->outstanding_cmds[cnt] = NULL;
                                sp->cmd->result = res;
                                qla2x00_sp_compl(ha, sp);
@@ -1245,10 +1176,10 @@ qla2x00_config_dma_addressing(struct qla_hw_data *ha)
        /* Assume a 32bit DMA mask. */
        ha->flags.enable_64bit_addressing = 0;
 
-       if (!dma_set_mask(&ha->pdev->dev, DMA_64BIT_MASK)) {
+       if (!dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(64))) {
                /* Any upper-dword bits set? */
                if (MSD(dma_get_required_mask(&ha->pdev->dev)) &&
-                   !pci_set_consistent_dma_mask(ha->pdev, DMA_64BIT_MASK)) {
+                   !pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(64))) {
                        /* Ok, a 64bit DMA mask is applicable. */
                        ha->flags.enable_64bit_addressing = 1;
                        ha->isp_ops->calc_req_entries = qla2x00_calc_iocbs_64;
@@ -1257,8 +1188,8 @@ qla2x00_config_dma_addressing(struct qla_hw_data *ha)
                }
        }
 
-       dma_set_mask(&ha->pdev->dev, DMA_32BIT_MASK);
-       pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK);
+       dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(32));
+       pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(32));
 }
 
 static void
@@ -1351,9 +1282,6 @@ static struct isp_operations qla2100_isp_ops = {
        .write_optrom           = qla2x00_write_optrom_data,
        .get_flash_version      = qla2x00_get_flash_version,
        .start_scsi             = qla2x00_start_scsi,
-       .wrt_req_reg            = NULL,
-       .wrt_rsp_reg            = NULL,
-       .rd_req_reg             = NULL,
 };
 
 static struct isp_operations qla2300_isp_ops = {
@@ -1389,9 +1317,6 @@ static struct isp_operations qla2300_isp_ops = {
        .write_optrom           = qla2x00_write_optrom_data,
        .get_flash_version      = qla2x00_get_flash_version,
        .start_scsi             = qla2x00_start_scsi,
-       .wrt_req_reg            = NULL,
-       .wrt_rsp_reg            = NULL,
-       .rd_req_reg             = NULL,
 };
 
 static struct isp_operations qla24xx_isp_ops = {
@@ -1427,9 +1352,6 @@ static struct isp_operations qla24xx_isp_ops = {
        .write_optrom           = qla24xx_write_optrom_data,
        .get_flash_version      = qla24xx_get_flash_version,
        .start_scsi             = qla24xx_start_scsi,
-       .wrt_req_reg            = qla24xx_wrt_req_reg,
-       .wrt_rsp_reg            = qla24xx_wrt_rsp_reg,
-       .rd_req_reg             = qla24xx_rd_req_reg,
 };
 
 static struct isp_operations qla25xx_isp_ops = {
@@ -1465,9 +1387,6 @@ static struct isp_operations qla25xx_isp_ops = {
        .write_optrom           = qla24xx_write_optrom_data,
        .get_flash_version      = qla24xx_get_flash_version,
        .start_scsi             = qla24xx_start_scsi,
-       .wrt_req_reg            = qla24xx_wrt_req_reg,
-       .wrt_rsp_reg            = qla24xx_wrt_rsp_reg,
-       .rd_req_reg             = qla24xx_rd_req_reg,
 };
 
 static struct isp_operations qla81xx_isp_ops = {
@@ -1493,8 +1412,8 @@ static struct isp_operations qla81xx_isp_ops = {
        .build_iocbs            = NULL,
        .prep_ms_iocb           = qla24xx_prep_ms_iocb,
        .prep_ms_fdmi_iocb      = qla24xx_prep_ms_fdmi_iocb,
-       .read_nvram             = qla25xx_read_nvram_data,
-       .write_nvram            = qla25xx_write_nvram_data,
+       .read_nvram             = NULL,
+       .write_nvram            = NULL,
        .fw_dump                = qla81xx_fw_dump,
        .beacon_on              = qla24xx_beacon_on,
        .beacon_off             = qla24xx_beacon_off,
@@ -1503,9 +1422,6 @@ static struct isp_operations qla81xx_isp_ops = {
        .write_optrom           = qla24xx_write_optrom_data,
        .get_flash_version      = qla24xx_get_flash_version,
        .start_scsi             = qla24xx_start_scsi,
-       .wrt_req_reg            = qla24xx_wrt_req_reg,
-       .wrt_rsp_reg            = qla24xx_wrt_rsp_reg,
-       .rd_req_reg             = qla24xx_rd_req_reg,
 };
 
 static inline void
@@ -1727,7 +1643,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        struct rsp_que *rsp = NULL;
 
        bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
-       sht = &qla2x00_driver_template;
+       sht = &qla2xxx_driver_template;
        if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8432 ||
@@ -1736,7 +1652,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532 ||
            pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001) {
                bars = pci_select_bars(pdev, IORESOURCE_MEM);
-               sht = &qla24xx_driver_template;
                mem_only = 1;
        }
 
@@ -1927,10 +1842,16 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        ha->rsp_q_map[0] = rsp;
        ha->req_q_map[0] = req;
 
+       /* FWI2-capable only. */
+       req->req_q_in = &ha->iobase->isp24.req_q_in;
+       req->req_q_out = &ha->iobase->isp24.req_q_out;
+       rsp->rsp_q_in = &ha->iobase->isp24.rsp_q_in;
+       rsp->rsp_q_out = &ha->iobase->isp24.rsp_q_out;
        if (ha->mqenable) {
-               ha->isp_ops->wrt_req_reg = qla25xx_wrt_req_reg;
-               ha->isp_ops->wrt_rsp_reg = qla25xx_wrt_rsp_reg;
-               ha->isp_ops->rd_req_reg = qla25xx_rd_req_reg;
+               req->req_q_in = &ha->mqiobase->isp25mq.req_q_in;
+               req->req_q_out = &ha->mqiobase->isp25mq.req_q_out;
+               rsp->rsp_q_in = &ha->mqiobase->isp25mq.rsp_q_in;
+               rsp->rsp_q_out =  &ha->mqiobase->isp25mq.rsp_q_out;
        }
 
        if (qla2x00_initialize_adapter(base_vha)) {
@@ -2000,6 +1921,16 @@ probe_init_failed:
        ha->max_queues = 0;
 
 probe_failed:
+       if (base_vha->timer_active)
+               qla2x00_stop_timer(base_vha);
+       base_vha->flags.online = 0;
+       if (ha->dpc_thread) {
+               struct task_struct *t = ha->dpc_thread;
+
+               ha->dpc_thread = NULL;
+               kthread_stop(t);
+       }
+
        qla2x00_free_device(base_vha);
 
        scsi_host_put(base_vha->host);
@@ -2033,10 +1964,30 @@ qla2x00_remove_one(struct pci_dev *pdev)
 
        set_bit(UNLOADING, &base_vha->dpc_flags);
 
+       qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
+
        qla2x00_dfs_remove(base_vha);
 
        qla84xx_put_chip(base_vha);
 
+       /* Disable timer */
+       if (base_vha->timer_active)
+               qla2x00_stop_timer(base_vha);
+
+       base_vha->flags.online = 0;
+
+       /* Kill the kernel thread for this host */
+       if (ha->dpc_thread) {
+               struct task_struct *t = ha->dpc_thread;
+
+               /*
+                * qla2xxx_wake_dpc checks for ->dpc_thread
+                * so we need to zero it out.
+                */
+               ha->dpc_thread = NULL;
+               kthread_stop(t);
+       }
+
        qla2x00_free_sysfs_attr(base_vha);
 
        fc_remove_host(base_vha->host);
@@ -2065,25 +2016,6 @@ static void
 qla2x00_free_device(scsi_qla_host_t *vha)
 {
        struct qla_hw_data *ha = vha->hw;
-       qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
-
-       /* Disable timer */
-       if (vha->timer_active)
-               qla2x00_stop_timer(vha);
-
-       vha->flags.online = 0;
-
-       /* Kill the kernel thread for this host */
-       if (ha->dpc_thread) {
-               struct task_struct *t = ha->dpc_thread;
-
-               /*
-                * qla2xxx_wake_dpc checks for ->dpc_thread
-                * so we need to zero it out.
-                */
-               ha->dpc_thread = NULL;
-               kthread_stop(t);
-       }
 
        if (ha->flags.fce_enabled)
                qla2x00_disable_fce_trace(vha, NULL, NULL);
@@ -2313,9 +2245,19 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
        } else
                ha->npiv_info = NULL;
 
+       /* Get consistent memory allocated for EX-INIT-CB. */
+       if (IS_QLA81XX(ha)) {
+               ha->ex_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
+                   &ha->ex_init_cb_dma);
+               if (!ha->ex_init_cb)
+                       goto fail_ex_init_cb;
+       }
+
        INIT_LIST_HEAD(&ha->vp_list);
        return 1;
 
+fail_ex_init_cb:
+       kfree(ha->npiv_info);
 fail_npiv_info:
        dma_free_coherent(&ha->pdev->dev, ((*rsp)->length + 1) *
                sizeof(response_t), (*rsp)->ring, (*rsp)->dma);
@@ -2398,18 +2340,22 @@ qla2x00_mem_free(struct qla_hw_data *ha)
        if (ha->sfp_data)
                dma_pool_free(ha->s_dma_pool, ha->sfp_data, ha->sfp_data_dma);
 
+       if (ha->edc_data)
+               dma_pool_free(ha->s_dma_pool, ha->edc_data, ha->edc_data_dma);
+
        if (ha->ms_iocb)
                dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
 
+       if (ha->ex_init_cb)
+               dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma);
+
        if (ha->s_dma_pool)
                dma_pool_destroy(ha->s_dma_pool);
 
-
        if (ha->gid_list)
                dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list,
                ha->gid_list_dma);
 
-
        if (ha->init_cb)
                dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
                ha->init_cb, ha->init_cb_dma);
@@ -2428,6 +2374,8 @@ qla2x00_mem_free(struct qla_hw_data *ha)
        ha->ms_iocb_dma = 0;
        ha->init_cb = NULL;
        ha->init_cb_dma = 0;
+       ha->ex_init_cb = NULL;
+       ha->ex_init_cb_dma = 0;
 
        ha->s_dma_pool = NULL;
 
@@ -2914,19 +2862,11 @@ qla2x00_timer(scsi_qla_host_t *vha)
                                spin_unlock_irqrestore(&ha->hardware_lock,
                                                                cpu_flags);
                        }
-                       set_bit(ABORT_QUEUES_NEEDED, &vha->dpc_flags);
                        start_dpc++;
                }
 
                /* if the loop has been down for 4 minutes, reinit adapter */
                if (atomic_dec_and_test(&vha->loop_down_timer) != 0) {
-                       DEBUG(printk("scsi(%ld): Loop down exceed 4 mins - "
-                           "restarting queues.\n",
-                           vha->host_no));
-
-                       set_bit(RESTART_QUEUES_NEEDED, &vha->dpc_flags);
-                       start_dpc++;
-
                        if (!(vha->device_flags & DFLG_NO_CABLE) &&
                            !vha->vp_idx) {
                                DEBUG(printk("scsi(%ld): Loop down - "
@@ -3053,6 +2993,8 @@ qla2x00_release_firmware(void)
 static pci_ers_result_t
 qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
 {
+       scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
+
        switch (state) {
        case pci_channel_io_normal:
                return PCI_ERS_RESULT_CAN_RECOVER;
@@ -3060,7 +3002,7 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
                pci_disable_device(pdev);
                return PCI_ERS_RESULT_NEED_RESET;
        case pci_channel_io_perm_failure:
-               qla2x00_remove_one(pdev);
+               qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
                return PCI_ERS_RESULT_DISCONNECT;
        }
        return PCI_ERS_RESULT_NEED_RESET;