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 + -
显示快捷键?