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