Commit 9efa27bf authored by David S. Miller's avatar David S. Miller

Merge branch 'xgene-Add-ethtool-stats-and-bug-fixes'

Iyappan Subramanian says:

====================
drivers: net: xgene: Add ethtool stats and bug fixes

This patch set,

- adds ethtool extended statistics support
- addresses errata workarounds
- fixes bugs related to statistics

v2: Address review comments from v1
	- Adds lock to protect mdio-xgene indirect MAC access
	- Refactors xgene-enet indirect MAC read/write functions
	- Uses mdio-xgene MAC access routines, if xgene-enet port
	  use the same HW.
v1:
	- Initial version
Signed-off-by: default avatarIyappan Subramanian <isubramanian@apm.com>
Signed-off-by: default avatarQuan Nguyen <qnguyen@apm.com>
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a95cfad9 8aba8474
...@@ -23,9 +23,17 @@ ...@@ -23,9 +23,17 @@
struct xgene_gstrings_stats { struct xgene_gstrings_stats {
char name[ETH_GSTRING_LEN]; char name[ETH_GSTRING_LEN];
int offset; 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[] = { static const struct xgene_gstrings_stats gstrings_stats[] = {
XGENE_STAT(rx_packets), XGENE_STAT(rx_packets),
...@@ -40,7 +48,65 @@ static const struct xgene_gstrings_stats gstrings_stats[] = { ...@@ -40,7 +48,65 @@ static const struct xgene_gstrings_stats gstrings_stats[] = {
XGENE_STAT(rx_fifo_errors) 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_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, static void xgene_get_drvinfo(struct net_device *ndev,
struct ethtool_drvinfo *info) struct ethtool_drvinfo *info)
...@@ -142,6 +208,11 @@ static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data) ...@@ -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); memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
p += 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) 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) ...@@ -149,18 +220,71 @@ static int xgene_get_sset_count(struct net_device *ndev, int sset)
if (sset != ETH_SS_STATS) if (sset != ETH_SS_STATS)
return -EINVAL; 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, static void xgene_get_ethtool_stats(struct net_device *ndev,
struct ethtool_stats *dummy, struct ethtool_stats *dummy,
u64 *data) u64 *data)
{ {
void *pdata = netdev_priv(ndev); struct xgene_enet_pdata *pdata = netdev_priv(ndev);
struct rtnl_link_stats64 stats;
int i; int i;
dev_get_stats(ndev, &stats);
for (i = 0; i < XGENE_STATS_LEN; i++) 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, static void xgene_get_pauseparam(struct net_device *ndev,
......
...@@ -205,30 +205,24 @@ static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring) ...@@ -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, void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
struct xgene_enet_pdata *pdata,
enum xgene_enet_err_code status) enum xgene_enet_err_code status)
{ {
switch (status) { switch (status) {
case INGRESS_CRC: case INGRESS_CRC:
ring->rx_crc_errors++; ring->rx_crc_errors++;
ring->rx_dropped++;
break; break;
case INGRESS_CHECKSUM: case INGRESS_CHECKSUM:
case INGRESS_CHECKSUM_COMPUTE: case INGRESS_CHECKSUM_COMPUTE:
ring->rx_errors++; ring->rx_errors++;
ring->rx_dropped++;
break; break;
case INGRESS_TRUNC_FRAME: case INGRESS_TRUNC_FRAME:
ring->rx_frame_errors++; ring->rx_frame_errors++;
ring->rx_dropped++;
break; break;
case INGRESS_PKT_LEN: case INGRESS_PKT_LEN:
ring->rx_length_errors++; ring->rx_length_errors++;
ring->rx_dropped++;
break; break;
case INGRESS_PKT_UNDER: case INGRESS_PKT_UNDER:
ring->rx_frame_errors++; ring->rx_frame_errors++;
ring->rx_dropped++;
break; break;
case INGRESS_FIFO_OVERRUN: case INGRESS_FIFO_OVERRUN:
ring->rx_fifo_errors++; ring->rx_fifo_errors++;
...@@ -270,42 +264,39 @@ static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata, ...@@ -270,42 +264,39 @@ static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata,
iowrite32(val, addr); iowrite32(val, addr);
} }
static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr, void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, u32 wr_addr, u32 wr_data)
void __iomem *cmd, void __iomem *cmd_done,
u32 wr_addr, u32 wr_data)
{ {
u32 done; void __iomem *addr, *wr, *cmd, *cmd_done;
struct net_device *ndev = pdata->ndev;
u8 wait = 10; 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;
spin_lock(&pdata->mac_lock);
iowrite32(wr_addr, addr); iowrite32(wr_addr, addr);
iowrite32(wr_data, wr); iowrite32(wr_data, wr);
iowrite32(XGENE_ENET_WR_CMD, cmd); iowrite32(XGENE_ENET_WR_CMD, cmd);
/* wait for write command to complete */
while (!(done = ioread32(cmd_done)) && wait--) while (!(done = ioread32(cmd_done)) && wait--)
udelay(1); udelay(1);
if (!done) if (!done)
return false; netdev_err(ndev, "mac write failed, addr: %04x data: %08x\n",
wr_addr, wr_data);
iowrite32(0, cmd); iowrite32(0, cmd);
spin_unlock(&pdata->mac_lock);
return true;
}
static void xgene_enet_wr_mcx_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_rd_csr(struct xgene_enet_pdata *pdata, 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, ...@@ -332,42 +323,69 @@ static void xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *pdata,
*val = ioread32(addr); *val = ioread32(addr);
} }
static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd, u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 rd_addr)
void __iomem *cmd, void __iomem *cmd_done,
u32 rd_addr, u32 *rd_data)
{ {
u32 done; void __iomem *addr, *rd, *cmd, *cmd_done;
u32 done, rd_data;
u8 wait = 10; 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;
spin_lock(&pdata->mac_lock);
iowrite32(rd_addr, addr); iowrite32(rd_addr, addr);
iowrite32(XGENE_ENET_RD_CMD, cmd); iowrite32(XGENE_ENET_RD_CMD, cmd);
/* wait for read command to complete */
while (!(done = ioread32(cmd_done)) && wait--) while (!(done = ioread32(cmd_done)) && wait--)
udelay(1); udelay(1);
if (!done) if (!done)
return false; netdev_err(pdata->ndev, "mac read failed, addr: %04x\n",
rd_addr);
*rd_data = ioread32(rd); rd_data = ioread32(rd);
iowrite32(0, cmd); iowrite32(0, cmd);
spin_unlock(&pdata->mac_lock);
return true; return rd_data;
} }
static void xgene_enet_rd_mcx_mac(struct xgene_enet_pdata *pdata, u32 xgene_enet_rd_stat(struct xgene_enet_pdata *pdata, u32 rd_addr)
u32 rd_addr, u32 *rd_data)
{ {
void __iomem *addr, *rd, *cmd, *cmd_done; void __iomem *addr, *rd, *cmd, *cmd_done;
u32 done, rd_data;
u8 wait = 10;
addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; addr = pdata->mcx_stats_addr + STAT_ADDR_REG_OFFSET;
rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET; rd = pdata->mcx_stats_addr + STAT_READ_REG_OFFSET;
cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; cmd = pdata->mcx_stats_addr + STAT_COMMAND_REG_OFFSET;
cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_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);
if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data)) while (!(done = ioread32(cmd_done)) && wait--)
netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n", udelay(1);
if (!done)
netdev_err(pdata->ndev, "mac stats read failed, addr: %04x\n",
rd_addr); 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) 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) ...@@ -379,8 +397,8 @@ static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
(dev_addr[1] << 8) | dev_addr[0]; (dev_addr[1] << 8) | dev_addr[0];
addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16); addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16);
xgene_enet_wr_mcx_mac(pdata, STATION_ADDR0_ADDR, addr0); xgene_enet_wr_mac(pdata, STATION_ADDR0_ADDR, addr0);
xgene_enet_wr_mcx_mac(pdata, STATION_ADDR1_ADDR, addr1); xgene_enet_wr_mac(pdata, STATION_ADDR1_ADDR, addr1);
} }
static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata) 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) ...@@ -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) 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_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, 0);
} }
static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata) 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) ...@@ -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_CONFIG0_REG_0_ADDR, &icm0);
xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2); xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2);
xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_2_ADDR, &mc2); mc2 = xgene_enet_rd_mac(pdata, MAC_CONFIG_2_ADDR);
xgene_enet_rd_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, &intf_ctl); intf_ctl = xgene_enet_rd_mac(pdata, INTERFACE_CONTROL_ADDR);
xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii); xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii);
switch (pdata->phy_speed) { switch (pdata->phy_speed) {
...@@ -495,8 +513,8 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata) ...@@ -495,8 +513,8 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata)
} }
mc2 |= FULL_DUPLEX2 | PAD_CRC | LENGTH_CHK; mc2 |= FULL_DUPLEX2 | PAD_CRC | LENGTH_CHK;
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2); xgene_enet_wr_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl); xgene_enet_wr_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii); xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
xgene_enet_configure_clock(pdata); xgene_enet_configure_clock(pdata);
...@@ -506,7 +524,7 @@ static void xgene_gmac_set_speed(struct xgene_enet_pdata *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) 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, 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) ...@@ -528,14 +546,14 @@ static void xgene_gmac_flowctl_tx(struct xgene_enet_pdata *pdata, bool enable)
{ {
u32 data; 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) if (enable)
data |= TX_FLOW_EN; data |= TX_FLOW_EN;
else else
data &= ~TX_FLOW_EN; 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); 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) ...@@ -544,14 +562,14 @@ static void xgene_gmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable)
{ {
u32 data; 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) if (enable)
data |= RX_FLOW_EN; data |= RX_FLOW_EN;
else else
data &= ~RX_FLOW_EN; 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) static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
...@@ -565,9 +583,9 @@ 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); xgene_gmac_set_mac_addr(pdata);
/* Adjust MDC clock frequency */ /* 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); 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 */ /* Enable drop if bufpool not available */
xgene_enet_rd_csr(pdata, RSIF_CONFIG_REG_ADDR, &value); xgene_enet_rd_csr(pdata, RSIF_CONFIG_REG_ADDR, &value);
...@@ -600,6 +618,18 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata) ...@@ -600,6 +618,18 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
xgene_enet_wr_csr(pdata, CFG_BYPASS_ADDR, RESUME_TX); 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) static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
{ {
u32 val = 0xffffffff; u32 val = 0xffffffff;
...@@ -637,32 +667,32 @@ static void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata) ...@@ -637,32 +667,32 @@ static void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata)
{ {
u32 data; u32 data;
xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN); xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN);
} }
static void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata) static void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata)
{ {
u32 data; u32 data;
xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN); xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN);
} }
static void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata) static void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata)
{ {
u32 data; u32 data;
xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN); xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN);
} }
static void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata) static void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
{ {
u32 data; u32 data;
xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR);
xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN); xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN);
} }
bool xgene_ring_mgr_init(struct xgene_enet_pdata *p) bool xgene_ring_mgr_init(struct xgene_enet_pdata *p)
...@@ -733,27 +763,6 @@ static void xgene_enet_clear(struct xgene_enet_pdata *pdata, ...@@ -733,27 +763,6 @@ static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata) static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
{ {
struct device *dev = &pdata->pdev->dev; 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 (dev->of_node) {
if (!IS_ERR(pdata->clk)) if (!IS_ERR(pdata->clk))
...@@ -1009,6 +1018,7 @@ const struct xgene_mac_ops xgene_gmac_ops = { ...@@ -1009,6 +1018,7 @@ const struct xgene_mac_ops xgene_gmac_ops = {
.tx_enable = xgene_gmac_tx_enable, .tx_enable = xgene_gmac_tx_enable,
.rx_disable = xgene_gmac_rx_disable, .rx_disable = xgene_gmac_rx_disable,
.tx_disable = xgene_gmac_tx_disable, .tx_disable = xgene_gmac_tx_disable,
.get_drop_cnt = xgene_gmac_get_drop_cnt,
.set_speed = xgene_gmac_set_speed, .set_speed = xgene_gmac_set_speed,
.set_mac_addr = xgene_gmac_set_mac_addr, .set_mac_addr = xgene_gmac_set_mac_addr,
.set_framesize = xgene_enet_set_frame_size, .set_framesize = xgene_enet_set_frame_size,
......
...@@ -115,6 +115,7 @@ enum xgene_enet_rm { ...@@ -115,6 +115,7 @@ enum xgene_enet_rm {
#define BLOCK_ETH_CLKRST_CSR_OFFSET 0xc000 #define BLOCK_ETH_CLKRST_CSR_OFFSET 0xc000
#define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000 #define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000
#define BLOCK_ETH_MAC_OFFSET 0x0000 #define BLOCK_ETH_MAC_OFFSET 0x0000
#define BLOCK_ETH_STATS_OFFSET 0x0000
#define BLOCK_ETH_MAC_CSR_OFFSET 0x2800 #define BLOCK_ETH_MAC_CSR_OFFSET 0x2800
#define CLKEN_ADDR 0xc208 #define CLKEN_ADDR 0xc208
...@@ -126,6 +127,12 @@ enum xgene_enet_rm { ...@@ -126,6 +127,12 @@ enum xgene_enet_rm {
#define MAC_READ_REG_OFFSET 0x0c #define MAC_READ_REG_OFFSET 0x0c
#define MAC_COMMAND_DONE_REG_OFFSET 0x10 #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_ADDR_REG_OFFSET 0x00
#define PCS_COMMAND_REG_OFFSET 0x04 #define PCS_COMMAND_REG_OFFSET 0x04
#define PCS_WRITE_REG_OFFSET 0x08 #define PCS_WRITE_REG_OFFSET 0x08
...@@ -185,6 +192,10 @@ enum xgene_enet_rm { ...@@ -185,6 +192,10 @@ enum xgene_enet_rm {
#define CFG_CLE_NXTFPSEL0(val) (((val) << 20) & GENMASK(23, 20)) #define CFG_CLE_NXTFPSEL0(val) (((val) << 20) & GENMASK(23, 20))
#define ICM_CONFIG0_REG_0_ADDR 0x0400 #define ICM_CONFIG0_REG_0_ADDR 0x0400
#define ICM_CONFIG2_REG_0_ADDR 0x0410 #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 RX_DV_GATE_REG_0_ADDR 0x05fc
#define TX_DV_GATE_EN0 BIT(2) #define TX_DV_GATE_EN0 BIT(2)
#define RX_DV_GATE_EN0 BIT(1) #define RX_DV_GATE_EN0 BIT(1)
...@@ -217,12 +228,53 @@ enum xgene_enet_rm { ...@@ -217,12 +228,53 @@ enum xgene_enet_rm {
#define FULL_DUPLEX2 BIT(0) #define FULL_DUPLEX2 BIT(0)
#define PAD_CRC BIT(2) #define PAD_CRC BIT(2)
#define LENGTH_CHK BIT(4) #define LENGTH_CHK BIT(4)
#define SCAN_AUTO_INCR BIT(5)
#define TBYT_ADDR 0x38 #define TR64_ADDR 0x20
#define TPKT_ADDR 0x39 #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 TDRP_ADDR 0x45
#define TJBR_ADDR 0x46
#define TFCS_ADDR 0x47 #define TFCS_ADDR 0x47
#define TXCF_ADDR 0x48
#define TOVR_ADDR 0x49
#define TUND_ADDR 0x4a #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 #define TSO_IPPROTO_TCP 1
...@@ -380,14 +432,16 @@ static inline u16 xgene_enet_get_numslots(u16 id, u32 size) ...@@ -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, void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
struct xgene_enet_pdata *pdata,
enum xgene_enet_err_code status); enum xgene_enet_err_code status);
int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata); int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
void xgene_enet_mdio_remove(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); bool xgene_ring_mgr_init(struct xgene_enet_pdata *p);
int xgene_enet_phy_connect(struct net_device *ndev); int xgene_enet_phy_connect(struct net_device *ndev);
void xgene_enet_phy_disconnect(struct xgene_enet_pdata *pdata); 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_mac_ops xgene_gmac_ops;
extern const struct xgene_port_ops xgene_gport_ops; extern const struct xgene_port_ops xgene_gport_ops;
......
...@@ -246,9 +246,9 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring, ...@@ -246,9 +246,9 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
skb_frag_t *frag; skb_frag_t *frag;
dma_addr_t *frag_dma_addr; dma_addr_t *frag_dma_addr;
u16 skb_index; u16 skb_index;
u8 status;
int i, ret = 0;
u8 mss_index; u8 mss_index;
u8 status;
int i;
skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0)); skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
skb = cp_ring->cp_skb[skb_index]; skb = cp_ring->cp_skb[skb_index];
...@@ -275,19 +275,17 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring, ...@@ -275,19 +275,17 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
/* Checking for error */ /* Checking for error */
status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0)); status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
if (unlikely(status > 2)) { if (unlikely(status > 2)) {
xgene_enet_parse_error(cp_ring, netdev_priv(cp_ring->ndev), cp_ring->tx_dropped++;
status); cp_ring->tx_errors++;
ret = -EIO;
} }
if (likely(skb)) { if (likely(skb)) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
} else { } else {
netdev_err(cp_ring->ndev, "completion skb is NULL\n"); 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) 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, ...@@ -658,6 +656,18 @@ static void xgene_enet_free_pagepool(struct xgene_enet_desc_ring *buf_pool,
buf_pool->head = head; 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 */ /* 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) 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, ...@@ -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) | status = (GET_VAL(ELERR, le64_to_cpu(raw_desc->m0)) << LERR_LEN) |
GET_VAL(LERR, le64_to_cpu(raw_desc->m0)); GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
if (unlikely(status)) { 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); dev_kfree_skb_any(skb);
xgene_enet_free_pagepool(page_pool, raw_desc, exp_desc); 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; goto out;
} }
} }
...@@ -1466,10 +1481,9 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev) ...@@ -1466,10 +1481,9 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
static void xgene_enet_get_stats64( static void xgene_enet_get_stats64(
struct net_device *ndev, struct net_device *ndev,
struct rtnl_link_stats64 *storage) struct rtnl_link_stats64 *stats)
{ {
struct xgene_enet_pdata *pdata = netdev_priv(ndev); struct xgene_enet_pdata *pdata = netdev_priv(ndev);
struct rtnl_link_stats64 *stats = &pdata->stats;
struct xgene_enet_desc_ring *ring; struct xgene_enet_desc_ring *ring;
int i; int i;
...@@ -1478,6 +1492,8 @@ static void xgene_enet_get_stats64( ...@@ -1478,6 +1492,8 @@ static void xgene_enet_get_stats64(
if (ring) { if (ring) {
stats->tx_packets += ring->tx_packets; stats->tx_packets += ring->tx_packets;
stats->tx_bytes += ring->tx_bytes; 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( ...@@ -1486,14 +1502,18 @@ static void xgene_enet_get_stats64(
if (ring) { if (ring) {
stats->rx_packets += ring->rx_packets; stats->rx_packets += ring->rx_packets;
stats->rx_bytes += ring->rx_bytes; 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_crc_errors +
ring->rx_frame_errors + ring->rx_frame_errors +
ring->rx_fifo_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) 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) ...@@ -1788,12 +1808,15 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII || if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII ||
pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) { pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
pdata->mcx_mac_addr = pdata->base_addr + BLOCK_ETH_MAC_OFFSET; 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) ? offset = (pdata->enet_id == XGENE_ENET1) ?
BLOCK_ETH_MAC_CSR_OFFSET : BLOCK_ETH_MAC_CSR_OFFSET :
X2_BLOCK_ETH_MAC_CSR_OFFSET; X2_BLOCK_ETH_MAC_CSR_OFFSET;
pdata->mcx_mac_csr_addr = base_addr + offset; pdata->mcx_mac_csr_addr = base_addr + offset;
} else { } else {
pdata->mcx_mac_addr = base_addr + BLOCK_AXG_MAC_OFFSET; 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->mcx_mac_csr_addr = base_addr + BLOCK_AXG_MAC_CSR_OFFSET;
pdata->pcs_addr = base_addr + BLOCK_PCS_OFFSET; pdata->pcs_addr = base_addr + BLOCK_PCS_OFFSET;
} }
...@@ -2055,6 +2078,7 @@ static int xgene_enet_probe(struct platform_device *pdev) ...@@ -2055,6 +2078,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
goto err; goto err;
xgene_enet_setup_ops(pdata); xgene_enet_setup_ops(pdata);
spin_lock_init(&pdata->mac_lock);
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) { if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
ndev->features |= NETIF_F_TSO | NETIF_F_RXCSUM; ndev->features |= NETIF_F_TSO | NETIF_F_RXCSUM;
...@@ -2085,6 +2109,11 @@ static int xgene_enet_probe(struct platform_device *pdev) ...@@ -2085,6 +2109,11 @@ static int xgene_enet_probe(struct platform_device *pdev)
goto err1; goto err1;
} }
spin_lock_init(&pdata->stats_lock);
ret = xgene_extd_stats_init(pdata);
if (ret)
goto err2;
xgene_enet_napi_add(pdata); xgene_enet_napi_add(pdata);
ret = register_netdev(ndev); ret = register_netdev(ndev);
if (ret) { if (ret) {
...@@ -2130,8 +2159,8 @@ static int xgene_enet_remove(struct platform_device *pdev) ...@@ -2130,8 +2159,8 @@ static int xgene_enet_remove(struct platform_device *pdev)
xgene_enet_mdio_remove(pdata); xgene_enet_mdio_remove(pdata);
unregister_netdev(ndev); unregister_netdev(ndev);
pdata->port_ops->shutdown(pdata);
xgene_enet_delete_desc_rings(pdata); xgene_enet_delete_desc_rings(pdata);
pdata->port_ops->shutdown(pdata);
free_netdev(ndev); free_netdev(ndev);
return 0; return 0;
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#define XGENE_DRV_VERSION "v1.0" #define XGENE_DRV_VERSION "v1.0"
#define ETHER_MIN_PACKET 64 #define ETHER_MIN_PACKET 64
#define ETHER_STD_PACKET 1518
#define XGENE_ENET_STD_MTU 1536 #define XGENE_ENET_STD_MTU 1536
#define XGENE_ENET_MAX_MTU 9600 #define XGENE_ENET_MAX_MTU 9600
#define SKB_BUFFER_SIZE (XGENE_ENET_STD_MTU - NET_IP_ALIGN) #define SKB_BUFFER_SIZE (XGENE_ENET_STD_MTU - NET_IP_ALIGN)
...@@ -138,6 +139,8 @@ struct xgene_enet_desc_ring { ...@@ -138,6 +139,8 @@ struct xgene_enet_desc_ring {
__le64 *exp_bufs; __le64 *exp_bufs;
u64 tx_packets; u64 tx_packets;
u64 tx_bytes; u64 tx_bytes;
u64 tx_dropped;
u64 tx_errors;
u64 rx_packets; u64 rx_packets;
u64 rx_bytes; u64 rx_bytes;
u64 rx_dropped; u64 rx_dropped;
...@@ -155,6 +158,7 @@ struct xgene_mac_ops { ...@@ -155,6 +158,7 @@ struct xgene_mac_ops {
void (*rx_enable)(struct xgene_enet_pdata *pdata); void (*rx_enable)(struct xgene_enet_pdata *pdata);
void (*tx_disable)(struct xgene_enet_pdata *pdata); void (*tx_disable)(struct xgene_enet_pdata *pdata);
void (*rx_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_speed)(struct xgene_enet_pdata *pdata);
void (*set_mac_addr)(struct xgene_enet_pdata *pdata); void (*set_mac_addr)(struct xgene_enet_pdata *pdata);
void (*set_framesize)(struct xgene_enet_pdata *pdata, int framesize); void (*set_framesize)(struct xgene_enet_pdata *pdata, int framesize);
...@@ -212,6 +216,7 @@ struct xgene_enet_pdata { ...@@ -212,6 +216,7 @@ struct xgene_enet_pdata {
void __iomem *eth_diag_csr_addr; void __iomem *eth_diag_csr_addr;
void __iomem *mcx_mac_addr; void __iomem *mcx_mac_addr;
void __iomem *mcx_mac_csr_addr; void __iomem *mcx_mac_csr_addr;
void __iomem *mcx_stats_addr;
void __iomem *base_addr; void __iomem *base_addr;
void __iomem *pcs_addr; void __iomem *pcs_addr;
void __iomem *ring_csr_addr; void __iomem *ring_csr_addr;
...@@ -219,8 +224,12 @@ struct xgene_enet_pdata { ...@@ -219,8 +224,12 @@ struct xgene_enet_pdata {
int phy_mode; int phy_mode;
enum xgene_enet_rm rm; enum xgene_enet_rm rm;
struct xgene_enet_cle cle; 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; const struct xgene_mac_ops *mac_ops;
spinlock_t mac_lock; /* mac lock */
const struct xgene_port_ops *port_ops; const struct xgene_port_ops *port_ops;
struct xgene_ring_ops *ring_ops; struct xgene_ring_ops *ring_ops;
const struct xgene_cle_ops *cle_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) ...@@ -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); 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__ */ #endif /* __XGENE_ENET_MAIN_H__ */
...@@ -54,41 +54,6 @@ static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata, ...@@ -54,41 +54,6 @@ static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata,
iowrite32(val, addr); 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) static u32 xgene_enet_rd_csr(struct xgene_enet_pdata *p, u32 offset)
{ {
return ioread32(p->eth_csr_addr + 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) ...@@ -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); 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) static int xgene_enet_ecc_init(struct xgene_enet_pdata *p)
{ {
struct net_device *ndev = p->ndev; struct net_device *ndev = p->ndev;
...@@ -166,6 +95,24 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *p) ...@@ -166,6 +95,24 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *p)
return -ENODEV; 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) static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p)
{ {
u32 val; u32 val;
...@@ -587,26 +534,6 @@ static void xgene_enet_clear(struct xgene_enet_pdata *pdata, ...@@ -587,26 +534,6 @@ static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
static void xgene_enet_shutdown(struct xgene_enet_pdata *p) static void xgene_enet_shutdown(struct xgene_enet_pdata *p)
{ {
struct device *dev = &p->pdev->dev; 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 (dev->of_node) {
if (!IS_ERR(p->clk)) if (!IS_ERR(p->clk))
...@@ -671,6 +598,7 @@ const struct xgene_mac_ops xgene_sgmac_ops = { ...@@ -671,6 +598,7 @@ const struct xgene_mac_ops xgene_sgmac_ops = {
.tx_enable = xgene_sgmac_tx_enable, .tx_enable = xgene_sgmac_tx_enable,
.rx_disable = xgene_sgmac_rx_disable, .rx_disable = xgene_sgmac_rx_disable,
.tx_disable = xgene_sgmac_tx_disable, .tx_disable = xgene_sgmac_tx_disable,
.get_drop_cnt = xgene_sgmac_get_drop_cnt,
.set_speed = xgene_sgmac_set_speed, .set_speed = xgene_sgmac_set_speed,
.set_mac_addr = xgene_sgmac_set_mac_addr, .set_mac_addr = xgene_sgmac_set_mac_addr,
.set_framesize = xgene_sgmac_set_frame_size, .set_framesize = xgene_sgmac_set_frame_size,
......
...@@ -71,21 +71,6 @@ static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr, ...@@ -71,21 +71,6 @@ static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr,
return true; 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, static void xgene_enet_wr_pcs(struct xgene_enet_pdata *pdata,
u32 wr_addr, u32 wr_data) u32 wr_addr, u32 wr_data)
{ {
...@@ -148,21 +133,6 @@ static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd, ...@@ -148,21 +133,6 @@ static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
return true; 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, static bool xgene_enet_rd_pcs(struct xgene_enet_pdata *pdata,
u32 rd_addr, u32 *rd_data) u32 rd_addr, u32 *rd_data)
{ {
...@@ -210,6 +180,18 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata) ...@@ -210,6 +180,18 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
return 0; 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) static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata)
{ {
xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQASSOC_ADDR, 0); 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) ...@@ -300,7 +282,7 @@ static void xgene_xgmac_flowctl_tx(struct xgene_enet_pdata *pdata, bool enable)
{ {
u32 data; u32 data;
xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1);
if (enable) if (enable)
data |= HSTTCTLEN; data |= HSTTCTLEN;
...@@ -316,7 +298,7 @@ static void xgene_xgmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable) ...@@ -316,7 +298,7 @@ static void xgene_xgmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable)
{ {
u32 data; u32 data;
xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1);
if (enable) if (enable)
data |= HSTRCTLEN; data |= HSTRCTLEN;
...@@ -332,7 +314,7 @@ static void xgene_xgmac_init(struct xgene_enet_pdata *pdata) ...@@ -332,7 +314,7 @@ static void xgene_xgmac_init(struct xgene_enet_pdata *pdata)
xgene_xgmac_reset(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 |= HSTPPEN;
data &= ~HSTLENCHK; data &= ~HSTLENCHK;
xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data); xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data);
...@@ -379,7 +361,7 @@ static void xgene_xgmac_rx_enable(struct xgene_enet_pdata *pdata) ...@@ -379,7 +361,7 @@ static void xgene_xgmac_rx_enable(struct xgene_enet_pdata *pdata)
{ {
u32 data; 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); 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) ...@@ -387,7 +369,7 @@ static void xgene_xgmac_tx_enable(struct xgene_enet_pdata *pdata)
{ {
u32 data; 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); 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) ...@@ -395,7 +377,7 @@ static void xgene_xgmac_rx_disable(struct xgene_enet_pdata *pdata)
{ {
u32 data; 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); 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) ...@@ -403,7 +385,7 @@ static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata)
{ {
u32 data; 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); 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, ...@@ -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) static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
{ {
struct device *dev = &pdata->pdev->dev; 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 (dev->of_node) {
if (!IS_ERR(pdata->clk)) if (!IS_ERR(pdata->clk))
...@@ -567,6 +529,7 @@ const struct xgene_mac_ops xgene_xgmac_ops = { ...@@ -567,6 +529,7 @@ const struct xgene_mac_ops xgene_xgmac_ops = {
.set_mac_addr = xgene_xgmac_set_mac_addr, .set_mac_addr = xgene_xgmac_set_mac_addr,
.set_framesize = xgene_xgmac_set_frame_size, .set_framesize = xgene_xgmac_set_frame_size,
.set_mss = xgene_xgmac_set_mss, .set_mss = xgene_xgmac_set_mss,
.get_drop_cnt = xgene_xgmac_get_drop_cnt,
.link_state = xgene_enet_link_state, .link_state = xgene_enet_link_state,
.enable_tx_pause = xgene_xgmac_enable_tx_pause, .enable_tx_pause = xgene_xgmac_enable_tx_pause,
.flowctl_rx = xgene_xgmac_flowctl_rx, .flowctl_rx = xgene_xgmac_flowctl_rx,
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#define X2_BLOCK_ETH_MAC_CSR_OFFSET 0x3000 #define X2_BLOCK_ETH_MAC_CSR_OFFSET 0x3000
#define BLOCK_AXG_MAC_OFFSET 0x0800 #define BLOCK_AXG_MAC_OFFSET 0x0800
#define BLOCK_AXG_STATS_OFFSET 0x0800
#define BLOCK_AXG_MAC_CSR_OFFSET 0x2000 #define BLOCK_AXG_MAC_CSR_OFFSET 0x2000
#define BLOCK_PCS_OFFSET 0x3800 #define BLOCK_PCS_OFFSET 0x3800
...@@ -70,6 +71,8 @@ ...@@ -70,6 +71,8 @@
#define XG_RSIF_CONFIG1_REG_ADDR 0x00b8 #define XG_RSIF_CONFIG1_REG_ADDR 0x00b8
#define XG_RSIF_PLC_CLE_BUFF_THRESH 0x1 #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 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_REG0_ADDR 0x0160
#define XCLE_BYPASS_REG1_ADDR 0x0164 #define XCLE_BYPASS_REG1_ADDR 0x0164
#define XG_CFG_BYPASS_ADDR 0x0204 #define XG_CFG_BYPASS_ADDR 0x0204
...@@ -80,6 +83,8 @@ ...@@ -80,6 +83,8 @@
#define XG_ENET_SPARE_CFG_REG_ADDR 0x040c #define XG_ENET_SPARE_CFG_REG_ADDR 0x040c
#define XG_ENET_SPARE_CFG_REG_1_ADDR 0x0410 #define XG_ENET_SPARE_CFG_REG_1_ADDR 0x0410
#define XGENET_RX_DV_GATE_REG_0_ADDR 0x0804 #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_ECM_CFG_0_ADDR 0x0880
#define XGENET_CSR_MULTI_DPF0_ADDR 0x0888 #define XGENET_CSR_MULTI_DPF0_ADDR 0x0888
#define XGENET_CSR_MULTI_DPF1_ADDR 0x088c #define XGENET_CSR_MULTI_DPF1_ADDR 0x088c
......
...@@ -34,76 +34,73 @@ ...@@ -34,76 +34,73 @@
static bool xgene_mdio_status; 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; void __iomem *addr, *rd, *cmd, *cmd_done;
u32 done, rd_data = BUSY_MASK; u32 done, rd_data = BUSY_MASK;
u8 wait = 10; u8 wait = 10;
addr = base_addr + MAC_ADDR_REG_OFFSET; addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET;
rd = base_addr + MAC_READ_REG_OFFSET; rd = pdata->mac_csr_addr + MAC_READ_REG_OFFSET;
cmd = base_addr + MAC_COMMAND_REG_OFFSET; cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET;
cmd_done = base_addr + MAC_COMMAND_DONE_REG_OFFSET; cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET;
spin_lock(&pdata->mac_lock);
iowrite32(rd_addr, addr); iowrite32(rd_addr, addr);
iowrite32(XGENE_ENET_RD_CMD, cmd); iowrite32(XGENE_ENET_RD_CMD, cmd);
while (wait--) { while (!(done = ioread32(cmd_done)) && wait--)
done = ioread32(cmd_done);
if (done)
break;
udelay(1); udelay(1);
}
if (!done)
return rd_data;
if (done)
rd_data = ioread32(rd); rd_data = ioread32(rd);
iowrite32(0, cmd); iowrite32(0, cmd);
spin_unlock(&pdata->mac_lock);
return rd_data; 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; void __iomem *addr, *wr, *cmd, *cmd_done;
u8 wait = 10; u8 wait = 10;
u32 done; u32 done;
addr = base_addr + MAC_ADDR_REG_OFFSET; addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET;
wr = base_addr + MAC_WRITE_REG_OFFSET; wr = pdata->mac_csr_addr + MAC_WRITE_REG_OFFSET;
cmd = base_addr + MAC_COMMAND_REG_OFFSET; cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET;
cmd_done = base_addr + MAC_COMMAND_DONE_REG_OFFSET; cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET;
spin_lock(&pdata->mac_lock);
iowrite32(wr_addr, addr); iowrite32(wr_addr, addr);
iowrite32(wr_data, wr); iowrite32(data, wr);
iowrite32(XGENE_ENET_WR_CMD, cmd); iowrite32(XGENE_ENET_WR_CMD, cmd);
while (wait--) { while (!(done = ioread32(cmd_done)) && wait--)
done = ioread32(cmd_done);
if (done)
break;
udelay(1); udelay(1);
}
if (!done) if (!done)
pr_err("MCX mac write failed, addr: 0x%04x\n", wr_addr); pr_err("MCX mac write failed, addr: 0x%04x\n", wr_addr);
iowrite32(0, cmd); 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) 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; u32 data, done;
u8 wait = 10; u8 wait = 10;
data = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg); data = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg);
xgene_enet_wr_mac(addr, MII_MGMT_ADDRESS_ADDR, data); xgene_mdio_wr_mac(pdata, MII_MGMT_ADDRESS_ADDR, data);
xgene_enet_wr_mac(addr, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK); xgene_mdio_wr_mac(pdata, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK);
do { do {
usleep_range(5, 10); 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--); } while ((done & BUSY_MASK) && wait--);
if (done & BUSY_MASK) { if (done & BUSY_MASK) {
...@@ -111,8 +108,8 @@ int xgene_mdio_rgmii_read(struct mii_bus *bus, int phy_id, int reg) ...@@ -111,8 +108,8 @@ int xgene_mdio_rgmii_read(struct mii_bus *bus, int phy_id, int reg)
return -EBUSY; return -EBUSY;
} }
data = xgene_enet_rd_mac(addr, MII_MGMT_STATUS_ADDR); data = xgene_mdio_rd_mac(pdata, MII_MGMT_STATUS_ADDR);
xgene_enet_wr_mac(addr, MII_MGMT_COMMAND_ADDR, 0); xgene_mdio_wr_mac(pdata, MII_MGMT_COMMAND_ADDR, 0);
return data; return data;
} }
...@@ -120,17 +117,17 @@ EXPORT_SYMBOL(xgene_mdio_rgmii_read); ...@@ -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) 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; u32 val, done;
u8 wait = 10; u8 wait = 10;
val = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg); 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 { do {
usleep_range(5, 10); 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--); } while ((done & BUSY_MASK) && wait--);
if (done & BUSY_MASK) { if (done & BUSY_MASK) {
...@@ -174,8 +171,8 @@ static int xgene_enet_ecc_init(struct xgene_mdio_pdata *pdata) ...@@ -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) 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_mdio_wr_mac(pdata, 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, 0);
} }
static int xgene_mdio_reset(struct xgene_mdio_pdata *pdata) static int xgene_mdio_reset(struct xgene_mdio_pdata *pdata)
...@@ -375,6 +372,9 @@ static int xgene_mdio_probe(struct platform_device *pdev) ...@@ -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->mdio_csr_addr = csr_base + BLOCK_XG_MDIO_CSR_OFFSET;
pdata->diag_csr_addr = csr_base + BLOCK_DIAG_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) { if (dev->of_node) {
pdata->clk = devm_clk_get(dev, NULL); pdata->clk = devm_clk_get(dev, NULL);
if (IS_ERR(pdata->clk)) { if (IS_ERR(pdata->clk)) {
...@@ -396,7 +396,7 @@ static int xgene_mdio_probe(struct platform_device *pdev) ...@@ -396,7 +396,7 @@ static int xgene_mdio_probe(struct platform_device *pdev)
if (mdio_id == XGENE_MDIO_RGMII) { if (mdio_id == XGENE_MDIO_RGMII) {
mdio_bus->read = xgene_mdio_rgmii_read; mdio_bus->read = xgene_mdio_rgmii_read;
mdio_bus->write = xgene_mdio_rgmii_write; 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", snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s",
"xgene-mii-rgmii"); "xgene-mii-rgmii");
} else { } else {
......
...@@ -102,6 +102,7 @@ struct xgene_mdio_pdata { ...@@ -102,6 +102,7 @@ struct xgene_mdio_pdata {
void __iomem *mdio_csr_addr; void __iomem *mdio_csr_addr;
struct mii_bus *mdio_bus; struct mii_bus *mdio_bus;
int mdio_id; int mdio_id;
spinlock_t mac_lock; /* mac lock */
}; };
/* Set the specified value into a bit-field defined by its starting position /* 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) ...@@ -132,6 +133,8 @@ static inline u64 xgene_enet_get_field_value(int pos, int len, u64 src)
#define GET_BIT(field, src) \ #define GET_BIT(field, src) \
xgene_enet_get_field_value(field ## _POS, 1, 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_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); 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); struct phy_device *xgene_enet_phy_register(struct mii_bus *bus, int phy_addr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment