diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2010-05-10 11:59:37 +0200 | 
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2010-05-10 14:20:42 +0200 | 
| commit | dbb6be6d5e974c42bbecd183effaa0df69e1dd8b (patch) | |
| tree | 5735cb47e70853d057a9881dd0ce44b83e88fa63 /drivers/scsi/bfa/bfa_intr.c | |
| parent | 6a867a395558a7f882d041783e4cdea6744ca2bf (diff) | |
| parent | b57f95a38233a2e73b679bea4a5453a1cc2a1cc9 (diff) | |
| download | olio-linux-3.10-dbb6be6d5e974c42bbecd183effaa0df69e1dd8b.tar.xz olio-linux-3.10-dbb6be6d5e974c42bbecd183effaa0df69e1dd8b.zip  | |
Merge branch 'linus' into timers/core
Reason: Further posix_cpu_timer patches depend on mainline changes
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/scsi/bfa/bfa_intr.c')
| -rw-r--r-- | drivers/scsi/bfa/bfa_intr.c | 111 | 
1 files changed, 81 insertions, 30 deletions
diff --git a/drivers/scsi/bfa/bfa_intr.c b/drivers/scsi/bfa/bfa_intr.c index b36540e4ed7..0eba3f930d5 100644 --- a/drivers/scsi/bfa/bfa_intr.c +++ b/drivers/scsi/bfa/bfa_intr.c @@ -15,7 +15,7 @@   * General Public License for more details.   */  #include <bfa.h> -#include <bfi/bfi_cbreg.h> +#include <bfi/bfi_ctreg.h>  #include <bfa_port_priv.h>  #include <bfa_intr_priv.h>  #include <cs/bfa_debug.h> @@ -34,6 +34,26 @@ bfa_msix_lpu(struct bfa_s *bfa)  	bfa_ioc_mbox_isr(&bfa->ioc);  } +static void +bfa_reqq_resume(struct bfa_s *bfa, int qid) +{ +	struct list_head *waitq, *qe, *qen; +	struct bfa_reqq_wait_s *wqe; + +	waitq = bfa_reqq(bfa, qid); +	list_for_each_safe(qe, qen, waitq) { +		/** +		 * Callback only as long as there is room in request queue +		 */ +		if (bfa_reqq_full(bfa, qid)) +			break; + +		list_del(qe); +		wqe = (struct bfa_reqq_wait_s *) qe; +		wqe->qresume(wqe->cbarg); +	} +} +  void  bfa_msix_all(struct bfa_s *bfa, int vec)  { @@ -96,7 +116,8 @@ bfa_isr_enable(struct bfa_s *bfa)  	bfa_msix_install(bfa);  	intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 | -		       __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS); +		       __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | +		       __HFN_INT_LL_HALT);  	if (pci_func == 0)  		intr_unmask |= (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 | @@ -127,23 +148,18 @@ bfa_isr_disable(struct bfa_s *bfa)  void  bfa_msix_reqq(struct bfa_s *bfa, int qid)  { -	struct list_head 		*waitq, *qe, *qen; -	struct bfa_reqq_wait_s	*wqe; +	struct list_head *waitq;  	qid &= (BFI_IOC_MAX_CQS - 1); -	waitq = bfa_reqq(bfa, qid); -	list_for_each_safe(qe, qen, waitq) { -		/** -		 * Callback only as long as there is room in request queue -		 */ -		if (bfa_reqq_full(bfa, qid)) -			break; +	bfa->iocfc.hwif.hw_reqq_ack(bfa, qid); -		list_del(qe); -		wqe = (struct bfa_reqq_wait_s *) qe; -		wqe->qresume(wqe->cbarg); -	} +	/** +	 * Resume any pending requests in the corresponding reqq. +	 */ +	waitq = bfa_reqq(bfa, qid); +	if (!list_empty(waitq)) +		bfa_reqq_resume(bfa, qid);  }  void @@ -157,26 +173,27 @@ bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)  }  void -bfa_msix_rspq(struct bfa_s *bfa, int rsp_qid) +bfa_msix_rspq(struct bfa_s *bfa, int qid)  { -	struct bfi_msg_s      *m; -	u32        pi, ci; +	struct bfi_msg_s *m; +	u32 pi, ci; +	struct list_head *waitq; -	bfa_trc_fp(bfa, rsp_qid); +	bfa_trc_fp(bfa, qid); -	rsp_qid &= (BFI_IOC_MAX_CQS - 1); +	qid &= (BFI_IOC_MAX_CQS - 1); -	bfa->iocfc.hwif.hw_rspq_ack(bfa, rsp_qid); +	bfa->iocfc.hwif.hw_rspq_ack(bfa, qid); -	ci = bfa_rspq_ci(bfa, rsp_qid); -	pi = bfa_rspq_pi(bfa, rsp_qid); +	ci = bfa_rspq_ci(bfa, qid); +	pi = bfa_rspq_pi(bfa, qid);  	bfa_trc_fp(bfa, ci);  	bfa_trc_fp(bfa, pi);  	if (bfa->rme_process) {  		while (ci != pi) { -			m = bfa_rspq_elem(bfa, rsp_qid, ci); +			m = bfa_rspq_elem(bfa, qid, ci);  			bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX);  			bfa_isrs[m->mhdr.msg_class] (bfa, m); @@ -188,25 +205,59 @@ bfa_msix_rspq(struct bfa_s *bfa, int rsp_qid)  	/**  	 * update CI  	 */ -	bfa_rspq_ci(bfa, rsp_qid) = pi; -	bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[rsp_qid], pi); +	bfa_rspq_ci(bfa, qid) = pi; +	bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[qid], pi);  	bfa_os_mmiowb(); + +	/** +	 * Resume any pending requests in the corresponding reqq. +	 */ +	waitq = bfa_reqq(bfa, qid); +	if (!list_empty(waitq)) +		bfa_reqq_resume(bfa, qid);  }  void  bfa_msix_lpu_err(struct bfa_s *bfa, int vec)  { -	u32 intr; +	u32 intr, curr_value;  	intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);  	if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))  		bfa_msix_lpu(bfa); -	if (intr & (__HFN_INT_ERR_EMC | -		    __HFN_INT_ERR_LPU0 | __HFN_INT_ERR_LPU1 | -		    __HFN_INT_ERR_PSS)) +	intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 | +		__HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT); + +	if (intr) { +		if (intr & __HFN_INT_LL_HALT) { +			/** +			 * If LL_HALT bit is set then FW Init Halt LL Port +			 * Register needs to be cleared as well so Interrupt +			 * Status Register will be cleared. +			 */ +			curr_value = bfa_reg_read(bfa->ioc.ioc_regs.ll_halt); +			curr_value &= ~__FW_INIT_HALT_P; +			bfa_reg_write(bfa->ioc.ioc_regs.ll_halt, curr_value); +		} + +		if (intr & __HFN_INT_ERR_PSS) { +			/** +			 * ERR_PSS bit needs to be cleared as well in case +			 * interrups are shared so driver's interrupt handler is +			 * still called eventhough it is already masked out. +			 */ +			curr_value = bfa_reg_read( +				bfa->ioc.ioc_regs.pss_err_status_reg); +			curr_value &= __PSS_ERR_STATUS_SET; +			bfa_reg_write(bfa->ioc.ioc_regs.pss_err_status_reg, +				curr_value); +		} + +		bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr);  		bfa_msix_errint(bfa, intr); +	}  }  void  |