qla_os.c
来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 2,583 行 · 第 1/5 页
C
2,583 行
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_QLA54XX(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" " 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)); /* 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);void qla2x00_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_set_drvdata(pdev, NULL);}EXPORT_SYMBOL_GPL(qla2x00_remove_one);static voidqla2x00_free_device(scsi_qla_host_t *ha){ /* Abort any outstanding IO descriptors. */ if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) qla2x00_cancel_io_descriptors(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); } /* Stop currently executing firmware. */ qla2x00_stop_firmware(ha); /* turn-off interrupts on the card */ if (ha->interrupts_on) ha->isp_ops.disable_intrs(ha); qla2x00_mem_free(ha); ha->flags.online = 0; /* Detach interrupts */ if (ha->host->irq) free_irq(ha->host->irq, ha); /* release io space registers */ if (ha->iobase) iounmap(ha->iobase); pci_release_regions(ha->pdev); pci_disable_device(ha->pdev);}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) 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; list_for_each_entry(fcport, &ha->fcports, list) { if (fcport->port_type != FCT_TARGET) 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) 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.*/static uint8_tqla2x00_mem_alloc(scsi_qla_host_t *ha){ char name[16]; uint8_t status = 1; int retry= 10; do { /* * This will loop only once if everything goes well, else some * number of retries will be performed to get around a kernel * bug where available mem is not allocated until after a * little delay and a retry. */ ha->request_ring = dma_alloc_coherent(&ha->pdev->dev, (ha->request_q_length + 1) * sizeof(request_t), &ha->request_dma, GFP_KERNEL); if (ha->request_ring == NULL) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - request_ring\n"); qla2x00_mem_free(ha); msleep(100); continue; } ha->response_ring = dma_alloc_coherent(&ha->pdev->dev, (ha->response_q_length + 1) * sizeof(response_t), &ha->response_dma, GFP_KERNEL); if (ha->response_ring == NULL) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - response_ring\n"); qla2x00_mem_free(ha); msleep(100); continue; } ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE, &ha->gid_list_dma, GFP_KERNEL); if (ha->gid_list == NULL) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - gid_list\n"); qla2x00_mem_free(ha); msleep(100); continue; } ha->rlc_rsp = dma_alloc_coherent(&ha->pdev->dev, sizeof(rpt_lun_cmd_rsp_t), &ha->rlc_rsp_dma, GFP_KERNEL); if (ha->rlc_rsp == NULL) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - rlc"); qla2x00_mem_free(ha); msleep(100); continue; } snprintf(name, sizeof(name), "qla2xxx_%ld", ha->host_no); ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, DMA_POOL_SIZE, 8, 0); if (ha->s_dma_pool == NULL) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - s_dma_pool\n"); qla2x00_mem_free(ha); msleep(100); continue; } /* get consistent memory allocated for init control block */ ha->init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &ha->init_cb_dma); if (ha->init_cb == NULL) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - init_cb\n"); qla2x00_mem_free(ha); msleep(100); continue; } memset(ha->init_cb, 0, ha->init_cb_size); /* Get consistent memory allocated for Get Port Database cmd */ ha->iodesc_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &ha->iodesc_pd_dma); if (ha->iodesc_pd == NULL) { /* error */ qla_printk(KERN_WARNING, ha, "Memory Allocation failed - iodesc_pd\n"); qla2x00_mem_free(ha); msleep(100); continue; } memset(ha->iodesc_pd, 0, PORT_DATABASE_SIZE); /* Allocate ioctl related memory. */ if (qla2x00_alloc_ioctl_mem(ha)) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - ioctl_mem\n"); qla2x00_mem_free(ha); msleep(100); continue; } if (qla2x00_allocate_sp_pool(ha)) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - " "qla2x00_allocate_sp_pool()\n"); qla2x00_mem_free(ha); msleep(100); continue; } /* Allocate memory for SNS commands */ if (IS_QLA2100(ha) || IS_QLA2200(ha)) { /* Get consistent memory allocated for SNS commands */ ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma, GFP_KERNEL); if (ha->sns_cmd == NULL) { /* error */ qla_printk(KERN_WARNING, ha, "Memory Allocation failed - sns_cmd\n"); qla2x00_mem_free(ha); msleep(100); continue; } memset(ha->sns_cmd, 0, sizeof(struct sns_cmd_pkt)); } else { /* Get consistent memory allocated for MS IOCB */ ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &ha->ms_iocb_dma); if (ha->ms_iocb == NULL) { /* error */ qla_printk(KERN_WARNING, ha, "Memory Allocation failed - ms_iocb\n"); qla2x00_mem_free(ha); msleep(100); continue; } memset(ha->ms_iocb, 0, sizeof(ms_iocb_entry_t)); /* * Get consistent memory allocated for CT SNS * commands */ ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, GFP_KERNEL); if (ha->ct_sns == NULL) { /* error */ qla_printk(KERN_WARNING, ha, "Memory Allocation failed - ct_sns\n"); qla2x00_mem_free(ha); msleep(100); continue; } memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt)); } /* Done all allocations without any error. */ status = 0; } while (retry-- && status != 0); if (status) { printk(KERN_WARNING "%s(): **** FAILED ****\n", __func__); } return(status);}/** qla2x00_mem_free* Frees all adapter allocated memory.** Input:* ha = adapter block pointer.*/static voidqla2x00_mem_free(scsi_qla_host_t *ha){ struct list_head *fcpl, *fcptemp; fc_port_t *fcport; if (ha == NULL) { /* error */ DEBUG2(printk("%s(): ERROR invalid ha pointer.\n", __func__)); return; } /* free ioctl memory */ qla2x00_free_ioctl_mem(ha); /* free sp pool */ qla2x00_free_sp_pool(ha); if (ha->sns_cmd) dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt), ha->sns_cmd, ha->sns_cmd_dma); if (ha->ct_sns) dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt), ha->ct_sns, ha->ct_sns_dma); if (ha->ms_iocb) dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); if (ha->iodesc_pd) dma_pool_free(ha->s_dma_pool, ha->iodesc_pd, ha->iodesc_pd_dma); if (ha->init_cb)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?