qla_os.c
来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 2,583 行 · 第 1/5 页
C
2,583 行
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; vfree(ha->optrom_buffer);}/* * 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_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){ 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 (fcport->port_type != FCT_TARGET) continue; /* * 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) { 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); 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 (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))) { 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_flags)) { DEBUG(printk("scsi(%ld): Rescan flagged fcports...\n", ha->host_no)); qla2x00_rescan_fcports(ha); DEBUG(printk("scsi(%ld): Rescan flagged fcports..." "end.\n", ha->host_no)); } if (!ha->interrupts_on) ha->isp_ops.enable_intrs(ha); if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags)) ha->isp_ops.beacon_blink(ha); ha->dpc_active = 0; } /* End of while(1) */ DEBUG(printk("scsi(%ld): DPC handler exiting\n", ha->host_no)); /* * Make sure that nobody tries to wake us up again. */ ha->dpc_active = 0; return 0;}voidqla2xxx_wake_dpc(scsi_qla_host_t *ha){ if (ha->dpc_thread) wake_up_process(ha->dpc_thread);}/** qla2x00_rst_aen* Processes asynchronous reset.** Input:* ha = adapter block pointer.*/static voidqla2x00_rst_aen(scsi_qla_host_t *ha){ if (ha->flags.online && !ha->flags.reset_active && !atomic_read(&ha->loop_down_timer) && !(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) { do { clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); /* * Issue marker command only when we are going to start * the I/O. */ ha->marker_needed = 1; } while (!atomic_read(&ha->loop_down_timer) && (test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags))); }}static voidqla2x00_sp_free_dma(scsi_qla_host_t *ha, srb_t *sp){ struct scsi_cmnd *cmd = sp->cmd; if (sp->flags & SRB_DMA_VALID) { if (cmd->use_sg) { dma_unmap_sg(&ha->pdev->dev, cmd->request_buffer, cmd->use_sg, cmd->sc_data_direction); } else if (cmd->request_bufflen) { dma_unmap_single(&ha->pdev->dev, sp->dma_handle, cmd->request_bufflen, cmd->sc_data_direction); } sp->flags &= ~SRB_DMA_VALID; } CMD_SP(cmd) = NULL;}voidqla2x00_sp_compl(scsi_qla_host_t *ha, srb_t *sp){ struct scsi_cmnd *cmd = sp->cmd; qla2x00_sp_free_dma(ha, sp); mempool_free(sp, ha->srb_mempool); cmd->scsi_done(cmd);}/*************************************************************************** qla2x00_timer** Description:* One second timer** Context: Interrupt***************************************************************************/static voidqla2x00_timer(scsi_qla_host_t *ha){ unsigned long cpu_flags = 0; fc_port_t *fcport; int start_dpc = 0; int index; srb_t *sp; int t; /* * Ports - Port down timer. * * Whenever, a port is in the LOST state we start decrementing its port * down timer every second until it reaches zero. Once it reaches zero * the port it marked DEAD. */ t = 0; list_for_each_entry(fcport, &ha->fcports, list) { if (fcport->port_type != FCT_TARGET) continue; if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) { if (atomic_read(&fcport->port_down_timer) == 0) continue; if (atomic_dec_and_test(&fcport->port_down_timer) != 0) atomic_set(&fcport->state, FCS_DEVICE_DEAD); DEBUG(printk("scsi(%ld): fcport-%d - port retry count: " "%d remaining\n", ha->host_no, t, atomic_read(&fcport->port_down_timer))); } t++; } /* End of for fcport */ /* Loop down handler. */ if (atomic_read(&ha->loop_down_timer) > 0 && !(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) && ha->flags.online) { if (atomic_read(&ha->loop_down_timer) == ha->loop_down_abort_time) { DEBUG(printk("scsi(%ld): Loop Down - aborting the " "queues before time expire\n", ha->host_no)); if (!IS_QLA2100(ha) && ha->link_down_timeout) atomic_set(&ha->loop_state, LOOP_DEAD); /* Schedule an ISP abort to return any tape commands. */ spin_lock_irqsave(&ha->hardware_lock, cpu_flags); for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { fc_port_t *sfcp; sp = ha->outstanding_cmds[index]; if (!sp) continue; sfcp = sp->fcport; if (!(sfcp->flags & FCF_TAPE_PRESENT)) continue; set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; } spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); set_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags); start_dpc++; } /* if the loop has been down for 4 minutes, reinit adapter */ if (atomic_dec_and_test(&ha->loop_down_timer) != 0) { DEBUG(printk("scsi(%ld): Loop down exceed 4 mins - " "restarting queues.\n", ha->host_no)); set_bit(RESTART_QUEUES_NEEDED, &ha->dpc_flags); start_dpc++; if (!(ha->device_flags & DFLG_NO_CABLE)) { DEBUG(printk("scsi(%ld): Loop down - " "aborting ISP.\n", ha->host_no)); qla_printk(KERN_WARNING, ha, "Loop down - aborting ISP.\n"); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); } } DEBUG3(printk("scsi(%ld): Loop Down - seconds remaining %d\n", ha->host_no, atomic_read(&ha->loop_down_timer))); } /* Check if beacon LED needs to be blinked */ if (ha->beacon_blink_led == 1) { set_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags); start_dpc++; } /* Schedule the DPC routine if needed */ if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags) || test_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags) || start_dpc || test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) || test_bit(RELOGIN_NEEDED, &ha->dpc_flags))) qla2xxx_wake_dpc(ha); qla2x00_restart_timer(ha, WATCH_INTERVAL);}/* XXX(hch): crude hack to emulate a down_timeout() */intqla2x00_down_timeout(struct semaphore *sema, unsigned long timeout){ const unsigned int step = 100; /* msecs
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?