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

📄 qla_isr.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * QLogic Fibre Channel HBA Driver * Copyright (c)  2003-2005 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */#include "qla_def.h"static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);static void qla2x00_async_event(scsi_qla_host_t *, uint16_t *);static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t);static void qla2x00_status_entry(scsi_qla_host_t *, void *);static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *);static void qla2x00_error_entry(scsi_qla_host_t *, sts_entry_t *);static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *);static void qla24xx_ms_entry(scsi_qla_host_t *, struct ct_entry_24xx *);/** * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. * @irq: * @dev_id: SCSI driver HA context * @regs: * * Called by system whenever the host adapter generates an interrupt. * * Returns handled flag. */irqreturn_tqla2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs){	scsi_qla_host_t	*ha;	struct device_reg_2xxx __iomem *reg;	int		status;	unsigned long	flags;	unsigned long	iter;	uint16_t	mb[4];	ha = (scsi_qla_host_t *) dev_id;	if (!ha) {		printk(KERN_INFO		    "%s(): NULL host pointer\n", __func__);		return (IRQ_NONE);	}	reg = &ha->iobase->isp;	status = 0;	spin_lock_irqsave(&ha->hardware_lock, flags);	for (iter = 50; iter--; ) {		if ((RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) == 0)			break;		if (RD_REG_WORD(&reg->semaphore) & BIT_0) {			WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);			RD_REG_WORD(&reg->hccr);			/* Get mailbox data. */			mb[0] = RD_MAILBOX_REG(ha, reg, 0);			if (mb[0] > 0x3fff && mb[0] < 0x8000) {				qla2x00_mbx_completion(ha, mb[0]);				status |= MBX_INTERRUPT;			} else if (mb[0] > 0x7fff && mb[0] < 0xc000) {				mb[1] = RD_MAILBOX_REG(ha, reg, 1);				mb[2] = RD_MAILBOX_REG(ha, reg, 2);				mb[3] = RD_MAILBOX_REG(ha, reg, 3);				qla2x00_async_event(ha, mb);			} else {				/*EMPTY*/				DEBUG2(printk("scsi(%ld): Unrecognized "				    "interrupt type (%d).\n",				    ha->host_no, mb[0]));			}			/* Release mailbox registers. */			WRT_REG_WORD(&reg->semaphore, 0);			RD_REG_WORD(&reg->semaphore);		} else {			qla2x00_process_response_queue(ha);			WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);			RD_REG_WORD(&reg->hccr);		}	}	spin_unlock_irqrestore(&ha->hardware_lock, flags);	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {		spin_lock_irqsave(&ha->mbx_reg_lock, flags);		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);		up(&ha->mbx_intr_sem);		spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);	}	return (IRQ_HANDLED);}/** * qla2300_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. * @irq: * @dev_id: SCSI driver HA context * @regs: * * Called by system whenever the host adapter generates an interrupt. * * Returns handled flag. */irqreturn_tqla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs){	scsi_qla_host_t	*ha;	struct device_reg_2xxx __iomem *reg;	int		status;	unsigned long	flags;	unsigned long	iter;	uint32_t	stat;	uint16_t	hccr;	uint16_t	mb[4];	ha = (scsi_qla_host_t *) dev_id;	if (!ha) {		printk(KERN_INFO		    "%s(): NULL host pointer\n", __func__);		return (IRQ_NONE);	}	reg = &ha->iobase->isp;	status = 0;	spin_lock_irqsave(&ha->hardware_lock, flags);	for (iter = 50; iter--; ) {		stat = RD_REG_DWORD(&reg->u.isp2300.host_status);		if (stat & HSR_RISC_PAUSED) {			hccr = RD_REG_WORD(&reg->hccr);			if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8))				qla_printk(KERN_INFO, ha,				    "Parity error -- HCCR=%x.\n", hccr);			else				qla_printk(KERN_INFO, ha,				    "RISC paused -- HCCR=%x.\n", hccr);			/*			 * Issue a "HARD" reset in order for the RISC			 * interrupt bit to be cleared.  Schedule a big			 * hammmer to get out of the RISC PAUSED state.			 */			WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);			RD_REG_WORD(&reg->hccr);			set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);			break;		} else if ((stat & HSR_RISC_INT) == 0)			break;		switch (stat & 0xff) {		case 0x1:		case 0x2:		case 0x10:		case 0x11:			qla2x00_mbx_completion(ha, MSW(stat));			status |= MBX_INTERRUPT;			/* Release mailbox registers. */			WRT_REG_WORD(&reg->semaphore, 0);			break;		case 0x12:			mb[0] = MSW(stat);			mb[1] = RD_MAILBOX_REG(ha, reg, 1);			mb[2] = RD_MAILBOX_REG(ha, reg, 2);			mb[3] = RD_MAILBOX_REG(ha, reg, 3);			qla2x00_async_event(ha, mb);			break;		case 0x13:			qla2x00_process_response_queue(ha);			break;		case 0x15:			mb[0] = MBA_CMPLT_1_16BIT;			mb[1] = MSW(stat);			qla2x00_async_event(ha, mb);			break;		case 0x16:			mb[0] = MBA_SCSI_COMPLETION;			mb[1] = MSW(stat);			mb[2] = RD_MAILBOX_REG(ha, reg, 2);			qla2x00_async_event(ha, mb);			break;		default:			DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "			    "(%d).\n",			    ha->host_no, stat & 0xff));			break;		}		WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);		RD_REG_WORD_RELAXED(&reg->hccr);	}	spin_unlock_irqrestore(&ha->hardware_lock, flags);	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {		spin_lock_irqsave(&ha->mbx_reg_lock, flags);		set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);		up(&ha->mbx_intr_sem);		spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);	}	return (IRQ_HANDLED);}/** * qla2x00_mbx_completion() - Process mailbox command completions. * @ha: SCSI driver HA context * @mb0: Mailbox0 register */static voidqla2x00_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0){	uint16_t	cnt;	uint16_t __iomem *wptr;	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;	/* Load return mailbox registers. */	ha->flags.mbox_int = 1;	ha->mailbox_out[0] = mb0;	wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 1);	for (cnt = 1; cnt < ha->mbx_count; cnt++) {		if (IS_QLA2200(ha) && cnt == 8)			wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 8);		if (cnt == 4 || cnt == 5)			ha->mailbox_out[cnt] = qla2x00_debounce_register(wptr);		else			ha->mailbox_out[cnt] = RD_REG_WORD(wptr);		wptr++;	}	if (ha->mcp) {		DEBUG3(printk("%s(%ld): Got mailbox completion. cmd=%x.\n",		    __func__, ha->host_no, ha->mcp->mb[0]));	} else {		DEBUG2_3(printk("%s(%ld): MBX pointer ERROR!\n",		    __func__, ha->host_no));	}}/** * qla2x00_async_event() - Process aynchronous events. * @ha: SCSI driver HA context * @mb: Mailbox registers (0 - 3) */static voidqla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb){#define LS_UNKNOWN	2	static char	*link_speeds[5] = { "1", "2", "?", "4", "10" };	char		*link_speed;	uint16_t	handle_cnt;	uint16_t	cnt;	uint32_t	handles[5];	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;	uint32_t	rscn_entry, host_pid;	uint8_t		rscn_queue_index;	/* Setup to process RIO completion. */	handle_cnt = 0;	switch (mb[0]) {	case MBA_SCSI_COMPLETION:		handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1]));		handle_cnt = 1;		break;	case MBA_CMPLT_1_16BIT:		handles[0] = mb[1];		handle_cnt = 1;		mb[0] = MBA_SCSI_COMPLETION;		break;	case MBA_CMPLT_2_16BIT:		handles[0] = mb[1];		handles[1] = mb[2];		handle_cnt = 2;		mb[0] = MBA_SCSI_COMPLETION;		break;	case MBA_CMPLT_3_16BIT:		handles[0] = mb[1];		handles[1] = mb[2];		handles[2] = mb[3];		handle_cnt = 3;		mb[0] = MBA_SCSI_COMPLETION;		break;	case MBA_CMPLT_4_16BIT:		handles[0] = mb[1];		handles[1] = mb[2];		handles[2] = mb[3];		handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6);		handle_cnt = 4;		mb[0] = MBA_SCSI_COMPLETION;		break;	case MBA_CMPLT_5_16BIT:		handles[0] = mb[1];		handles[1] = mb[2];		handles[2] = mb[3];		handles[3] = (uint32_t)RD_MAILBOX_REG(ha, reg, 6);		handles[4] = (uint32_t)RD_MAILBOX_REG(ha, reg, 7);		handle_cnt = 5;		mb[0] = MBA_SCSI_COMPLETION;		break;	case MBA_CMPLT_2_32BIT:		handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1]));		handles[1] = le32_to_cpu(		    ((uint32_t)(RD_MAILBOX_REG(ha, reg, 7) << 16)) |		    RD_MAILBOX_REG(ha, reg, 6));		handle_cnt = 2;		mb[0] = MBA_SCSI_COMPLETION;		break;	default:		break;	}	switch (mb[0]) {	case MBA_SCSI_COMPLETION:	/* Fast Post */		if (!ha->flags.online)			break;		for (cnt = 0; cnt < handle_cnt; cnt++)			qla2x00_process_completed_request(ha, handles[cnt]);		break;	case MBA_RESET:			/* Reset */		DEBUG2(printk("scsi(%ld): Asynchronous RESET.\n", ha->host_no));		set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);		break;	case MBA_SYSTEM_ERR:		/* System Error */		mb[1] = RD_MAILBOX_REG(ha, reg, 1);		mb[2] = RD_MAILBOX_REG(ha, reg, 2);		mb[3] = RD_MAILBOX_REG(ha, reg, 3);		qla_printk(KERN_INFO, ha,		    "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n",		    mb[1], mb[2], mb[3]);		ha->isp_ops.fw_dump(ha, 1);		if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {			if (mb[1] == 0 && mb[2] == 0) {				qla_printk(KERN_ERR, ha,				    "Unrecoverable Hardware Error: adapter "				    "marked OFFLINE!\n");				ha->flags.online = 0;			} else				set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);		} else if (mb[1] == 0) {			qla_printk(KERN_INFO, ha,			    "Unrecoverable Hardware Error: adapter marked "			    "OFFLINE!\n");			ha->flags.online = 0;		} else			set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);		break;	case MBA_REQ_TRANSFER_ERR:	/* Request Transfer Error */		DEBUG2(printk("scsi(%ld): ISP Request Transfer Error.\n",		    ha->host_no));		qla_printk(KERN_WARNING, ha, "ISP Request Transfer Error.\n");		set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);		break;	case MBA_RSP_TRANSFER_ERR:	/* Response Transfer Error */		DEBUG2(printk("scsi(%ld): ISP Response Transfer Error.\n",		    ha->host_no));		qla_printk(KERN_WARNING, ha, "ISP Response Transfer Error.\n");		set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);		break;	case MBA_WAKEUP_THRES:		/* Request Queue Wake-up */		DEBUG2(printk("scsi(%ld): Asynchronous WAKEUP_THRES.\n",		    ha->host_no));		break;	case MBA_LIP_OCCURRED:		/* Loop Initialization Procedure */		DEBUG2(printk("scsi(%ld): LIP occured (%x).\n", ha->host_no,		    mb[1]));		qla_printk(KERN_INFO, ha, "LIP occured (%x).\n", mb[1]);		if (atomic_read(&ha->loop_state) != LOOP_DOWN) {			atomic_set(&ha->loop_state, LOOP_DOWN);			atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);			qla2x00_mark_all_devices_lost(ha);		}		set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);		ha->flags.management_server_logged_in = 0;		/* Update AEN queue. */		qla2x00_enqueue_aen(ha, MBA_LIP_OCCURRED, NULL);		break;	case MBA_LOOP_UP:		/* Loop Up Event */		ha->link_data_rate = 0;		if (IS_QLA2100(ha) || IS_QLA2200(ha)) {			link_speed = link_speeds[0];		} else {			link_speed = link_speeds[LS_UNKNOWN];			if (mb[1] < 5)				link_speed = link_speeds[mb[1]];			ha->link_data_rate = mb[1];		}		DEBUG2(printk("scsi(%ld): Asynchronous LOOP UP (%s Gbps).\n",		    ha->host_no, link_speed));		qla_printk(KERN_INFO, ha, "LOOP UP detected (%s Gbps).\n",		    link_speed);		ha->flags.management_server_logged_in = 0;		/* Update AEN queue. */		qla2x00_enqueue_aen(ha, MBA_LOOP_UP, NULL);		break;	case MBA_LOOP_DOWN:		/* Loop Down Event */		DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN (%x).\n",		    ha->host_no, mb[1]));		qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x).\n", mb[1]);		if (atomic_read(&ha->loop_state) != LOOP_DOWN) {			atomic_set(&ha->loop_state, LOOP_DOWN);			atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);			ha->device_flags |= DFLG_NO_CABLE;			qla2x00_mark_all_devices_lost(ha);		}		ha->flags.management_server_logged_in = 0;		ha->link_data_rate = 0;		if (ql2xfdmienable)			set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);		/* Update AEN queue. */		qla2x00_enqueue_aen(ha, MBA_LOOP_DOWN, NULL);		break;	case MBA_LIP_RESET:		/* LIP reset occurred */		DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n",		    ha->host_no, mb[1]));		qla_printk(KERN_INFO, ha,		    "LIP reset occured (%x).\n", mb[1]);		if (atomic_read(&ha->loop_state) != LOOP_DOWN) {			atomic_set(&ha->loop_state, LOOP_DOWN);			atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);			qla2x00_mark_all_devices_lost(ha);		}		set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);		ha->operating_mode = LOOP;		ha->flags.management_server_logged_in = 0;		/* Update AEN queue. */		qla2x00_enqueue_aen(ha, MBA_LIP_RESET, NULL);		break;	case MBA_POINT_TO_POINT:	/* Point-to-Point */		if (IS_QLA2100(ha))			break;		DEBUG2(printk("scsi(%ld): Asynchronous P2P MODE received.\n",		    ha->host_no));		/*		 * Until there's a transition from loop down to loop up, treat		 * this as loop down only.		 */		if (atomic_read(&ha->loop_state) != LOOP_DOWN) {			atomic_set(&ha->loop_state, LOOP_DOWN);			if (!atomic_read(&ha->loop_down_timer))				atomic_set(&ha->loop_down_timer,				    LOOP_DOWN_TIME);			qla2x00_mark_all_devices_lost(ha);		}		if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) {			set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);		}		set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);		break;	case MBA_CHG_IN_CONNECTION:	/* Change in connection mode */		if (IS_QLA2100(ha))			break;		DEBUG2(printk("scsi(%ld): Asynchronous Change In Connection "		    "received.\n",		    ha->host_no));		qla_printk(KERN_INFO, ha,		    "Configuration change detected: value=%x.\n", mb[1]);		if (atomic_read(&ha->loop_state) != LOOP_DOWN) {			atomic_set(&ha->loop_state, LOOP_DOWN);			if (!atomic_read(&ha->loop_down_timer))				atomic_set(&ha->loop_down_timer,				    LOOP_DOWN_TIME);			qla2x00_mark_all_devices_lost(ha);		}		set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);		set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);

⌨️ 快捷键说明

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