⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qla_os.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
* 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){	DECLARE_MUTEX_LOCKED(sem);	scsi_qla_host_t *ha;	fc_port_t	*fcport;	uint8_t		status;	uint16_t	next_loopid;	ha = (scsi_qla_host_t *)data;	lock_kernel();	daemonize("%s_dpc", ha->host_str);	allow_signal(SIGHUP);	ha->dpc_wait = &sem;	set_user_nice(current, -20);	unlock_kernel();	complete(&ha->dpc_inited);	while (1) {		DEBUG3(printk("qla2x00: DPC handler sleeping\n"));		if (down_interruptible(&sem))			break;		if (ha->dpc_should_die)			break;		DEBUG3(printk("qla2x00: DPC handler waking up\n"));		/* Initialization not yet finished. Don't do anything yet. */		if (!ha->flags.init_done || ha->dpc_active)			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(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->loop_id);					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));						fcport->port_login_retry_count =						    ha->port_down_retry_count * PORT_RETRY_TIME;						atomic_set(&fcport->state, FCS_ONLINE);						atomic_set(&fcport->port_down_timer,						    ha->port_down_retry_count * PORT_RETRY_TIME);						fcport->login_retry = 0;					} 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);		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_wait = NULL;	ha->dpc_active = 0;	complete_and_exit(&ha->dpc_exited, 0);}/**  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)));	}	/* 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) ||	    start_dpc ||	    test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) ||	    test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||	    test_bit(RELOGIN_NEEDED, &ha->dpc_flags)) &&	    ha->dpc_wait && !ha->dpc_active) {		up(ha->dpc_wait);	}	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 */	unsigned int iterations = jiffies_to_msecs(timeout)/100;	do {		if (!down_trylock(sema))			return 0;		if (msleep_interruptible(step))			break;	} while (--iterations >= 0);	return -ETIMEDOUT;}static struct qla_board_info qla_board_tbl[] = {	{		.drv_name	= "qla2400",		.isp_name	= "ISP2422",		.fw_fname	= "ql2400_fw.bin",		.sht		= &qla24xx_driver_template,	},	{		.drv_name	= "qla2400",		.isp_name	= "ISP2432",		.fw_fname	= "ql2400_fw.bin",		.sht		= &qla24xx_driver_template,	},};static struct pci_device_id qla2xxx_pci_tbl[] = {	{		.vendor		= PCI_VENDOR_ID_QLOGIC,		.device		= PCI_DEVICE_ID_QLOGIC_ISP2422,		.subvendor	= PCI_ANY_ID,		.subdevice	= PCI_ANY_ID,		.driver_data	= (unsigned long)&qla_board_tbl[0],	},	{		.vendor		= PCI_VENDOR_ID_QLOGIC,		.device		= PCI_DEVICE_ID_QLOGIC_ISP2432,		.subvendor	= PCI_ANY_ID,		.subdevice	= PCI_ANY_ID,		.driver_data	= (unsigned long)&qla_board_tbl[1],	},	{0, 0},};MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);static int __devinitqla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id){	return qla2x00_probe_one(pdev,	    (struct qla_board_info *)id->driver_data);}static void __devexitqla2xxx_remove_one(struct pci_dev *pdev){	qla2x00_remove_one(pdev);}static struct pci_driver qla2xxx_pci_driver = {	.name		= "qla2xxx",	.id_table	= qla2xxx_pci_tbl,	.probe		= qla2xxx_probe_one,	.remove		= __devexit_p(qla2xxx_remove_one),};/** * qla2x00_module_init - Module initialization. **/static int __initqla2x00_module_init(void){	int ret = 0;	/* Allocate cache for SRBs. */	srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,	    SLAB_HWCACHE_ALIGN, NULL, NULL);	if (srb_cachep == NULL) {		printk(KERN_ERR		    "qla2xxx: Unable to allocate SRB cache...Failing load!\n");		return -ENOMEM;	}	/* Derive version string. */	strcpy(qla2x00_version_str, QLA2XXX_VERSION);#if DEBUG_QLA2100	strcat(qla2x00_version_str, "-debug");#endif	qla2xxx_transport_template =	    fc_attach_transport(&qla2xxx_transport_functions);	if (!qla2xxx_transport_template)		return -ENODEV;	printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n");	ret = pci_module_init(&qla2xxx_pci_driver);	if (ret) {		kmem_cache_destroy(srb_cachep);		fc_release_transport(qla2xxx_transport_template);	}	return ret;}/** * qla2x00_module_exit - Module cleanup. **/static void __exitqla2x00_module_exit(void){	pci_unregister_driver(&qla2xxx_pci_driver);	kmem_cache_destroy(srb_cachep);	fc_release_transport(qla2xxx_transport_template);}module_init(qla2x00_module_init);module_exit(qla2x00_module_exit);MODULE_AUTHOR("QLogic Corporation");MODULE_DESCRIPTION("QLogic Fibre Channel HBA Driver");MODULE_LICENSE("GPL");MODULE_VERSION(QLA2XXX_VERSION);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -