1 /*
2 * Copyright 2008-2013 Solarflare Communications Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26 #include "efsys.h"
27 #include "efx.h"
28 #include "efx_types.h"
29 #include "efx_regs.h"
30 #include "efx_impl.h"
31 #include "falcon_stats.h"
32 #include "falcon_xmac.h"
33
34 #if EFSYS_OPT_MAC_FALCON_XMAC
35
36 static __checkReturn int
37 falcon_xmac_xgxs_reset(
38 __in efx_nic_t *enp)
39 {
40 efx_oword_t oword;
41 unsigned int count;
42 int rc;
43
44 /* Reset the XGMAC via the Vendor Register */
45 EFX_POPULATE_OWORD_1(oword, FRF_AB_XX_RST_XX_EN, 1);
46 EFX_BAR_WRITEO(enp, FR_AB_XX_PWR_RST_REG, &oword);
47
48 count = 0;
49 do {
50 EFSYS_PROBE1(wait, unsigned int, count);
51
52 /* Spin for 10us */
53 EFSYS_SPIN(10);
54
55 /* Test for reset complete */
56 EFX_BAR_READO(enp, FR_AB_XX_PWR_RST_REG, &oword);
57 if (EFX_OWORD_FIELD(oword, FRF_AB_XX_RST_XX_EN) == 0 &&
58 EFX_OWORD_FIELD(oword, FRF_AB_XX_SD_RST_ACT) == 0)
59 goto done;
60 } while (++count < 1000);
61
62 rc = ETIMEDOUT;
63 goto fail1;
64
65 done:
66 return (0);
67
68 fail1:
69 EFSYS_PROBE1(fail1, int, rc);
70
71 return (rc);
72 }
73
74 static void
75 falcon_xmac_xgxs_reconfigure(
76 __in efx_nic_t *enp)
77 {
78 #if EFSYS_OPT_LOOPBACK
79 efx_port_t *epp = &(enp->en_port);
80 #endif /* EFSYS_OPT_LOOPBACK */
81 efx_oword_t oword;
82 uint32_t force_sig;
83 uint32_t force_sig_val;
84 uint32_t xgxs_lb_en;
85 uint32_t xgmii_lb_en;
86 uint32_t lpbk;
87 boolean_t need_reset;
88
89 #if EFSYS_OPT_LOOPBACK
90 force_sig =
91 (epp->ep_loopback_type == EFX_LOOPBACK_XGXS ||
92 epp->ep_loopback_type == EFX_LOOPBACK_XAUI) ?
93 1 : 0;
94 force_sig_val =
95 (epp->ep_loopback_type == EFX_LOOPBACK_XGXS ||
96 epp->ep_loopback_type == EFX_LOOPBACK_XAUI) ?
97 1 : 0;
98 xgxs_lb_en = (epp->ep_loopback_type == EFX_LOOPBACK_XGXS) ?
99 1 : 0;
100 xgmii_lb_en = (epp->ep_loopback_type == EFX_LOOPBACK_XGMII) ?
101 1 : 0;
102 lpbk = (epp->ep_loopback_type == EFX_LOOPBACK_XAUI) ?
103 1 : 0;
104 #else /* EFSYS_OPT_LOOPBACK */
105 force_sig = 0;
106 force_sig_val = 0;
107 xgxs_lb_en = 0;
108 xgmii_lb_en = 0;
109 lpbk = 0;
110 #endif /* EFSYS_OPT_LOOPBACK */
111
112 EFX_BAR_READO(enp, FR_AB_XX_CORE_STAT_REG, &oword);
113 need_reset =
114 (EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG0) != force_sig ||
115 EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG0_VAL) != force_sig_val ||
116 EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG1) != force_sig ||
117 EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG1_VAL) != force_sig_val ||
118 EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG2) != force_sig ||
119 EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG2_VAL) != force_sig_val ||
120 EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG3) != force_sig ||
121 EFX_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG3_VAL) != force_sig_val ||
122 EFX_OWORD_FIELD(oword, FRF_AB_XX_XGXS_LB_EN) != xgxs_lb_en ||
123 EFX_OWORD_FIELD(oword, FRF_AB_XX_XGMII_LB_EN) != xgmii_lb_en);
124
125 EFX_BAR_READO(enp, FR_AB_XX_SD_CTL_REG, &oword);
126 need_reset |= (EFX_OWORD_FIELD(oword, FRF_AB_XX_LPBKA) != lpbk ||
127 EFX_OWORD_FIELD(oword, FRF_AB_XX_LPBKB) != lpbk ||
128 EFX_OWORD_FIELD(oword, FRF_AB_XX_LPBKC) != lpbk ||
129 EFX_OWORD_FIELD(oword, FRF_AB_XX_LPBKD) != lpbk);
130
131 if (need_reset)
132 (void) falcon_xmac_xgxs_reset(enp);
133
134 EFX_BAR_READO(enp, FR_AB_XX_CORE_STAT_REG, &oword);
135 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG0, force_sig);
136 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG0_VAL, force_sig_val);
137 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG1, force_sig);
138 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG1_VAL, force_sig_val);
139 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG2, force_sig);
140 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG2_VAL, force_sig_val);
141 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG3, force_sig);
142 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_FORCE_SIG3_VAL, force_sig_val);
143 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_XGXS_LB_EN, xgxs_lb_en);
144 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_XGMII_LB_EN, xgmii_lb_en);
145 EFX_BAR_WRITEO(enp, FR_AB_XX_CORE_STAT_REG, &oword);
146
147 EFX_BAR_READO(enp, FR_AB_XX_SD_CTL_REG, &oword);
148 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_LPBKD, lpbk);
149 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_LPBKB, lpbk);
150 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_LPBKC, lpbk);
151 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_LPBKA, lpbk);
152 EFX_BAR_WRITEO(enp, FR_AB_XX_SD_CTL_REG, &oword);
153 }
154
155 static void
156 falcon_xmac_core_reconfigure(
157 __in efx_nic_t *enp)
158 {
159 efx_port_t *epp = &(enp->en_port);
160 efx_oword_t oword;
161
162 EFX_POPULATE_OWORD_3(oword,
163 FRF_AB_XM_RX_JUMBO_MODE, 1,
164 FRF_AB_XM_TX_STAT_EN, 1,
165 FRF_AB_XM_RX_STAT_EN, 1);
166
167 EFX_BAR_WRITEO(enp, FR_AB_XM_GLB_CFG_REG, &oword);
168
169 EFX_POPULATE_OWORD_6(oword,
170 FRF_AB_XM_TXEN, 1,
171 FRF_AB_XM_TX_PRMBL, 1,
172 FRF_AB_XM_AUTO_PAD, 1,
173 FRF_AB_XM_TXCRC, 1,
174 FRF_AB_XM_FCNTL, 1,
175 FRF_AB_XM_IPG, 3);
176
177 EFX_BAR_WRITEO(enp, FR_AB_XM_TX_CFG_REG, &oword);
178
179 EFX_POPULATE_OWORD_6(oword,
180 FRF_AB_XM_RXEN, 1,
181 FRF_AB_XM_AUTO_DEPAD, 0,
182 FRF_AB_XM_REJ_BCAST, (epp->ep_brdcst) ? 0 : 1,
183 FRF_AB_XM_ACPT_ALL_MCAST, 1,
184 FRF_AB_XM_ACPT_ALL_UCAST, (epp->ep_unicst) ? 1 : 0,
185 FRF_AB_XM_PASS_CRC_ERR, 1);
186
187 EFX_BAR_WRITEO(enp, FR_AB_XM_RX_CFG_REG, &oword);
188
189 EFX_POPULATE_OWORD_2(oword,
190 FRF_AB_XM_PAUSE_TIME, 0xfffe,
191 FRF_AB_XM_DIS_FCNTL, (epp->ep_fcntl != 0) ? 0 : 1);
192
193 EFX_BAR_WRITEO(enp, FR_AB_XM_FC_REG, &oword);
194
195 EFX_POPULATE_OWORD_1(oword, FRF_AB_XM_ADR_LO,
196 ((uint32_t)epp->ep_mac_addr[0] << 0) |
197 ((uint32_t)epp->ep_mac_addr[1] << 8) |
198 ((uint32_t)epp->ep_mac_addr[2] << 16) |
199 ((uint32_t)epp->ep_mac_addr[3] << 24));
200
201 EFX_BAR_WRITEO(enp, FR_AB_XM_ADR_LO_REG, &oword);
202
203 EFX_POPULATE_OWORD_1(oword, FRF_AB_XM_ADR_HI,
204 ((uint32_t)epp->ep_mac_addr[4] << 0) |
205 ((uint32_t)epp->ep_mac_addr[5] << 8));
206
207 EFX_BAR_WRITEO(enp, FR_AB_XM_ADR_HI_REG, &oword);
208
209 EFX_POPULATE_OWORD_1(oword,
210 FRF_AB_XM_MAX_RX_FRM_SIZE_HI, epp->ep_mac_pdu >> 3);
211
212 EFX_BAR_WRITEO(enp, FR_AB_XM_RX_PARAM_REG, &oword);
213
214 EFX_POPULATE_OWORD_2(oword,
215 FRF_AB_XM_MAX_TX_FRM_SIZE_HI, epp->ep_mac_pdu >> 3,
216 FRF_AB_XM_TX_JUMBO_MODE, 1);
217
218 EFX_BAR_WRITEO(enp, FR_AB_XM_TX_PARAM_REG, &oword);
219 }
220
221 __checkReturn int
222 falcon_xmac_reset(
223 __in efx_nic_t *enp)
224 {
225 efx_port_t *epp = &(enp->en_port);
226 efx_oword_t oword;
227 int rc;
228
229 EFSYS_ASSERT3U(epp->ep_mac_type, ==, EFX_MAC_FALCON_XMAC);
230
231 EFSYS_PROBE(reset);
232
233 /* Ensure that the XMAC registers are accessible */
234 EFX_BAR_READO(enp, FR_AB_NIC_STAT_REG, &oword);
235 EFX_SET_OWORD_FIELD(oword, FRF_BB_EE_STRAP_EN, 1);
236 EFX_SET_OWORD_FIELD(oword, FRF_BB_EE_STRAP, 0x5);
237 EFX_BAR_WRITEO(enp, FR_AB_NIC_STAT_REG, &oword);
238
239 if ((rc = falcon_mac_wrapper_disable(enp)) != 0)
240 goto fail1;
241
242 /*
243 * Force the PHY XAUI state machine to restart after the EM block
244 * reset. Don't do this if we're now in a MAC level loopback.
245 */
246 #if EFSYS_OPT_LOOPBACK
247 if ((1 << epp->ep_loopback_type) & ~EFX_LOOPBACK_MAC_MASK)
248 #endif
249 if ((rc = falcon_xmac_xgxs_reset(enp)) != 0)
250 goto fail2;
251
252 epp->ep_mac_poll_needed = B_TRUE;
253
254 enp->en_reset_flags |= EFX_RESET_MAC;
255
256 return (0);
257
258 fail2:
259 EFSYS_PROBE(fail2);
260 fail1:
261 EFSYS_PROBE1(fail1, int, rc);
262
263 return (rc);
264 }
265
266 __checkReturn int
267 falcon_xmac_reconfigure(
268 __in efx_nic_t *enp)
269 {
270 efx_port_t *epp = &(enp->en_port);
271
272 EFSYS_PROBE(reconfigure);
273
274 EFSYS_ASSERT3U(epp->ep_mac_type, ==, EFX_MAC_FALCON_XMAC);
275 EFSYS_ASSERT(epp->ep_link_mode == EFX_LINK_UNKNOWN ||
276 epp->ep_link_mode == EFX_LINK_DOWN ||
277 epp->ep_link_mode == EFX_LINK_10000FDX);
278
279 falcon_xmac_xgxs_reconfigure(enp);
280 falcon_xmac_core_reconfigure(enp);
281
282 falcon_mac_wrapper_enable(enp);
283
284 return (0);
285 }
286
287 #if EFSYS_OPT_MAC_STATS
288 static uint32_t
289 falcon_xmac_stat_read(
290 __in efsys_mem_t *esmp,
291 __in unsigned int offset,
292 __in unsigned int width)
293 {
294 uint32_t val;
295
296 switch (width) {
297 case 2: {
298 efx_dword_t dword;
299
300 EFSYS_MEM_READD(esmp, offset, &dword);
301
302 val = (uint16_t)EFX_DWORD_FIELD(dword, EFX_WORD_0);
303 break;
304 }
305 case 4: {
306 efx_dword_t dword;
307
308 EFSYS_MEM_READD(esmp, offset, &dword);
309
310 val = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
311 break;
312 }
313 case 6: {
314 efx_qword_t qword;
315
316 EFSYS_MEM_READQ(esmp, offset, &qword);
317
318 val = EFX_QWORD_FIELD(qword, EFX_DWORD_0);
319 break;
320 }
321 default:
322 EFSYS_ASSERT(B_FALSE);
323
324 val = 0;
325 break;
326 }
327
328 return (val);
329 }
330
331 #define XMAC_STAT_READ(_esmp, _id) \
332 falcon_xmac_stat_read((_esmp), XG_STAT_OFFSET(_id), \
333 XG_STAT_WIDTH(_id))
334
335 #define XMAC_STAT_INCR(_esmp, _stat, _id) \
336 do { \
337 delta = XMAC_STAT_READ(_esmp, _id); \
338 EFSYS_STAT_INCR(&(_stat), delta); \
339 _NOTE(CONSTANTCONDITION) \
340 } while (0)
341
342 #define XMAC_STAT_DECR(_esmp, _stat, _id) \
343 do { \
344 delta = XMAC_STAT_READ(_esmp, _id); \
345 EFSYS_STAT_DECR(&(_stat), delta); \
346 _NOTE(CONSTANTCONDITION) \
347 } while (0)
348
349 __checkReturn int
350 falcon_xmac_stats_update(
351 __in efx_nic_t *enp,
352 __in efsys_mem_t *esmp,
353 __in_ecount(EFX_MAC_NSTATS) efsys_stat_t *stat,
354 __out_opt uint32_t *generationp)
355 {
356 efx_port_t *epp = &(enp->en_port);
357 efx_oword_t oword;
358 uint32_t delta;
359
360 _NOTE(ARGUNUSED(generationp));
361 EFSYS_ASSERT3U(epp->ep_mac_type, ==, EFX_MAC_FALCON_XMAC);
362
363 /* Check the DMA flag */
364 if (XMAC_STAT_READ(esmp, DMA_DONE) != DMA_IS_DONE)
365 return (EAGAIN);
366 EFSYS_MEM_READ_BARRIER();
367
368 /* RX */
369 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_OCTETS], RX_OCTETS);
370 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_PKTS], RX_PKTS);
371 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_UNICST_PKTS], RX_UNICAST_PKTS);
372 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_MULTICST_PKTS],
373 RX_MULTICAST_PKTS);
374 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_BRDCST_PKTS], RX_BROADCAST_PKTS);
375 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_PAUSE_PKTS], RX_PAUSE_PKTS);
376 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_LE_64_PKTS], RX_UNDERSIZE_PKTS);
377
378 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_LE_64_PKTS], RX_PKTS_64_OCTETS);
379 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_65_TO_127_PKTS],
380 RX_PKTS_65_TO_127_OCTETS);
381 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_128_TO_255_PKTS],
382 RX_PKTS_128_TO_255_OCTETS);
383 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_256_TO_511_PKTS],
384 RX_PKTS_256_TO_511_OCTETS);
385 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_512_TO_1023_PKTS],
386 RX_PKTS_512_TO_1023_OCTETS);
387 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_1024_TO_15XX_PKTS],
388 RX_PKTS_1024_TO_15XX_OCTETS);
389
390 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_GE_15XX_PKTS],
391 RX_PKTS_15XX_TO_MAX_OCTETS);
392 XMAC_STAT_DECR(esmp, stat[EFX_MAC_RX_GE_15XX_PKTS],
393 RX_OVERSIZE_PKTS);
394
395 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_ERRORS], RX_PKTS);
396 XMAC_STAT_DECR(esmp, stat[EFX_MAC_RX_ERRORS], RX_PKTS_OK);
397
398 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_FCS_ERRORS],
399 RX_UNDERSIZE_FCS_ERROR_PKTS);
400 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_FCS_ERRORS], RX_FCS_ERROR_PKTS);
401 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_DROP_EVENTS], RX_DROP_EVENTS);
402 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_SYMBOL_ERRORS], RX_SYMBOL_ERROR);
403 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_ALIGN_ERRORS], RX_ALIGN_ERROR);
404 XMAC_STAT_INCR(esmp, stat[EFX_MAC_RX_INTERNAL_ERRORS],
405 RX_INTERNAL_MAC_ERROR);
406
407 EFX_BAR_READO(enp, FR_AZ_RX_NODESC_DROP_REG, &oword);
408 delta = (uint32_t)EFX_OWORD_FIELD(oword, FRF_AZ_RX_NODESC_DROP_CNT);
409 EFSYS_STAT_INCR(&(stat[EFX_MAC_RX_NODESC_DROP_CNT]), delta);
410
411 /* TX */
412 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_OCTETS], TX_OCTETS);
413 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_PKTS], TX_PKTS);
414 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_UNICST_PKTS], TX_UNICAST_PKTS);
415 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_MULTICST_PKTS],
416 TX_MULTICAST_PKTS);
417 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_BRDCST_PKTS], TX_BROADCAST_PKTS);
418 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_PAUSE_PKTS], TX_PAUSE_PKTS);
419
420 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_LE_64_PKTS], TX_UNDERSIZE_PKTS);
421 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_LE_64_PKTS], TX_PKTS_64_OCTETS);
422 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_65_TO_127_PKTS],
423 TX_PKTS_65_TO_127_OCTETS);
424 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_128_TO_255_PKTS],
425 TX_PKTS_128_TO_255_OCTETS);
426 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_256_TO_511_PKTS],
427 TX_PKTS_256_TO_511_OCTETS);
428 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_512_TO_1023_PKTS],
429 TX_PKTS_512_TO_1023_OCTETS);
430 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_1024_TO_15XX_PKTS],
431 TX_PKTS_1024_TO_15XX_OCTETS);
432 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_GE_15XX_PKTS],
433 TX_PKTS_15XX_TO_MAX_OCTETS);
434 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_GE_15XX_PKTS],
435 TX_OVERSIZE_PKTS);
436
437 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_ERRORS], TX_MAC_SRC_ERR_PKTS);
438 XMAC_STAT_INCR(esmp, stat[EFX_MAC_TX_ERRORS], TX_IP_SRC_ERR_PKTS);
439
440 return (0);
441 }
442 #endif /* EFSYS_OPT_MAC_STATS */
443
444 static void
445 falcon_xmac_downlink_check(
446 __in efx_nic_t *enp,
447 __out boolean_t *upp)
448 {
449 efx_port_t *epp = &(enp->en_port);
450 efx_oword_t oword;
451 boolean_t align_done;
452 boolean_t sync_stat;
453
454 EFSYS_ASSERT3U(epp->ep_mac_type, ==, EFX_MAC_FALCON_XMAC);
455
456 /* XGXS state irrelevent in XGMII loopback */
457 #if EFSYS_OPT_LOOPBACK
458 if (epp->ep_loopback_type == EFX_LOOPBACK_XGMII) {
459 *upp = B_TRUE;
460 return;
461 }
462 #endif /* EFSYS_OPT_LOOPBACK */
463
464 EFX_BAR_READO(enp, FR_AB_XX_CORE_STAT_REG, &oword);
465
466 align_done = (EFX_OWORD_FIELD(oword, FRF_AB_XX_ALIGN_DONE) != 0);
467 sync_stat = (EFX_OWORD_FIELD(oword, FRF_AB_XX_SYNC_STAT0) != 0 &&
468 EFX_OWORD_FIELD(oword, FRF_AB_XX_SYNC_STAT1) != 0 &&
469 EFX_OWORD_FIELD(oword, FRF_AB_XX_SYNC_STAT2) != 0 &&
470 EFX_OWORD_FIELD(oword, FRF_AB_XX_SYNC_STAT3) != 0);
471
472 *upp = (align_done && sync_stat);
473
474 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_COMMA_DET_CH0, 1);
475 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_COMMA_DET_CH1, 1);
476 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_COMMA_DET_CH2, 1);
477 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_COMMA_DET_CH3, 1);
478
479 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_CHAR_ERR_CH0, 1);
480 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_CHAR_ERR_CH1, 1);
481 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_CHAR_ERR_CH2, 1);
482 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_CHAR_ERR_CH3, 1);
483
484 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_DISPERR_CH0, 1);
485 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_DISPERR_CH1, 1);
486 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_DISPERR_CH2, 1);
487 EFX_SET_OWORD_FIELD(oword, FRF_AB_XX_DISPERR_CH3, 1);
488
489 EFX_BAR_WRITEO(enp, FR_AB_XX_CORE_STAT_REG, &oword);
490 }
491
492 void
493 falcon_xmac_poll(
494 __in efx_nic_t *enp,
495 __out boolean_t *mac_upp)
496 {
497 efx_port_t *epp = &(enp->en_port);
498 efx_phy_ops_t *epop = epp->ep_epop;
499 boolean_t mac_up = B_TRUE;
500 boolean_t ok;
501
502 /* Poll the mac link state if required */
503 if (epp->ep_mac_poll_needed) {
504 falcon_xmac_downlink_check(enp, &mac_up);
505 if (!mac_up)
506 goto done;
507 #if EFSYS_OPT_LOOPBACK
508 /* PHYXS link state irrelevent in MAC loopback */
509 if ((1 << epp->ep_loopback_type) & EFX_LOOPBACK_MAC_MASK)
510 goto done;
511 #endif
512 if (epop->epo_uplink_check != NULL) {
513 if (epop->epo_uplink_check(enp, &ok) == 0)
514 mac_up = ok;
515 }
516 }
517
518 done:
519 *mac_upp = mac_up;
520
521 /*
522 * If the XAUI link (and therefore wireside link) are UP, then we
523 * can use XGMT interrupts rather than polling the link state to spot
524 * downwards transitions. To spot upwards transitions, we must poll
525 */
526 epp->ep_mac_poll_needed = !mac_up;
527 if (mac_up) {
528 efx_oword_t oword;
529
530 /* ACK the interrupt */
531 EFX_BAR_READO(enp, FR_AB_XM_MGT_INT_REG, &oword);
532 } else {
533 (void) falcon_xmac_xgxs_reset(enp);
534 }
535 }
536
537 #endif /* EFSYS_OPT_MAC_FALCON_XMAC */