📄 qla_os.c
字号:
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){ int ret; /* 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_pid >= 0) { ha->dpc_should_die = 1; wmb(); ret = kill_proc(ha->dpc_pid, SIGHUP, 1); if (ret) { qla_printk(KERN_ERR, ha, "Unable to signal DPC thread -- (%d)\n", ret); /* TODO: SOMETHING MORE??? */ } else { wait_for_completion(&ha->dpc_exited); } } /* 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->pdev->irq) free_irq(ha->pdev->irq, ha); /* release io space registers */ if (ha->iobase) iounmap(ha->iobase); pci_release_regions(ha->pdev); pci_disable_device(ha->pdev);}/* * 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){ if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) schedule_work(&fcport->rport_del_work); /* * 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){ 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 && fcport->rport) schedule_work(&fcport->rport_del_work); atomic_set(&fcport->state, FCS_DEVICE_LOST); }}/** 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; unsigned int wtime;/* max wait time if mbx cmd is busy. */ if (ha == NULL) { /* error */ DEBUG2(printk("%s(): ERROR invalid ha pointer.\n", __func__)); return; } /* Make sure all other threads are stopped. */ wtime = 60 * 1000; while (ha->dpc_wait && wtime) wtime = msleep_interruptible(wtime); /* 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) dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma); if (ha->s_dma_pool) dma_pool_destroy(ha->s_dma_pool); if (ha->rlc_rsp) dma_free_coherent(&ha->pdev->dev, sizeof(rpt_lun_cmd_rsp_t), ha->rlc_rsp, ha->rlc_rsp_dma); if (ha->gid_list) dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list, ha->gid_list_dma); if (ha->response_ring) dma_free_coherent(&ha->pdev->dev, (ha->response_q_length + 1) * sizeof(response_t), ha->response_ring, ha->response_dma); if (ha->request_ring) dma_free_coherent(&ha->pdev->dev, (ha->request_q_length + 1) * sizeof(request_t), ha->request_ring, ha->request_dma); ha->sns_cmd = NULL; ha->sns_cmd_dma = 0; ha->ct_sns = NULL; ha->ct_sns_dma = 0; ha->ms_iocb = NULL; ha->ms_iocb_dma = 0; ha->iodesc_pd = NULL; ha->iodesc_pd_dma = 0; ha->init_cb = NULL; ha->init_cb_dma = 0; ha->s_dma_pool = NULL; ha->rlc_rsp = NULL; ha->rlc_rsp_dma = 0; ha->gid_list = NULL; ha->gid_list_dma = 0; ha->response_ring = NULL; ha->response_dma = 0; ha->request_ring = NULL; ha->request_dma = 0; list_for_each_safe(fcpl, fcptemp, &ha->fcports) { fcport = list_entry(fcpl, fc_port_t, list); /* fc ports */ list_del_init(&fcport->list); kfree(fcport); } INIT_LIST_HEAD(&ha->fcports); if (ha->fw_dump) free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order); vfree(ha->fw_dump24); vfree(ha->fw_dump_buffer); ha->fw_dump = NULL; ha->fw_dump24 = NULL; ha->fw_dumped = 0; ha->fw_dump_reading = 0; ha->fw_dump_buffer = NULL;}/* * qla2x00_allocate_sp_pool * This routine is called during initialization to allocate * memory for local srb_t. * * Input: * ha = adapter block pointer. * * Context: * Kernel context. * * Note: Sets the ref_count for non Null sp to one. */static intqla2x00_allocate_sp_pool(scsi_qla_host_t *ha){ int rval; rval = QLA_SUCCESS; ha->srb_mempool = mempool_create(SRB_MIN_REQ, mempool_alloc_slab, mempool_free_slab, srb_cachep); if (ha->srb_mempool == NULL) { qla_printk(KERN_INFO, ha, "Unable to allocate SRB mempool.\n"); rval = QLA_FUNCTION_FAILED; } return (rval);}/* * This routine frees all adapter allocated memory. * */static voidqla2x00_free_sp_pool( scsi_qla_host_t *ha){ if (ha->srb_mempool) { mempool_destroy(ha->srb_mempool); ha->srb_mempool = NULL; }}/*************************************************************************** qla2x00_do_dpc* This kernel thread is a task that is schedule by the interrupt handler* to perform the background processing for interrupts.** Notes:* This task always run in the context of a kernel thread. It* is kick-off by the driver's detect code and starts up
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -