qla_os.c
来自「linux 内核源代码」· C语言 代码 · 共 2,525 行 · 第 1/5 页
C
2,525 行
{ 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; } /* get consistent memory allocated for init control block */ ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size, &ha->init_cb_dma, GFP_KERNEL); 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); snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME, 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; } 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)); if (IS_FWI2_CAPABLE(ha)) { /* * Get consistent memory allocated for SFP * block. */ ha->sfp_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &ha->sfp_data_dma); if (ha->sfp_data == NULL) { qla_printk(KERN_WARNING, ha, "Memory Allocation failed - " "sfp_data\n"); qla2x00_mem_free(ha); msleep(100); continue; } memset(ha->sfp_data, 0, SFP_BLOCK_SIZE); } } /* Get memory for cached NVRAM */ ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL); if (ha->nvram == NULL) { /* error */ qla_printk(KERN_WARNING, ha, "Memory Allocation failed - nvram cache\n"); qla2x00_mem_free(ha); msleep(100); continue; } /* 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.*/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 sp pool */ qla2x00_free_sp_pool(ha); if (ha->fw_dump) { if (ha->eft) dma_free_coherent(&ha->pdev->dev, ntohl(ha->fw_dump->eft_size), ha->eft, ha->eft_dma); vfree(ha->fw_dump); } 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->sfp_data) dma_pool_free(ha->s_dma_pool, ha->sfp_data, ha->sfp_data_dma); if (ha->ms_iocb) dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); if (ha->s_dma_pool) dma_pool_destroy(ha->s_dma_pool); if (ha->init_cb) dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb, ha->init_cb_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->eft = NULL; ha->eft_dma = 0; 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->init_cb = NULL; ha->init_cb_dma = 0; ha->s_dma_pool = NULL; 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); ha->fw_dump = NULL; ha->fw_dumped = 0; ha->fw_dump_reading = 0; vfree(ha->optrom_buffer); kfree(ha->nvram);}/* * 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. */static intqla2x00_allocate_sp_pool(scsi_qla_host_t *ha){ int rval; rval = QLA_SUCCESS; ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, 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* up one per adapter. It immediately goes to sleep and waits for* some fibre event. When either the interrupt handler or* the timer routine detects a event it will one of the task* bits then wake us up.**************************************************************************/static intqla2x00_do_dpc(void *data){ int rval; scsi_qla_host_t *ha; fc_port_t *fcport; uint8_t status; uint16_t next_loopid; ha = (scsi_qla_host_t *)data; set_user_nice(current, -20); while (!kthread_should_stop()) { DEBUG3(printk("qla2x00: DPC handler sleeping\n")); set_current_state(TASK_INTERRUPTIBLE); schedule(); __set_current_state(TASK_RUNNING); DEBUG3(printk("qla2x00: DPC handler waking up\n")); /* Initialization not yet finished. Don't do anything yet. */ if (!ha->flags.init_done) continue; DEBUG3(printk("scsi(%ld): DPC handler\n", ha->host_no)); ha->dpc_active = 1; if (ha->flags.mbox_busy) { ha->dpc_active = 0; continue; } if (test_and_clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) { DEBUG(printk("scsi(%ld): dpc: sched " "qla2x00_abort_isp ha = %p\n", ha->host_no, ha)); if (!(test_and_set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) { if (qla2x00_abort_isp(ha)) { /* failed. retry later */ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); } clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); } DEBUG(printk("scsi(%ld): dpc: qla2x00_abort_isp end\n", ha->host_no)); } if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags)) qla2x00_update_fcports(ha); if (test_and_clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) { DEBUG(printk("scsi(%ld): dpc: sched loop_reset()\n", ha->host_no)); qla2x00_loop_reset(ha); } if (test_and_clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) && (!(test_and_set_bit(RESET_ACTIVE, &ha->dpc_flags)))) { DEBUG(printk("scsi(%ld): qla2x00_reset_marker()\n", ha->host_no)); qla2x00_rst_aen(ha); clear_bit(RESET_ACTIVE, &ha->dpc_flags); } /* Retry each device up to login retry count */ if ((test_and_clear_bit(RELOGIN_NEEDED, &ha->dpc_flags)) && !test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) && atomic_read(&ha->loop_state) != LOOP_DOWN) { DEBUG(printk("scsi(%ld): qla2x00_port_login()\n", ha->host_no)); next_loopid = 0; list_for_each_entry(fcport, &ha->fcports, list) { /* * If the port is not ONLINE then try to login * to it if we haven't run out of retries. */ if (atomic_read(&fcport->state) != FCS_ONLINE && fcport->login_retry) { if (fcport->flags & FCF_FABRIC_DEVICE) { if (fcport->flags & FCF_TAPE_PRESENT) ha->isp_ops->fabric_logout( ha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); status = qla2x00_fabric_login( ha, fcport, &next_loopid); } else status = qla2x00_local_device_login( ha, fcport); fcport->login_retry--; if (status == QLA_SUCCESS) { fcport->old_loop_id = fcport->loop_id; DEBUG(printk("scsi(%ld): port login OK: logged in ID 0x%x\n", ha->host_no, fcport->loop_id)); qla2x00_update_fcport(ha, fcport); } else if (status == 1) { set_bit(RELOGIN_NEEDED, &ha->dpc_flags); /* retry the login again */ DEBUG(printk("scsi(%ld): Retrying %d login again loop_id 0x%x\n", ha->host_no, fcport->login_retry, fcport->loop_id)); } else { fcport->login_retry = 0; } if (fcport->login_retry == 0) fcport->loop_id = FC_NO_LOOP_ID; } if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) break; } DEBUG(printk("scsi(%ld): qla2x00_port_login - end\n", ha->host_no)); } if ((test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags)) && atomic_read(&ha->loop_state) != LOOP_DOWN) { clear_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags); DEBUG(printk("scsi(%ld): qla2x00_login_retry()\n", ha->host_no)); set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); DEBUG(printk("scsi(%ld): qla2x00_login_retry - end\n", ha->host_no)); } if (test_and_clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { DEBUG(printk("scsi(%ld): qla2x00_loop_resync()\n", ha->host_no)); if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags))) { rval = qla2x00_loop_resync(ha); clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags); } DEBUG(printk("scsi(%ld): qla2x00_loop_resync - end\n", ha->host_no)); } if (test_and_clear_bit(FCPORT_RESCAN_NEEDED, &ha->dpc_fl
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?