12c6ad81dSFurong Xu // SPDX-License-Identifier: GPL-2.0-only 22c6ad81dSFurong Xu /* 32c6ad81dSFurong Xu * Copyright (C) 2024 Furong Xu <0x1207@gmail.com> 42c6ad81dSFurong Xu * stmmac FPE(802.3 Qbu) handling 52c6ad81dSFurong Xu */ 62c6ad81dSFurong Xu #include "stmmac.h" 72c6ad81dSFurong Xu #include "stmmac_fpe.h" 82c6ad81dSFurong Xu #include "dwmac4.h" 92c6ad81dSFurong Xu #include "dwmac5.h" 102c6ad81dSFurong Xu #include "dwxgmac2.h" 112c6ad81dSFurong Xu 1261e6051fSFurong Xu #define GMAC5_MAC_FPE_CTRL_STS 0x00000234 1361e6051fSFurong Xu #define XGMAC_MAC_FPE_CTRL_STS 0x00000280 142c6ad81dSFurong Xu 1561e6051fSFurong Xu #define GMAC5_MTL_FPE_CTRL_STS 0x00000c90 1661e6051fSFurong Xu #define XGMAC_MTL_FPE_CTRL_STS 0x00001090 172c6ad81dSFurong Xu /* Preemption Classification */ 1861e6051fSFurong Xu #define FPE_MTL_PREEMPTION_CLASS GENMASK(15, 8) 192c6ad81dSFurong Xu /* Additional Fragment Size of preempted frames */ 2061e6051fSFurong Xu #define FPE_MTL_ADD_FRAG_SZ GENMASK(1, 0) 212c6ad81dSFurong Xu 2261e6051fSFurong Xu #define STMMAC_MAC_FPE_CTRL_STS_TRSP BIT(19) 2361e6051fSFurong Xu #define STMMAC_MAC_FPE_CTRL_STS_TVER BIT(18) 2461e6051fSFurong Xu #define STMMAC_MAC_FPE_CTRL_STS_RRSP BIT(17) 2561e6051fSFurong Xu #define STMMAC_MAC_FPE_CTRL_STS_RVER BIT(16) 2661e6051fSFurong Xu #define STMMAC_MAC_FPE_CTRL_STS_SRSP BIT(2) 2761e6051fSFurong Xu #define STMMAC_MAC_FPE_CTRL_STS_SVER BIT(1) 2861e6051fSFurong Xu #define STMMAC_MAC_FPE_CTRL_STS_EFPE BIT(0) 292c6ad81dSFurong Xu 30c9cd9a5aSFurong Xu struct stmmac_fpe_reg { 31c9cd9a5aSFurong Xu const u32 mac_fpe_reg; /* offset of MAC_FPE_CTRL_STS */ 32c9cd9a5aSFurong Xu const u32 mtl_fpe_reg; /* offset of MTL_FPE_CTRL_STS */ 33c9cd9a5aSFurong Xu const u32 rxq_ctrl1_reg; /* offset of MAC_RxQ_Ctrl1 */ 34c9cd9a5aSFurong Xu const u32 fprq_mask; /* Frame Preemption Residue Queue */ 35c9cd9a5aSFurong Xu const u32 int_en_reg; /* offset of MAC_Interrupt_Enable */ 36c9cd9a5aSFurong Xu const u32 int_en_bit; /* Frame Preemption Interrupt Enable */ 37c9cd9a5aSFurong Xu }; 38c9cd9a5aSFurong Xu 39af478ca8SFurong Xu bool stmmac_fpe_supported(struct stmmac_priv *priv) 40af478ca8SFurong Xu { 41c9cd9a5aSFurong Xu return priv->dma_cap.fpesel && priv->fpe_cfg.reg && 42c9cd9a5aSFurong Xu priv->hw->mac->fpe_map_preemption_class; 43af478ca8SFurong Xu } 44af478ca8SFurong Xu 45*9ff2aa42SVladimir Oltean static void stmmac_fpe_configure_tx(struct ethtool_mmsv *mmsv, bool tx_enable) 462c6ad81dSFurong Xu { 47*9ff2aa42SVladimir Oltean struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv); 48*9ff2aa42SVladimir Oltean struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg); 49c9cd9a5aSFurong Xu const struct stmmac_fpe_reg *reg = cfg->reg; 50c9cd9a5aSFurong Xu u32 num_rxq = priv->plat->rx_queues_to_use; 51c9cd9a5aSFurong Xu void __iomem *ioaddr = priv->ioaddr; 522c6ad81dSFurong Xu u32 value; 532c6ad81dSFurong Xu 542c6ad81dSFurong Xu if (tx_enable) { 5561e6051fSFurong Xu cfg->fpe_csr = STMMAC_MAC_FPE_CTRL_STS_EFPE; 56c9cd9a5aSFurong Xu value = readl(ioaddr + reg->rxq_ctrl1_reg); 57c9cd9a5aSFurong Xu value &= ~reg->fprq_mask; 58c9cd9a5aSFurong Xu /* Keep this SHIFT, FIELD_PREP() expects a constant mask :-/ */ 59c9cd9a5aSFurong Xu value |= (num_rxq - 1) << __ffs(reg->fprq_mask); 60c9cd9a5aSFurong Xu writel(value, ioaddr + reg->rxq_ctrl1_reg); 612c6ad81dSFurong Xu } else { 622c6ad81dSFurong Xu cfg->fpe_csr = 0; 632c6ad81dSFurong Xu } 64c9cd9a5aSFurong Xu writel(cfg->fpe_csr, ioaddr + reg->mac_fpe_reg); 65*9ff2aa42SVladimir Oltean } 66*9ff2aa42SVladimir Oltean 67*9ff2aa42SVladimir Oltean static void stmmac_fpe_configure_pmac(struct ethtool_mmsv *mmsv, bool pmac_enable) 68*9ff2aa42SVladimir Oltean { 69*9ff2aa42SVladimir Oltean struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv); 70*9ff2aa42SVladimir Oltean struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg); 71*9ff2aa42SVladimir Oltean const struct stmmac_fpe_reg *reg = cfg->reg; 72*9ff2aa42SVladimir Oltean void __iomem *ioaddr = priv->ioaddr; 73*9ff2aa42SVladimir Oltean u32 value; 742c6ad81dSFurong Xu 75c9cd9a5aSFurong Xu value = readl(ioaddr + reg->int_en_reg); 762c6ad81dSFurong Xu 772c6ad81dSFurong Xu if (pmac_enable) { 78c9cd9a5aSFurong Xu if (!(value & reg->int_en_bit)) { 792c6ad81dSFurong Xu /* Dummy read to clear any pending masked interrupts */ 80c9cd9a5aSFurong Xu readl(ioaddr + reg->mac_fpe_reg); 812c6ad81dSFurong Xu 82c9cd9a5aSFurong Xu value |= reg->int_en_bit; 832c6ad81dSFurong Xu } 842c6ad81dSFurong Xu } else { 85c9cd9a5aSFurong Xu value &= ~reg->int_en_bit; 862c6ad81dSFurong Xu } 872c6ad81dSFurong Xu 88c9cd9a5aSFurong Xu writel(value, ioaddr + reg->int_en_reg); 892c6ad81dSFurong Xu } 902c6ad81dSFurong Xu 91*9ff2aa42SVladimir Oltean static void stmmac_fpe_send_mpacket(struct ethtool_mmsv *mmsv, 92*9ff2aa42SVladimir Oltean enum ethtool_mpacket type) 932c6ad81dSFurong Xu { 94*9ff2aa42SVladimir Oltean struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv); 95*9ff2aa42SVladimir Oltean struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg); 96*9ff2aa42SVladimir Oltean const struct stmmac_fpe_reg *reg = cfg->reg; 97c9cd9a5aSFurong Xu void __iomem *ioaddr = priv->ioaddr; 98*9ff2aa42SVladimir Oltean u32 value = cfg->fpe_csr; 992c6ad81dSFurong Xu 100*9ff2aa42SVladimir Oltean if (type == ETHTOOL_MPACKET_VERIFY) 10161e6051fSFurong Xu value |= STMMAC_MAC_FPE_CTRL_STS_SVER; 102*9ff2aa42SVladimir Oltean else if (type == ETHTOOL_MPACKET_RESPONSE) 10361e6051fSFurong Xu value |= STMMAC_MAC_FPE_CTRL_STS_SRSP; 1042c6ad81dSFurong Xu 105c9cd9a5aSFurong Xu writel(value, ioaddr + reg->mac_fpe_reg); 1062c6ad81dSFurong Xu } 1072c6ad81dSFurong Xu 108*9ff2aa42SVladimir Oltean static const struct ethtool_mmsv_ops stmmac_mmsv_ops = { 109*9ff2aa42SVladimir Oltean .configure_tx = stmmac_fpe_configure_tx, 110*9ff2aa42SVladimir Oltean .configure_pmac = stmmac_fpe_configure_pmac, 111*9ff2aa42SVladimir Oltean .send_mpacket = stmmac_fpe_send_mpacket, 112*9ff2aa42SVladimir Oltean }; 113*9ff2aa42SVladimir Oltean 114c9cd9a5aSFurong Xu static void stmmac_fpe_event_status(struct stmmac_priv *priv, int status) 1152c6ad81dSFurong Xu { 1162c6ad81dSFurong Xu struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg; 117*9ff2aa42SVladimir Oltean struct ethtool_mmsv *mmsv = &fpe_cfg->mmsv; 1182c6ad81dSFurong Xu 119*9ff2aa42SVladimir Oltean if (status == FPE_EVENT_UNKNOWN) 120*9ff2aa42SVladimir Oltean return; 1212c6ad81dSFurong Xu 1222c6ad81dSFurong Xu if ((status & FPE_EVENT_RVER) == FPE_EVENT_RVER) 123*9ff2aa42SVladimir Oltean ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET); 1242c6ad81dSFurong Xu 125*9ff2aa42SVladimir Oltean if ((status & FPE_EVENT_TVER) == FPE_EVENT_TVER) 126*9ff2aa42SVladimir Oltean ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET); 1272c6ad81dSFurong Xu 128*9ff2aa42SVladimir Oltean if ((status & FPE_EVENT_RRSP) == FPE_EVENT_RRSP) 129*9ff2aa42SVladimir Oltean ethtool_mmsv_event_handle(mmsv, ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET); 1302c6ad81dSFurong Xu } 1312c6ad81dSFurong Xu 132c9cd9a5aSFurong Xu void stmmac_fpe_irq_status(struct stmmac_priv *priv) 1332c6ad81dSFurong Xu { 134c9cd9a5aSFurong Xu const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg; 135c9cd9a5aSFurong Xu void __iomem *ioaddr = priv->ioaddr; 136c9cd9a5aSFurong Xu struct net_device *dev = priv->dev; 137c9cd9a5aSFurong Xu int status = FPE_EVENT_UNKNOWN; 1382c6ad81dSFurong Xu u32 value; 1392c6ad81dSFurong Xu 1402c6ad81dSFurong Xu /* Reads from the MAC_FPE_CTRL_STS register should only be performed 1412c6ad81dSFurong Xu * here, since the status flags of MAC_FPE_CTRL_STS are "clear on read" 1422c6ad81dSFurong Xu */ 143c9cd9a5aSFurong Xu value = readl(ioaddr + reg->mac_fpe_reg); 1442c6ad81dSFurong Xu 14561e6051fSFurong Xu if (value & STMMAC_MAC_FPE_CTRL_STS_TRSP) { 1462c6ad81dSFurong Xu status |= FPE_EVENT_TRSP; 1472c6ad81dSFurong Xu netdev_dbg(dev, "FPE: Respond mPacket is transmitted\n"); 1482c6ad81dSFurong Xu } 1492c6ad81dSFurong Xu 15061e6051fSFurong Xu if (value & STMMAC_MAC_FPE_CTRL_STS_TVER) { 1512c6ad81dSFurong Xu status |= FPE_EVENT_TVER; 1522c6ad81dSFurong Xu netdev_dbg(dev, "FPE: Verify mPacket is transmitted\n"); 1532c6ad81dSFurong Xu } 1542c6ad81dSFurong Xu 15561e6051fSFurong Xu if (value & STMMAC_MAC_FPE_CTRL_STS_RRSP) { 1562c6ad81dSFurong Xu status |= FPE_EVENT_RRSP; 1572c6ad81dSFurong Xu netdev_dbg(dev, "FPE: Respond mPacket is received\n"); 1582c6ad81dSFurong Xu } 1592c6ad81dSFurong Xu 16061e6051fSFurong Xu if (value & STMMAC_MAC_FPE_CTRL_STS_RVER) { 1612c6ad81dSFurong Xu status |= FPE_EVENT_RVER; 1622c6ad81dSFurong Xu netdev_dbg(dev, "FPE: Verify mPacket is received\n"); 1632c6ad81dSFurong Xu } 1642c6ad81dSFurong Xu 165c9cd9a5aSFurong Xu stmmac_fpe_event_status(priv, status); 1662c6ad81dSFurong Xu } 1672c6ad81dSFurong Xu 1682c6ad81dSFurong Xu void stmmac_fpe_init(struct stmmac_priv *priv) 1692c6ad81dSFurong Xu { 170*9ff2aa42SVladimir Oltean ethtool_mmsv_init(&priv->fpe_cfg.mmsv, priv->dev, 171*9ff2aa42SVladimir Oltean &stmmac_mmsv_ops); 172c9cd9a5aSFurong Xu 173c9cd9a5aSFurong Xu if ((!priv->fpe_cfg.reg || !priv->hw->mac->fpe_map_preemption_class) && 174c9cd9a5aSFurong Xu priv->dma_cap.fpesel) 175c9cd9a5aSFurong Xu dev_info(priv->device, "FPE is not supported by driver.\n"); 1762c6ad81dSFurong Xu } 1772c6ad81dSFurong Xu 178c9cd9a5aSFurong Xu int stmmac_fpe_get_add_frag_size(struct stmmac_priv *priv) 1792c6ad81dSFurong Xu { 180c9cd9a5aSFurong Xu const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg; 181c9cd9a5aSFurong Xu void __iomem *ioaddr = priv->ioaddr; 182c9cd9a5aSFurong Xu 183c9cd9a5aSFurong Xu return FIELD_GET(FPE_MTL_ADD_FRAG_SZ, readl(ioaddr + reg->mtl_fpe_reg)); 1842c6ad81dSFurong Xu } 1852c6ad81dSFurong Xu 186c9cd9a5aSFurong Xu void stmmac_fpe_set_add_frag_size(struct stmmac_priv *priv, u32 add_frag_size) 1872c6ad81dSFurong Xu { 188c9cd9a5aSFurong Xu const struct stmmac_fpe_reg *reg = priv->fpe_cfg.reg; 189c9cd9a5aSFurong Xu void __iomem *ioaddr = priv->ioaddr; 1902c6ad81dSFurong Xu u32 value; 1912c6ad81dSFurong Xu 192c9cd9a5aSFurong Xu value = readl(ioaddr + reg->mtl_fpe_reg); 19361e6051fSFurong Xu writel(u32_replace_bits(value, add_frag_size, FPE_MTL_ADD_FRAG_SZ), 194c9cd9a5aSFurong Xu ioaddr + reg->mtl_fpe_reg); 1952c6ad81dSFurong Xu } 1962c6ad81dSFurong Xu 1972c6ad81dSFurong Xu #define ALG_ERR_MSG "TX algorithm SP is not suitable for one-to-many mapping" 1982c6ad81dSFurong Xu #define WEIGHT_ERR_MSG "TXQ weight %u differs across other TXQs in TC: [%u]" 1992c6ad81dSFurong Xu 2002c6ad81dSFurong Xu int dwmac5_fpe_map_preemption_class(struct net_device *ndev, 2012c6ad81dSFurong Xu struct netlink_ext_ack *extack, u32 pclass) 2022c6ad81dSFurong Xu { 2032c6ad81dSFurong Xu u32 val, offset, count, queue_weight, preemptible_txqs = 0; 2042c6ad81dSFurong Xu struct stmmac_priv *priv = netdev_priv(ndev); 2052558fe30SFurong Xu int num_tc = netdev_get_num_tc(ndev); 2062c6ad81dSFurong Xu 2072c6ad81dSFurong Xu if (!pclass) 2082c6ad81dSFurong Xu goto update_mapping; 2092c6ad81dSFurong Xu 2102c6ad81dSFurong Xu /* DWMAC CORE4+ can not program TC:TXQ mapping to hardware. 2112c6ad81dSFurong Xu * 2122c6ad81dSFurong Xu * Synopsys Databook: 2132c6ad81dSFurong Xu * "The number of Tx DMA channels is equal to the number of Tx queues, 2142c6ad81dSFurong Xu * and is direct one-to-one mapping." 2152c6ad81dSFurong Xu */ 2162c6ad81dSFurong Xu for (u32 tc = 0; tc < num_tc; tc++) { 2172c6ad81dSFurong Xu count = ndev->tc_to_txq[tc].count; 2182c6ad81dSFurong Xu offset = ndev->tc_to_txq[tc].offset; 2192c6ad81dSFurong Xu 2202c6ad81dSFurong Xu if (pclass & BIT(tc)) 2212c6ad81dSFurong Xu preemptible_txqs |= GENMASK(offset + count - 1, offset); 2222c6ad81dSFurong Xu 2232c6ad81dSFurong Xu /* This is 1:1 mapping, go to next TC */ 2242c6ad81dSFurong Xu if (count == 1) 2252c6ad81dSFurong Xu continue; 2262c6ad81dSFurong Xu 2272c6ad81dSFurong Xu if (priv->plat->tx_sched_algorithm == MTL_TX_ALGORITHM_SP) { 2282c6ad81dSFurong Xu NL_SET_ERR_MSG_MOD(extack, ALG_ERR_MSG); 2292c6ad81dSFurong Xu return -EINVAL; 2302c6ad81dSFurong Xu } 2312c6ad81dSFurong Xu 2322c6ad81dSFurong Xu queue_weight = priv->plat->tx_queues_cfg[offset].weight; 2332c6ad81dSFurong Xu 2342c6ad81dSFurong Xu for (u32 i = 1; i < count; i++) { 2352c6ad81dSFurong Xu if (priv->plat->tx_queues_cfg[offset + i].weight != 2362c6ad81dSFurong Xu queue_weight) { 2372c6ad81dSFurong Xu NL_SET_ERR_MSG_FMT_MOD(extack, WEIGHT_ERR_MSG, 2382c6ad81dSFurong Xu queue_weight, tc); 2392c6ad81dSFurong Xu return -EINVAL; 2402c6ad81dSFurong Xu } 2412c6ad81dSFurong Xu } 2422c6ad81dSFurong Xu } 2432c6ad81dSFurong Xu 2442c6ad81dSFurong Xu update_mapping: 24561e6051fSFurong Xu val = readl(priv->ioaddr + GMAC5_MTL_FPE_CTRL_STS); 24661e6051fSFurong Xu writel(u32_replace_bits(val, preemptible_txqs, FPE_MTL_PREEMPTION_CLASS), 24761e6051fSFurong Xu priv->ioaddr + GMAC5_MTL_FPE_CTRL_STS); 2482c6ad81dSFurong Xu 2492c6ad81dSFurong Xu return 0; 2502c6ad81dSFurong Xu } 2512c6ad81dSFurong Xu 252b440d677SFurong Xu int dwxgmac3_fpe_map_preemption_class(struct net_device *ndev, 253b440d677SFurong Xu struct netlink_ext_ack *extack, u32 pclass) 254b440d677SFurong Xu { 255b440d677SFurong Xu u32 val, offset, count, preemptible_txqs = 0; 256b440d677SFurong Xu struct stmmac_priv *priv = netdev_priv(ndev); 257b440d677SFurong Xu int num_tc = netdev_get_num_tc(ndev); 258b440d677SFurong Xu 259b440d677SFurong Xu if (!num_tc) { 260b440d677SFurong Xu /* Restore default TC:Queue mapping */ 261b440d677SFurong Xu for (u32 i = 0; i < priv->plat->tx_queues_to_use; i++) { 262b440d677SFurong Xu val = readl(priv->ioaddr + XGMAC_MTL_TXQ_OPMODE(i)); 263b440d677SFurong Xu writel(u32_replace_bits(val, i, XGMAC_Q2TCMAP), 264b440d677SFurong Xu priv->ioaddr + XGMAC_MTL_TXQ_OPMODE(i)); 265b440d677SFurong Xu } 266b440d677SFurong Xu } 267b440d677SFurong Xu 268b440d677SFurong Xu /* Synopsys Databook: 269b440d677SFurong Xu * "All Queues within a traffic class are selected in a round robin 270b440d677SFurong Xu * fashion (when packets are available) when the traffic class is 271b440d677SFurong Xu * selected by the scheduler for packet transmission. This is true for 272b440d677SFurong Xu * any of the scheduling algorithms." 273b440d677SFurong Xu */ 274b440d677SFurong Xu for (u32 tc = 0; tc < num_tc; tc++) { 275b440d677SFurong Xu count = ndev->tc_to_txq[tc].count; 276b440d677SFurong Xu offset = ndev->tc_to_txq[tc].offset; 277b440d677SFurong Xu 278b440d677SFurong Xu if (pclass & BIT(tc)) 279b440d677SFurong Xu preemptible_txqs |= GENMASK(offset + count - 1, offset); 280b440d677SFurong Xu 281b440d677SFurong Xu for (u32 i = 0; i < count; i++) { 282b440d677SFurong Xu val = readl(priv->ioaddr + XGMAC_MTL_TXQ_OPMODE(offset + i)); 283b440d677SFurong Xu writel(u32_replace_bits(val, tc, XGMAC_Q2TCMAP), 284b440d677SFurong Xu priv->ioaddr + XGMAC_MTL_TXQ_OPMODE(offset + i)); 285b440d677SFurong Xu } 286b440d677SFurong Xu } 287b440d677SFurong Xu 288b440d677SFurong Xu val = readl(priv->ioaddr + XGMAC_MTL_FPE_CTRL_STS); 289b440d677SFurong Xu writel(u32_replace_bits(val, preemptible_txqs, FPE_MTL_PREEMPTION_CLASS), 290b440d677SFurong Xu priv->ioaddr + XGMAC_MTL_FPE_CTRL_STS); 291b440d677SFurong Xu 292b440d677SFurong Xu return 0; 293b440d677SFurong Xu } 294b440d677SFurong Xu 295c9cd9a5aSFurong Xu const struct stmmac_fpe_reg dwmac5_fpe_reg = { 296c9cd9a5aSFurong Xu .mac_fpe_reg = GMAC5_MAC_FPE_CTRL_STS, 297c9cd9a5aSFurong Xu .mtl_fpe_reg = GMAC5_MTL_FPE_CTRL_STS, 298c9cd9a5aSFurong Xu .rxq_ctrl1_reg = GMAC_RXQ_CTRL1, 299c9cd9a5aSFurong Xu .fprq_mask = GMAC_RXQCTRL_FPRQ, 300c9cd9a5aSFurong Xu .int_en_reg = GMAC_INT_EN, 301c9cd9a5aSFurong Xu .int_en_bit = GMAC_INT_FPE_EN, 302c9cd9a5aSFurong Xu }; 3032c6ad81dSFurong Xu 304c9cd9a5aSFurong Xu const struct stmmac_fpe_reg dwxgmac3_fpe_reg = { 305c9cd9a5aSFurong Xu .mac_fpe_reg = XGMAC_MAC_FPE_CTRL_STS, 306c9cd9a5aSFurong Xu .mtl_fpe_reg = XGMAC_MTL_FPE_CTRL_STS, 307c9cd9a5aSFurong Xu .rxq_ctrl1_reg = XGMAC_RXQ_CTRL1, 308df9e7b02SFurong Xu .fprq_mask = XGMAC_FPRQ, 309c9cd9a5aSFurong Xu .int_en_reg = XGMAC_INT_EN, 310c9cd9a5aSFurong Xu .int_en_bit = XGMAC_FPEIE, 311c9cd9a5aSFurong Xu }; 312