diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c index 28fdedc30b74..0fdec78c5399 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c @@ -23,9 +23,17 @@ struct xgene_gstrings_stats { char name[ETH_GSTRING_LEN]; int offset; + u32 addr; + u32 mask; }; -#define XGENE_STAT(m) { #m, offsetof(struct xgene_enet_pdata, stats.m) } +#define XGENE_STAT(m) { #m, offsetof(struct rtnl_link_stats64, m) } +#define XGENE_EXTD_STAT(s, a, m) \ + { \ + .name = #s, \ + .addr = a ## _ADDR, \ + .mask = m \ + } static const struct xgene_gstrings_stats gstrings_stats[] = { XGENE_STAT(rx_packets), @@ -40,7 +48,65 @@ static const struct xgene_gstrings_stats gstrings_stats[] = { XGENE_STAT(rx_fifo_errors) }; +static const struct xgene_gstrings_stats gstrings_extd_stats[] = { + XGENE_EXTD_STAT(tx_rx_64b_frame_cntr, TR64, 31), + XGENE_EXTD_STAT(tx_rx_127b_frame_cntr, TR127, 31), + XGENE_EXTD_STAT(tx_rx_255b_frame_cntr, TR255, 31), + XGENE_EXTD_STAT(tx_rx_511b_frame_cntr, TR511, 31), + XGENE_EXTD_STAT(tx_rx_1023b_frame_cntr, TR1K, 31), + XGENE_EXTD_STAT(tx_rx_1518b_frame_cntr, TRMAX, 31), + XGENE_EXTD_STAT(tx_rx_1522b_frame_cntr, TRMGV, 31), + XGENE_EXTD_STAT(rx_fcs_error_cntr, RFCS, 16), + XGENE_EXTD_STAT(rx_multicast_pkt_cntr, RMCA, 31), + XGENE_EXTD_STAT(rx_broadcast_pkt_cntr, RBCA, 31), + XGENE_EXTD_STAT(rx_ctrl_frame_pkt_cntr, RXCF, 16), + XGENE_EXTD_STAT(rx_pause_frame_pkt_cntr, RXPF, 16), + XGENE_EXTD_STAT(rx_unk_opcode_cntr, RXUO, 16), + XGENE_EXTD_STAT(rx_align_err_cntr, RALN, 16), + XGENE_EXTD_STAT(rx_frame_len_err_cntr, RFLR, 16), + XGENE_EXTD_STAT(rx_frame_len_err_recov_cntr, DUMP, 0), + XGENE_EXTD_STAT(rx_code_err_cntr, RCDE, 16), + XGENE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE, 16), + XGENE_EXTD_STAT(rx_undersize_pkt_cntr, RUND, 16), + XGENE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR, 16), + XGENE_EXTD_STAT(rx_fragments_cntr, RFRG, 16), + XGENE_EXTD_STAT(rx_jabber_cntr, RJBR, 16), + XGENE_EXTD_STAT(rx_jabber_recov_cntr, DUMP, 0), + XGENE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP, 16), + XGENE_EXTD_STAT(rx_overrun_cntr, DUMP, 0), + XGENE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA, 31), + XGENE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA, 31), + XGENE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF, 16), + XGENE_EXTD_STAT(tx_defer_pkt_cntr, TDFR, 31), + XGENE_EXTD_STAT(tx_excv_defer_pkt_cntr, TEDF, 31), + XGENE_EXTD_STAT(tx_single_col_pkt_cntr, TSCL, 31), + XGENE_EXTD_STAT(tx_multi_col_pkt_cntr, TMCL, 31), + XGENE_EXTD_STAT(tx_late_col_pkt_cntr, TLCL, 31), + XGENE_EXTD_STAT(tx_excv_col_pkt_cntr, TXCL, 31), + XGENE_EXTD_STAT(tx_total_col_cntr, TNCL, 31), + XGENE_EXTD_STAT(tx_pause_frames_hnrd_cntr, TPFH, 16), + XGENE_EXTD_STAT(tx_drop_frame_cntr, TDRP, 16), + XGENE_EXTD_STAT(tx_jabber_frame_cntr, TJBR, 12), + XGENE_EXTD_STAT(tx_fcs_error_cntr, TFCS, 12), + XGENE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF, 12), + XGENE_EXTD_STAT(tx_oversize_frame_cntr, TOVR, 12), + XGENE_EXTD_STAT(tx_undersize_frame_cntr, TUND, 12), + XGENE_EXTD_STAT(tx_fragments_cntr, TFRG, 12), + XGENE_EXTD_STAT(tx_underrun_cntr, DUMP, 0) +}; + #define XGENE_STATS_LEN ARRAY_SIZE(gstrings_stats) +#define XGENE_EXTD_STATS_LEN ARRAY_SIZE(gstrings_extd_stats) +#define RFCS_IDX 7 +#define RALN_IDX 13 +#define RFLR_IDX 14 +#define FALSE_RFLR_IDX 15 +#define RUND_IDX 18 +#define FALSE_RJBR_IDX 22 +#define RX_OVERRUN_IDX 24 +#define TFCS_IDX 38 +#define TFRG_IDX 42 +#define TX_UNDERRUN_IDX 43 static void xgene_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) @@ -142,6 +208,11 @@ static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data) memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } + + for (i = 0; i < XGENE_EXTD_STATS_LEN; i++) { + memcpy(p, gstrings_extd_stats[i].name, ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } } static int xgene_get_sset_count(struct net_device *ndev, int sset) @@ -149,18 +220,71 @@ static int xgene_get_sset_count(struct net_device *ndev, int sset) if (sset != ETH_SS_STATS) return -EINVAL; - return XGENE_STATS_LEN; + return XGENE_STATS_LEN + XGENE_EXTD_STATS_LEN; +} + +static void xgene_get_extd_stats(struct xgene_enet_pdata *pdata) +{ + u32 rx_drop, tx_drop; + u32 mask, tmp; + int i; + + for (i = 0; i < XGENE_EXTD_STATS_LEN; i++) { + tmp = xgene_enet_rd_stat(pdata, gstrings_extd_stats[i].addr); + if (gstrings_extd_stats[i].mask) { + mask = GENMASK(gstrings_extd_stats[i].mask - 1, 0); + pdata->extd_stats[i] += (tmp & mask); + } + } + + if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) { + /* Errata 10GE_10 - SW should intepret RALN as 0 */ + pdata->extd_stats[RALN_IDX] = 0; + } else { + /* Errata ENET_15 - Fixes RFCS, RFLR, TFCS counter */ + pdata->extd_stats[RFCS_IDX] -= pdata->extd_stats[RALN_IDX]; + pdata->extd_stats[RFLR_IDX] -= pdata->extd_stats[RUND_IDX]; + pdata->extd_stats[TFCS_IDX] -= pdata->extd_stats[TFRG_IDX]; + } + + pdata->mac_ops->get_drop_cnt(pdata, &rx_drop, &tx_drop); + pdata->extd_stats[RX_OVERRUN_IDX] += rx_drop; + pdata->extd_stats[TX_UNDERRUN_IDX] += tx_drop; + + /* Errata 10GE_8 - Update Frame recovered from Errata 10GE_8/ENET_11 */ + pdata->extd_stats[FALSE_RFLR_IDX] = pdata->false_rflr; + /* Errata ENET_15 - Jabber Frame recov'ed from Errata 10GE_10/ENET_15 */ + pdata->extd_stats[FALSE_RJBR_IDX] = pdata->vlan_rjbr; +} + +int xgene_extd_stats_init(struct xgene_enet_pdata *pdata) +{ + pdata->extd_stats = devm_kmalloc_array(&pdata->pdev->dev, + XGENE_EXTD_STATS_LEN, sizeof(u64), GFP_KERNEL); + if (!pdata->extd_stats) + return -ENOMEM; + + xgene_get_extd_stats(pdata); + memset(pdata->extd_stats, 0, XGENE_EXTD_STATS_LEN * sizeof(u64)); + + return 0; } static void xgene_get_ethtool_stats(struct net_device *ndev, struct ethtool_stats *dummy, u64 *data) { - void *pdata = netdev_priv(ndev); + struct xgene_enet_pdata *pdata = netdev_priv(ndev); + struct rtnl_link_stats64 stats; int i; + dev_get_stats(ndev, &stats); for (i = 0; i < XGENE_STATS_LEN; i++) - *data++ = *(u64 *)(pdata + gstrings_stats[i].offset); + data[i] = *(u64 *)((char *)&stats + gstrings_stats[i].offset); + + xgene_get_extd_stats(pdata); + for (i = 0; i < XGENE_EXTD_STATS_LEN; i++) + data[i + XGENE_STATS_LEN] = pdata->extd_stats[i]; } static void xgene_get_pauseparam(struct net_device *ndev, diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c index 2a835e07adfb..6ac27c7522a7 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c @@ -205,30 +205,24 @@ static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring) } void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring, - struct xgene_enet_pdata *pdata, enum xgene_enet_err_code status) { switch (status) { case INGRESS_CRC: ring->rx_crc_errors++; - ring->rx_dropped++; break; case INGRESS_CHECKSUM: case INGRESS_CHECKSUM_COMPUTE: ring->rx_errors++; - ring->rx_dropped++; break; case INGRESS_TRUNC_FRAME: ring->rx_frame_errors++; - ring->rx_dropped++; break; case INGRESS_PKT_LEN: ring->rx_length_errors++; - ring->rx_dropped++; break; case INGRESS_PKT_UNDER: ring->rx_frame_errors++; - ring->rx_dropped++; break; case INGRESS_FIFO_OVERRUN: ring->rx_fifo_errors++; @@ -270,42 +264,39 @@ static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata, iowrite32(val, addr); } -static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr, - void __iomem *cmd, void __iomem *cmd_done, - u32 wr_addr, u32 wr_data) -{ - u32 done; - u8 wait = 10; - - iowrite32(wr_addr, addr); - iowrite32(wr_data, wr); - iowrite32(XGENE_ENET_WR_CMD, cmd); - - /* wait for write command to complete */ - while (!(done = ioread32(cmd_done)) && wait--) - udelay(1); - - if (!done) - return false; - - iowrite32(0, cmd); - - return true; -} - -static void xgene_enet_wr_mcx_mac(struct xgene_enet_pdata *pdata, - u32 wr_addr, u32 wr_data) +void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, u32 wr_addr, u32 wr_data) { void __iomem *addr, *wr, *cmd, *cmd_done; + struct net_device *ndev = pdata->ndev; + u8 wait = 10; + u32 done; + + if (pdata->mdio_driver && ndev->phydev && + pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) { + struct mii_bus *bus = ndev->phydev->mdio.bus; + + return xgene_mdio_wr_mac(bus->priv, wr_addr, wr_data); + } addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET; cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET; - if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data)) - netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n", - wr_addr); + spin_lock(&pdata->mac_lock); + iowrite32(wr_addr, addr); + iowrite32(wr_data, wr); + iowrite32(XGENE_ENET_WR_CMD, cmd); + + while (!(done = ioread32(cmd_done)) && wait--) + udelay(1); + + if (!done) + netdev_err(ndev, "mac write failed, addr: %04x data: %08x\n", + wr_addr, wr_data); + + iowrite32(0, cmd); + spin_unlock(&pdata->mac_lock); } static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata, @@ -332,42 +323,69 @@ static void xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *pdata, *val = ioread32(addr); } -static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd, - void __iomem *cmd, void __iomem *cmd_done, - u32 rd_addr, u32 *rd_data) -{ - u32 done; - u8 wait = 10; - - iowrite32(rd_addr, addr); - iowrite32(XGENE_ENET_RD_CMD, cmd); - - /* wait for read command to complete */ - while (!(done = ioread32(cmd_done)) && wait--) - udelay(1); - - if (!done) - return false; - - *rd_data = ioread32(rd); - iowrite32(0, cmd); - - return true; -} - -static void xgene_enet_rd_mcx_mac(struct xgene_enet_pdata *pdata, - u32 rd_addr, u32 *rd_data) +u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 rd_addr) { void __iomem *addr, *rd, *cmd, *cmd_done; + u32 done, rd_data; + u8 wait = 10; + + if (pdata->mdio_driver && pdata->ndev->phydev && + pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) { + struct mii_bus *bus = pdata->ndev->phydev->mdio.bus; + + return xgene_mdio_rd_mac(bus->priv, rd_addr); + } addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET; cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET; - if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data)) - netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n", + spin_lock(&pdata->mac_lock); + iowrite32(rd_addr, addr); + iowrite32(XGENE_ENET_RD_CMD, cmd); + + while (!(done = ioread32(cmd_done)) && wait--) + udelay(1); + + if (!done) + netdev_err(pdata->ndev, "mac read failed, addr: %04x\n", rd_addr); + + rd_data = ioread32(rd); + iowrite32(0, cmd); + spin_unlock(&pdata->mac_lock); + + return rd_data; +} + +u32 xgene_enet_rd_stat(struct xgene_enet_pdata *pdata, u32 rd_addr) +{ + void __iomem *addr, *rd, *cmd, *cmd_done; + u32 done, rd_data; + u8 wait = 10; + + addr = pdata->mcx_stats_addr + STAT_ADDR_REG_OFFSET; + rd = pdata->mcx_stats_addr + STAT_READ_REG_OFFSET; + cmd = pdata->mcx_stats_addr + STAT_COMMAND_REG_OFFSET; + cmd_done = pdata->mcx_stats_addr + STAT_COMMAND_DONE_REG_OFFSET; + + spin_lock(&pdata->stats_lock); + iowrite32(rd_addr, addr); + iowrite32(XGENE_ENET_RD_CMD, cmd); + + while (!(done = ioread32(cmd_done)) && wait--) + udelay(1); + + if (!done) + netdev_err(pdata->ndev, "mac stats read failed, addr: %04x\n", + rd_addr); + + rd_data = ioread32(rd); + iowrite32(0, cmd); + spin_unlock(&pdata->stats_lock); + + return rd_data; } static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata) @@ -379,8 +397,8 @@ static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata) (dev_addr[1] << 8) | dev_addr[0]; addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16); - xgene_enet_wr_mcx_mac(pdata, STATION_ADDR0_ADDR, addr0); - xgene_enet_wr_mcx_mac(pdata, STATION_ADDR1_ADDR, addr1); + xgene_enet_wr_mac(pdata, STATION_ADDR0_ADDR, addr0); + xgene_enet_wr_mac(pdata, STATION_ADDR1_ADDR, addr1); } static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata) @@ -405,8 +423,8 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata) static void xgene_gmac_reset(struct xgene_enet_pdata *pdata) { - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1); - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0); + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1); + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, 0); } static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata) @@ -456,8 +474,8 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata) xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, &icm0); xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2); - xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_2_ADDR, &mc2); - xgene_enet_rd_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, &intf_ctl); + mc2 = xgene_enet_rd_mac(pdata, MAC_CONFIG_2_ADDR); + intf_ctl = xgene_enet_rd_mac(pdata, INTERFACE_CONTROL_ADDR); xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii); switch (pdata->phy_speed) { @@ -495,8 +513,8 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata) } mc2 |= FULL_DUPLEX2 | PAD_CRC | LENGTH_CHK; - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2); - xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl); + xgene_enet_wr_mac(pdata, MAC_CONFIG_2_ADDR, mc2); + xgene_enet_wr_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl); xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii); xgene_enet_configure_clock(pdata); @@ -506,7 +524,7 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata) static void xgene_enet_set_frame_size(struct xgene_enet_pdata *pdata, int size) { - xgene_enet_wr_mcx_mac(pdata, MAX_FRAME_LEN_ADDR, size); + xgene_enet_wr_mac(pdata, MAX_FRAME_LEN_ADDR, size); } static void xgene_gmac_enable_tx_pause(struct xgene_enet_pdata *pdata, @@ -528,14 +546,14 @@ static void xgene_gmac_flowctl_tx(struct xgene_enet_pdata *pdata, bool enable) { u32 data; - xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); + data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR); if (enable) data |= TX_FLOW_EN; else data &= ~TX_FLOW_EN; - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data); + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data); pdata->mac_ops->enable_tx_pause(pdata, enable); } @@ -544,14 +562,14 @@ static void xgene_gmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable) { u32 data; - xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); + data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR); if (enable) data |= RX_FLOW_EN; else data &= ~RX_FLOW_EN; - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data); + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data); } static void xgene_gmac_init(struct xgene_enet_pdata *pdata) @@ -565,9 +583,9 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata) xgene_gmac_set_mac_addr(pdata); /* Adjust MDC clock frequency */ - xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &value); + value = xgene_enet_rd_mac(pdata, MII_MGMT_CONFIG_ADDR); MGMT_CLOCK_SEL_SET(&value, 7); - xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, value); + xgene_enet_wr_mac(pdata, MII_MGMT_CONFIG_ADDR, value); /* Enable drop if bufpool not available */ xgene_enet_rd_csr(pdata, RSIF_CONFIG_REG_ADDR, &value); @@ -600,6 +618,18 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata) xgene_enet_wr_csr(pdata, CFG_BYPASS_ADDR, RESUME_TX); } +static void xgene_gmac_get_drop_cnt(struct xgene_enet_pdata *pdata, + u32 *rx, u32 *tx) +{ + u32 count; + + xgene_enet_rd_mcx_csr(pdata, ICM_ECM_DROP_COUNT_REG0_ADDR, &count); + *rx = ICM_DROP_COUNT(count); + *tx = ECM_DROP_COUNT(count); + /* Errata: 10GE_4 - Fix ICM_ECM_DROP_COUNT not clear-on-read */ + xgene_enet_rd_mcx_csr(pdata, ECM_CONFIG0_REG_0_ADDR, &count); +} + static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata) { u32 val = 0xffffffff; @@ -637,32 +667,32 @@ static void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata) { u32 data; - xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN); + data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR); + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN); } static void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata) { u32 data; - xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN); + data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR); + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN); } static void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata) { u32 data; - xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN); + data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR); + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN); } static void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata) { u32 data; - xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN); + data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR); + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN); } bool xgene_ring_mgr_init(struct xgene_enet_pdata *p) @@ -733,27 +763,6 @@ static void xgene_enet_clear(struct xgene_enet_pdata *pdata, static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata) { struct device *dev = &pdata->pdev->dev; - struct xgene_enet_desc_ring *ring; - u32 pb; - int i; - - pb = 0; - for (i = 0; i < pdata->rxq_cnt; i++) { - ring = pdata->rx_ring[i]->buf_pool; - pb |= BIT(xgene_enet_get_fpsel(ring->id)); - ring = pdata->rx_ring[i]->page_pool; - if (ring) - pb |= BIT(xgene_enet_get_fpsel(ring->id)); - - } - xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb); - - pb = 0; - for (i = 0; i < pdata->txq_cnt; i++) { - ring = pdata->tx_ring[i]; - pb |= BIT(xgene_enet_ring_bufnum(ring->id)); - } - xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb); if (dev->of_node) { if (!IS_ERR(pdata->clk)) @@ -1009,6 +1018,7 @@ const struct xgene_mac_ops xgene_gmac_ops = { .tx_enable = xgene_gmac_tx_enable, .rx_disable = xgene_gmac_rx_disable, .tx_disable = xgene_gmac_tx_disable, + .get_drop_cnt = xgene_gmac_get_drop_cnt, .set_speed = xgene_gmac_set_speed, .set_mac_addr = xgene_gmac_set_mac_addr, .set_framesize = xgene_enet_set_frame_size, diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h index d250bfe94d24..5d3e18d3c94c 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h @@ -115,6 +115,7 @@ enum xgene_enet_rm { #define BLOCK_ETH_CLKRST_CSR_OFFSET 0xc000 #define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000 #define BLOCK_ETH_MAC_OFFSET 0x0000 +#define BLOCK_ETH_STATS_OFFSET 0x0000 #define BLOCK_ETH_MAC_CSR_OFFSET 0x2800 #define CLKEN_ADDR 0xc208 @@ -126,6 +127,12 @@ enum xgene_enet_rm { #define MAC_READ_REG_OFFSET 0x0c #define MAC_COMMAND_DONE_REG_OFFSET 0x10 +#define STAT_ADDR_REG_OFFSET 0x14 +#define STAT_COMMAND_REG_OFFSET 0x18 +#define STAT_WRITE_REG_OFFSET 0x1c +#define STAT_READ_REG_OFFSET 0x20 +#define STAT_COMMAND_DONE_REG_OFFSET 0x24 + #define PCS_ADDR_REG_OFFSET 0x00 #define PCS_COMMAND_REG_OFFSET 0x04 #define PCS_WRITE_REG_OFFSET 0x08 @@ -185,6 +192,10 @@ enum xgene_enet_rm { #define CFG_CLE_NXTFPSEL0(val) (((val) << 20) & GENMASK(23, 20)) #define ICM_CONFIG0_REG_0_ADDR 0x0400 #define ICM_CONFIG2_REG_0_ADDR 0x0410 +#define ECM_CONFIG0_REG_0_ADDR 0x0500 +#define ECM_CONFIG0_REG_1_ADDR 0x0504 +#define ICM_ECM_DROP_COUNT_REG0_ADDR 0x0508 +#define ICM_ECM_DROP_COUNT_REG1_ADDR 0x050c #define RX_DV_GATE_REG_0_ADDR 0x05fc #define TX_DV_GATE_EN0 BIT(2) #define RX_DV_GATE_EN0 BIT(1) @@ -217,12 +228,53 @@ enum xgene_enet_rm { #define FULL_DUPLEX2 BIT(0) #define PAD_CRC BIT(2) #define LENGTH_CHK BIT(4) -#define SCAN_AUTO_INCR BIT(5) -#define TBYT_ADDR 0x38 -#define TPKT_ADDR 0x39 -#define TDRP_ADDR 0x45 -#define TFCS_ADDR 0x47 -#define TUND_ADDR 0x4a + +#define TR64_ADDR 0x20 +#define TR127_ADDR 0x21 +#define TR255_ADDR 0x22 +#define TR511_ADDR 0x23 +#define TR1K_ADDR 0x24 +#define TRMAX_ADDR 0x25 +#define TRMGV_ADDR 0x26 + +#define RFCS_ADDR 0x29 +#define RMCA_ADDR 0x2a +#define RBCA_ADDR 0x2b +#define RXCF_ADDR 0x2c +#define RXPF_ADDR 0x2d +#define RXUO_ADDR 0x2e +#define RALN_ADDR 0x2f +#define RFLR_ADDR 0x30 +#define RCDE_ADDR 0x31 +#define RCSE_ADDR 0x32 +#define RUND_ADDR 0x33 +#define ROVR_ADDR 0x34 +#define RFRG_ADDR 0x35 +#define RJBR_ADDR 0x36 +#define RDRP_ADDR 0x37 + +#define TMCA_ADDR 0x3a +#define TBCA_ADDR 0x3b +#define TXPF_ADDR 0x3c +#define TDFR_ADDR 0x3d +#define TEDF_ADDR 0x3e +#define TSCL_ADDR 0x3f +#define TMCL_ADDR 0x40 +#define TLCL_ADDR 0x41 +#define TXCL_ADDR 0x42 +#define TNCL_ADDR 0x43 +#define TPFH_ADDR 0x44 +#define TDRP_ADDR 0x45 +#define TJBR_ADDR 0x46 +#define TFCS_ADDR 0x47 +#define TXCF_ADDR 0x48 +#define TOVR_ADDR 0x49 +#define TUND_ADDR 0x4a +#define TFRG_ADDR 0x4b +#define DUMP_ADDR 0x27 + +#define ECM_DROP_COUNT(src) xgene_get_bits(src, 0, 15) +#define ICM_DROP_COUNT(src) xgene_get_bits(src, 16, 31) #define TSO_IPPROTO_TCP 1 @@ -380,14 +432,16 @@ static inline u16 xgene_enet_get_numslots(u16 id, u32 size) } void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring, - struct xgene_enet_pdata *pdata, enum xgene_enet_err_code status); - int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata); void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata); bool xgene_ring_mgr_init(struct xgene_enet_pdata *p); int xgene_enet_phy_connect(struct net_device *ndev); void xgene_enet_phy_disconnect(struct xgene_enet_pdata *pdata); +u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 rd_addr); +void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, u32 wr_addr, + u32 wr_data); +u32 xgene_enet_rd_stat(struct xgene_enet_pdata *pdata, u32 rd_addr); extern const struct xgene_mac_ops xgene_gmac_ops; extern const struct xgene_port_ops xgene_gport_ops; diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index 5f37ed3506d5..21cd4ef3e5eb 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -246,9 +246,9 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring, skb_frag_t *frag; dma_addr_t *frag_dma_addr; u16 skb_index; - u8 status; - int i, ret = 0; u8 mss_index; + u8 status; + int i; skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0)); skb = cp_ring->cp_skb[skb_index]; @@ -275,19 +275,17 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring, /* Checking for error */ status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0)); if (unlikely(status > 2)) { - xgene_enet_parse_error(cp_ring, netdev_priv(cp_ring->ndev), - status); - ret = -EIO; + cp_ring->tx_dropped++; + cp_ring->tx_errors++; } if (likely(skb)) { dev_kfree_skb_any(skb); } else { netdev_err(cp_ring->ndev, "completion skb is NULL\n"); - ret = -EIO; } - return ret; + return 0; } static int xgene_enet_setup_mss(struct net_device *ndev, u32 mss) @@ -658,6 +656,18 @@ static void xgene_enet_free_pagepool(struct xgene_enet_desc_ring *buf_pool, buf_pool->head = head; } +/* Errata 10GE_10 and ENET_15 - Fix duplicated HW statistic counters */ +static bool xgene_enet_errata_10GE_10(struct sk_buff *skb, u32 len, u8 status) +{ + if (status == INGRESS_CRC && + len >= (ETHER_STD_PACKET + 1) && + len <= (ETHER_STD_PACKET + 4) && + skb->protocol == htons(ETH_P_8021Q)) + return true; + + return false; +} + /* Errata 10GE_8 and ENET_11 - allow packet with length <=64B */ static bool xgene_enet_errata_10GE_8(struct sk_buff *skb, u32 len, u8 status) { @@ -708,10 +718,15 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring, status = (GET_VAL(ELERR, le64_to_cpu(raw_desc->m0)) << LERR_LEN) | GET_VAL(LERR, le64_to_cpu(raw_desc->m0)); if (unlikely(status)) { - if (!xgene_enet_errata_10GE_8(skb, datalen, status)) { + if (xgene_enet_errata_10GE_8(skb, datalen, status)) { + pdata->false_rflr++; + } else if (xgene_enet_errata_10GE_10(skb, datalen, status)) { + pdata->vlan_rjbr++; + } else { dev_kfree_skb_any(skb); xgene_enet_free_pagepool(page_pool, raw_desc, exp_desc); - xgene_enet_parse_error(rx_ring, pdata, status); + xgene_enet_parse_error(rx_ring, status); + rx_ring->rx_dropped++; goto out; } } @@ -1466,10 +1481,9 @@ err: static void xgene_enet_get_stats64( struct net_device *ndev, - struct rtnl_link_stats64 *storage) + struct rtnl_link_stats64 *stats) { struct xgene_enet_pdata *pdata = netdev_priv(ndev); - struct rtnl_link_stats64 *stats = &pdata->stats; struct xgene_enet_desc_ring *ring; int i; @@ -1478,6 +1492,8 @@ static void xgene_enet_get_stats64( if (ring) { stats->tx_packets += ring->tx_packets; stats->tx_bytes += ring->tx_bytes; + stats->tx_dropped += ring->tx_dropped; + stats->tx_errors += ring->tx_errors; } } @@ -1486,14 +1502,18 @@ static void xgene_enet_get_stats64( if (ring) { stats->rx_packets += ring->rx_packets; stats->rx_bytes += ring->rx_bytes; - stats->rx_errors += ring->rx_length_errors + + stats->rx_dropped += ring->rx_dropped; + stats->rx_errors += ring->rx_errors + + ring->rx_length_errors + ring->rx_crc_errors + ring->rx_frame_errors + ring->rx_fifo_errors; - stats->rx_dropped += ring->rx_dropped; + stats->rx_length_errors += ring->rx_length_errors; + stats->rx_crc_errors += ring->rx_crc_errors; + stats->rx_frame_errors += ring->rx_frame_errors; + stats->rx_fifo_errors += ring->rx_fifo_errors; } } - memcpy(storage, stats, sizeof(struct rtnl_link_stats64)); } static int xgene_enet_set_mac_address(struct net_device *ndev, void *addr) @@ -1788,12 +1808,15 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII || pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) { pdata->mcx_mac_addr = pdata->base_addr + BLOCK_ETH_MAC_OFFSET; + pdata->mcx_stats_addr = + pdata->base_addr + BLOCK_ETH_STATS_OFFSET; offset = (pdata->enet_id == XGENE_ENET1) ? BLOCK_ETH_MAC_CSR_OFFSET : X2_BLOCK_ETH_MAC_CSR_OFFSET; pdata->mcx_mac_csr_addr = base_addr + offset; } else { pdata->mcx_mac_addr = base_addr + BLOCK_AXG_MAC_OFFSET; + pdata->mcx_stats_addr = base_addr + BLOCK_AXG_STATS_OFFSET; pdata->mcx_mac_csr_addr = base_addr + BLOCK_AXG_MAC_CSR_OFFSET; pdata->pcs_addr = base_addr + BLOCK_PCS_OFFSET; } @@ -2055,6 +2078,7 @@ static int xgene_enet_probe(struct platform_device *pdev) goto err; xgene_enet_setup_ops(pdata); + spin_lock_init(&pdata->mac_lock); if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) { ndev->features |= NETIF_F_TSO | NETIF_F_RXCSUM; @@ -2085,6 +2109,11 @@ static int xgene_enet_probe(struct platform_device *pdev) goto err1; } + spin_lock_init(&pdata->stats_lock); + ret = xgene_extd_stats_init(pdata); + if (ret) + goto err2; + xgene_enet_napi_add(pdata); ret = register_netdev(ndev); if (ret) { @@ -2130,8 +2159,8 @@ static int xgene_enet_remove(struct platform_device *pdev) xgene_enet_mdio_remove(pdata); unregister_netdev(ndev); - pdata->port_ops->shutdown(pdata); xgene_enet_delete_desc_rings(pdata); + pdata->port_ops->shutdown(pdata); free_netdev(ndev); return 0; diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h index 0d4be2425ebc..985768596900 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h @@ -42,6 +42,7 @@ #define XGENE_DRV_VERSION "v1.0" #define ETHER_MIN_PACKET 64 +#define ETHER_STD_PACKET 1518 #define XGENE_ENET_STD_MTU 1536 #define XGENE_ENET_MAX_MTU 9600 #define SKB_BUFFER_SIZE (XGENE_ENET_STD_MTU - NET_IP_ALIGN) @@ -138,6 +139,8 @@ struct xgene_enet_desc_ring { __le64 *exp_bufs; u64 tx_packets; u64 tx_bytes; + u64 tx_dropped; + u64 tx_errors; u64 rx_packets; u64 rx_bytes; u64 rx_dropped; @@ -155,6 +158,7 @@ struct xgene_mac_ops { void (*rx_enable)(struct xgene_enet_pdata *pdata); void (*tx_disable)(struct xgene_enet_pdata *pdata); void (*rx_disable)(struct xgene_enet_pdata *pdata); + void (*get_drop_cnt)(struct xgene_enet_pdata *pdata, u32 *rx, u32 *tx); void (*set_speed)(struct xgene_enet_pdata *pdata); void (*set_mac_addr)(struct xgene_enet_pdata *pdata); void (*set_framesize)(struct xgene_enet_pdata *pdata, int framesize); @@ -212,6 +216,7 @@ struct xgene_enet_pdata { void __iomem *eth_diag_csr_addr; void __iomem *mcx_mac_addr; void __iomem *mcx_mac_csr_addr; + void __iomem *mcx_stats_addr; void __iomem *base_addr; void __iomem *pcs_addr; void __iomem *ring_csr_addr; @@ -219,8 +224,12 @@ struct xgene_enet_pdata { int phy_mode; enum xgene_enet_rm rm; struct xgene_enet_cle cle; - struct rtnl_link_stats64 stats; + u64 *extd_stats; + u64 false_rflr; + u64 vlan_rjbr; + spinlock_t stats_lock; /* statistics lock */ const struct xgene_mac_ops *mac_ops; + spinlock_t mac_lock; /* mac lock */ const struct xgene_port_ops *port_ops; struct xgene_ring_ops *ring_ops; const struct xgene_cle_ops *cle_ops; @@ -263,5 +272,6 @@ static inline u16 xgene_enet_dst_ring_num(struct xgene_enet_desc_ring *ring) } void xgene_enet_set_ethtool_ops(struct net_device *netdev); +int xgene_extd_stats_init(struct xgene_enet_pdata *pdata); #endif /* __XGENE_ENET_MAIN_H__ */ diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c index a8e063bdee3b..b1a83fdbefb8 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c @@ -54,41 +54,6 @@ static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata, iowrite32(val, addr); } -static bool xgene_enet_wr_indirect(struct xgene_indirect_ctl *ctl, - u32 wr_addr, u32 wr_data) -{ - int i; - - iowrite32(wr_addr, ctl->addr); - iowrite32(wr_data, ctl->ctl); - iowrite32(XGENE_ENET_WR_CMD, ctl->cmd); - - /* wait for write command to complete */ - for (i = 0; i < 10; i++) { - if (ioread32(ctl->cmd_done)) { - iowrite32(0, ctl->cmd); - return true; - } - udelay(1); - } - - return false; -} - -static void xgene_enet_wr_mac(struct xgene_enet_pdata *p, - u32 wr_addr, u32 wr_data) -{ - struct xgene_indirect_ctl ctl = { - .addr = p->mcx_mac_addr + MAC_ADDR_REG_OFFSET, - .ctl = p->mcx_mac_addr + MAC_WRITE_REG_OFFSET, - .cmd = p->mcx_mac_addr + MAC_COMMAND_REG_OFFSET, - .cmd_done = p->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET - }; - - if (!xgene_enet_wr_indirect(&ctl, wr_addr, wr_data)) - netdev_err(p->ndev, "mac write failed, addr: %04x\n", wr_addr); -} - static u32 xgene_enet_rd_csr(struct xgene_enet_pdata *p, u32 offset) { return ioread32(p->eth_csr_addr + offset); @@ -104,42 +69,6 @@ static u32 xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *p, u32 offset) return ioread32(p->mcx_mac_csr_addr + offset); } -static u32 xgene_enet_rd_indirect(struct xgene_indirect_ctl *ctl, u32 rd_addr) -{ - u32 rd_data; - int i; - - iowrite32(rd_addr, ctl->addr); - iowrite32(XGENE_ENET_RD_CMD, ctl->cmd); - - /* wait for read command to complete */ - for (i = 0; i < 10; i++) { - if (ioread32(ctl->cmd_done)) { - rd_data = ioread32(ctl->ctl); - iowrite32(0, ctl->cmd); - - return rd_data; - } - udelay(1); - } - - pr_err("%s: mac read failed, addr: %04x\n", __func__, rd_addr); - - return 0; -} - -static u32 xgene_enet_rd_mac(struct xgene_enet_pdata *p, u32 rd_addr) -{ - struct xgene_indirect_ctl ctl = { - .addr = p->mcx_mac_addr + MAC_ADDR_REG_OFFSET, - .ctl = p->mcx_mac_addr + MAC_READ_REG_OFFSET, - .cmd = p->mcx_mac_addr + MAC_COMMAND_REG_OFFSET, - .cmd_done = p->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET - }; - - return xgene_enet_rd_indirect(&ctl, rd_addr); -} - static int xgene_enet_ecc_init(struct xgene_enet_pdata *p) { struct net_device *ndev = p->ndev; @@ -166,6 +95,24 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *p) return -ENODEV; } +static void xgene_sgmac_get_drop_cnt(struct xgene_enet_pdata *pdata, + u32 *rx, u32 *tx) +{ + u32 addr, count; + + addr = (pdata->enet_id != XGENE_ENET1) ? + XG_MCX_ICM_ECM_DROP_COUNT_REG0_ADDR : + ICM_ECM_DROP_COUNT_REG0_ADDR + pdata->port_id * OFFSET_4; + count = xgene_enet_rd_mcx_csr(pdata, addr); + *rx = ICM_DROP_COUNT(count); + *tx = ECM_DROP_COUNT(count); + /* Errata: 10GE_4 - ICM_ECM_DROP_COUNT not clear-on-read */ + addr = (pdata->enet_id != XGENE_ENET1) ? + XG_MCX_ECM_CONFIG0_REG_0_ADDR : + ECM_CONFIG0_REG_0_ADDR + pdata->port_id * OFFSET_4; + xgene_enet_rd_mcx_csr(pdata, addr); +} + static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p) { u32 val; @@ -587,26 +534,6 @@ static void xgene_enet_clear(struct xgene_enet_pdata *pdata, static void xgene_enet_shutdown(struct xgene_enet_pdata *p) { struct device *dev = &p->pdev->dev; - struct xgene_enet_desc_ring *ring; - u32 pb; - int i; - - pb = 0; - for (i = 0; i < p->rxq_cnt; i++) { - ring = p->rx_ring[i]->buf_pool; - pb |= BIT(xgene_enet_get_fpsel(ring->id)); - ring = p->rx_ring[i]->page_pool; - if (ring) - pb |= BIT(xgene_enet_get_fpsel(ring->id)); - } - xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPRESET_ADDR, pb); - - pb = 0; - for (i = 0; i < p->txq_cnt; i++) { - ring = p->tx_ring[i]; - pb |= BIT(xgene_enet_ring_bufnum(ring->id)); - } - xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQRESET_ADDR, pb); if (dev->of_node) { if (!IS_ERR(p->clk)) @@ -671,6 +598,7 @@ const struct xgene_mac_ops xgene_sgmac_ops = { .tx_enable = xgene_sgmac_tx_enable, .rx_disable = xgene_sgmac_rx_disable, .tx_disable = xgene_sgmac_tx_disable, + .get_drop_cnt = xgene_sgmac_get_drop_cnt, .set_speed = xgene_sgmac_set_speed, .set_mac_addr = xgene_sgmac_set_mac_addr, .set_framesize = xgene_sgmac_set_frame_size, diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c index 423240c97d39..b7d75d067c7a 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c @@ -71,21 +71,6 @@ static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr, return true; } -static void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, - u32 wr_addr, u32 wr_data) -{ - void __iomem *addr, *wr, *cmd, *cmd_done; - - addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; - wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET; - cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; - cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET; - - if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data)) - netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n", - wr_addr); -} - static void xgene_enet_wr_pcs(struct xgene_enet_pdata *pdata, u32 wr_addr, u32 wr_data) { @@ -148,21 +133,6 @@ static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd, return true; } -static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, - u32 rd_addr, u32 *rd_data) -{ - void __iomem *addr, *rd, *cmd, *cmd_done; - - addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; - rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET; - cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; - cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET; - - if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data)) - netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n", - rd_addr); -} - static bool xgene_enet_rd_pcs(struct xgene_enet_pdata *pdata, u32 rd_addr, u32 *rd_data) { @@ -210,6 +180,18 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata) return 0; } +static void xgene_xgmac_get_drop_cnt(struct xgene_enet_pdata *pdata, + u32 *rx, u32 *tx) +{ + u32 count; + + xgene_enet_rd_axg_csr(pdata, XGENET_ICM_ECM_DROP_COUNT_REG0, &count); + *rx = ICM_DROP_COUNT(count); + *tx = ECM_DROP_COUNT(count); + /* Errata: 10GE_4 - ICM_ECM_DROP_COUNT not clear-on-read */ + xgene_enet_rd_axg_csr(pdata, XGENET_ECM_CONFIG0_REG_0, &count); +} + static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata) { xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQASSOC_ADDR, 0); @@ -300,7 +282,7 @@ static void xgene_xgmac_flowctl_tx(struct xgene_enet_pdata *pdata, bool enable) { u32 data; - xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); + data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1); if (enable) data |= HSTTCTLEN; @@ -316,7 +298,7 @@ static void xgene_xgmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable) { u32 data; - xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); + data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1); if (enable) data |= HSTRCTLEN; @@ -332,7 +314,7 @@ static void xgene_xgmac_init(struct xgene_enet_pdata *pdata) xgene_xgmac_reset(pdata); - xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); + data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1); data |= HSTPPEN; data &= ~HSTLENCHK; xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data); @@ -379,7 +361,7 @@ static void xgene_xgmac_rx_enable(struct xgene_enet_pdata *pdata) { u32 data; - xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); + data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1); xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data | HSTRFEN); } @@ -387,7 +369,7 @@ static void xgene_xgmac_tx_enable(struct xgene_enet_pdata *pdata) { u32 data; - xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); + data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1); xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data | HSTTFEN); } @@ -395,7 +377,7 @@ static void xgene_xgmac_rx_disable(struct xgene_enet_pdata *pdata) { u32 data; - xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); + data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1); xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTRFEN); } @@ -403,7 +385,7 @@ static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata) { u32 data; - xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); + data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1); xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTTFEN); } @@ -464,26 +446,6 @@ static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata, static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata) { struct device *dev = &pdata->pdev->dev; - struct xgene_enet_desc_ring *ring; - u32 pb; - int i; - - pb = 0; - for (i = 0; i < pdata->rxq_cnt; i++) { - ring = pdata->rx_ring[i]->buf_pool; - pb |= BIT(xgene_enet_get_fpsel(ring->id)); - ring = pdata->rx_ring[i]->page_pool; - if (ring) - pb |= BIT(xgene_enet_get_fpsel(ring->id)); - } - xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb); - - pb = 0; - for (i = 0; i < pdata->txq_cnt; i++) { - ring = pdata->tx_ring[i]; - pb |= BIT(xgene_enet_ring_bufnum(ring->id)); - } - xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb); if (dev->of_node) { if (!IS_ERR(pdata->clk)) @@ -567,6 +529,7 @@ const struct xgene_mac_ops xgene_xgmac_ops = { .set_mac_addr = xgene_xgmac_set_mac_addr, .set_framesize = xgene_xgmac_set_frame_size, .set_mss = xgene_xgmac_set_mss, + .get_drop_cnt = xgene_xgmac_get_drop_cnt, .link_state = xgene_enet_link_state, .enable_tx_pause = xgene_xgmac_enable_tx_pause, .flowctl_rx = xgene_xgmac_flowctl_rx, diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h index e644a429ebf4..a3b45517df45 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h @@ -23,6 +23,7 @@ #define X2_BLOCK_ETH_MAC_CSR_OFFSET 0x3000 #define BLOCK_AXG_MAC_OFFSET 0x0800 +#define BLOCK_AXG_STATS_OFFSET 0x0800 #define BLOCK_AXG_MAC_CSR_OFFSET 0x2000 #define BLOCK_PCS_OFFSET 0x3800 @@ -70,6 +71,8 @@ #define XG_RSIF_CONFIG1_REG_ADDR 0x00b8 #define XG_RSIF_PLC_CLE_BUFF_THRESH 0x1 #define RSIF_PLC_CLE_BUFF_THRESH_SET(dst, val) xgene_set_bits(dst, val, 0, 2) +#define XG_MCX_ECM_CONFIG0_REG_0_ADDR 0x0070 +#define XG_MCX_ICM_ECM_DROP_COUNT_REG0_ADDR 0x0124 #define XCLE_BYPASS_REG0_ADDR 0x0160 #define XCLE_BYPASS_REG1_ADDR 0x0164 #define XG_CFG_BYPASS_ADDR 0x0204 @@ -80,6 +83,8 @@ #define XG_ENET_SPARE_CFG_REG_ADDR 0x040c #define XG_ENET_SPARE_CFG_REG_1_ADDR 0x0410 #define XGENET_RX_DV_GATE_REG_0_ADDR 0x0804 +#define XGENET_ECM_CONFIG0_REG_0 0x0870 +#define XGENET_ICM_ECM_DROP_COUNT_REG0 0x0924 #define XGENET_CSR_ECM_CFG_0_ADDR 0x0880 #define XGENET_CSR_MULTI_DPF0_ADDR 0x0888 #define XGENET_CSR_MULTI_DPF1_ADDR 0x088c diff --git a/drivers/net/phy/mdio-xgene.c b/drivers/net/phy/mdio-xgene.c index 3e2ac07b6e37..bfd3090fb055 100644 --- a/drivers/net/phy/mdio-xgene.c +++ b/drivers/net/phy/mdio-xgene.c @@ -34,76 +34,73 @@ static bool xgene_mdio_status; -static u32 xgene_enet_rd_mac(void __iomem *base_addr, u32 rd_addr) +u32 xgene_mdio_rd_mac(struct xgene_mdio_pdata *pdata, u32 rd_addr) { void __iomem *addr, *rd, *cmd, *cmd_done; u32 done, rd_data = BUSY_MASK; u8 wait = 10; - addr = base_addr + MAC_ADDR_REG_OFFSET; - rd = base_addr + MAC_READ_REG_OFFSET; - cmd = base_addr + MAC_COMMAND_REG_OFFSET; - cmd_done = base_addr + MAC_COMMAND_DONE_REG_OFFSET; + addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET; + rd = pdata->mac_csr_addr + MAC_READ_REG_OFFSET; + cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET; + cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET; + spin_lock(&pdata->mac_lock); iowrite32(rd_addr, addr); iowrite32(XGENE_ENET_RD_CMD, cmd); - while (wait--) { - done = ioread32(cmd_done); - if (done) - break; + while (!(done = ioread32(cmd_done)) && wait--) udelay(1); - } - if (!done) - return rd_data; + if (done) + rd_data = ioread32(rd); - rd_data = ioread32(rd); iowrite32(0, cmd); + spin_unlock(&pdata->mac_lock); return rd_data; } +EXPORT_SYMBOL(xgene_mdio_rd_mac); -static void xgene_enet_wr_mac(void __iomem *base_addr, u32 wr_addr, u32 wr_data) +void xgene_mdio_wr_mac(struct xgene_mdio_pdata *pdata, u32 wr_addr, u32 data) { void __iomem *addr, *wr, *cmd, *cmd_done; u8 wait = 10; u32 done; - addr = base_addr + MAC_ADDR_REG_OFFSET; - wr = base_addr + MAC_WRITE_REG_OFFSET; - cmd = base_addr + MAC_COMMAND_REG_OFFSET; - cmd_done = base_addr + MAC_COMMAND_DONE_REG_OFFSET; + addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET; + wr = pdata->mac_csr_addr + MAC_WRITE_REG_OFFSET; + cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET; + cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET; + spin_lock(&pdata->mac_lock); iowrite32(wr_addr, addr); - iowrite32(wr_data, wr); + iowrite32(data, wr); iowrite32(XGENE_ENET_WR_CMD, cmd); - while (wait--) { - done = ioread32(cmd_done); - if (done) - break; + while (!(done = ioread32(cmd_done)) && wait--) udelay(1); - } if (!done) pr_err("MCX mac write failed, addr: 0x%04x\n", wr_addr); iowrite32(0, cmd); + spin_unlock(&pdata->mac_lock); } +EXPORT_SYMBOL(xgene_mdio_wr_mac); int xgene_mdio_rgmii_read(struct mii_bus *bus, int phy_id, int reg) { - void __iomem *addr = (void __iomem *)bus->priv; + struct xgene_mdio_pdata *pdata = (struct xgene_mdio_pdata *)bus->priv; u32 data, done; u8 wait = 10; data = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg); - xgene_enet_wr_mac(addr, MII_MGMT_ADDRESS_ADDR, data); - xgene_enet_wr_mac(addr, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK); + xgene_mdio_wr_mac(pdata, MII_MGMT_ADDRESS_ADDR, data); + xgene_mdio_wr_mac(pdata, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK); do { usleep_range(5, 10); - done = xgene_enet_rd_mac(addr, MII_MGMT_INDICATORS_ADDR); + done = xgene_mdio_rd_mac(pdata, MII_MGMT_INDICATORS_ADDR); } while ((done & BUSY_MASK) && wait--); if (done & BUSY_MASK) { @@ -111,8 +108,8 @@ int xgene_mdio_rgmii_read(struct mii_bus *bus, int phy_id, int reg) return -EBUSY; } - data = xgene_enet_rd_mac(addr, MII_MGMT_STATUS_ADDR); - xgene_enet_wr_mac(addr, MII_MGMT_COMMAND_ADDR, 0); + data = xgene_mdio_rd_mac(pdata, MII_MGMT_STATUS_ADDR); + xgene_mdio_wr_mac(pdata, MII_MGMT_COMMAND_ADDR, 0); return data; } @@ -120,17 +117,17 @@ EXPORT_SYMBOL(xgene_mdio_rgmii_read); int xgene_mdio_rgmii_write(struct mii_bus *bus, int phy_id, int reg, u16 data) { - void __iomem *addr = (void __iomem *)bus->priv; + struct xgene_mdio_pdata *pdata = (struct xgene_mdio_pdata *)bus->priv; u32 val, done; u8 wait = 10; val = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg); - xgene_enet_wr_mac(addr, MII_MGMT_ADDRESS_ADDR, val); + xgene_mdio_wr_mac(pdata, MII_MGMT_ADDRESS_ADDR, val); - xgene_enet_wr_mac(addr, MII_MGMT_CONTROL_ADDR, data); + xgene_mdio_wr_mac(pdata, MII_MGMT_CONTROL_ADDR, data); do { usleep_range(5, 10); - done = xgene_enet_rd_mac(addr, MII_MGMT_INDICATORS_ADDR); + done = xgene_mdio_rd_mac(pdata, MII_MGMT_INDICATORS_ADDR); } while ((done & BUSY_MASK) && wait--); if (done & BUSY_MASK) { @@ -174,8 +171,8 @@ static int xgene_enet_ecc_init(struct xgene_mdio_pdata *pdata) static void xgene_gmac_reset(struct xgene_mdio_pdata *pdata) { - xgene_enet_wr_mac(pdata->mac_csr_addr, MAC_CONFIG_1_ADDR, SOFT_RESET); - xgene_enet_wr_mac(pdata->mac_csr_addr, MAC_CONFIG_1_ADDR, 0); + xgene_mdio_wr_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET); + xgene_mdio_wr_mac(pdata, MAC_CONFIG_1_ADDR, 0); } static int xgene_mdio_reset(struct xgene_mdio_pdata *pdata) @@ -375,6 +372,9 @@ static int xgene_mdio_probe(struct platform_device *pdev) pdata->mdio_csr_addr = csr_base + BLOCK_XG_MDIO_CSR_OFFSET; pdata->diag_csr_addr = csr_base + BLOCK_DIAG_CSR_OFFSET; + if (mdio_id == XGENE_MDIO_RGMII) + spin_lock_init(&pdata->mac_lock); + if (dev->of_node) { pdata->clk = devm_clk_get(dev, NULL); if (IS_ERR(pdata->clk)) { @@ -396,7 +396,7 @@ static int xgene_mdio_probe(struct platform_device *pdev) if (mdio_id == XGENE_MDIO_RGMII) { mdio_bus->read = xgene_mdio_rgmii_read; mdio_bus->write = xgene_mdio_rgmii_write; - mdio_bus->priv = (void __force *)pdata->mac_csr_addr; + mdio_bus->priv = (void __force *)pdata; snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s", "xgene-mii-rgmii"); } else { diff --git a/drivers/net/phy/mdio-xgene.h b/drivers/net/phy/mdio-xgene.h index 594a11d42401..3c85f3e30baa 100644 --- a/drivers/net/phy/mdio-xgene.h +++ b/drivers/net/phy/mdio-xgene.h @@ -102,6 +102,7 @@ struct xgene_mdio_pdata { void __iomem *mdio_csr_addr; struct mii_bus *mdio_bus; int mdio_id; + spinlock_t mac_lock; /* mac lock */ }; /* Set the specified value into a bit-field defined by its starting position @@ -132,6 +133,8 @@ static inline u64 xgene_enet_get_field_value(int pos, int len, u64 src) #define GET_BIT(field, src) \ xgene_enet_get_field_value(field ## _POS, 1, src) +u32 xgene_mdio_rd_mac(struct xgene_mdio_pdata *pdata, u32 rd_addr); +void xgene_mdio_wr_mac(struct xgene_mdio_pdata *pdata, u32 wr_addr, u32 data); int xgene_mdio_rgmii_read(struct mii_bus *bus, int phy_id, int reg); int xgene_mdio_rgmii_write(struct mii_bus *bus, int phy_id, int reg, u16 data); struct phy_device *xgene_enet_phy_register(struct mii_bus *bus, int phy_addr);