📄 qla_os.c
字号:
/* Abort Target command will clear Reservation */ return ha->isp_ops.abort_target(reset_fcport);}static intqla2xxx_slave_alloc(struct scsi_device *sdev){ struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); if (!rport || fc_remote_port_chkready(rport)) return -ENXIO; sdev->hostdata = *(fc_port_t **)rport->dd_data; return 0;}static intqla2xxx_slave_configure(struct scsi_device *sdev){ scsi_qla_host_t *ha = to_qla_host(sdev->host); struct fc_rport *rport = starget_to_rport(sdev->sdev_target); if (sdev->tagged_supported) scsi_activate_tcq(sdev, 32); else scsi_deactivate_tcq(sdev, 32); rport->dev_loss_tmo = ha->port_down_retry_count + 5; return 0;}static voidqla2xxx_slave_destroy(struct scsi_device *sdev){ sdev->hostdata = NULL;}static intqla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth){ scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); return sdev->queue_depth;}static intqla2x00_change_queue_type(struct scsi_device *sdev, int tag_type){ if (sdev->tagged_supported) { scsi_set_tag_type(sdev, tag_type); if (tag_type) scsi_activate_tcq(sdev, sdev->queue_depth); else scsi_deactivate_tcq(sdev, sdev->queue_depth); } else tag_type = 0; return tag_type;}/** * qla2x00_config_dma_addressing() - Configure OS DMA addressing method. * @ha: HA context * * At exit, the @ha's flags.enable_64bit_addressing set to indicated * supported addressing method. */static voidqla2x00_config_dma_addressing(scsi_qla_host_t *ha){ /* Assume a 32bit DMA mask. */ ha->flags.enable_64bit_addressing = 0; if (!dma_set_mask(&ha->pdev->dev, DMA_64BIT_MASK)) { /* Any upper-dword bits set? */ if (MSD(dma_get_required_mask(&ha->pdev->dev)) && !pci_set_consistent_dma_mask(ha->pdev, DMA_64BIT_MASK)) { /* Ok, a 64bit DMA mask is applicable. */ ha->flags.enable_64bit_addressing = 1; ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_64; ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_64; return; } } dma_set_mask(&ha->pdev->dev, DMA_32BIT_MASK); pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK);}static intqla2x00_iospace_config(scsi_qla_host_t *ha){ unsigned long pio, pio_len, pio_flags; unsigned long mmio, mmio_len, mmio_flags; /* We only need PIO for Flash operations on ISP2312 v2 chips. */ pio = pci_resource_start(ha->pdev, 0); pio_len = pci_resource_len(ha->pdev, 0); pio_flags = pci_resource_flags(ha->pdev, 0); if (pio_flags & IORESOURCE_IO) { if (pio_len < MIN_IOBASE_LEN) { qla_printk(KERN_WARNING, ha, "Invalid PCI I/O region size (%s)...\n", pci_name(ha->pdev)); pio = 0; } } else { qla_printk(KERN_WARNING, ha, "region #0 not a PIO resource (%s)...\n", pci_name(ha->pdev)); pio = 0; } /* Use MMIO operations for all accesses. */ mmio = pci_resource_start(ha->pdev, 1); mmio_len = pci_resource_len(ha->pdev, 1); mmio_flags = pci_resource_flags(ha->pdev, 1); if (!(mmio_flags & IORESOURCE_MEM)) { qla_printk(KERN_ERR, ha, "region #0 not an MMIO resource (%s), aborting\n", pci_name(ha->pdev)); goto iospace_error_exit; } if (mmio_len < MIN_IOBASE_LEN) { qla_printk(KERN_ERR, ha, "Invalid PCI mem region size (%s), aborting\n", pci_name(ha->pdev)); goto iospace_error_exit; } if (pci_request_regions(ha->pdev, ha->brd_info->drv_name)) { qla_printk(KERN_WARNING, ha, "Failed to reserve PIO/MMIO regions (%s)\n", pci_name(ha->pdev)); goto iospace_error_exit; } ha->pio_address = pio; ha->pio_length = pio_len; ha->iobase = ioremap(mmio, MIN_IOBASE_LEN); if (!ha->iobase) { qla_printk(KERN_ERR, ha, "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev)); goto iospace_error_exit; } return (0);iospace_error_exit: return (-ENOMEM);}static voidqla2x00_enable_intrs(scsi_qla_host_t *ha){ unsigned long flags = 0; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; spin_lock_irqsave(&ha->hardware_lock, flags); ha->interrupts_on = 1; /* enable risc and host interrupts */ WRT_REG_WORD(®->ictrl, ICR_EN_INT | ICR_EN_RISC); RD_REG_WORD(®->ictrl); spin_unlock_irqrestore(&ha->hardware_lock, flags);}static voidqla2x00_disable_intrs(scsi_qla_host_t *ha){ unsigned long flags = 0; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; spin_lock_irqsave(&ha->hardware_lock, flags); ha->interrupts_on = 0; /* disable risc and host interrupts */ WRT_REG_WORD(®->ictrl, 0); RD_REG_WORD(®->ictrl); spin_unlock_irqrestore(&ha->hardware_lock, flags);}static voidqla24xx_enable_intrs(scsi_qla_host_t *ha){ unsigned long flags = 0; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; spin_lock_irqsave(&ha->hardware_lock, flags); ha->interrupts_on = 1; WRT_REG_DWORD(®->ictrl, ICRX_EN_RISC_INT); RD_REG_DWORD(®->ictrl); spin_unlock_irqrestore(&ha->hardware_lock, flags);}static voidqla24xx_disable_intrs(scsi_qla_host_t *ha){ unsigned long flags = 0; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; spin_lock_irqsave(&ha->hardware_lock, flags); ha->interrupts_on = 0; WRT_REG_DWORD(®->ictrl, 0); RD_REG_DWORD(®->ictrl); spin_unlock_irqrestore(&ha->hardware_lock, flags);}/* * PCI driver interface */int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info){ int ret = -ENODEV; device_reg_t __iomem *reg; struct Scsi_Host *host; scsi_qla_host_t *ha; unsigned long flags = 0; unsigned long wait_switch = 0; char pci_info[20]; char fw_str[30]; fc_port_t *fcport; if (pci_enable_device(pdev)) goto probe_out; host = scsi_host_alloc(brd_info->sht ? brd_info->sht: &qla2x00_driver_template, sizeof(scsi_qla_host_t)); if (host == NULL) { printk(KERN_WARNING "qla2xxx: Couldn't allocate host from scsi layer!\n"); goto probe_disable_device; } /* Clear our data area */ ha = (scsi_qla_host_t *)host->hostdata; memset(ha, 0, sizeof(scsi_qla_host_t)); ha->pdev = pdev; ha->host = host; ha->host_no = host->host_no; ha->brd_info = brd_info; sprintf(ha->host_str, "%s_%ld", ha->brd_info->drv_name, ha->host_no); ha->dpc_pid = -1; /* Configure PCI I/O space */ ret = qla2x00_iospace_config(ha); if (ret) goto probe_failed; qla_printk(KERN_INFO, ha, "Found an %s, irq %d, iobase 0x%p\n", ha->brd_info->isp_name, pdev->irq, ha->iobase); spin_lock_init(&ha->hardware_lock); ha->prev_topology = 0; ha->ports = MAX_BUSES; ha->init_cb_size = sizeof(init_cb_t); ha->mgmt_svr_loop_id = MANAGEMENT_SERVER; /* Assign ISP specific operations. */ ha->isp_ops.pci_config = qla2100_pci_config; ha->isp_ops.reset_chip = qla2x00_reset_chip; ha->isp_ops.chip_diag = qla2x00_chip_diag; ha->isp_ops.config_rings = qla2x00_config_rings; ha->isp_ops.reset_adapter = qla2x00_reset_adapter; ha->isp_ops.nvram_config = qla2x00_nvram_config; ha->isp_ops.update_fw_options = qla2x00_update_fw_options; ha->isp_ops.load_risc = qla2x00_load_risc; ha->isp_ops.pci_info_str = qla2x00_pci_info_str; ha->isp_ops.fw_version_str = qla2x00_fw_version_str; ha->isp_ops.intr_handler = qla2100_intr_handler; ha->isp_ops.enable_intrs = qla2x00_enable_intrs; ha->isp_ops.disable_intrs = qla2x00_disable_intrs; ha->isp_ops.abort_command = qla2x00_abort_command; ha->isp_ops.abort_target = qla2x00_abort_target; ha->isp_ops.fabric_login = qla2x00_login_fabric; ha->isp_ops.fabric_logout = qla2x00_fabric_logout; ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_32; ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_32; ha->isp_ops.prep_ms_iocb = qla2x00_prep_ms_iocb; ha->isp_ops.prep_ms_fdmi_iocb = qla2x00_prep_ms_fdmi_iocb; ha->isp_ops.read_nvram = qla2x00_read_nvram_data; ha->isp_ops.write_nvram = qla2x00_write_nvram_data; ha->isp_ops.fw_dump = qla2100_fw_dump; ha->isp_ops.ascii_fw_dump = qla2100_ascii_fw_dump; if (IS_QLA2100(ha)) { host->max_id = MAX_TARGETS_2100; ha->mbx_count = MAILBOX_REGISTER_COUNT_2100; ha->request_q_length = REQUEST_ENTRY_CNT_2100; ha->response_q_length = RESPONSE_ENTRY_CNT_2100; ha->last_loop_id = SNS_LAST_LOOP_ID_2100; host->sg_tablesize = 32; ha->gid_list_info_size = 4; } else if (IS_QLA2200(ha)) { host->max_id = MAX_TARGETS_2200; ha->mbx_count = MAILBOX_REGISTER_COUNT; ha->request_q_length = REQUEST_ENTRY_CNT_2200; ha->response_q_length = RESPONSE_ENTRY_CNT_2100; ha->last_loop_id = SNS_LAST_LOOP_ID_2100; ha->gid_list_info_size = 4; } else if (IS_QLA23XX(ha)) { host->max_id = MAX_TARGETS_2200; ha->mbx_count = MAILBOX_REGISTER_COUNT; ha->request_q_length = REQUEST_ENTRY_CNT_2200; ha->response_q_length = RESPONSE_ENTRY_CNT_2300; ha->last_loop_id = SNS_LAST_LOOP_ID_2300; ha->isp_ops.pci_config = qla2300_pci_config; ha->isp_ops.intr_handler = qla2300_intr_handler; ha->isp_ops.fw_dump = qla2300_fw_dump; ha->isp_ops.ascii_fw_dump = qla2300_ascii_fw_dump; ha->gid_list_info_size = 6; } else if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { host->max_id = MAX_TARGETS_2200; ha->mbx_count = MAILBOX_REGISTER_COUNT; ha->request_q_length = REQUEST_ENTRY_CNT_24XX; ha->response_q_length = RESPONSE_ENTRY_CNT_2300; ha->last_loop_id = SNS_LAST_LOOP_ID_2300; ha->init_cb_size = sizeof(struct init_cb_24xx); ha->mgmt_svr_loop_id = 10; ha->isp_ops.pci_config = qla24xx_pci_config; ha->isp_ops.reset_chip = qla24xx_reset_chip; ha->isp_ops.chip_diag = qla24xx_chip_diag; ha->isp_ops.config_rings = qla24xx_config_rings; ha->isp_ops.reset_adapter = qla24xx_reset_adapter; ha->isp_ops.nvram_config = qla24xx_nvram_config; ha->isp_ops.update_fw_options = qla24xx_update_fw_options; ha->isp_ops.load_risc = qla24xx_load_risc_flash; if (ql2xfwloadbin) ha->isp_ops.load_risc = qla24xx_load_risc_hotplug; ha->isp_ops.pci_info_str = qla24xx_pci_info_str; ha->isp_ops.fw_version_str = qla24xx_fw_version_str; ha->isp_ops.intr_handler = qla24xx_intr_handler; ha->isp_ops.enable_intrs = qla24xx_enable_intrs; ha->isp_ops.disable_intrs = qla24xx_disable_intrs; ha->isp_ops.abort_command = qla24xx_abort_command; ha->isp_ops.abort_target = qla24xx_abort_target; ha->isp_ops.fabric_login = qla24xx_login_fabric; ha->isp_ops.fabric_logout = qla24xx_fabric_logout; ha->isp_ops.prep_ms_iocb = qla24xx_prep_ms_iocb; ha->isp_ops.prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb; ha->isp_ops.read_nvram = qla24xx_read_nvram_data; ha->isp_ops.write_nvram = qla24xx_write_nvram_data; ha->isp_ops.fw_dump = qla24xx_fw_dump; ha->isp_ops.ascii_fw_dump = qla24xx_ascii_fw_dump; ha->gid_list_info_size = 8; } host->can_queue = ha->request_q_length + 128; /* load the F/W, read paramaters, and init the H/W */ ha->instance = num_hosts; init_MUTEX(&ha->mbx_cmd_sem); init_MUTEX_LOCKED(&ha->mbx_intr_sem); INIT_LIST_HEAD(&ha->list); INIT_LIST_HEAD(&ha->fcports); INIT_LIST_HEAD(&ha->rscn_fcports); /* * These locks are used to prevent more than one CPU * from modifying the queue at the same time. The * higher level "host_lock" will reduce most * contention for these locks. */ spin_lock_init(&ha->mbx_reg_lock); init_completion(&ha->dpc_inited); init_completion(&ha->dpc_exited); qla2x00_config_dma_addressing(ha); if (qla2x00_mem_alloc(ha)) { qla_printk(KERN_WARNING, ha, "[ERROR] Failed to allocate memory for adapter\n"); ret = -ENOMEM; goto probe_failed; } if (qla2x00_initialize_adapter(ha) && !(ha->device_flags & DFLG_NO_CABLE)) { qla_printk(KERN_WARNING, ha, "Failed to initialize adapter\n"); DEBUG2(printk("scsi(%ld): Failed to initialize adapter - " "Adapter flags %x.\n", ha->host_no, ha->device_flags)); ret = -ENODEV; goto probe_failed; } /* * Startup the kernel thread for this host adapter */ ha->dpc_should_die = 0; ha->dpc_pid = kernel_thread(qla2x00_do_dpc, ha, 0); if (ha->dpc_pid < 0) { qla_printk(KERN_WARNING, ha, "Unable to start DPC thread!\n"); ret = -ENODEV; goto probe_failed; } wait_for_completion(&ha->dpc_inited); host->this_id = 255; host->cmd_per_lun = 3; host->unique_id = ha->instance; host->max_cmd_len = MAX_CMDSZ; host->max_channel = ha->ports - 1; host->max_lun = MAX_LUNS; host->transportt = qla2xxx_transport_template; ret = request_irq(pdev->irq, ha->isp_ops.intr_handler, SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha); if (ret) { qla_printk(KERN_WARNING, ha, "Failed to reserve interrupt %d already in use.\n", pdev->irq); goto probe_failed; } host->irq = pdev->irq; /* Initialized the timer */ qla2x00_start_timer(ha, qla2x00_timer, WATCH_INTERVAL); DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n", ha->host_no, ha)); ha->isp_ops.disable_intrs(ha); spin_lock_irqsave(&ha->hardware_lock, flags); reg = ha->iobase; if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_HOST_INT); WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_RISC_INT); } else { WRT_REG_WORD(®->isp.semaphore, 0); WRT_REG_WORD(®->isp.hccr, HCCR_CLR_RISC_INT); WRT_REG_WORD(®->isp.hccr, HCCR_CLR_HOST_INT); /* Enable proper parity */ if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) { if (IS_QLA2300(ha)) /* SRAM parity */ WRT_REG_WORD(®->isp.hccr, (HCCR_ENABLE_PARITY + 0x1)); else /* SRAM, Instruction RAM and GP RAM parity */ WRT_REG_WORD(®->isp.hccr, (HCCR_ENABLE_PARITY + 0x7)); } } spin_unlock_irqrestore(&ha->hardware_lock, flags); ha->isp_ops.enable_intrs(ha); /* v2.19.5b6 */ /* * Wait around max loop_reset_delay secs for the devices to come * on-line. We don't want Linux scanning before we are ready. * */ for (wait_switch = jiffies + (ha->loop_reset_delay * HZ); time_before(jiffies,wait_switch) && !(ha->device_flags & (DFLG_NO_CABLE | DFLG_FABRIC_DEVICES)) && (ha->device_flags & SWITCH_FOUND) ;) { qla2x00_check_fabric_devices(ha); msleep(10); } pci_set_drvdata(pdev, ha); ha->flags.init_done = 1; num_hosts++; ret = scsi_add_host(host, &pdev->dev); if (ret) goto probe_failed; qla2x00_alloc_sysfs_attr(ha); qla2x00_init_host_attr(ha); qla_printk(KERN_INFO, ha, "\n" " QLogic Fibre Channel HBA Driver: %s\n" " QLogic %s - %s\n" " %s: %s @ %s hdma%c, host#=%ld, fw=%s\n", qla2x00_version_str, ha->model_number, ha->model_desc ? ha->model_desc: "", ha->brd_info->isp_name, ha->isp_ops.pci_info_str(ha, pci_info), pci_name(pdev), ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no, ha->isp_ops.fw_version_str(ha, fw_str)); /* Go with fc_rport registration. */ list_for_each_entry(fcport, &ha->fcports, list) qla2x00_reg_remote_port(ha, fcport); return 0;probe_failed: qla2x00_free_device(ha); scsi_host_put(host);probe_disable_device: pci_disable_device(pdev);probe_out: return ret;}EXPORT_SYMBOL_GPL(qla2x00_probe_one);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -