Commit 2d07d8e4 authored by Quan Nguyen's avatar Quan Nguyen Committed by David S. Miller

drivers: net: xgene: Extend ethtool statistics

This patch adds extended ethtool statistics support.
Signed-off-by: default avatarQuan Nguyen <qnguyen@apm.com>
Signed-off-by: default avatarIyappan Subramanian <isubramanian@apm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6f22a7ad
......@@ -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 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,51 @@ 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_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_dropped_pkt_cntr, RDRP, 16),
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)
};
#define XGENE_STATS_LEN ARRAY_SIZE(gstrings_stats)
#define XGENE_EXTD_STATS_LEN ARRAY_SIZE(gstrings_extd_stats)
static void xgene_get_drvinfo(struct net_device *ndev,
struct ethtool_drvinfo *info)
......@@ -142,6 +194,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,19 +206,49 @@ 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 tmp;
int i;
for (i = 0; i < XGENE_EXTD_STATS_LEN; i++) {
tmp = xgene_enet_rd_stat(pdata, gstrings_extd_stats[i].addr);
pdata->extd_stats[i] += tmp &
GENMASK(gstrings_extd_stats[i].mask - 1, 0);
}
}
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)
{
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[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,
......
......@@ -359,6 +359,35 @@ u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 rd_addr)
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)
{
u32 addr0, addr1;
......
......@@ -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
......@@ -218,6 +225,49 @@ enum xgene_enet_rm {
#define PAD_CRC BIT(2)
#define LENGTH_CHK BIT(4)
#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 TSO_IPPROTO_TCP 1
#define USERINFO_POS 0
......@@ -383,6 +433,7 @@ 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;
......
......@@ -1792,12 +1792,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;
}
......@@ -2090,6 +2093,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) {
......
......@@ -214,6 +214,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;
......@@ -221,6 +222,8 @@ struct xgene_enet_pdata {
int phy_mode;
enum xgene_enet_rm rm;
struct xgene_enet_cle cle;
u64 *extd_stats;
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;
......@@ -265,5 +268,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__ */
......@@ -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
......
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