xref: /freebsd/sys/dev/liquidio/base/cn23xx_pf_device.c (revision f173c2b77e0287807852bb7ba982643f33bdf8a0)
1*f173c2b7SSean Bruno /*
2*f173c2b7SSean Bruno  *   BSD LICENSE
3*f173c2b7SSean Bruno  *
4*f173c2b7SSean Bruno  *   Copyright(c) 2017 Cavium, Inc.. All rights reserved.
5*f173c2b7SSean Bruno  *   All rights reserved.
6*f173c2b7SSean Bruno  *
7*f173c2b7SSean Bruno  *   Redistribution and use in source and binary forms, with or without
8*f173c2b7SSean Bruno  *   modification, are permitted provided that the following conditions
9*f173c2b7SSean Bruno  *   are met:
10*f173c2b7SSean Bruno  *
11*f173c2b7SSean Bruno  *     * Redistributions of source code must retain the above copyright
12*f173c2b7SSean Bruno  *       notice, this list of conditions and the following disclaimer.
13*f173c2b7SSean Bruno  *     * Redistributions in binary form must reproduce the above copyright
14*f173c2b7SSean Bruno  *       notice, this list of conditions and the following disclaimer in
15*f173c2b7SSean Bruno  *       the documentation and/or other materials provided with the
16*f173c2b7SSean Bruno  *       distribution.
17*f173c2b7SSean Bruno  *     * Neither the name of Cavium, Inc. nor the names of its
18*f173c2b7SSean Bruno  *       contributors may be used to endorse or promote products derived
19*f173c2b7SSean Bruno  *       from this software without specific prior written permission.
20*f173c2b7SSean Bruno  *
21*f173c2b7SSean Bruno  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*f173c2b7SSean Bruno  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*f173c2b7SSean Bruno  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24*f173c2b7SSean Bruno  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25*f173c2b7SSean Bruno  *   OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26*f173c2b7SSean Bruno  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27*f173c2b7SSean Bruno  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28*f173c2b7SSean Bruno  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29*f173c2b7SSean Bruno  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30*f173c2b7SSean Bruno  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31*f173c2b7SSean Bruno  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*f173c2b7SSean Bruno  */
33*f173c2b7SSean Bruno /*$FreeBSD$*/
34*f173c2b7SSean Bruno 
35*f173c2b7SSean Bruno #include "lio_bsd.h"
36*f173c2b7SSean Bruno #include "lio_common.h"
37*f173c2b7SSean Bruno #include "lio_droq.h"
38*f173c2b7SSean Bruno #include "lio_iq.h"
39*f173c2b7SSean Bruno #include "lio_response_manager.h"
40*f173c2b7SSean Bruno #include "lio_device.h"
41*f173c2b7SSean Bruno #include "cn23xx_pf_device.h"
42*f173c2b7SSean Bruno #include "lio_main.h"
43*f173c2b7SSean Bruno #include "lio_rss.h"
44*f173c2b7SSean Bruno 
45*f173c2b7SSean Bruno static int
46*f173c2b7SSean Bruno lio_cn23xx_pf_soft_reset(struct octeon_device *oct)
47*f173c2b7SSean Bruno {
48*f173c2b7SSean Bruno 
49*f173c2b7SSean Bruno 	lio_write_csr64(oct, LIO_CN23XX_SLI_WIN_WR_MASK_REG, 0xFF);
50*f173c2b7SSean Bruno 
51*f173c2b7SSean Bruno 	lio_dev_dbg(oct, "BIST enabled for CN23XX soft reset\n");
52*f173c2b7SSean Bruno 
53*f173c2b7SSean Bruno 	lio_write_csr64(oct, LIO_CN23XX_SLI_SCRATCH1, 0x1234ULL);
54*f173c2b7SSean Bruno 
55*f173c2b7SSean Bruno 	/* Initiate chip-wide soft reset */
56*f173c2b7SSean Bruno 	lio_pci_readq(oct, LIO_CN23XX_RST_SOFT_RST);
57*f173c2b7SSean Bruno 	lio_pci_writeq(oct, 1, LIO_CN23XX_RST_SOFT_RST);
58*f173c2b7SSean Bruno 
59*f173c2b7SSean Bruno 	/* Wait for 100ms as Octeon resets. */
60*f173c2b7SSean Bruno 	lio_mdelay(100);
61*f173c2b7SSean Bruno 
62*f173c2b7SSean Bruno 	if (lio_read_csr64(oct, LIO_CN23XX_SLI_SCRATCH1)) {
63*f173c2b7SSean Bruno 		lio_dev_err(oct, "Soft reset failed\n");
64*f173c2b7SSean Bruno 		return (1);
65*f173c2b7SSean Bruno 	}
66*f173c2b7SSean Bruno 
67*f173c2b7SSean Bruno 	lio_dev_dbg(oct, "Reset completed\n");
68*f173c2b7SSean Bruno 
69*f173c2b7SSean Bruno 	/* restore the  reset value */
70*f173c2b7SSean Bruno 	lio_write_csr64(oct, LIO_CN23XX_SLI_WIN_WR_MASK_REG, 0xFF);
71*f173c2b7SSean Bruno 
72*f173c2b7SSean Bruno 	return (0);
73*f173c2b7SSean Bruno }
74*f173c2b7SSean Bruno 
75*f173c2b7SSean Bruno static void
76*f173c2b7SSean Bruno lio_cn23xx_pf_enable_error_reporting(struct octeon_device *oct)
77*f173c2b7SSean Bruno {
78*f173c2b7SSean Bruno 	uint32_t	corrtable_err_status, uncorrectable_err_mask, regval;
79*f173c2b7SSean Bruno 
80*f173c2b7SSean Bruno 	regval = lio_read_pci_cfg(oct, LIO_CN23XX_CFG_PCIE_DEVCTL);
81*f173c2b7SSean Bruno 	if (regval & LIO_CN23XX_CFG_PCIE_DEVCTL_MASK) {
82*f173c2b7SSean Bruno 		uncorrectable_err_mask = 0;
83*f173c2b7SSean Bruno 		corrtable_err_status = 0;
84*f173c2b7SSean Bruno 		uncorrectable_err_mask =
85*f173c2b7SSean Bruno 		    lio_read_pci_cfg(oct,
86*f173c2b7SSean Bruno 				     LIO_CN23XX_CFG_PCIE_UNCORRECT_ERR_MASK);
87*f173c2b7SSean Bruno 		corrtable_err_status =
88*f173c2b7SSean Bruno 		    lio_read_pci_cfg(oct,
89*f173c2b7SSean Bruno 				     LIO_CN23XX_CFG_PCIE_CORRECT_ERR_STATUS);
90*f173c2b7SSean Bruno 		lio_dev_err(oct, "PCI-E Fatal error detected;\n"
91*f173c2b7SSean Bruno 			    "\tdev_ctl_status_reg = 0x%08x\n"
92*f173c2b7SSean Bruno 			    "\tuncorrectable_error_mask_reg = 0x%08x\n"
93*f173c2b7SSean Bruno 			    "\tcorrectable_error_status_reg = 0x%08x\n",
94*f173c2b7SSean Bruno 			    regval, uncorrectable_err_mask,
95*f173c2b7SSean Bruno 			    corrtable_err_status);
96*f173c2b7SSean Bruno 	}
97*f173c2b7SSean Bruno 
98*f173c2b7SSean Bruno 	regval |= 0xf;	/* Enable Link error reporting */
99*f173c2b7SSean Bruno 
100*f173c2b7SSean Bruno 	lio_dev_dbg(oct, "Enabling PCI-E error reporting..\n");
101*f173c2b7SSean Bruno 	lio_write_pci_cfg(oct, LIO_CN23XX_CFG_PCIE_DEVCTL, regval);
102*f173c2b7SSean Bruno }
103*f173c2b7SSean Bruno 
104*f173c2b7SSean Bruno static uint32_t
105*f173c2b7SSean Bruno lio_cn23xx_pf_coprocessor_clock(struct octeon_device *oct)
106*f173c2b7SSean Bruno {
107*f173c2b7SSean Bruno 	/*
108*f173c2b7SSean Bruno 	 * Bits 29:24 of RST_BOOT[PNR_MUL] holds the ref.clock MULTIPLIER
109*f173c2b7SSean Bruno 	 * for SLI.
110*f173c2b7SSean Bruno 	 */
111*f173c2b7SSean Bruno 
112*f173c2b7SSean Bruno 	/* TBD: get the info in Hand-shake */
113*f173c2b7SSean Bruno 	return (((lio_pci_readq(oct, LIO_CN23XX_RST_BOOT) >> 24) & 0x3f) * 50);
114*f173c2b7SSean Bruno }
115*f173c2b7SSean Bruno 
116*f173c2b7SSean Bruno uint32_t
117*f173c2b7SSean Bruno lio_cn23xx_pf_get_oq_ticks(struct octeon_device *oct, uint32_t time_intr_in_us)
118*f173c2b7SSean Bruno {
119*f173c2b7SSean Bruno 	/* This gives the SLI clock per microsec */
120*f173c2b7SSean Bruno 	uint32_t	oqticks_per_us = lio_cn23xx_pf_coprocessor_clock(oct);
121*f173c2b7SSean Bruno 
122*f173c2b7SSean Bruno 	oct->pfvf_hsword.coproc_tics_per_us = oqticks_per_us;
123*f173c2b7SSean Bruno 
124*f173c2b7SSean Bruno 	/* This gives the clock cycles per millisecond */
125*f173c2b7SSean Bruno 	oqticks_per_us *= 1000;
126*f173c2b7SSean Bruno 
127*f173c2b7SSean Bruno 	/* This gives the oq ticks (1024 core clock cycles) per millisecond */
128*f173c2b7SSean Bruno 	oqticks_per_us /= 1024;
129*f173c2b7SSean Bruno 
130*f173c2b7SSean Bruno 	/*
131*f173c2b7SSean Bruno 	 * time_intr is in microseconds. The next 2 steps gives the oq ticks
132*f173c2b7SSean Bruno 	 * corresponding to time_intr.
133*f173c2b7SSean Bruno 	 */
134*f173c2b7SSean Bruno 	oqticks_per_us *= time_intr_in_us;
135*f173c2b7SSean Bruno 	oqticks_per_us /= 1000;
136*f173c2b7SSean Bruno 
137*f173c2b7SSean Bruno 	return (oqticks_per_us);
138*f173c2b7SSean Bruno }
139*f173c2b7SSean Bruno 
140*f173c2b7SSean Bruno static void
141*f173c2b7SSean Bruno lio_cn23xx_pf_setup_global_mac_regs(struct octeon_device *oct)
142*f173c2b7SSean Bruno {
143*f173c2b7SSean Bruno 	uint64_t	reg_val;
144*f173c2b7SSean Bruno 	uint16_t	mac_no = oct->pcie_port;
145*f173c2b7SSean Bruno 	uint16_t	pf_num = oct->pf_num;
146*f173c2b7SSean Bruno 	/* programming SRN and TRS for each MAC(0..3)  */
147*f173c2b7SSean Bruno 
148*f173c2b7SSean Bruno 	lio_dev_dbg(oct, "%s: Using pcie port %d\n", __func__, mac_no);
149*f173c2b7SSean Bruno 	/* By default, mapping all 64 IOQs to  a single MACs */
150*f173c2b7SSean Bruno 
151*f173c2b7SSean Bruno 	reg_val =
152*f173c2b7SSean Bruno 	    lio_read_csr64(oct, LIO_CN23XX_SLI_PKT_MAC_RINFO64(mac_no, pf_num));
153*f173c2b7SSean Bruno 
154*f173c2b7SSean Bruno 	/* setting SRN <6:0>  */
155*f173c2b7SSean Bruno 	reg_val = pf_num * LIO_CN23XX_PF_MAX_RINGS;
156*f173c2b7SSean Bruno 
157*f173c2b7SSean Bruno 	/* setting TRS <23:16> */
158*f173c2b7SSean Bruno 	reg_val = reg_val |
159*f173c2b7SSean Bruno 	    (oct->sriov_info.trs << LIO_CN23XX_PKT_MAC_CTL_RINFO_TRS_BIT_POS);
160*f173c2b7SSean Bruno 
161*f173c2b7SSean Bruno 	/* write these settings to MAC register */
162*f173c2b7SSean Bruno 	lio_write_csr64(oct, LIO_CN23XX_SLI_PKT_MAC_RINFO64(mac_no, pf_num),
163*f173c2b7SSean Bruno 			reg_val);
164*f173c2b7SSean Bruno 
165*f173c2b7SSean Bruno 	lio_dev_dbg(oct, "SLI_PKT_MAC(%d)_PF(%d)_RINFO : 0x%016lx\n", mac_no,
166*f173c2b7SSean Bruno 		    pf_num,
167*f173c2b7SSean Bruno 		    lio_read_csr64(oct,
168*f173c2b7SSean Bruno 				   LIO_CN23XX_SLI_PKT_MAC_RINFO64(mac_no,
169*f173c2b7SSean Bruno 								  pf_num)));
170*f173c2b7SSean Bruno }
171*f173c2b7SSean Bruno 
172*f173c2b7SSean Bruno static int
173*f173c2b7SSean Bruno lio_cn23xx_pf_reset_io_queues(struct octeon_device *oct)
174*f173c2b7SSean Bruno {
175*f173c2b7SSean Bruno 	uint64_t	d64;
176*f173c2b7SSean Bruno 	uint32_t	ern, loop = BUSY_READING_REG_PF_LOOP_COUNT;
177*f173c2b7SSean Bruno 	uint32_t	q_no, srn;
178*f173c2b7SSean Bruno 	int		ret_val = 0;
179*f173c2b7SSean Bruno 
180*f173c2b7SSean Bruno 	srn = oct->sriov_info.pf_srn;
181*f173c2b7SSean Bruno 	ern = srn + oct->sriov_info.num_pf_rings;
182*f173c2b7SSean Bruno 
183*f173c2b7SSean Bruno 	/* As per HRM reg description, s/w cant write 0 to ENB. */
184*f173c2b7SSean Bruno 	/* to make the queue off, need to set the RST bit. */
185*f173c2b7SSean Bruno 
186*f173c2b7SSean Bruno 	/* Reset the Enable bit for all the 64 IQs.  */
187*f173c2b7SSean Bruno 	for (q_no = srn; q_no < ern; q_no++) {
188*f173c2b7SSean Bruno 		/* set RST bit to 1. This bit applies to both IQ and OQ */
189*f173c2b7SSean Bruno 		d64 = lio_read_csr64(oct,
190*f173c2b7SSean Bruno 				     LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
191*f173c2b7SSean Bruno 		d64 = d64 | LIO_CN23XX_PKT_INPUT_CTL_RST;
192*f173c2b7SSean Bruno 		lio_write_csr64(oct,
193*f173c2b7SSean Bruno 				LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no), d64);
194*f173c2b7SSean Bruno 	}
195*f173c2b7SSean Bruno 
196*f173c2b7SSean Bruno 	/* wait until the RST bit is clear or the RST and quiet bits are set */
197*f173c2b7SSean Bruno 	for (q_no = srn; q_no < ern; q_no++) {
198*f173c2b7SSean Bruno 		volatile uint64_t reg_val =
199*f173c2b7SSean Bruno 			lio_read_csr64(oct,
200*f173c2b7SSean Bruno 				       LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
201*f173c2b7SSean Bruno 		while ((reg_val & LIO_CN23XX_PKT_INPUT_CTL_RST) &&
202*f173c2b7SSean Bruno 		       !(reg_val & LIO_CN23XX_PKT_INPUT_CTL_QUIET) &&
203*f173c2b7SSean Bruno 		       loop) {
204*f173c2b7SSean Bruno 			reg_val = lio_read_csr64(oct,
205*f173c2b7SSean Bruno 				       LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
206*f173c2b7SSean Bruno 			loop--;
207*f173c2b7SSean Bruno 		}
208*f173c2b7SSean Bruno 
209*f173c2b7SSean Bruno 		if (!loop) {
210*f173c2b7SSean Bruno 			lio_dev_err(oct,
211*f173c2b7SSean Bruno 				    "clearing the reset reg failed or setting the quiet reg failed for qno: %u\n",
212*f173c2b7SSean Bruno 				    q_no);
213*f173c2b7SSean Bruno 			return (-1);
214*f173c2b7SSean Bruno 		}
215*f173c2b7SSean Bruno 
216*f173c2b7SSean Bruno 		reg_val &= ~LIO_CN23XX_PKT_INPUT_CTL_RST;
217*f173c2b7SSean Bruno 		lio_write_csr64(oct, LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
218*f173c2b7SSean Bruno 				reg_val);
219*f173c2b7SSean Bruno 
220*f173c2b7SSean Bruno 		reg_val = lio_read_csr64(oct,
221*f173c2b7SSean Bruno 					 LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
222*f173c2b7SSean Bruno 		if (reg_val & LIO_CN23XX_PKT_INPUT_CTL_RST) {
223*f173c2b7SSean Bruno 			lio_dev_err(oct, "clearing the reset failed for qno: %u\n",
224*f173c2b7SSean Bruno 				    q_no);
225*f173c2b7SSean Bruno 			ret_val = -1;
226*f173c2b7SSean Bruno 		}
227*f173c2b7SSean Bruno 	}
228*f173c2b7SSean Bruno 
229*f173c2b7SSean Bruno 	return (ret_val);
230*f173c2b7SSean Bruno }
231*f173c2b7SSean Bruno 
232*f173c2b7SSean Bruno static int
233*f173c2b7SSean Bruno lio_cn23xx_pf_setup_global_input_regs(struct octeon_device *oct)
234*f173c2b7SSean Bruno {
235*f173c2b7SSean Bruno 	struct lio_cn23xx_pf	*cn23xx = (struct lio_cn23xx_pf *)oct->chip;
236*f173c2b7SSean Bruno 	struct lio_instr_queue	*iq;
237*f173c2b7SSean Bruno 	uint64_t		intr_threshold;
238*f173c2b7SSean Bruno 	uint64_t		pf_num, reg_val;
239*f173c2b7SSean Bruno 	uint32_t		q_no, ern, srn;
240*f173c2b7SSean Bruno 
241*f173c2b7SSean Bruno 	pf_num = oct->pf_num;
242*f173c2b7SSean Bruno 
243*f173c2b7SSean Bruno 	srn = oct->sriov_info.pf_srn;
244*f173c2b7SSean Bruno 	ern = srn + oct->sriov_info.num_pf_rings;
245*f173c2b7SSean Bruno 
246*f173c2b7SSean Bruno 	if (lio_cn23xx_pf_reset_io_queues(oct))
247*f173c2b7SSean Bruno 		return (-1);
248*f173c2b7SSean Bruno 
249*f173c2b7SSean Bruno 	/*
250*f173c2b7SSean Bruno 	 * Set the MAC_NUM and PVF_NUM in IQ_PKT_CONTROL reg
251*f173c2b7SSean Bruno 	 * for all queues.Only PF can set these bits.
252*f173c2b7SSean Bruno 	 * bits 29:30 indicate the MAC num.
253*f173c2b7SSean Bruno 	 * bits 32:47 indicate the PVF num.
254*f173c2b7SSean Bruno 	 */
255*f173c2b7SSean Bruno 	for (q_no = 0; q_no < ern; q_no++) {
256*f173c2b7SSean Bruno 		reg_val = oct->pcie_port <<
257*f173c2b7SSean Bruno 			LIO_CN23XX_PKT_INPUT_CTL_MAC_NUM_POS;
258*f173c2b7SSean Bruno 
259*f173c2b7SSean Bruno 		reg_val |= pf_num << LIO_CN23XX_PKT_INPUT_CTL_PF_NUM_POS;
260*f173c2b7SSean Bruno 
261*f173c2b7SSean Bruno 		lio_write_csr64(oct, LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
262*f173c2b7SSean Bruno 				reg_val);
263*f173c2b7SSean Bruno 	}
264*f173c2b7SSean Bruno 
265*f173c2b7SSean Bruno 	/*
266*f173c2b7SSean Bruno 	 * Select ES, RO, NS, RDSIZE,DPTR Fomat#0 for
267*f173c2b7SSean Bruno 	 * pf queues
268*f173c2b7SSean Bruno 	 */
269*f173c2b7SSean Bruno 	for (q_no = srn; q_no < ern; q_no++) {
270*f173c2b7SSean Bruno 		uint32_t	inst_cnt_reg;
271*f173c2b7SSean Bruno 
272*f173c2b7SSean Bruno 		iq = oct->instr_queue[q_no];
273*f173c2b7SSean Bruno 		if (iq != NULL)
274*f173c2b7SSean Bruno 			inst_cnt_reg = iq->inst_cnt_reg;
275*f173c2b7SSean Bruno 		else
276*f173c2b7SSean Bruno 			inst_cnt_reg = LIO_CN23XX_SLI_IQ_INSTR_COUNT64(q_no);
277*f173c2b7SSean Bruno 
278*f173c2b7SSean Bruno 		reg_val =
279*f173c2b7SSean Bruno 		    lio_read_csr64(oct, LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
280*f173c2b7SSean Bruno 
281*f173c2b7SSean Bruno 		reg_val |= LIO_CN23XX_PKT_INPUT_CTL_MASK;
282*f173c2b7SSean Bruno 
283*f173c2b7SSean Bruno 		lio_write_csr64(oct, LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
284*f173c2b7SSean Bruno 				reg_val);
285*f173c2b7SSean Bruno 
286*f173c2b7SSean Bruno 		/* Set WMARK level for triggering PI_INT */
287*f173c2b7SSean Bruno 		/* intr_threshold = LIO_CN23XX_DEF_IQ_INTR_THRESHOLD & */
288*f173c2b7SSean Bruno 		intr_threshold = LIO_GET_IQ_INTR_PKT_CFG(cn23xx->conf) &
289*f173c2b7SSean Bruno 		    LIO_CN23XX_PKT_IN_DONE_WMARK_MASK;
290*f173c2b7SSean Bruno 
291*f173c2b7SSean Bruno 		lio_write_csr64(oct, inst_cnt_reg,
292*f173c2b7SSean Bruno 				(lio_read_csr64(oct, inst_cnt_reg) &
293*f173c2b7SSean Bruno 				 ~(LIO_CN23XX_PKT_IN_DONE_WMARK_MASK <<
294*f173c2b7SSean Bruno 				   LIO_CN23XX_PKT_IN_DONE_WMARK_BIT_POS)) |
295*f173c2b7SSean Bruno 				(intr_threshold <<
296*f173c2b7SSean Bruno 				 LIO_CN23XX_PKT_IN_DONE_WMARK_BIT_POS));
297*f173c2b7SSean Bruno 	}
298*f173c2b7SSean Bruno 	return (0);
299*f173c2b7SSean Bruno }
300*f173c2b7SSean Bruno 
301*f173c2b7SSean Bruno static void
302*f173c2b7SSean Bruno lio_cn23xx_pf_setup_global_output_regs(struct octeon_device *oct)
303*f173c2b7SSean Bruno {
304*f173c2b7SSean Bruno 	struct lio_cn23xx_pf *cn23xx = (struct lio_cn23xx_pf *)oct->chip;
305*f173c2b7SSean Bruno 	uint64_t	time_threshold;
306*f173c2b7SSean Bruno 	uint32_t	ern, q_no, reg_val, srn;
307*f173c2b7SSean Bruno 
308*f173c2b7SSean Bruno 	srn = oct->sriov_info.pf_srn;
309*f173c2b7SSean Bruno 	ern = srn + oct->sriov_info.num_pf_rings;
310*f173c2b7SSean Bruno 
311*f173c2b7SSean Bruno 	if (LIO_GET_IS_SLI_BP_ON_CFG(cn23xx->conf)) {
312*f173c2b7SSean Bruno 		lio_write_csr64(oct, LIO_CN23XX_SLI_OQ_WMARK, 32);
313*f173c2b7SSean Bruno 	} else {
314*f173c2b7SSean Bruno 		/* Set Output queue watermark to 0 to disable backpressure */
315*f173c2b7SSean Bruno 		lio_write_csr64(oct, LIO_CN23XX_SLI_OQ_WMARK, 0);
316*f173c2b7SSean Bruno 	}
317*f173c2b7SSean Bruno 
318*f173c2b7SSean Bruno 	for (q_no = srn; q_no < ern; q_no++) {
319*f173c2b7SSean Bruno 		reg_val = lio_read_csr32(oct,
320*f173c2b7SSean Bruno 					 LIO_CN23XX_SLI_OQ_PKT_CONTROL(q_no));
321*f173c2b7SSean Bruno 
322*f173c2b7SSean Bruno 		/* set IPTR & DPTR */
323*f173c2b7SSean Bruno 		reg_val |= LIO_CN23XX_PKT_OUTPUT_CTL_DPTR;
324*f173c2b7SSean Bruno 
325*f173c2b7SSean Bruno 		/* reset BMODE */
326*f173c2b7SSean Bruno 		reg_val &= ~(LIO_CN23XX_PKT_OUTPUT_CTL_BMODE);
327*f173c2b7SSean Bruno 
328*f173c2b7SSean Bruno 		/*
329*f173c2b7SSean Bruno 		 * No Relaxed Ordering, No Snoop, 64-bit Byte swap for
330*f173c2b7SSean Bruno 		 * Output Queue ScatterList reset ROR_P, NSR_P
331*f173c2b7SSean Bruno 		 */
332*f173c2b7SSean Bruno 		reg_val &= ~(LIO_CN23XX_PKT_OUTPUT_CTL_ROR_P);
333*f173c2b7SSean Bruno 		reg_val &= ~(LIO_CN23XX_PKT_OUTPUT_CTL_NSR_P);
334*f173c2b7SSean Bruno 
335*f173c2b7SSean Bruno #if BYTE_ORDER == LITTLE_ENDIAN
336*f173c2b7SSean Bruno 		reg_val &= ~(LIO_CN23XX_PKT_OUTPUT_CTL_ES_P);
337*f173c2b7SSean Bruno #else	/* BYTE_ORDER != LITTLE_ENDIAN  */
338*f173c2b7SSean Bruno 		reg_val |= (LIO_CN23XX_PKT_OUTPUT_CTL_ES_P);
339*f173c2b7SSean Bruno #endif	/* BYTE_ORDER == LITTLE_ENDIAN */
340*f173c2b7SSean Bruno 
341*f173c2b7SSean Bruno 		/*
342*f173c2b7SSean Bruno 		 * No Relaxed Ordering, No Snoop, 64-bit Byte swap for
343*f173c2b7SSean Bruno 		 * Output Queue Data reset ROR, NSR
344*f173c2b7SSean Bruno 		 */
345*f173c2b7SSean Bruno 		reg_val &= ~(LIO_CN23XX_PKT_OUTPUT_CTL_ROR);
346*f173c2b7SSean Bruno 		reg_val &= ~(LIO_CN23XX_PKT_OUTPUT_CTL_NSR);
347*f173c2b7SSean Bruno 		/* set the ES bit */
348*f173c2b7SSean Bruno 		reg_val |= (LIO_CN23XX_PKT_OUTPUT_CTL_ES);
349*f173c2b7SSean Bruno 
350*f173c2b7SSean Bruno 		/* write all the selected settings */
351*f173c2b7SSean Bruno 		lio_write_csr32(oct, LIO_CN23XX_SLI_OQ_PKT_CONTROL(q_no),
352*f173c2b7SSean Bruno 				reg_val);
353*f173c2b7SSean Bruno 
354*f173c2b7SSean Bruno 		/*
355*f173c2b7SSean Bruno 		 * Enabling these interrupt in oct->fn_list.enable_interrupt()
356*f173c2b7SSean Bruno 		 * routine which called after IOQ init.
357*f173c2b7SSean Bruno 		 * Set up interrupt packet and time thresholds
358*f173c2b7SSean Bruno 		 * for all the OQs
359*f173c2b7SSean Bruno 		 */
360*f173c2b7SSean Bruno 		time_threshold =lio_cn23xx_pf_get_oq_ticks(
361*f173c2b7SSean Bruno 		       oct, (uint32_t)LIO_GET_OQ_INTR_TIME_CFG(cn23xx->conf));
362*f173c2b7SSean Bruno 
363*f173c2b7SSean Bruno 		lio_write_csr64(oct, LIO_CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no),
364*f173c2b7SSean Bruno 				(LIO_GET_OQ_INTR_PKT_CFG(cn23xx->conf) |
365*f173c2b7SSean Bruno 				 (time_threshold << 32)));
366*f173c2b7SSean Bruno 	}
367*f173c2b7SSean Bruno 
368*f173c2b7SSean Bruno 	/* Setting the water mark level for pko back pressure * */
369*f173c2b7SSean Bruno 	lio_write_csr64(oct, LIO_CN23XX_SLI_OQ_WMARK, 0x40);
370*f173c2b7SSean Bruno 
371*f173c2b7SSean Bruno 	/* Enable channel-level backpressure */
372*f173c2b7SSean Bruno 	if (oct->pf_num)
373*f173c2b7SSean Bruno 		lio_write_csr64(oct, LIO_CN23XX_SLI_OUT_BP_EN2_W1S,
374*f173c2b7SSean Bruno 				0xffffffffffffffffULL);
375*f173c2b7SSean Bruno 	else
376*f173c2b7SSean Bruno 		lio_write_csr64(oct, LIO_CN23XX_SLI_OUT_BP_EN_W1S,
377*f173c2b7SSean Bruno 				0xffffffffffffffffULL);
378*f173c2b7SSean Bruno }
379*f173c2b7SSean Bruno 
380*f173c2b7SSean Bruno static int
381*f173c2b7SSean Bruno lio_cn23xx_pf_setup_device_regs(struct octeon_device *oct)
382*f173c2b7SSean Bruno {
383*f173c2b7SSean Bruno 
384*f173c2b7SSean Bruno 	lio_cn23xx_pf_enable_error_reporting(oct);
385*f173c2b7SSean Bruno 
386*f173c2b7SSean Bruno 	/* program the MAC(0..3)_RINFO before setting up input/output regs */
387*f173c2b7SSean Bruno 	lio_cn23xx_pf_setup_global_mac_regs(oct);
388*f173c2b7SSean Bruno 
389*f173c2b7SSean Bruno 	if (lio_cn23xx_pf_setup_global_input_regs(oct))
390*f173c2b7SSean Bruno 		return (-1);
391*f173c2b7SSean Bruno 
392*f173c2b7SSean Bruno 	lio_cn23xx_pf_setup_global_output_regs(oct);
393*f173c2b7SSean Bruno 
394*f173c2b7SSean Bruno 	/*
395*f173c2b7SSean Bruno 	 * Default error timeout value should be 0x200000 to avoid host hang
396*f173c2b7SSean Bruno 	 * when reads invalid register
397*f173c2b7SSean Bruno 	 */
398*f173c2b7SSean Bruno 	lio_write_csr64(oct, LIO_CN23XX_SLI_WINDOW_CTL,
399*f173c2b7SSean Bruno 			LIO_CN23XX_SLI_WINDOW_CTL_DEFAULT);
400*f173c2b7SSean Bruno 
401*f173c2b7SSean Bruno 	/* set SLI_PKT_IN_JABBER to handle large VXLAN packets */
402*f173c2b7SSean Bruno 	lio_write_csr64(oct, LIO_CN23XX_SLI_PKT_IN_JABBER,
403*f173c2b7SSean Bruno 			LIO_CN23XX_MAX_INPUT_JABBER);
404*f173c2b7SSean Bruno 	return (0);
405*f173c2b7SSean Bruno }
406*f173c2b7SSean Bruno 
407*f173c2b7SSean Bruno static void
408*f173c2b7SSean Bruno lio_cn23xx_pf_setup_iq_regs(struct octeon_device *oct, uint32_t iq_no)
409*f173c2b7SSean Bruno {
410*f173c2b7SSean Bruno 	struct lio_instr_queue	*iq = oct->instr_queue[iq_no];
411*f173c2b7SSean Bruno 	uint64_t		pkt_in_done;
412*f173c2b7SSean Bruno 
413*f173c2b7SSean Bruno 	iq_no += oct->sriov_info.pf_srn;
414*f173c2b7SSean Bruno 
415*f173c2b7SSean Bruno 	/* Write the start of the input queue's ring and its size  */
416*f173c2b7SSean Bruno 	lio_write_csr64(oct, LIO_CN23XX_SLI_IQ_BASE_ADDR64(iq_no),
417*f173c2b7SSean Bruno 			iq->base_addr_dma);
418*f173c2b7SSean Bruno 	lio_write_csr32(oct, LIO_CN23XX_SLI_IQ_SIZE(iq_no), iq->max_count);
419*f173c2b7SSean Bruno 
420*f173c2b7SSean Bruno 	/*
421*f173c2b7SSean Bruno 	 * Remember the doorbell & instruction count register addr
422*f173c2b7SSean Bruno 	 * for this queue
423*f173c2b7SSean Bruno 	 */
424*f173c2b7SSean Bruno 	iq->doorbell_reg = LIO_CN23XX_SLI_IQ_DOORBELL(iq_no);
425*f173c2b7SSean Bruno 	iq->inst_cnt_reg = LIO_CN23XX_SLI_IQ_INSTR_COUNT64(iq_no);
426*f173c2b7SSean Bruno 	lio_dev_dbg(oct, "InstQ[%d]:dbell reg @ 0x%x instcnt_reg @ 0x%x\n",
427*f173c2b7SSean Bruno 		    iq_no, iq->doorbell_reg, iq->inst_cnt_reg);
428*f173c2b7SSean Bruno 
429*f173c2b7SSean Bruno 	/*
430*f173c2b7SSean Bruno 	 * Store the current instruction counter (used in flush_iq
431*f173c2b7SSean Bruno 	 * calculation)
432*f173c2b7SSean Bruno 	 */
433*f173c2b7SSean Bruno 	pkt_in_done = lio_read_csr64(oct, iq->inst_cnt_reg);
434*f173c2b7SSean Bruno 
435*f173c2b7SSean Bruno 	if (oct->msix_on) {
436*f173c2b7SSean Bruno 		/* Set CINT_ENB to enable IQ interrupt   */
437*f173c2b7SSean Bruno 		lio_write_csr64(oct, iq->inst_cnt_reg,
438*f173c2b7SSean Bruno 				(pkt_in_done | LIO_CN23XX_INTR_CINT_ENB));
439*f173c2b7SSean Bruno 	} else {
440*f173c2b7SSean Bruno 		/*
441*f173c2b7SSean Bruno 		 * Clear the count by writing back what we read, but don't
442*f173c2b7SSean Bruno 		 * enable interrupts
443*f173c2b7SSean Bruno 		 */
444*f173c2b7SSean Bruno 		lio_write_csr64(oct, iq->inst_cnt_reg, pkt_in_done);
445*f173c2b7SSean Bruno 	}
446*f173c2b7SSean Bruno 
447*f173c2b7SSean Bruno 	iq->reset_instr_cnt = 0;
448*f173c2b7SSean Bruno }
449*f173c2b7SSean Bruno 
450*f173c2b7SSean Bruno static void
451*f173c2b7SSean Bruno lio_cn23xx_pf_setup_oq_regs(struct octeon_device *oct, uint32_t oq_no)
452*f173c2b7SSean Bruno {
453*f173c2b7SSean Bruno 	struct lio_droq		*droq = oct->droq[oq_no];
454*f173c2b7SSean Bruno 	struct lio_cn23xx_pf	*cn23xx = (struct lio_cn23xx_pf *)oct->chip;
455*f173c2b7SSean Bruno 	uint64_t		cnt_threshold;
456*f173c2b7SSean Bruno 	uint64_t		time_threshold;
457*f173c2b7SSean Bruno 	uint32_t		reg_val;
458*f173c2b7SSean Bruno 
459*f173c2b7SSean Bruno 	oq_no += oct->sriov_info.pf_srn;
460*f173c2b7SSean Bruno 
461*f173c2b7SSean Bruno 	lio_write_csr64(oct, LIO_CN23XX_SLI_OQ_BASE_ADDR64(oq_no),
462*f173c2b7SSean Bruno 			droq->desc_ring_dma);
463*f173c2b7SSean Bruno 	lio_write_csr32(oct, LIO_CN23XX_SLI_OQ_SIZE(oq_no), droq->max_count);
464*f173c2b7SSean Bruno 
465*f173c2b7SSean Bruno 	lio_write_csr32(oct, LIO_CN23XX_SLI_OQ_BUFF_INFO_SIZE(oq_no),
466*f173c2b7SSean Bruno 			droq->buffer_size);
467*f173c2b7SSean Bruno 
468*f173c2b7SSean Bruno 	/* pkt_sent and pkts_credit regs */
469*f173c2b7SSean Bruno 	droq->pkts_sent_reg = LIO_CN23XX_SLI_OQ_PKTS_SENT(oq_no);
470*f173c2b7SSean Bruno 	droq->pkts_credit_reg = LIO_CN23XX_SLI_OQ_PKTS_CREDIT(oq_no);
471*f173c2b7SSean Bruno 
472*f173c2b7SSean Bruno 	if (!oct->msix_on) {
473*f173c2b7SSean Bruno 		/*
474*f173c2b7SSean Bruno 		 * Enable this output queue to generate Packet Timer
475*f173c2b7SSean Bruno 		 * Interrupt
476*f173c2b7SSean Bruno 		 */
477*f173c2b7SSean Bruno 		reg_val =
478*f173c2b7SSean Bruno 		    lio_read_csr32(oct, LIO_CN23XX_SLI_OQ_PKT_CONTROL(oq_no));
479*f173c2b7SSean Bruno 		reg_val |= LIO_CN23XX_PKT_OUTPUT_CTL_TENB;
480*f173c2b7SSean Bruno 		lio_write_csr32(oct, LIO_CN23XX_SLI_OQ_PKT_CONTROL(oq_no),
481*f173c2b7SSean Bruno 				reg_val);
482*f173c2b7SSean Bruno 
483*f173c2b7SSean Bruno 		/*
484*f173c2b7SSean Bruno 		 * Enable this output queue to generate Packet Count
485*f173c2b7SSean Bruno 		 * Interrupt
486*f173c2b7SSean Bruno 		 */
487*f173c2b7SSean Bruno 		reg_val =
488*f173c2b7SSean Bruno 		    lio_read_csr32(oct, LIO_CN23XX_SLI_OQ_PKT_CONTROL(oq_no));
489*f173c2b7SSean Bruno 		reg_val |= LIO_CN23XX_PKT_OUTPUT_CTL_CENB;
490*f173c2b7SSean Bruno 		lio_write_csr32(oct, LIO_CN23XX_SLI_OQ_PKT_CONTROL(oq_no),
491*f173c2b7SSean Bruno 				reg_val);
492*f173c2b7SSean Bruno 	} else {
493*f173c2b7SSean Bruno 		time_threshold = lio_cn23xx_pf_get_oq_ticks(oct,
494*f173c2b7SSean Bruno 			(uint32_t)LIO_GET_OQ_INTR_TIME_CFG(cn23xx->conf));
495*f173c2b7SSean Bruno 		cnt_threshold = (uint32_t)LIO_GET_OQ_INTR_PKT_CFG(cn23xx->conf);
496*f173c2b7SSean Bruno 
497*f173c2b7SSean Bruno 		lio_write_csr64(oct, LIO_CN23XX_SLI_OQ_PKT_INT_LEVELS(oq_no),
498*f173c2b7SSean Bruno 				((time_threshold << 32 | cnt_threshold)));
499*f173c2b7SSean Bruno 	}
500*f173c2b7SSean Bruno }
501*f173c2b7SSean Bruno 
502*f173c2b7SSean Bruno 
503*f173c2b7SSean Bruno static int
504*f173c2b7SSean Bruno lio_cn23xx_pf_enable_io_queues(struct octeon_device *oct)
505*f173c2b7SSean Bruno {
506*f173c2b7SSean Bruno 	uint64_t	reg_val;
507*f173c2b7SSean Bruno 	uint32_t	ern, loop = BUSY_READING_REG_PF_LOOP_COUNT;
508*f173c2b7SSean Bruno 	uint32_t	q_no, srn;
509*f173c2b7SSean Bruno 
510*f173c2b7SSean Bruno 	srn = oct->sriov_info.pf_srn;
511*f173c2b7SSean Bruno 	ern = srn + oct->num_iqs;
512*f173c2b7SSean Bruno 
513*f173c2b7SSean Bruno 	for (q_no = srn; q_no < ern; q_no++) {
514*f173c2b7SSean Bruno 		/* set the corresponding IQ IS_64B bit */
515*f173c2b7SSean Bruno 		if (oct->io_qmask.iq64B & BIT_ULL(q_no - srn)) {
516*f173c2b7SSean Bruno 			reg_val = lio_read_csr64(oct,
517*f173c2b7SSean Bruno 					LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
518*f173c2b7SSean Bruno 			reg_val = reg_val | LIO_CN23XX_PKT_INPUT_CTL_IS_64B;
519*f173c2b7SSean Bruno 			lio_write_csr64(oct,
520*f173c2b7SSean Bruno 					LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
521*f173c2b7SSean Bruno 					reg_val);
522*f173c2b7SSean Bruno 		}
523*f173c2b7SSean Bruno 		/* set the corresponding IQ ENB bit */
524*f173c2b7SSean Bruno 		if (oct->io_qmask.iq & BIT_ULL(q_no - srn)) {
525*f173c2b7SSean Bruno 			/*
526*f173c2b7SSean Bruno 			 * IOQs are in reset by default in PEM2 mode,
527*f173c2b7SSean Bruno 			 * clearing reset bit
528*f173c2b7SSean Bruno 			 */
529*f173c2b7SSean Bruno 			reg_val = lio_read_csr64(oct,
530*f173c2b7SSean Bruno 					LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
531*f173c2b7SSean Bruno 
532*f173c2b7SSean Bruno 			if (reg_val & LIO_CN23XX_PKT_INPUT_CTL_RST) {
533*f173c2b7SSean Bruno 				while ((reg_val &
534*f173c2b7SSean Bruno 					LIO_CN23XX_PKT_INPUT_CTL_RST) &&
535*f173c2b7SSean Bruno 				       !(reg_val &
536*f173c2b7SSean Bruno 					 LIO_CN23XX_PKT_INPUT_CTL_QUIET) &&
537*f173c2b7SSean Bruno 				       loop) {
538*f173c2b7SSean Bruno 					reg_val = lio_read_csr64(oct,
539*f173c2b7SSean Bruno 					LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
540*f173c2b7SSean Bruno 					loop--;
541*f173c2b7SSean Bruno 				}
542*f173c2b7SSean Bruno 				if (!loop) {
543*f173c2b7SSean Bruno 					lio_dev_err(oct, "clearing the reset reg failed or setting the quiet reg failed for qno: %u\n",
544*f173c2b7SSean Bruno 						    q_no);
545*f173c2b7SSean Bruno 					return (-1);
546*f173c2b7SSean Bruno 				}
547*f173c2b7SSean Bruno 				reg_val = reg_val &
548*f173c2b7SSean Bruno 					~LIO_CN23XX_PKT_INPUT_CTL_RST;
549*f173c2b7SSean Bruno 				lio_write_csr64(oct,
550*f173c2b7SSean Bruno 					LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
551*f173c2b7SSean Bruno 					reg_val);
552*f173c2b7SSean Bruno 
553*f173c2b7SSean Bruno 				reg_val = lio_read_csr64(oct,
554*f173c2b7SSean Bruno 					LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
555*f173c2b7SSean Bruno 				if (reg_val & LIO_CN23XX_PKT_INPUT_CTL_RST) {
556*f173c2b7SSean Bruno 					lio_dev_err(oct, "clearing the reset failed for qno: %u\n",
557*f173c2b7SSean Bruno 						    q_no);
558*f173c2b7SSean Bruno 					return (-1);
559*f173c2b7SSean Bruno 				}
560*f173c2b7SSean Bruno 			}
561*f173c2b7SSean Bruno 			reg_val = lio_read_csr64(oct,
562*f173c2b7SSean Bruno 					LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
563*f173c2b7SSean Bruno 			reg_val = reg_val | LIO_CN23XX_PKT_INPUT_CTL_RING_ENB;
564*f173c2b7SSean Bruno 			lio_write_csr64(oct,
565*f173c2b7SSean Bruno 					LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
566*f173c2b7SSean Bruno 					reg_val);
567*f173c2b7SSean Bruno 		}
568*f173c2b7SSean Bruno 	}
569*f173c2b7SSean Bruno 	for (q_no = srn; q_no < ern; q_no++) {
570*f173c2b7SSean Bruno 		uint32_t	reg_val;
571*f173c2b7SSean Bruno 		/* set the corresponding OQ ENB bit */
572*f173c2b7SSean Bruno 		if (oct->io_qmask.oq & BIT_ULL(q_no - srn)) {
573*f173c2b7SSean Bruno 			reg_val = lio_read_csr32(oct,
574*f173c2b7SSean Bruno 					LIO_CN23XX_SLI_OQ_PKT_CONTROL(q_no));
575*f173c2b7SSean Bruno 			reg_val = reg_val | LIO_CN23XX_PKT_OUTPUT_CTL_RING_ENB;
576*f173c2b7SSean Bruno 			lio_write_csr32(oct,
577*f173c2b7SSean Bruno 					LIO_CN23XX_SLI_OQ_PKT_CONTROL(q_no),
578*f173c2b7SSean Bruno 					reg_val);
579*f173c2b7SSean Bruno 		}
580*f173c2b7SSean Bruno 	}
581*f173c2b7SSean Bruno 	return (0);
582*f173c2b7SSean Bruno }
583*f173c2b7SSean Bruno 
584*f173c2b7SSean Bruno static void
585*f173c2b7SSean Bruno lio_cn23xx_pf_disable_io_queues(struct octeon_device *oct)
586*f173c2b7SSean Bruno {
587*f173c2b7SSean Bruno 	volatile uint64_t	d64;
588*f173c2b7SSean Bruno 	volatile uint32_t	d32;
589*f173c2b7SSean Bruno 	int			loop;
590*f173c2b7SSean Bruno 	unsigned int		q_no;
591*f173c2b7SSean Bruno 	uint32_t		ern, srn;
592*f173c2b7SSean Bruno 
593*f173c2b7SSean Bruno 	srn = oct->sriov_info.pf_srn;
594*f173c2b7SSean Bruno 	ern = srn + oct->num_iqs;
595*f173c2b7SSean Bruno 
596*f173c2b7SSean Bruno 	/* Disable Input Queues. */
597*f173c2b7SSean Bruno 	for (q_no = srn; q_no < ern; q_no++) {
598*f173c2b7SSean Bruno 		loop = lio_ms_to_ticks(1000);
599*f173c2b7SSean Bruno 
600*f173c2b7SSean Bruno 		/* start the Reset for a particular ring */
601*f173c2b7SSean Bruno 		d64 = lio_read_csr64(oct,
602*f173c2b7SSean Bruno 				     LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
603*f173c2b7SSean Bruno 		d64 &= ~LIO_CN23XX_PKT_INPUT_CTL_RING_ENB;
604*f173c2b7SSean Bruno 		d64 |= LIO_CN23XX_PKT_INPUT_CTL_RST;
605*f173c2b7SSean Bruno 		lio_write_csr64(oct, LIO_CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
606*f173c2b7SSean Bruno 				d64);
607*f173c2b7SSean Bruno 
608*f173c2b7SSean Bruno 		/*
609*f173c2b7SSean Bruno 		 * Wait until hardware indicates that the particular IQ
610*f173c2b7SSean Bruno 		 * is out of reset.
611*f173c2b7SSean Bruno 		 */
612*f173c2b7SSean Bruno 		d64 = lio_read_csr64(oct, LIO_CN23XX_SLI_PKT_IOQ_RING_RST);
613*f173c2b7SSean Bruno 		while (!(d64 & BIT_ULL(q_no)) && loop--) {
614*f173c2b7SSean Bruno 			d64 = lio_read_csr64(oct,
615*f173c2b7SSean Bruno 					     LIO_CN23XX_SLI_PKT_IOQ_RING_RST);
616*f173c2b7SSean Bruno 			lio_sleep_timeout(1);
617*f173c2b7SSean Bruno 			loop--;
618*f173c2b7SSean Bruno 		}
619*f173c2b7SSean Bruno 
620*f173c2b7SSean Bruno 		/* Reset the doorbell register for this Input Queue. */
621*f173c2b7SSean Bruno 		lio_write_csr32(oct, LIO_CN23XX_SLI_IQ_DOORBELL(q_no),
622*f173c2b7SSean Bruno 				0xFFFFFFFF);
623*f173c2b7SSean Bruno 		while (((lio_read_csr64(oct,
624*f173c2b7SSean Bruno 					LIO_CN23XX_SLI_IQ_DOORBELL(q_no))) !=
625*f173c2b7SSean Bruno 			0ULL) && loop--) {
626*f173c2b7SSean Bruno 			lio_sleep_timeout(1);
627*f173c2b7SSean Bruno 		}
628*f173c2b7SSean Bruno 	}
629*f173c2b7SSean Bruno 
630*f173c2b7SSean Bruno 	/* Disable Output Queues. */
631*f173c2b7SSean Bruno 	for (q_no = srn; q_no < ern; q_no++) {
632*f173c2b7SSean Bruno 		loop = lio_ms_to_ticks(1000);
633*f173c2b7SSean Bruno 
634*f173c2b7SSean Bruno 		/*
635*f173c2b7SSean Bruno 		 * Wait until hardware indicates that the particular IQ
636*f173c2b7SSean Bruno 		 * is out of reset.It given that SLI_PKT_RING_RST is
637*f173c2b7SSean Bruno 		 * common for both IQs and OQs
638*f173c2b7SSean Bruno 		 */
639*f173c2b7SSean Bruno 		d64 = lio_read_csr64(oct, LIO_CN23XX_SLI_PKT_IOQ_RING_RST);
640*f173c2b7SSean Bruno 		while (!(d64 & BIT_ULL(q_no)) && loop--) {
641*f173c2b7SSean Bruno 			d64 = lio_read_csr64(oct,
642*f173c2b7SSean Bruno 					     LIO_CN23XX_SLI_PKT_IOQ_RING_RST);
643*f173c2b7SSean Bruno 			lio_sleep_timeout(1);
644*f173c2b7SSean Bruno 			loop--;
645*f173c2b7SSean Bruno 		}
646*f173c2b7SSean Bruno 
647*f173c2b7SSean Bruno 		/* Reset the doorbell register for this Output Queue. */
648*f173c2b7SSean Bruno 		lio_write_csr32(oct, LIO_CN23XX_SLI_OQ_PKTS_CREDIT(q_no),
649*f173c2b7SSean Bruno 				0xFFFFFFFF);
650*f173c2b7SSean Bruno 		while ((lio_read_csr64(oct,
651*f173c2b7SSean Bruno 				       LIO_CN23XX_SLI_OQ_PKTS_CREDIT(q_no)) !=
652*f173c2b7SSean Bruno 			0ULL) && loop--) {
653*f173c2b7SSean Bruno 			lio_sleep_timeout(1);
654*f173c2b7SSean Bruno 		}
655*f173c2b7SSean Bruno 
656*f173c2b7SSean Bruno 		/* clear the SLI_PKT(0..63)_CNTS[CNT] reg value */
657*f173c2b7SSean Bruno 		d32 = lio_read_csr32(oct, LIO_CN23XX_SLI_OQ_PKTS_SENT(q_no));
658*f173c2b7SSean Bruno 		lio_write_csr32(oct, LIO_CN23XX_SLI_OQ_PKTS_SENT(q_no),	d32);
659*f173c2b7SSean Bruno 	}
660*f173c2b7SSean Bruno }
661*f173c2b7SSean Bruno 
662*f173c2b7SSean Bruno static uint64_t
663*f173c2b7SSean Bruno lio_cn23xx_pf_msix_interrupt_handler(void *dev)
664*f173c2b7SSean Bruno {
665*f173c2b7SSean Bruno 	struct lio_ioq_vector	*ioq_vector = (struct lio_ioq_vector *)dev;
666*f173c2b7SSean Bruno 	struct octeon_device	*oct = ioq_vector->oct_dev;
667*f173c2b7SSean Bruno 	struct lio_droq		*droq = oct->droq[ioq_vector->droq_index];
668*f173c2b7SSean Bruno 	uint64_t		pkts_sent;
669*f173c2b7SSean Bruno 	uint64_t		ret = 0;
670*f173c2b7SSean Bruno 
671*f173c2b7SSean Bruno 	if (droq == NULL) {
672*f173c2b7SSean Bruno 		lio_dev_err(oct, "23XX bringup FIXME: oct pfnum:%d ioq_vector->ioq_num :%d droq is NULL\n",
673*f173c2b7SSean Bruno 			    oct->pf_num, ioq_vector->ioq_num);
674*f173c2b7SSean Bruno 		return (0);
675*f173c2b7SSean Bruno 	}
676*f173c2b7SSean Bruno 	pkts_sent = lio_read_csr64(oct, droq->pkts_sent_reg);
677*f173c2b7SSean Bruno 
678*f173c2b7SSean Bruno 	/*
679*f173c2b7SSean Bruno 	 * If our device has interrupted, then proceed. Also check
680*f173c2b7SSean Bruno 	 * for all f's if interrupt was triggered on an error
681*f173c2b7SSean Bruno 	 * and the PCI read fails.
682*f173c2b7SSean Bruno 	 */
683*f173c2b7SSean Bruno 	if (!pkts_sent || (pkts_sent == 0xFFFFFFFFFFFFFFFFULL))
684*f173c2b7SSean Bruno 		return (ret);
685*f173c2b7SSean Bruno 
686*f173c2b7SSean Bruno 	/* Write count reg in sli_pkt_cnts to clear these int. */
687*f173c2b7SSean Bruno 	if (pkts_sent & LIO_CN23XX_INTR_PO_INT)
688*f173c2b7SSean Bruno 		ret |= LIO_MSIX_PO_INT;
689*f173c2b7SSean Bruno 
690*f173c2b7SSean Bruno 	if (pkts_sent & LIO_CN23XX_INTR_PI_INT)
691*f173c2b7SSean Bruno 		/* We will clear the count when we update the read_index. */
692*f173c2b7SSean Bruno 		ret |= LIO_MSIX_PI_INT;
693*f173c2b7SSean Bruno 
694*f173c2b7SSean Bruno 	/*
695*f173c2b7SSean Bruno 	 * Never need to handle msix mbox intr for pf. They arrive on the last
696*f173c2b7SSean Bruno 	 * msix
697*f173c2b7SSean Bruno 	 */
698*f173c2b7SSean Bruno 	return (ret);
699*f173c2b7SSean Bruno }
700*f173c2b7SSean Bruno 
701*f173c2b7SSean Bruno static void
702*f173c2b7SSean Bruno lio_cn23xx_pf_interrupt_handler(void *dev)
703*f173c2b7SSean Bruno {
704*f173c2b7SSean Bruno 	struct octeon_device	*oct = (struct octeon_device *)dev;
705*f173c2b7SSean Bruno 	struct lio_cn23xx_pf	*cn23xx = (struct lio_cn23xx_pf *)oct->chip;
706*f173c2b7SSean Bruno 	uint64_t		intr64;
707*f173c2b7SSean Bruno 
708*f173c2b7SSean Bruno 	lio_dev_dbg(oct, "In %s octeon_dev @ %p\n", __func__, oct);
709*f173c2b7SSean Bruno 	intr64 = lio_read_csr64(oct, cn23xx->intr_sum_reg64);
710*f173c2b7SSean Bruno 
711*f173c2b7SSean Bruno 	oct->int_status = 0;
712*f173c2b7SSean Bruno 
713*f173c2b7SSean Bruno 	if (intr64 & LIO_CN23XX_INTR_ERR)
714*f173c2b7SSean Bruno 		lio_dev_err(oct, "Error Intr: 0x%016llx\n",
715*f173c2b7SSean Bruno 			    LIO_CAST64(intr64));
716*f173c2b7SSean Bruno 
717*f173c2b7SSean Bruno 	if (oct->msix_on != LIO_FLAG_MSIX_ENABLED) {
718*f173c2b7SSean Bruno 		if (intr64 & LIO_CN23XX_INTR_PKT_DATA)
719*f173c2b7SSean Bruno 			oct->int_status |= LIO_DEV_INTR_PKT_DATA;
720*f173c2b7SSean Bruno 	}
721*f173c2b7SSean Bruno 
722*f173c2b7SSean Bruno 	if (intr64 & (LIO_CN23XX_INTR_DMA0_FORCE))
723*f173c2b7SSean Bruno 		oct->int_status |= LIO_DEV_INTR_DMA0_FORCE;
724*f173c2b7SSean Bruno 
725*f173c2b7SSean Bruno 	if (intr64 & (LIO_CN23XX_INTR_DMA1_FORCE))
726*f173c2b7SSean Bruno 		oct->int_status |= LIO_DEV_INTR_DMA1_FORCE;
727*f173c2b7SSean Bruno 
728*f173c2b7SSean Bruno 	/* Clear the current interrupts */
729*f173c2b7SSean Bruno 	lio_write_csr64(oct, cn23xx->intr_sum_reg64, intr64);
730*f173c2b7SSean Bruno }
731*f173c2b7SSean Bruno 
732*f173c2b7SSean Bruno static void
733*f173c2b7SSean Bruno lio_cn23xx_pf_bar1_idx_setup(struct octeon_device *oct, uint64_t core_addr,
734*f173c2b7SSean Bruno 			     uint32_t idx, int valid)
735*f173c2b7SSean Bruno {
736*f173c2b7SSean Bruno 	volatile uint64_t	bar1;
737*f173c2b7SSean Bruno 	uint64_t		reg_adr;
738*f173c2b7SSean Bruno 
739*f173c2b7SSean Bruno 	if (!valid) {
740*f173c2b7SSean Bruno 		reg_adr = lio_pci_readq(oct,
741*f173c2b7SSean Bruno 				LIO_CN23XX_PEM_BAR1_INDEX_REG(oct->pcie_port,
742*f173c2b7SSean Bruno 							      idx));
743*f173c2b7SSean Bruno 		bar1 = reg_adr;
744*f173c2b7SSean Bruno 		lio_pci_writeq(oct, (bar1 & 0xFFFFFFFEULL),
745*f173c2b7SSean Bruno 			       LIO_CN23XX_PEM_BAR1_INDEX_REG(oct->pcie_port,
746*f173c2b7SSean Bruno 							     idx));
747*f173c2b7SSean Bruno 		reg_adr = lio_pci_readq(oct,
748*f173c2b7SSean Bruno 				LIO_CN23XX_PEM_BAR1_INDEX_REG(oct->pcie_port,
749*f173c2b7SSean Bruno 							      idx));
750*f173c2b7SSean Bruno 		bar1 = reg_adr;
751*f173c2b7SSean Bruno 		return;
752*f173c2b7SSean Bruno 	}
753*f173c2b7SSean Bruno 	/*
754*f173c2b7SSean Bruno 	 *  The PEM(0..3)_BAR1_INDEX(0..15)[ADDR_IDX]<23:4> stores
755*f173c2b7SSean Bruno 	 *  bits <41:22> of the Core Addr
756*f173c2b7SSean Bruno 	 */
757*f173c2b7SSean Bruno 	lio_pci_writeq(oct, (((core_addr >> 22) << 4) | LIO_PCI_BAR1_MASK),
758*f173c2b7SSean Bruno 		       LIO_CN23XX_PEM_BAR1_INDEX_REG(oct->pcie_port, idx));
759*f173c2b7SSean Bruno 
760*f173c2b7SSean Bruno 	bar1 = lio_pci_readq(oct, LIO_CN23XX_PEM_BAR1_INDEX_REG(oct->pcie_port,
761*f173c2b7SSean Bruno 								idx));
762*f173c2b7SSean Bruno }
763*f173c2b7SSean Bruno 
764*f173c2b7SSean Bruno static void
765*f173c2b7SSean Bruno lio_cn23xx_pf_bar1_idx_write(struct octeon_device *oct, uint32_t idx,
766*f173c2b7SSean Bruno 			     uint32_t mask)
767*f173c2b7SSean Bruno {
768*f173c2b7SSean Bruno 
769*f173c2b7SSean Bruno 	lio_pci_writeq(oct, mask,
770*f173c2b7SSean Bruno 		       LIO_CN23XX_PEM_BAR1_INDEX_REG(oct->pcie_port, idx));
771*f173c2b7SSean Bruno }
772*f173c2b7SSean Bruno 
773*f173c2b7SSean Bruno static uint32_t
774*f173c2b7SSean Bruno lio_cn23xx_pf_bar1_idx_read(struct octeon_device *oct, uint32_t idx)
775*f173c2b7SSean Bruno {
776*f173c2b7SSean Bruno 
777*f173c2b7SSean Bruno 	return ((uint32_t)lio_pci_readq(oct,
778*f173c2b7SSean Bruno 				LIO_CN23XX_PEM_BAR1_INDEX_REG(oct->pcie_port,
779*f173c2b7SSean Bruno 							      idx)));
780*f173c2b7SSean Bruno }
781*f173c2b7SSean Bruno 
782*f173c2b7SSean Bruno /* always call with lock held */
783*f173c2b7SSean Bruno static uint32_t
784*f173c2b7SSean Bruno lio_cn23xx_pf_update_read_index(struct lio_instr_queue *iq)
785*f173c2b7SSean Bruno {
786*f173c2b7SSean Bruno 	struct octeon_device	*oct = iq->oct_dev;
787*f173c2b7SSean Bruno 	uint32_t	new_idx;
788*f173c2b7SSean Bruno 	uint32_t	last_done;
789*f173c2b7SSean Bruno 	uint32_t	pkt_in_done = lio_read_csr32(oct, iq->inst_cnt_reg);
790*f173c2b7SSean Bruno 
791*f173c2b7SSean Bruno 	last_done = pkt_in_done - iq->pkt_in_done;
792*f173c2b7SSean Bruno 	iq->pkt_in_done = pkt_in_done;
793*f173c2b7SSean Bruno 
794*f173c2b7SSean Bruno 	/*
795*f173c2b7SSean Bruno 	 * Modulo of the new index with the IQ size will give us
796*f173c2b7SSean Bruno 	 * the new index.  The iq->reset_instr_cnt is always zero for
797*f173c2b7SSean Bruno 	 * cn23xx, so no extra adjustments are needed.
798*f173c2b7SSean Bruno 	 */
799*f173c2b7SSean Bruno 	new_idx = (iq->octeon_read_index +
800*f173c2b7SSean Bruno 		   ((uint32_t)(last_done & LIO_CN23XX_PKT_IN_DONE_CNT_MASK))) %
801*f173c2b7SSean Bruno 	    iq->max_count;
802*f173c2b7SSean Bruno 
803*f173c2b7SSean Bruno 	return (new_idx);
804*f173c2b7SSean Bruno }
805*f173c2b7SSean Bruno 
806*f173c2b7SSean Bruno static void
807*f173c2b7SSean Bruno lio_cn23xx_pf_enable_interrupt(struct octeon_device *oct, uint8_t intr_flag)
808*f173c2b7SSean Bruno {
809*f173c2b7SSean Bruno 	struct lio_cn23xx_pf	*cn23xx = (struct lio_cn23xx_pf *)oct->chip;
810*f173c2b7SSean Bruno 	uint64_t		intr_val = 0;
811*f173c2b7SSean Bruno 
812*f173c2b7SSean Bruno 	/* Divide the single write to multiple writes based on the flag. */
813*f173c2b7SSean Bruno 	/* Enable Interrupt */
814*f173c2b7SSean Bruno 	if (intr_flag == OCTEON_ALL_INTR) {
815*f173c2b7SSean Bruno 		lio_write_csr64(oct, cn23xx->intr_enb_reg64,
816*f173c2b7SSean Bruno 				cn23xx->intr_mask64);
817*f173c2b7SSean Bruno 	} else if (intr_flag & OCTEON_OUTPUT_INTR) {
818*f173c2b7SSean Bruno 		intr_val = lio_read_csr64(oct, cn23xx->intr_enb_reg64);
819*f173c2b7SSean Bruno 		intr_val |= LIO_CN23XX_INTR_PKT_DATA;
820*f173c2b7SSean Bruno 		lio_write_csr64(oct, cn23xx->intr_enb_reg64, intr_val);
821*f173c2b7SSean Bruno 	}
822*f173c2b7SSean Bruno }
823*f173c2b7SSean Bruno 
824*f173c2b7SSean Bruno static void
825*f173c2b7SSean Bruno lio_cn23xx_pf_disable_interrupt(struct octeon_device *oct, uint8_t intr_flag)
826*f173c2b7SSean Bruno {
827*f173c2b7SSean Bruno 	struct lio_cn23xx_pf	*cn23xx = (struct lio_cn23xx_pf *)oct->chip;
828*f173c2b7SSean Bruno 	uint64_t		intr_val = 0;
829*f173c2b7SSean Bruno 
830*f173c2b7SSean Bruno 	/* Disable Interrupts */
831*f173c2b7SSean Bruno 	if (intr_flag == OCTEON_ALL_INTR) {
832*f173c2b7SSean Bruno 		lio_write_csr64(oct, cn23xx->intr_enb_reg64, 0);
833*f173c2b7SSean Bruno 	} else if (intr_flag & OCTEON_OUTPUT_INTR) {
834*f173c2b7SSean Bruno 		intr_val = lio_read_csr64(oct, cn23xx->intr_enb_reg64);
835*f173c2b7SSean Bruno 		intr_val &= ~LIO_CN23XX_INTR_PKT_DATA;
836*f173c2b7SSean Bruno 		lio_write_csr64(oct, cn23xx->intr_enb_reg64, intr_val);
837*f173c2b7SSean Bruno 	}
838*f173c2b7SSean Bruno }
839*f173c2b7SSean Bruno 
840*f173c2b7SSean Bruno static void
841*f173c2b7SSean Bruno lio_cn23xx_pf_get_pcie_qlmport(struct octeon_device *oct)
842*f173c2b7SSean Bruno {
843*f173c2b7SSean Bruno 	oct->pcie_port = (lio_read_csr32(oct,
844*f173c2b7SSean Bruno 					 LIO_CN23XX_SLI_MAC_NUMBER)) & 0xff;
845*f173c2b7SSean Bruno 
846*f173c2b7SSean Bruno 	lio_dev_dbg(oct, "CN23xx uses PCIE Port %d\n",
847*f173c2b7SSean Bruno 		    oct->pcie_port);
848*f173c2b7SSean Bruno }
849*f173c2b7SSean Bruno 
850*f173c2b7SSean Bruno static void
851*f173c2b7SSean Bruno lio_cn23xx_pf_get_pf_num(struct octeon_device *oct)
852*f173c2b7SSean Bruno {
853*f173c2b7SSean Bruno 	uint32_t	fdl_bit;
854*f173c2b7SSean Bruno 
855*f173c2b7SSean Bruno 	/* Read Function Dependency Link reg to get the function number */
856*f173c2b7SSean Bruno 	fdl_bit = lio_read_pci_cfg(oct, LIO_CN23XX_PCIE_SRIOV_FDL);
857*f173c2b7SSean Bruno 	oct->pf_num = ((fdl_bit >> LIO_CN23XX_PCIE_SRIOV_FDL_BIT_POS) &
858*f173c2b7SSean Bruno 		       LIO_CN23XX_PCIE_SRIOV_FDL_MASK);
859*f173c2b7SSean Bruno }
860*f173c2b7SSean Bruno 
861*f173c2b7SSean Bruno static void
862*f173c2b7SSean Bruno lio_cn23xx_pf_setup_reg_address(struct octeon_device *oct)
863*f173c2b7SSean Bruno {
864*f173c2b7SSean Bruno 	struct lio_cn23xx_pf	*cn23xx = (struct lio_cn23xx_pf *)oct->chip;
865*f173c2b7SSean Bruno 
866*f173c2b7SSean Bruno 	oct->reg_list.pci_win_wr_addr = LIO_CN23XX_SLI_WIN_WR_ADDR64;
867*f173c2b7SSean Bruno 
868*f173c2b7SSean Bruno 	oct->reg_list.pci_win_rd_addr_hi = LIO_CN23XX_SLI_WIN_RD_ADDR_HI;
869*f173c2b7SSean Bruno 	oct->reg_list.pci_win_rd_addr_lo = LIO_CN23XX_SLI_WIN_RD_ADDR64;
870*f173c2b7SSean Bruno 	oct->reg_list.pci_win_rd_addr = LIO_CN23XX_SLI_WIN_RD_ADDR64;
871*f173c2b7SSean Bruno 
872*f173c2b7SSean Bruno 	oct->reg_list.pci_win_wr_data_hi = LIO_CN23XX_SLI_WIN_WR_DATA_HI;
873*f173c2b7SSean Bruno 	oct->reg_list.pci_win_wr_data_lo = LIO_CN23XX_SLI_WIN_WR_DATA_LO;
874*f173c2b7SSean Bruno 	oct->reg_list.pci_win_wr_data = LIO_CN23XX_SLI_WIN_WR_DATA64;
875*f173c2b7SSean Bruno 
876*f173c2b7SSean Bruno 	oct->reg_list.pci_win_rd_data = LIO_CN23XX_SLI_WIN_RD_DATA64;
877*f173c2b7SSean Bruno 
878*f173c2b7SSean Bruno 	lio_cn23xx_pf_get_pcie_qlmport(oct);
879*f173c2b7SSean Bruno 
880*f173c2b7SSean Bruno 	cn23xx->intr_mask64 = LIO_CN23XX_INTR_MASK;
881*f173c2b7SSean Bruno 	if (!oct->msix_on)
882*f173c2b7SSean Bruno 		cn23xx->intr_mask64 |= LIO_CN23XX_INTR_PKT_TIME;
883*f173c2b7SSean Bruno 
884*f173c2b7SSean Bruno 	cn23xx->intr_sum_reg64 =
885*f173c2b7SSean Bruno 	    LIO_CN23XX_SLI_MAC_PF_INT_SUM64(oct->pcie_port, oct->pf_num);
886*f173c2b7SSean Bruno 	cn23xx->intr_enb_reg64 =
887*f173c2b7SSean Bruno 	    LIO_CN23XX_SLI_MAC_PF_INT_ENB64(oct->pcie_port, oct->pf_num);
888*f173c2b7SSean Bruno }
889*f173c2b7SSean Bruno 
890*f173c2b7SSean Bruno static int
891*f173c2b7SSean Bruno lio_cn23xx_pf_sriov_config(struct octeon_device *oct)
892*f173c2b7SSean Bruno {
893*f173c2b7SSean Bruno 	struct lio_cn23xx_pf	*cn23xx = (struct lio_cn23xx_pf *)oct->chip;
894*f173c2b7SSean Bruno 	uint32_t		num_pf_rings, total_rings, max_rings;
895*f173c2b7SSean Bruno 	cn23xx->conf = (struct lio_config *)lio_get_config_info(oct, LIO_23XX);
896*f173c2b7SSean Bruno 
897*f173c2b7SSean Bruno 	max_rings = LIO_CN23XX_PF_MAX_RINGS;
898*f173c2b7SSean Bruno 
899*f173c2b7SSean Bruno 	if (oct->sriov_info.num_pf_rings) {
900*f173c2b7SSean Bruno 		num_pf_rings = oct->sriov_info.num_pf_rings;
901*f173c2b7SSean Bruno 		if (num_pf_rings > max_rings) {
902*f173c2b7SSean Bruno 			num_pf_rings = min(mp_ncpus, max_rings);
903*f173c2b7SSean Bruno 			lio_dev_warn(oct, "num_queues_per_pf requested %u is more than available rings (%u). Reducing to %u\n",
904*f173c2b7SSean Bruno 				     oct->sriov_info.num_pf_rings,
905*f173c2b7SSean Bruno 				     max_rings, num_pf_rings);
906*f173c2b7SSean Bruno 		}
907*f173c2b7SSean Bruno 	} else {
908*f173c2b7SSean Bruno #ifdef RSS
909*f173c2b7SSean Bruno 		num_pf_rings = min(rss_getnumbuckets(), mp_ncpus);
910*f173c2b7SSean Bruno #else
911*f173c2b7SSean Bruno 		num_pf_rings = min(mp_ncpus, max_rings);
912*f173c2b7SSean Bruno #endif
913*f173c2b7SSean Bruno 
914*f173c2b7SSean Bruno 	}
915*f173c2b7SSean Bruno 
916*f173c2b7SSean Bruno 	total_rings = num_pf_rings;
917*f173c2b7SSean Bruno 	oct->sriov_info.trs = total_rings;
918*f173c2b7SSean Bruno 	oct->sriov_info.pf_srn = total_rings - num_pf_rings;
919*f173c2b7SSean Bruno 	oct->sriov_info.num_pf_rings = num_pf_rings;
920*f173c2b7SSean Bruno 
921*f173c2b7SSean Bruno 	lio_dev_dbg(oct, "trs:%d pf_srn:%d num_pf_rings:%d\n",
922*f173c2b7SSean Bruno 		    oct->sriov_info.trs, oct->sriov_info.pf_srn,
923*f173c2b7SSean Bruno 		    oct->sriov_info.num_pf_rings);
924*f173c2b7SSean Bruno 
925*f173c2b7SSean Bruno 	return (0);
926*f173c2b7SSean Bruno }
927*f173c2b7SSean Bruno 
928*f173c2b7SSean Bruno int
929*f173c2b7SSean Bruno lio_cn23xx_pf_setup_device(struct octeon_device *oct)
930*f173c2b7SSean Bruno {
931*f173c2b7SSean Bruno 	uint64_t	BAR0, BAR1;
932*f173c2b7SSean Bruno 	uint32_t	data32;
933*f173c2b7SSean Bruno 
934*f173c2b7SSean Bruno 	data32 = lio_read_pci_cfg(oct, 0x10);
935*f173c2b7SSean Bruno 	BAR0 = (uint64_t)(data32 & ~0xf);
936*f173c2b7SSean Bruno 	data32 = lio_read_pci_cfg(oct, 0x14);
937*f173c2b7SSean Bruno 	BAR0 |= ((uint64_t)data32 << 32);
938*f173c2b7SSean Bruno 	data32 = lio_read_pci_cfg(oct, 0x18);
939*f173c2b7SSean Bruno 	BAR1 = (uint64_t)(data32 & ~0xf);
940*f173c2b7SSean Bruno 	data32 = lio_read_pci_cfg(oct, 0x1c);
941*f173c2b7SSean Bruno 	BAR1 |= ((uint64_t)data32 << 32);
942*f173c2b7SSean Bruno 
943*f173c2b7SSean Bruno 	if (!BAR0 || !BAR1) {
944*f173c2b7SSean Bruno 		if (!BAR0)
945*f173c2b7SSean Bruno 			lio_dev_err(oct, "Device BAR0 unassigned\n");
946*f173c2b7SSean Bruno 
947*f173c2b7SSean Bruno 		if (!BAR1)
948*f173c2b7SSean Bruno 			lio_dev_err(oct, "Device BAR1 unassigned\n");
949*f173c2b7SSean Bruno 
950*f173c2b7SSean Bruno 		return (1);
951*f173c2b7SSean Bruno 	}
952*f173c2b7SSean Bruno 
953*f173c2b7SSean Bruno 	if (lio_map_pci_barx(oct, 0))
954*f173c2b7SSean Bruno 		return (1);
955*f173c2b7SSean Bruno 
956*f173c2b7SSean Bruno 	if (lio_map_pci_barx(oct, 1)) {
957*f173c2b7SSean Bruno 		lio_dev_err(oct, "%s CN23XX BAR1 map failed\n", __func__);
958*f173c2b7SSean Bruno 		lio_unmap_pci_barx(oct, 0);
959*f173c2b7SSean Bruno 		return (1);
960*f173c2b7SSean Bruno 	}
961*f173c2b7SSean Bruno 
962*f173c2b7SSean Bruno 	lio_cn23xx_pf_get_pf_num(oct);
963*f173c2b7SSean Bruno 
964*f173c2b7SSean Bruno 	if (lio_cn23xx_pf_sriov_config(oct)) {
965*f173c2b7SSean Bruno 		lio_unmap_pci_barx(oct, 0);
966*f173c2b7SSean Bruno 		lio_unmap_pci_barx(oct, 1);
967*f173c2b7SSean Bruno 		return (1);
968*f173c2b7SSean Bruno 	}
969*f173c2b7SSean Bruno 	lio_write_csr64(oct, LIO_CN23XX_SLI_MAC_CREDIT_CNT,
970*f173c2b7SSean Bruno 			0x3F802080802080ULL);
971*f173c2b7SSean Bruno 
972*f173c2b7SSean Bruno 	oct->fn_list.setup_iq_regs = lio_cn23xx_pf_setup_iq_regs;
973*f173c2b7SSean Bruno 	oct->fn_list.setup_oq_regs = lio_cn23xx_pf_setup_oq_regs;
974*f173c2b7SSean Bruno 	oct->fn_list.process_interrupt_regs = lio_cn23xx_pf_interrupt_handler;
975*f173c2b7SSean Bruno 	oct->fn_list.msix_interrupt_handler =
976*f173c2b7SSean Bruno 		lio_cn23xx_pf_msix_interrupt_handler;
977*f173c2b7SSean Bruno 
978*f173c2b7SSean Bruno 	oct->fn_list.soft_reset = lio_cn23xx_pf_soft_reset;
979*f173c2b7SSean Bruno 	oct->fn_list.setup_device_regs = lio_cn23xx_pf_setup_device_regs;
980*f173c2b7SSean Bruno 	oct->fn_list.update_iq_read_idx = lio_cn23xx_pf_update_read_index;
981*f173c2b7SSean Bruno 
982*f173c2b7SSean Bruno 	oct->fn_list.bar1_idx_setup = lio_cn23xx_pf_bar1_idx_setup;
983*f173c2b7SSean Bruno 	oct->fn_list.bar1_idx_write = lio_cn23xx_pf_bar1_idx_write;
984*f173c2b7SSean Bruno 	oct->fn_list.bar1_idx_read = lio_cn23xx_pf_bar1_idx_read;
985*f173c2b7SSean Bruno 
986*f173c2b7SSean Bruno 	oct->fn_list.enable_interrupt = lio_cn23xx_pf_enable_interrupt;
987*f173c2b7SSean Bruno 	oct->fn_list.disable_interrupt = lio_cn23xx_pf_disable_interrupt;
988*f173c2b7SSean Bruno 
989*f173c2b7SSean Bruno 	oct->fn_list.enable_io_queues = lio_cn23xx_pf_enable_io_queues;
990*f173c2b7SSean Bruno 	oct->fn_list.disable_io_queues = lio_cn23xx_pf_disable_io_queues;
991*f173c2b7SSean Bruno 
992*f173c2b7SSean Bruno 	lio_cn23xx_pf_setup_reg_address(oct);
993*f173c2b7SSean Bruno 
994*f173c2b7SSean Bruno 	oct->coproc_clock_rate = 1000000ULL *
995*f173c2b7SSean Bruno 		lio_cn23xx_pf_coprocessor_clock(oct);
996*f173c2b7SSean Bruno 
997*f173c2b7SSean Bruno 	return (0);
998*f173c2b7SSean Bruno }
999*f173c2b7SSean Bruno 
1000*f173c2b7SSean Bruno int
1001*f173c2b7SSean Bruno lio_cn23xx_pf_fw_loaded(struct octeon_device *oct)
1002*f173c2b7SSean Bruno {
1003*f173c2b7SSean Bruno 	uint64_t	val;
1004*f173c2b7SSean Bruno 
1005*f173c2b7SSean Bruno 	val = lio_read_csr64(oct, LIO_CN23XX_SLI_SCRATCH2);
1006*f173c2b7SSean Bruno 	return ((val >> SCR2_BIT_FW_LOADED) & 1ULL);
1007*f173c2b7SSean Bruno }
1008*f173c2b7SSean Bruno 
1009