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 */