xref: /linux/drivers/scsi/bfa/bfa_hw_cb.c (revision 52fa7bf9eadac744eff74d71234c785aade6032f)
1*52fa7bf9SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
27725ccfdSJing Huang /*
3889d0d42SAnil Gurumurthy  * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
4889d0d42SAnil Gurumurthy  * Copyright (c) 2014- QLogic Corporation.
57725ccfdSJing Huang  * All rights reserved
6889d0d42SAnil Gurumurthy  * www.qlogic.com
77725ccfdSJing Huang  *
831e1d569SAnil Gurumurthy  * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
97725ccfdSJing Huang  */
107725ccfdSJing Huang 
11f16a1750SMaggie Zhang #include "bfad_drv.h"
12a36c61f9SKrishna Gudipati #include "bfa_modules.h"
1311189208SKrishna Gudipati #include "bfi_reg.h"
147725ccfdSJing Huang 
157725ccfdSJing Huang void
167725ccfdSJing Huang bfa_hwcb_reginit(struct bfa_s *bfa)
177725ccfdSJing Huang {
187725ccfdSJing Huang 	struct bfa_iocfc_regs_s	*bfa_regs = &bfa->iocfc.bfa_regs;
1953440260SJing Huang 	void __iomem *kva = bfa_ioc_bar0(&bfa->ioc);
2011189208SKrishna Gudipati 	int	fn = bfa_ioc_pcifn(&bfa->ioc);
217725ccfdSJing Huang 
227725ccfdSJing Huang 	if (fn == 0) {
237725ccfdSJing Huang 		bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
247725ccfdSJing Huang 		bfa_regs->intr_mask   = (kva + HOSTFN0_INT_MSK);
257725ccfdSJing Huang 	} else {
267725ccfdSJing Huang 		bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS);
277725ccfdSJing Huang 		bfa_regs->intr_mask   = (kva + HOSTFN1_INT_MSK);
287725ccfdSJing Huang 	}
297725ccfdSJing Huang }
307725ccfdSJing Huang 
31f5713c5dSKrishna Gudipati static void
32f5713c5dSKrishna Gudipati bfa_hwcb_reqq_ack_msix(struct bfa_s *bfa, int reqq)
33f5713c5dSKrishna Gudipati {
3453440260SJing Huang 	writel(__HFN_INT_CPE_Q0 << CPE_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), reqq),
3553440260SJing Huang 			bfa->iocfc.bfa_regs.intr_status);
36f5713c5dSKrishna Gudipati }
37f5713c5dSKrishna Gudipati 
38ca6e0ea7SKrishna Gudipati /*
39ca6e0ea7SKrishna Gudipati  * Actions to respond RME Interrupt for Crossbow ASIC:
40ca6e0ea7SKrishna Gudipati  * - Write 1 to Interrupt Status register
41ca6e0ea7SKrishna Gudipati  *              INTX - done in bfa_intx()
42ca6e0ea7SKrishna Gudipati  *              MSIX - done in bfa_hwcb_rspq_ack_msix()
43ca6e0ea7SKrishna Gudipati  * - Update CI (only if new CI)
44ca6e0ea7SKrishna Gudipati  */
457725ccfdSJing Huang static void
46ca6e0ea7SKrishna Gudipati bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq, u32 ci)
477725ccfdSJing Huang {
4853440260SJing Huang 	writel(__HFN_INT_RME_Q0 << RME_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), rspq),
4953440260SJing Huang 		bfa->iocfc.bfa_regs.intr_status);
50ca6e0ea7SKrishna Gudipati 
51ca6e0ea7SKrishna Gudipati 	if (bfa_rspq_ci(bfa, rspq) == ci)
52ca6e0ea7SKrishna Gudipati 		return;
53ca6e0ea7SKrishna Gudipati 
54ca6e0ea7SKrishna Gudipati 	bfa_rspq_ci(bfa, rspq) = ci;
55ca6e0ea7SKrishna Gudipati 	writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]);
56ca6e0ea7SKrishna Gudipati }
57ca6e0ea7SKrishna Gudipati 
58ca6e0ea7SKrishna Gudipati void
59ca6e0ea7SKrishna Gudipati bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq, u32 ci)
60ca6e0ea7SKrishna Gudipati {
61ca6e0ea7SKrishna Gudipati 	if (bfa_rspq_ci(bfa, rspq) == ci)
62ca6e0ea7SKrishna Gudipati 		return;
63ca6e0ea7SKrishna Gudipati 
64ca6e0ea7SKrishna Gudipati 	bfa_rspq_ci(bfa, rspq) = ci;
65ca6e0ea7SKrishna Gudipati 	writel(ci, bfa->iocfc.bfa_regs.rme_q_ci[rspq]);
667725ccfdSJing Huang }
677725ccfdSJing Huang 
687725ccfdSJing Huang void
697725ccfdSJing Huang bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
707725ccfdSJing Huang 		 u32 *num_vecs, u32 *max_vec_bit)
717725ccfdSJing Huang {
727725ccfdSJing Huang #define __HFN_NUMINTS	13
737725ccfdSJing Huang 	if (bfa_ioc_pcifn(&bfa->ioc) == 0) {
747725ccfdSJing Huang 		*msix_vecs_bmap = (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
757725ccfdSJing Huang 				   __HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
767725ccfdSJing Huang 				   __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
777725ccfdSJing Huang 				   __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
787725ccfdSJing Huang 				   __HFN_INT_MBOX_LPU0);
797725ccfdSJing Huang 		*max_vec_bit = __HFN_INT_MBOX_LPU0;
807725ccfdSJing Huang 	} else {
817725ccfdSJing Huang 		*msix_vecs_bmap = (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
827725ccfdSJing Huang 				   __HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
837725ccfdSJing Huang 				   __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
847725ccfdSJing Huang 				   __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
857725ccfdSJing Huang 				   __HFN_INT_MBOX_LPU1);
867725ccfdSJing Huang 		*max_vec_bit = __HFN_INT_MBOX_LPU1;
877725ccfdSJing Huang 	}
887725ccfdSJing Huang 
897725ccfdSJing Huang 	*msix_vecs_bmap |= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
907725ccfdSJing Huang 			    __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS);
917725ccfdSJing Huang 	*num_vecs = __HFN_NUMINTS;
927725ccfdSJing Huang }
937725ccfdSJing Huang 
945fbe25c7SJing Huang /*
95775c7742SKrishna Gudipati  * Dummy interrupt handler for handling spurious interrupts.
96775c7742SKrishna Gudipati  */
97775c7742SKrishna Gudipati static void
98775c7742SKrishna Gudipati bfa_hwcb_msix_dummy(struct bfa_s *bfa, int vec)
99775c7742SKrishna Gudipati {
100775c7742SKrishna Gudipati }
101775c7742SKrishna Gudipati 
102775c7742SKrishna Gudipati /*
1037725ccfdSJing Huang  * No special setup required for crossbow -- vector assignments are implicit.
1047725ccfdSJing Huang  */
1057725ccfdSJing Huang void
1067725ccfdSJing Huang bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs)
1077725ccfdSJing Huang {
108d4b671c5SJing Huang 	WARN_ON((nvecs != 1) && (nvecs != __HFN_NUMINTS));
1097725ccfdSJing Huang 
1107725ccfdSJing Huang 	bfa->msix.nvecs = nvecs;
111775c7742SKrishna Gudipati 	bfa_hwcb_msix_uninstall(bfa);
112775c7742SKrishna Gudipati }
113775c7742SKrishna Gudipati 
114775c7742SKrishna Gudipati void
115775c7742SKrishna Gudipati bfa_hwcb_msix_ctrl_install(struct bfa_s *bfa)
116775c7742SKrishna Gudipati {
117775c7742SKrishna Gudipati 	int i;
118775c7742SKrishna Gudipati 
119775c7742SKrishna Gudipati 	if (bfa->msix.nvecs == 0)
120775c7742SKrishna Gudipati 		return;
121775c7742SKrishna Gudipati 
122775c7742SKrishna Gudipati 	if (bfa->msix.nvecs == 1) {
12310a07379SKrishna Gudipati 		for (i = BFI_MSIX_CPE_QMIN_CB; i < BFI_MSIX_CB_MAX; i++)
124775c7742SKrishna Gudipati 			bfa->msix.handler[i] = bfa_msix_all;
125775c7742SKrishna Gudipati 		return;
126775c7742SKrishna Gudipati 	}
127775c7742SKrishna Gudipati 
128775c7742SKrishna Gudipati 	for (i = BFI_MSIX_RME_QMAX_CB+1; i < BFI_MSIX_CB_MAX; i++)
129775c7742SKrishna Gudipati 		bfa->msix.handler[i] = bfa_msix_lpu_err;
130775c7742SKrishna Gudipati }
131775c7742SKrishna Gudipati 
132775c7742SKrishna Gudipati void
133775c7742SKrishna Gudipati bfa_hwcb_msix_queue_install(struct bfa_s *bfa)
134775c7742SKrishna Gudipati {
135775c7742SKrishna Gudipati 	int i;
136775c7742SKrishna Gudipati 
137775c7742SKrishna Gudipati 	if (bfa->msix.nvecs == 0)
138775c7742SKrishna Gudipati 		return;
139775c7742SKrishna Gudipati 
140775c7742SKrishna Gudipati 	if (bfa->msix.nvecs == 1) {
141775c7742SKrishna Gudipati 		for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++)
1427725ccfdSJing Huang 			bfa->msix.handler[i] = bfa_msix_all;
1437725ccfdSJing Huang 		return;
1447725ccfdSJing Huang 	}
1457725ccfdSJing Huang 
14611189208SKrishna Gudipati 	for (i = BFI_MSIX_CPE_QMIN_CB; i <= BFI_MSIX_CPE_QMAX_CB; i++)
1477725ccfdSJing Huang 		bfa->msix.handler[i] = bfa_msix_reqq;
1487725ccfdSJing Huang 
14911189208SKrishna Gudipati 	for (i = BFI_MSIX_RME_QMIN_CB; i <= BFI_MSIX_RME_QMAX_CB; i++)
1507725ccfdSJing Huang 		bfa->msix.handler[i] = bfa_msix_rspq;
1517725ccfdSJing Huang }
1527725ccfdSJing Huang 
1537725ccfdSJing Huang void
1547725ccfdSJing Huang bfa_hwcb_msix_uninstall(struct bfa_s *bfa)
1557725ccfdSJing Huang {
156775c7742SKrishna Gudipati 	int i;
157775c7742SKrishna Gudipati 
158775c7742SKrishna Gudipati 	for (i = 0; i < BFI_MSIX_CB_MAX; i++)
159775c7742SKrishna Gudipati 		bfa->msix.handler[i] = bfa_hwcb_msix_dummy;
1607725ccfdSJing Huang }
1617725ccfdSJing Huang 
1625fbe25c7SJing Huang /*
1637725ccfdSJing Huang  * No special enable/disable -- vector assignments are implicit.
1647725ccfdSJing Huang  */
1657725ccfdSJing Huang void
1667725ccfdSJing Huang bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix)
1677725ccfdSJing Huang {
168ca6e0ea7SKrishna Gudipati 	if (msix) {
169f5713c5dSKrishna Gudipati 		bfa->iocfc.hwif.hw_reqq_ack = bfa_hwcb_reqq_ack_msix;
1707725ccfdSJing Huang 		bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix;
171ca6e0ea7SKrishna Gudipati 	} else {
172ca6e0ea7SKrishna Gudipati 		bfa->iocfc.hwif.hw_reqq_ack = NULL;
173ca6e0ea7SKrishna Gudipati 		bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
174ca6e0ea7SKrishna Gudipati 	}
1757725ccfdSJing Huang }
1767725ccfdSJing Huang 
17736d345a7SJing Huang void
17836d345a7SJing Huang bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end)
17936d345a7SJing Huang {
18011189208SKrishna Gudipati 	*start = BFI_MSIX_RME_QMIN_CB;
18111189208SKrishna Gudipati 	*end = BFI_MSIX_RME_QMAX_CB;
18236d345a7SJing Huang }
183