qla_os.c
来自「linux 内核源代码」· C语言 代码 · 共 2,525 行 · 第 1/5 页
C
2,525 行
skip_pio: /* 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; } 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 voidqla2xxx_scan_start(struct Scsi_Host *shost){ scsi_qla_host_t *ha = shost_priv(shost); set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); set_bit(RSCN_UPDATE, &ha->dpc_flags);}static intqla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time){ scsi_qla_host_t *ha = shost_priv(shost); if (!ha->host) return 1; if (time > ha->loop_reset_delay * HZ) return 1; return atomic_read(&ha->loop_state) == LOOP_READY;}/* * PCI driver interface */static int __devinitqla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id){ int ret = -ENODEV; device_reg_t __iomem *reg; struct Scsi_Host *host; scsi_qla_host_t *ha; unsigned long flags = 0; char pci_info[30]; char fw_str[30]; struct scsi_host_template *sht; int bars; bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO); sht = &qla2x00_driver_template; if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) { bars = pci_select_bars(pdev, IORESOURCE_MEM); sht = &qla24xx_driver_template; } if (pci_enable_device_bars(pdev, bars)) goto probe_out; if (pci_find_aer_capability(pdev)) if (pci_enable_pcie_error_reporting(pdev)) goto probe_out; host = scsi_host_alloc(sht, 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 = shost_priv(host); memset(ha, 0, sizeof(scsi_qla_host_t)); ha->pdev = pdev; ha->host = host; ha->host_no = host->host_no; sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no); ha->parent = NULL; ha->bars = bars; /* Set ISP-type information. */ qla2x00_set_isp_flags(ha); /* Configure PCI I/O space */ ret = qla2x00_iospace_config(ha); if (ret) goto probe_failed; qla_printk(KERN_INFO, ha, "Found an ISP%04X, irq %d, iobase 0x%p\n", pdev->device, pdev->irq, ha->iobase); spin_lock_init(&ha->hardware_lock); ha->prev_topology = 0; ha->init_cb_size = sizeof(init_cb_t); ha->mgmt_svr_loop_id = MANAGEMENT_SERVER + ha->vp_idx; ha->link_data_rate = PORT_SPEED_UNKNOWN; ha->optrom_size = OPTROM_SIZE_2300; ha->max_q_depth = MAX_Q_DEPTH; if (ql2xmaxqdepth != 0 && ql2xmaxqdepth <= 0xffffU) ha->max_q_depth = ql2xmaxqdepth; /* Assign ISP specific operations. */ 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; ha->isp_ops = &qla2100_isp_ops; } 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; ha->isp_ops = &qla2100_isp_ops; } 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->gid_list_info_size = 6; if (IS_QLA2322(ha) || IS_QLA6322(ha)) ha->optrom_size = OPTROM_SIZE_2322; ha->isp_ops = &qla2300_isp_ops; } else if (IS_QLA24XX(ha) || IS_QLA54XX(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 mid_init_cb_24xx); ha->mgmt_svr_loop_id = 10 + ha->vp_idx; ha->gid_list_info_size = 8; ha->optrom_size = OPTROM_SIZE_24XX; ha->isp_ops = &qla24xx_isp_ops; } else if (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 mid_init_cb_24xx); ha->mgmt_svr_loop_id = 10 + ha->vp_idx; ha->gid_list_info_size = 8; ha->optrom_size = OPTROM_SIZE_25XX; ha->isp_ops = &qla25xx_isp_ops; } 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(&ha->vport_sem); init_MUTEX_LOCKED(&ha->mbx_intr_sem); INIT_LIST_HEAD(&ha->list); INIT_LIST_HEAD(&ha->fcports); INIT_LIST_HEAD(&ha->vp_list); set_bit(0, (unsigned long *) ha->vp_idx_map); 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)) { 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_thread = kthread_create(qla2x00_do_dpc, ha, "%s_dpc", ha->host_str); if (IS_ERR(ha->dpc_thread)) { qla_printk(KERN_WARNING, ha, "Unable to start DPC thread!\n"); ret = PTR_ERR(ha->dpc_thread); goto probe_failed; } host->this_id = 255; host->cmd_per_lun = 3; host->unique_id = ha->instance; host->max_cmd_len = MAX_CMDSZ; host->max_channel = MAX_BUSES - 1; host->max_lun = MAX_LUNS; host->transportt = qla2xxx_transport_template; ret = qla2x00_request_irqs(ha); if (ret) goto probe_failed; /* 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_FWI2_CAPABLE(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); pci_set_drvdata(pdev, ha); ha->flags.init_done = 1; ha->flags.online = 1; num_hosts++; ret = scsi_add_host(host, &pdev->dev); if (ret) goto probe_failed; scsi_scan_host(host); 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" " ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n", qla2x00_version_str, ha->model_number, ha->model_desc ? ha->model_desc: "", pdev->device, 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)); return 0;probe_failed: qla2x00_free_device(ha); scsi_host_put(host);probe_disable_device: pci_disable_device(pdev);probe_out: return ret;}static voidqla2x00_remove_one(struct pci_dev *pdev){ scsi_qla_host_t *ha; ha = pci_get_drvdata(pdev); qla2x00_free_sysfs_attr(ha); fc_remove_host(ha->host); scsi_remove_host(ha->host); qla2x00_free_device(ha); scsi_host_put(ha->host); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL);}static voidqla2x00_free_device(scsi_qla_host_t *ha){ /* Disable timer */ if (ha->timer_active) qla2x00_stop_timer(ha); /* 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->eft) qla2x00_trace_control(ha, TC_DISABLE, 0, 0); ha->flags.online = 0; /* Stop currently executing firmware. */ qla2x00_try_to_stop_firmware(ha); /* turn-off interrupts on the card */ if (ha->interrupts_on) ha->isp_ops->disable_intrs(ha); qla2x00_mem_free(ha); qla2x00_free_irqs(ha); /* release io space registers */ if (ha->iobase) iounmap(ha->iobase); pci_release_selected_regions(ha->pdev, ha->bars);}static inline voidqla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport, int defer){ unsigned long flags; struct fc_rport *rport; if (!fcport->rport) return; rport = fcport->rport; if (defer) { spin_lock_irqsave(&fcport->rport_lock, flags); fcport->drport = rport; fcport->rport = NULL; *(fc_port_t **)rport->dd_data = NULL; spin_unlock_irqrestore(&fcport->rport_lock, flags); set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags); } else { spin_lock_irqsave(&fcport->rport_lock, flags); fcport->rport = NULL; *(fc_port_t **)rport->dd_data = NULL; spin_unlock_irqrestore(&fcport->rport_lock, flags); fc_remote_port_delete(rport); }}/* * qla2x00_mark_device_lost Updates fcport state when device goes offline. * * Input: ha = adapter block pointer. fcport = port structure pointer. * * Return: None. * * Context: */void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport, int do_login, int defer){ if (atomic_read(&fcport->state) == FCS_ONLINE && ha->vp_idx == fcport->vp_idx) qla2x00_schedule_rport_del(ha, fcport, defer); /* * We may need to retry the login, so don't change the state of the * port but do the retries. */ if (atomic_read(&fcport->state) != FCS_DEVICE_DEAD) atomic_set(&fcport->state, FCS_DEVICE_LOST); if (!do_login) return; if (fcport->login_retry == 0) { fcport->login_retry = ha->login_retry_count; set_bit(RELOGIN_NEEDED, &ha->dpc_flags); DEBUG(printk("scsi(%ld): Port login retry: " "%02x%02x%02x%02x%02x%02x%02x%02x, " "id = 0x%04x retry cnt=%d\n", ha->host_no, fcport->port_name[0], fcport->port_name[1], fcport->port_name[2], fcport->port_name[3], fcport->port_name[4], fcport->port_name[5], fcport->port_name[6], fcport->port_name[7], fcport->loop_id, fcport->login_retry)); }}/* * qla2x00_mark_all_devices_lost * Updates fcport state when device goes offline. * * Input: * ha = adapter block pointer. * fcport = port structure pointer. * * Return: * None. * * Context: */voidqla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer){ fc_port_t *fcport; scsi_qla_host_t *pha = to_qla_parent(ha); list_for_each_entry(fcport, &pha->fcports, list) { if (ha->vp_idx != 0 && ha->vp_idx != fcport->vp_idx) continue; /* * No point in marking the device as lost, if the device is * already DEAD. */ if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) continue; if (atomic_read(&fcport->state) == FCS_ONLINE) { if (defer) qla2x00_schedule_rport_del(ha, fcport, defer); else if (ha->vp_idx == fcport->vp_idx) qla2x00_schedule_rport_del(ha, fcport, defer); } atomic_set(&fcport->state, FCS_DEVICE_LOST); } if (defer) qla2xxx_wake_dpc(ha);}/** qla2x00_mem_alloc* Allocates adapter memory.** Returns:* 0 = success.* 1 = failure.*/uint8_tqla2x00_mem_alloc(scsi_qla_host_t *ha)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?