xref: /linux/drivers/net/ethernet/meta/fbnic/fbnic_mac.c (revision a3a02a52bcfcbcc4a637d4b68bf1bc391c9fad02)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) Meta Platforms, Inc. and affiliates. */
3 
4 #include <linux/bitfield.h>
5 #include <net/tcp.h>
6 
7 #include "fbnic.h"
8 #include "fbnic_mac.h"
9 #include "fbnic_netdev.h"
10 
11 static void fbnic_init_readrq(struct fbnic_dev *fbd, unsigned int offset,
12 			      unsigned int cls, unsigned int readrq)
13 {
14 	u32 val = rd32(fbd, offset);
15 
16 	/* The TDF_CTL masks are a superset of the RNI_RBP ones. So we can
17 	 * use them when setting either the TDE_CTF or RNI_RBP registers.
18 	 */
19 	val &= FBNIC_QM_TNI_TDF_CTL_MAX_OT | FBNIC_QM_TNI_TDF_CTL_MAX_OB;
20 
21 	val |= FIELD_PREP(FBNIC_QM_TNI_TDF_CTL_MRRS, readrq) |
22 	       FIELD_PREP(FBNIC_QM_TNI_TDF_CTL_CLS, cls);
23 
24 	wr32(fbd, offset, val);
25 }
26 
27 static void fbnic_init_mps(struct fbnic_dev *fbd, unsigned int offset,
28 			   unsigned int cls, unsigned int mps)
29 {
30 	u32 val = rd32(fbd, offset);
31 
32 	/* Currently all MPS masks are identical so just use the first one */
33 	val &= ~(FBNIC_QM_TNI_TCM_CTL_MPS | FBNIC_QM_TNI_TCM_CTL_CLS);
34 
35 	val |= FIELD_PREP(FBNIC_QM_TNI_TCM_CTL_MPS, mps) |
36 	       FIELD_PREP(FBNIC_QM_TNI_TCM_CTL_CLS, cls);
37 
38 	wr32(fbd, offset, val);
39 }
40 
41 static void fbnic_mac_init_axi(struct fbnic_dev *fbd)
42 {
43 	bool override_1k = false;
44 	int readrq, mps, cls;
45 
46 	/* All of the values are based on being a power of 2 starting
47 	 * with 64 == 0. Therefore we can either divide by 64 in the
48 	 * case of constants, or just subtract 6 from the log2 of the value
49 	 * in order to get the value we will be programming into the
50 	 * registers.
51 	 */
52 	readrq = ilog2(fbd->readrq) - 6;
53 	if (readrq > 3)
54 		override_1k = true;
55 	readrq = clamp(readrq, 0, 3);
56 
57 	mps = ilog2(fbd->mps) - 6;
58 	mps = clamp(mps, 0, 3);
59 
60 	cls = ilog2(L1_CACHE_BYTES) - 6;
61 	cls = clamp(cls, 0, 3);
62 
63 	/* Configure Tx/Rx AXI Paths w/ Read Request and Max Payload sizes */
64 	fbnic_init_readrq(fbd, FBNIC_QM_TNI_TDF_CTL, cls, readrq);
65 	fbnic_init_mps(fbd, FBNIC_QM_TNI_TCM_CTL, cls, mps);
66 
67 	/* Configure QM TNI TDE:
68 	 * - Max outstanding AXI beats to 704(768 - 64) - guaranetees 8% of
69 	 *   buffer capacity to descriptors.
70 	 * - Max outstanding transactions to 128
71 	 */
72 	wr32(fbd, FBNIC_QM_TNI_TDE_CTL,
73 	     FIELD_PREP(FBNIC_QM_TNI_TDE_CTL_MRRS_1K, override_1k ? 1 : 0) |
74 	     FIELD_PREP(FBNIC_QM_TNI_TDE_CTL_MAX_OB, 704) |
75 	     FIELD_PREP(FBNIC_QM_TNI_TDE_CTL_MAX_OT, 128) |
76 	     FIELD_PREP(FBNIC_QM_TNI_TDE_CTL_MRRS, readrq) |
77 	     FIELD_PREP(FBNIC_QM_TNI_TDE_CTL_CLS, cls));
78 
79 	fbnic_init_readrq(fbd, FBNIC_QM_RNI_RBP_CTL, cls, readrq);
80 	fbnic_init_mps(fbd, FBNIC_QM_RNI_RDE_CTL, cls, mps);
81 	fbnic_init_mps(fbd, FBNIC_QM_RNI_RCM_CTL, cls, mps);
82 
83 	/* Enable XALI AR/AW outbound */
84 	wr32(fbd, FBNIC_PUL_OB_TLP_HDR_AW_CFG,
85 	     FBNIC_PUL_OB_TLP_HDR_AW_CFG_BME);
86 	wr32(fbd, FBNIC_PUL_OB_TLP_HDR_AR_CFG,
87 	     FBNIC_PUL_OB_TLP_HDR_AR_CFG_BME);
88 }
89 
90 static void fbnic_mac_init_qm(struct fbnic_dev *fbd)
91 {
92 	u32 clock_freq;
93 
94 	/* Configure TSO behavior */
95 	wr32(fbd, FBNIC_QM_TQS_CTL0,
96 	     FIELD_PREP(FBNIC_QM_TQS_CTL0_LSO_TS_MASK,
97 			FBNIC_QM_TQS_CTL0_LSO_TS_LAST) |
98 	     FIELD_PREP(FBNIC_QM_TQS_CTL0_PREFETCH_THRESH,
99 			FBNIC_QM_TQS_CTL0_PREFETCH_THRESH_MIN));
100 
101 	/* Limit EDT to INT_MAX as this is the limit of the EDT Qdisc */
102 	wr32(fbd, FBNIC_QM_TQS_EDT_TS_RANGE, INT_MAX);
103 
104 	/* Configure MTU
105 	 * Due to known HW issue we cannot set the MTU to within 16 octets
106 	 * of a 64 octet aligned boundary. So we will set the TQS_MTU(s) to
107 	 * MTU + 1.
108 	 */
109 	wr32(fbd, FBNIC_QM_TQS_MTU_CTL0, FBNIC_MAX_JUMBO_FRAME_SIZE + 1);
110 	wr32(fbd, FBNIC_QM_TQS_MTU_CTL1,
111 	     FIELD_PREP(FBNIC_QM_TQS_MTU_CTL1_BULK,
112 			FBNIC_MAX_JUMBO_FRAME_SIZE + 1));
113 
114 	clock_freq = FBNIC_CLOCK_FREQ;
115 
116 	/* Be aggressive on the timings. We will have the interrupt
117 	 * threshold timer tick once every 1 usec and coalesce writes for
118 	 * up to 80 usecs.
119 	 */
120 	wr32(fbd, FBNIC_QM_TCQ_CTL0,
121 	     FIELD_PREP(FBNIC_QM_TCQ_CTL0_TICK_CYCLES,
122 			clock_freq / 1000000) |
123 	     FIELD_PREP(FBNIC_QM_TCQ_CTL0_COAL_WAIT,
124 			clock_freq / 12500));
125 
126 	/* We will have the interrupt threshold timer tick once every
127 	 * 1 usec and coalesce writes for up to 2 usecs.
128 	 */
129 	wr32(fbd, FBNIC_QM_RCQ_CTL0,
130 	     FIELD_PREP(FBNIC_QM_RCQ_CTL0_TICK_CYCLES,
131 			clock_freq / 1000000) |
132 	     FIELD_PREP(FBNIC_QM_RCQ_CTL0_COAL_WAIT,
133 			clock_freq / 500000));
134 
135 	/* Configure spacer control to 64 beats. */
136 	wr32(fbd, FBNIC_FAB_AXI4_AR_SPACER_2_CFG,
137 	     FBNIC_FAB_AXI4_AR_SPACER_MASK |
138 	     FIELD_PREP(FBNIC_FAB_AXI4_AR_SPACER_THREADSHOLD, 2));
139 }
140 
141 #define FBNIC_DROP_EN_MASK	0x7d
142 #define FBNIC_PAUSE_EN_MASK	0x14
143 #define FBNIC_ECN_EN_MASK	0x10
144 
145 struct fbnic_fifo_config {
146 	unsigned int addr;
147 	unsigned int size;
148 };
149 
150 /* Rx FIFO Configuration
151  * The table consists of 8 entries, of which only 4 are currently used
152  * The starting addr is in units of 64B and the size is in 2KB units
153  * Below is the human readable version of the table defined below:
154  * Function		Addr	Size
155  * ----------------------------------
156  * Network to Host/BMC	384K	64K
157  * Unused
158  * Unused
159  * Network to BMC	448K	32K
160  * Network to Host	0	384K
161  * Unused
162  * BMC to Host		480K	32K
163  * Unused
164  */
165 static const struct fbnic_fifo_config fifo_config[] = {
166 	{ .addr = 0x1800, .size = 0x20 },	/* Network to Host/BMC */
167 	{ },					/* Unused */
168 	{ },					/* Unused */
169 	{ .addr = 0x1c00, .size = 0x10 },	/* Network to BMC */
170 	{ .addr = 0x0000, .size = 0xc0 },	/* Network to Host */
171 	{ },					/* Unused */
172 	{ .addr = 0x1e00, .size = 0x10 },	/* BMC to Host */
173 	{ }					/* Unused */
174 };
175 
176 static void fbnic_mac_init_rxb(struct fbnic_dev *fbd)
177 {
178 	bool rx_enable;
179 	int i;
180 
181 	rx_enable = !!(rd32(fbd, FBNIC_RPC_RMI_CONFIG) &
182 		       FBNIC_RPC_RMI_CONFIG_ENABLE);
183 
184 	for (i = 0; i < 8; i++) {
185 		unsigned int size = fifo_config[i].size;
186 
187 		/* If we are coming up on a system that already has the
188 		 * Rx data path enabled we don't need to reconfigure the
189 		 * FIFOs. Instead we can check to verify the values are
190 		 * large enough to meet our needs, and use the values to
191 		 * populate the flow control, ECN, and drop thresholds.
192 		 */
193 		if (rx_enable) {
194 			size = FIELD_GET(FBNIC_RXB_PBUF_SIZE,
195 					 rd32(fbd, FBNIC_RXB_PBUF_CFG(i)));
196 			if (size < fifo_config[i].size)
197 				dev_warn(fbd->dev,
198 					 "fifo%d size of %d smaller than expected value of %d\n",
199 					 i, size << 11,
200 					 fifo_config[i].size << 11);
201 		} else {
202 			/* Program RXB Cuthrough */
203 			wr32(fbd, FBNIC_RXB_CT_SIZE(i),
204 			     FIELD_PREP(FBNIC_RXB_CT_SIZE_HEADER, 4) |
205 			     FIELD_PREP(FBNIC_RXB_CT_SIZE_PAYLOAD, 2));
206 
207 			/* The granularity for the packet buffer size is 2KB
208 			 * granularity while the packet buffer base address is
209 			 * only 64B granularity
210 			 */
211 			wr32(fbd, FBNIC_RXB_PBUF_CFG(i),
212 			     FIELD_PREP(FBNIC_RXB_PBUF_BASE_ADDR,
213 					fifo_config[i].addr) |
214 			     FIELD_PREP(FBNIC_RXB_PBUF_SIZE, size));
215 
216 			/* The granularity for the credits is 64B. This is
217 			 * based on RXB_PBUF_SIZE * 32 + 4.
218 			 */
219 			wr32(fbd, FBNIC_RXB_PBUF_CREDIT(i),
220 			     FIELD_PREP(FBNIC_RXB_PBUF_CREDIT_MASK,
221 					size ? size * 32 + 4 : 0));
222 		}
223 
224 		if (!size)
225 			continue;
226 
227 		/* Pause is size of FIFO with 56KB skid to start/stop */
228 		wr32(fbd, FBNIC_RXB_PAUSE_THLD(i),
229 		     !(FBNIC_PAUSE_EN_MASK & (1u << i)) ? 0x1fff :
230 		     FIELD_PREP(FBNIC_RXB_PAUSE_THLD_ON,
231 				size * 32 - 0x380) |
232 		     FIELD_PREP(FBNIC_RXB_PAUSE_THLD_OFF, 0x380));
233 
234 		/* Enable Drop when only one packet is left in the FIFO */
235 		wr32(fbd, FBNIC_RXB_DROP_THLD(i),
236 		     !(FBNIC_DROP_EN_MASK & (1u << i)) ? 0x1fff :
237 		     FIELD_PREP(FBNIC_RXB_DROP_THLD_ON,
238 				size * 32 -
239 				FBNIC_MAX_JUMBO_FRAME_SIZE / 64) |
240 		     FIELD_PREP(FBNIC_RXB_DROP_THLD_OFF,
241 				size * 32 -
242 				FBNIC_MAX_JUMBO_FRAME_SIZE / 64));
243 
244 		/* Enable ECN bit when 1/4 of RXB is filled with at least
245 		 * 1 room for one full jumbo frame before setting ECN
246 		 */
247 		wr32(fbd, FBNIC_RXB_ECN_THLD(i),
248 		     !(FBNIC_ECN_EN_MASK & (1u << i)) ? 0x1fff :
249 		     FIELD_PREP(FBNIC_RXB_ECN_THLD_ON,
250 				max_t(unsigned int,
251 				      size * 32 / 4,
252 				      FBNIC_MAX_JUMBO_FRAME_SIZE / 64)) |
253 		     FIELD_PREP(FBNIC_RXB_ECN_THLD_OFF,
254 				max_t(unsigned int,
255 				      size * 32 / 4,
256 				      FBNIC_MAX_JUMBO_FRAME_SIZE / 64)));
257 	}
258 
259 	/* For now only enable drop and ECN. We need to add driver/kernel
260 	 * interfaces for configuring pause.
261 	 */
262 	wr32(fbd, FBNIC_RXB_PAUSE_DROP_CTRL,
263 	     FIELD_PREP(FBNIC_RXB_PAUSE_DROP_CTRL_DROP_ENABLE,
264 			FBNIC_DROP_EN_MASK) |
265 	     FIELD_PREP(FBNIC_RXB_PAUSE_DROP_CTRL_ECN_ENABLE,
266 			FBNIC_ECN_EN_MASK));
267 
268 	/* Program INTF credits */
269 	wr32(fbd, FBNIC_RXB_INTF_CREDIT,
270 	     FBNIC_RXB_INTF_CREDIT_MASK0 |
271 	     FBNIC_RXB_INTF_CREDIT_MASK1 |
272 	     FBNIC_RXB_INTF_CREDIT_MASK2 |
273 	     FIELD_PREP(FBNIC_RXB_INTF_CREDIT_MASK3, 8));
274 
275 	/* Configure calendar slots.
276 	 * Rx: 0 - 62	RDE 1st, BMC 2nd
277 	 *     63	BMC 1st, RDE 2nd
278 	 */
279 	for (i = 0; i < 16; i++) {
280 		u32 calendar_val = (i == 15) ? 0x1e1b1b1b : 0x1b1b1b1b;
281 
282 		wr32(fbd, FBNIC_RXB_CLDR_PRIO_CFG(i), calendar_val);
283 	}
284 
285 	/* Split the credits for the DRR up as follows:
286 	 * Quantum0: 8000	Network to Host
287 	 * Quantum1: 0		Not used
288 	 * Quantum2: 80		BMC to Host
289 	 * Quantum3: 0		Not used
290 	 * Quantum4: 8000	Multicast to Host and BMC
291 	 */
292 	wr32(fbd, FBNIC_RXB_DWRR_RDE_WEIGHT0,
293 	     FIELD_PREP(FBNIC_RXB_DWRR_RDE_WEIGHT0_QUANTUM0, 0x40) |
294 	     FIELD_PREP(FBNIC_RXB_DWRR_RDE_WEIGHT0_QUANTUM2, 0x50));
295 	wr32(fbd, FBNIC_RXB_DWRR_RDE_WEIGHT0_EXT,
296 	     FIELD_PREP(FBNIC_RXB_DWRR_RDE_WEIGHT0_QUANTUM0, 0x1f));
297 	wr32(fbd, FBNIC_RXB_DWRR_RDE_WEIGHT1,
298 	     FIELD_PREP(FBNIC_RXB_DWRR_RDE_WEIGHT1_QUANTUM4, 0x40));
299 	wr32(fbd, FBNIC_RXB_DWRR_RDE_WEIGHT1_EXT,
300 	     FIELD_PREP(FBNIC_RXB_DWRR_RDE_WEIGHT1_QUANTUM4, 0x1f));
301 
302 	/* Program RXB FCS Endian register */
303 	wr32(fbd, FBNIC_RXB_ENDIAN_FCS, 0x0aaaaaa0);
304 }
305 
306 static void fbnic_mac_init_txb(struct fbnic_dev *fbd)
307 {
308 	int i;
309 
310 	wr32(fbd, FBNIC_TCE_TXB_CTRL, 0);
311 
312 	/* Configure Tx QM Credits */
313 	wr32(fbd, FBNIC_QM_TQS_CTL1,
314 	     FIELD_PREP(FBNIC_QM_TQS_CTL1_MC_MAX_CREDITS, 0x40) |
315 	     FIELD_PREP(FBNIC_QM_TQS_CTL1_BULK_MAX_CREDITS, 0x20));
316 
317 	/* Initialize internal Tx queues */
318 	wr32(fbd, FBNIC_TCE_TXB_TEI_Q0_CTRL, 0);
319 	wr32(fbd, FBNIC_TCE_TXB_TEI_Q1_CTRL, 0);
320 	wr32(fbd, FBNIC_TCE_TXB_MC_Q_CTRL,
321 	     FIELD_PREP(FBNIC_TCE_TXB_Q_CTRL_SIZE, 0x400) |
322 	     FIELD_PREP(FBNIC_TCE_TXB_Q_CTRL_START, 0x000));
323 	wr32(fbd, FBNIC_TCE_TXB_RX_TEI_Q_CTRL, 0);
324 	wr32(fbd, FBNIC_TCE_TXB_TX_BMC_Q_CTRL,
325 	     FIELD_PREP(FBNIC_TCE_TXB_Q_CTRL_SIZE, 0x200) |
326 	     FIELD_PREP(FBNIC_TCE_TXB_Q_CTRL_START, 0x400));
327 	wr32(fbd, FBNIC_TCE_TXB_RX_BMC_Q_CTRL,
328 	     FIELD_PREP(FBNIC_TCE_TXB_Q_CTRL_SIZE, 0x200) |
329 	     FIELD_PREP(FBNIC_TCE_TXB_Q_CTRL_START, 0x600));
330 
331 	wr32(fbd, FBNIC_TCE_LSO_CTRL,
332 	     FBNIC_TCE_LSO_CTRL_IPID_MODE_INC |
333 	     FIELD_PREP(FBNIC_TCE_LSO_CTRL_TCPF_CLR_1ST, TCPHDR_PSH |
334 							 TCPHDR_FIN) |
335 	     FIELD_PREP(FBNIC_TCE_LSO_CTRL_TCPF_CLR_MID, TCPHDR_PSH |
336 							 TCPHDR_CWR |
337 							 TCPHDR_FIN) |
338 	     FIELD_PREP(FBNIC_TCE_LSO_CTRL_TCPF_CLR_END, TCPHDR_CWR));
339 	wr32(fbd, FBNIC_TCE_CSO_CTRL, 0);
340 
341 	wr32(fbd, FBNIC_TCE_BMC_MAX_PKTSZ,
342 	     FIELD_PREP(FBNIC_TCE_BMC_MAX_PKTSZ_TX,
343 			FBNIC_MAX_JUMBO_FRAME_SIZE) |
344 	     FIELD_PREP(FBNIC_TCE_BMC_MAX_PKTSZ_RX,
345 			FBNIC_MAX_JUMBO_FRAME_SIZE));
346 	wr32(fbd, FBNIC_TCE_MC_MAX_PKTSZ,
347 	     FIELD_PREP(FBNIC_TCE_MC_MAX_PKTSZ_TMI,
348 			FBNIC_MAX_JUMBO_FRAME_SIZE));
349 
350 	/* Configure calendar slots.
351 	 * Tx: 0 - 62	TMI 1st, BMC 2nd
352 	 *     63	BMC 1st, TMI 2nd
353 	 */
354 	for (i = 0; i < 16; i++) {
355 		u32 calendar_val = (i == 15) ? 0x1e1b1b1b : 0x1b1b1b1b;
356 
357 		wr32(fbd, FBNIC_TCE_TXB_CLDR_SLOT_CFG(i), calendar_val);
358 	}
359 
360 	/* Configure DWRR */
361 	wr32(fbd, FBNIC_TCE_TXB_ENQ_WRR_CTRL,
362 	     FIELD_PREP(FBNIC_TCE_TXB_ENQ_WRR_CTRL_WEIGHT0, 0x64) |
363 	     FIELD_PREP(FBNIC_TCE_TXB_ENQ_WRR_CTRL_WEIGHT2, 0x04));
364 	wr32(fbd, FBNIC_TCE_TXB_TEI_DWRR_CTRL, 0);
365 	wr32(fbd, FBNIC_TCE_TXB_TEI_DWRR_CTRL_EXT, 0);
366 	wr32(fbd, FBNIC_TCE_TXB_BMC_DWRR_CTRL,
367 	     FIELD_PREP(FBNIC_TCE_TXB_BMC_DWRR_CTRL_QUANTUM0, 0x50) |
368 	     FIELD_PREP(FBNIC_TCE_TXB_BMC_DWRR_CTRL_QUANTUM1, 0x82));
369 	wr32(fbd, FBNIC_TCE_TXB_BMC_DWRR_CTRL_EXT, 0);
370 	wr32(fbd, FBNIC_TCE_TXB_NTWRK_DWRR_CTRL,
371 	     FIELD_PREP(FBNIC_TCE_TXB_NTWRK_DWRR_CTRL_QUANTUM1, 0x50) |
372 	     FIELD_PREP(FBNIC_TCE_TXB_NTWRK_DWRR_CTRL_QUANTUM2, 0x20));
373 	wr32(fbd, FBNIC_TCE_TXB_NTWRK_DWRR_CTRL_EXT,
374 	     FIELD_PREP(FBNIC_TCE_TXB_NTWRK_DWRR_CTRL_QUANTUM2, 0x03));
375 
376 	/* Configure SOP protocol protection */
377 	wr32(fbd, FBNIC_TCE_SOP_PROT_CTRL,
378 	     FIELD_PREP(FBNIC_TCE_SOP_PROT_CTRL_TBI, 0x78) |
379 	     FIELD_PREP(FBNIC_TCE_SOP_PROT_CTRL_TTI_FRM, 0x40) |
380 	     FIELD_PREP(FBNIC_TCE_SOP_PROT_CTRL_TTI_CM, 0x0c));
381 
382 	/* Conservative configuration on MAC interface Start of Packet
383 	 * protection FIFO. This sets the minimum depth of the FIFO before
384 	 * we start sending packets to the MAC measured in 64B units and
385 	 * up to 160 entries deep.
386 	 *
387 	 * For the ASIC the clock is fast enough that we will likely fill
388 	 * the SOP FIFO before the MAC can drain it. So just use a minimum
389 	 * value of 8.
390 	 */
391 	wr32(fbd, FBNIC_TMI_SOP_PROT_CTRL, 8);
392 
393 	wrfl(fbd);
394 	wr32(fbd, FBNIC_TCE_TXB_CTRL, FBNIC_TCE_TXB_CTRL_TCAM_ENABLE |
395 				      FBNIC_TCE_TXB_CTRL_LOAD);
396 }
397 
398 static void fbnic_mac_init_regs(struct fbnic_dev *fbd)
399 {
400 	fbnic_mac_init_axi(fbd);
401 	fbnic_mac_init_qm(fbd);
402 	fbnic_mac_init_rxb(fbd);
403 	fbnic_mac_init_txb(fbd);
404 }
405 
406 static void fbnic_mac_tx_pause_config(struct fbnic_dev *fbd, bool tx_pause)
407 {
408 	u32 rxb_pause_ctrl;
409 
410 	/* Enable generation of pause frames if enabled */
411 	rxb_pause_ctrl = rd32(fbd, FBNIC_RXB_PAUSE_DROP_CTRL);
412 	rxb_pause_ctrl &= ~FBNIC_RXB_PAUSE_DROP_CTRL_PAUSE_ENABLE;
413 	if (tx_pause)
414 		rxb_pause_ctrl |=
415 			FIELD_PREP(FBNIC_RXB_PAUSE_DROP_CTRL_PAUSE_ENABLE,
416 				   FBNIC_PAUSE_EN_MASK);
417 	wr32(fbd, FBNIC_RXB_PAUSE_DROP_CTRL, rxb_pause_ctrl);
418 }
419 
420 static int fbnic_pcs_get_link_event_asic(struct fbnic_dev *fbd)
421 {
422 	u32 pcs_intr_mask = rd32(fbd, FBNIC_SIG_PCS_INTR_STS);
423 
424 	if (pcs_intr_mask & FBNIC_SIG_PCS_INTR_LINK_DOWN)
425 		return FBNIC_LINK_EVENT_DOWN;
426 
427 	return (pcs_intr_mask & FBNIC_SIG_PCS_INTR_LINK_UP) ?
428 	       FBNIC_LINK_EVENT_UP : FBNIC_LINK_EVENT_NONE;
429 }
430 
431 static u32 __fbnic_mac_cmd_config_asic(struct fbnic_dev *fbd,
432 				       bool tx_pause, bool rx_pause)
433 {
434 	/* Enable MAC Promiscuous mode and Tx padding */
435 	u32 command_config = FBNIC_MAC_COMMAND_CONFIG_TX_PAD_EN |
436 			     FBNIC_MAC_COMMAND_CONFIG_PROMISC_EN;
437 	struct fbnic_net *fbn = netdev_priv(fbd->netdev);
438 
439 	/* Disable pause frames if not enabled */
440 	if (!tx_pause)
441 		command_config |= FBNIC_MAC_COMMAND_CONFIG_TX_PAUSE_DIS;
442 	if (!rx_pause)
443 		command_config |= FBNIC_MAC_COMMAND_CONFIG_RX_PAUSE_DIS;
444 
445 	/* Disable fault handling if no FEC is requested */
446 	if ((fbn->fec & FBNIC_FEC_MODE_MASK) == FBNIC_FEC_OFF)
447 		command_config |= FBNIC_MAC_COMMAND_CONFIG_FLT_HDL_DIS;
448 
449 	return command_config;
450 }
451 
452 static bool fbnic_mac_get_pcs_link_status(struct fbnic_dev *fbd)
453 {
454 	struct fbnic_net *fbn = netdev_priv(fbd->netdev);
455 	u32 pcs_status, lane_mask = ~0;
456 
457 	pcs_status = rd32(fbd, FBNIC_SIG_PCS_OUT0);
458 	if (!(pcs_status & FBNIC_SIG_PCS_OUT0_LINK))
459 		return false;
460 
461 	/* Define the expected lane mask for the status bits we need to check */
462 	switch (fbn->link_mode & FBNIC_LINK_MODE_MASK) {
463 	case FBNIC_LINK_100R2:
464 		lane_mask = 0xf;
465 		break;
466 	case FBNIC_LINK_50R1:
467 		lane_mask = 3;
468 		break;
469 	case FBNIC_LINK_50R2:
470 		switch (fbn->fec & FBNIC_FEC_MODE_MASK) {
471 		case FBNIC_FEC_OFF:
472 			lane_mask = 0x63;
473 			break;
474 		case FBNIC_FEC_RS:
475 			lane_mask = 5;
476 			break;
477 		case FBNIC_FEC_BASER:
478 			lane_mask = 0xf;
479 			break;
480 		}
481 		break;
482 	case FBNIC_LINK_25R1:
483 		lane_mask = 1;
484 		break;
485 	}
486 
487 	/* Use an XOR to remove the bits we expect to see set */
488 	switch (fbn->fec & FBNIC_FEC_MODE_MASK) {
489 	case FBNIC_FEC_OFF:
490 		lane_mask ^= FIELD_GET(FBNIC_SIG_PCS_OUT0_BLOCK_LOCK,
491 				       pcs_status);
492 		break;
493 	case FBNIC_FEC_RS:
494 		lane_mask ^= FIELD_GET(FBNIC_SIG_PCS_OUT0_AMPS_LOCK,
495 				       pcs_status);
496 		break;
497 	case FBNIC_FEC_BASER:
498 		lane_mask ^= FIELD_GET(FBNIC_SIG_PCS_OUT1_FCFEC_LOCK,
499 				       rd32(fbd, FBNIC_SIG_PCS_OUT1));
500 		break;
501 	}
502 
503 	/* If all lanes cancelled then we have a lock on all lanes */
504 	return !lane_mask;
505 }
506 
507 static bool fbnic_pcs_get_link_asic(struct fbnic_dev *fbd)
508 {
509 	bool link;
510 
511 	/* Flush status bits to clear possible stale data,
512 	 * bits should reset themselves back to 1 if link is truly up
513 	 */
514 	wr32(fbd, FBNIC_SIG_PCS_OUT0, FBNIC_SIG_PCS_OUT0_LINK |
515 				      FBNIC_SIG_PCS_OUT0_BLOCK_LOCK |
516 				      FBNIC_SIG_PCS_OUT0_AMPS_LOCK);
517 	wr32(fbd, FBNIC_SIG_PCS_OUT1, FBNIC_SIG_PCS_OUT1_FCFEC_LOCK);
518 	wrfl(fbd);
519 
520 	/* Clear interrupt state due to recent changes. */
521 	wr32(fbd, FBNIC_SIG_PCS_INTR_STS,
522 	     FBNIC_SIG_PCS_INTR_LINK_DOWN | FBNIC_SIG_PCS_INTR_LINK_UP);
523 
524 	link = fbnic_mac_get_pcs_link_status(fbd);
525 
526 	/* Enable interrupt to only capture changes in link state */
527 	wr32(fbd, FBNIC_SIG_PCS_INTR_MASK,
528 	     ~FBNIC_SIG_PCS_INTR_LINK_DOWN & ~FBNIC_SIG_PCS_INTR_LINK_UP);
529 	wr32(fbd, FBNIC_INTR_MASK_CLEAR(0), 1u << FBNIC_PCS_MSIX_ENTRY);
530 
531 	return link;
532 }
533 
534 static void fbnic_pcs_get_fw_settings(struct fbnic_dev *fbd)
535 {
536 	struct fbnic_net *fbn = netdev_priv(fbd->netdev);
537 	u8 link_mode = fbn->link_mode;
538 	u8 fec = fbn->fec;
539 
540 	/* Update FEC first to reflect FW current mode */
541 	if (fbn->fec & FBNIC_FEC_AUTO) {
542 		switch (fbd->fw_cap.link_fec) {
543 		case FBNIC_FW_LINK_FEC_NONE:
544 			fec = FBNIC_FEC_OFF;
545 			break;
546 		case FBNIC_FW_LINK_FEC_RS:
547 			fec = FBNIC_FEC_RS;
548 			break;
549 		case FBNIC_FW_LINK_FEC_BASER:
550 			fec = FBNIC_FEC_BASER;
551 			break;
552 		default:
553 			return;
554 		}
555 
556 		fbn->fec = fec;
557 	}
558 
559 	/* Do nothing if AUTO mode is not engaged */
560 	if (fbn->link_mode & FBNIC_LINK_AUTO) {
561 		switch (fbd->fw_cap.link_speed) {
562 		case FBNIC_FW_LINK_SPEED_25R1:
563 			link_mode = FBNIC_LINK_25R1;
564 			break;
565 		case FBNIC_FW_LINK_SPEED_50R2:
566 			link_mode = FBNIC_LINK_50R2;
567 			break;
568 		case FBNIC_FW_LINK_SPEED_50R1:
569 			link_mode = FBNIC_LINK_50R1;
570 			fec = FBNIC_FEC_RS;
571 			break;
572 		case FBNIC_FW_LINK_SPEED_100R2:
573 			link_mode = FBNIC_LINK_100R2;
574 			fec = FBNIC_FEC_RS;
575 			break;
576 		default:
577 			return;
578 		}
579 
580 		fbn->link_mode = link_mode;
581 	}
582 }
583 
584 static int fbnic_pcs_enable_asic(struct fbnic_dev *fbd)
585 {
586 	/* Mask and clear the PCS interrupt, will be enabled by link handler */
587 	wr32(fbd, FBNIC_SIG_PCS_INTR_MASK, ~0);
588 	wr32(fbd, FBNIC_SIG_PCS_INTR_STS, ~0);
589 
590 	/* Pull in settings from FW */
591 	fbnic_pcs_get_fw_settings(fbd);
592 
593 	return 0;
594 }
595 
596 static void fbnic_pcs_disable_asic(struct fbnic_dev *fbd)
597 {
598 	/* Mask and clear the PCS interrupt */
599 	wr32(fbd, FBNIC_SIG_PCS_INTR_MASK, ~0);
600 	wr32(fbd, FBNIC_SIG_PCS_INTR_STS, ~0);
601 }
602 
603 static void fbnic_mac_link_down_asic(struct fbnic_dev *fbd)
604 {
605 	u32 cmd_cfg, mac_ctrl;
606 
607 	cmd_cfg = __fbnic_mac_cmd_config_asic(fbd, false, false);
608 	mac_ctrl = rd32(fbd, FBNIC_SIG_MAC_IN0);
609 
610 	mac_ctrl |= FBNIC_SIG_MAC_IN0_RESET_FF_TX_CLK |
611 		    FBNIC_SIG_MAC_IN0_RESET_TX_CLK |
612 		    FBNIC_SIG_MAC_IN0_RESET_FF_RX_CLK |
613 		    FBNIC_SIG_MAC_IN0_RESET_RX_CLK;
614 
615 	wr32(fbd, FBNIC_SIG_MAC_IN0, mac_ctrl);
616 	wr32(fbd, FBNIC_MAC_COMMAND_CONFIG, cmd_cfg);
617 }
618 
619 static void fbnic_mac_link_up_asic(struct fbnic_dev *fbd,
620 				   bool tx_pause, bool rx_pause)
621 {
622 	u32 cmd_cfg, mac_ctrl;
623 
624 	fbnic_mac_tx_pause_config(fbd, tx_pause);
625 
626 	cmd_cfg = __fbnic_mac_cmd_config_asic(fbd, tx_pause, rx_pause);
627 	mac_ctrl = rd32(fbd, FBNIC_SIG_MAC_IN0);
628 
629 	mac_ctrl &= ~(FBNIC_SIG_MAC_IN0_RESET_FF_TX_CLK |
630 		      FBNIC_SIG_MAC_IN0_RESET_TX_CLK |
631 		      FBNIC_SIG_MAC_IN0_RESET_FF_RX_CLK |
632 		      FBNIC_SIG_MAC_IN0_RESET_RX_CLK);
633 	cmd_cfg |= FBNIC_MAC_COMMAND_CONFIG_RX_ENA |
634 		   FBNIC_MAC_COMMAND_CONFIG_TX_ENA;
635 
636 	wr32(fbd, FBNIC_SIG_MAC_IN0, mac_ctrl);
637 	wr32(fbd, FBNIC_MAC_COMMAND_CONFIG, cmd_cfg);
638 }
639 
640 static const struct fbnic_mac fbnic_mac_asic = {
641 	.init_regs = fbnic_mac_init_regs,
642 	.pcs_enable = fbnic_pcs_enable_asic,
643 	.pcs_disable = fbnic_pcs_disable_asic,
644 	.pcs_get_link = fbnic_pcs_get_link_asic,
645 	.pcs_get_link_event = fbnic_pcs_get_link_event_asic,
646 	.link_down = fbnic_mac_link_down_asic,
647 	.link_up = fbnic_mac_link_up_asic,
648 };
649 
650 /**
651  * fbnic_mac_init - Assign a MAC type and initialize the fbnic device
652  * @fbd: Device pointer to device to initialize
653  *
654  * Return: zero on success, negative on failure
655  *
656  * Initialize the MAC function pointers and initializes the MAC of
657  * the device.
658  **/
659 int fbnic_mac_init(struct fbnic_dev *fbd)
660 {
661 	fbd->mac = &fbnic_mac_asic;
662 
663 	fbd->mac->init_regs(fbd);
664 
665 	return 0;
666 }
667