From c1736983eefb0d2572d64dcfff5a1db29498b9fa Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra <vigneshr@ti.com> Date: Fri, 24 Jul 2020 00:20:02 +0000 Subject: [PATCH] net: ti: prueth_core: Add support for dumping FW's VLAN/MC table Add support for userspace to dump VLAN and Multicast filter table maintained by PRUETH firmware via ethtool IOCTL's register dump interface. This is helpful in debugging issues around these filters. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> Acked-by: Murali Karicheri <m-karicheri2@ti.com> Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> --- drivers/net/ethernet/ti/prueth.h | 5 +++ drivers/net/ethernet/ti/prueth_core.c | 64 +++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/drivers/net/ethernet/ti/prueth.h b/drivers/net/ethernet/ti/prueth.h index 69ea6affbb1ec..a345f172ac520 100644 --- a/drivers/net/ethernet/ti/prueth.h +++ b/drivers/net/ethernet/ti/prueth.h @@ -46,6 +46,11 @@ enum pruss_ethtype { #define PRUETH_IS_PRP(p) ((p)->eth_type == PRUSS_ETHTYPE_PRP) #define PRUETH_IS_LRE(p) (PRUETH_IS_HSR(p) || PRUETH_IS_PRP(p)) +#define PRUETH_REG_DUMP_VER 1 + +/* Encoding: 32-16: Reserved, 16-8: Reg dump version, 8-0: Ethertype */ +#define PRUETH_REG_DUMP_GET_VER(x) ((PRUETH_REG_DUMP_VER << 8) | ((x)->eth_type)) + /** * struct prueth_queue_desc - Queue descriptor * @rd_ptr: Read pointer, points to a buffer descriptor in Shared PRU RAM. diff --git a/drivers/net/ethernet/ti/prueth_core.c b/drivers/net/ethernet/ti/prueth_core.c index 3b27345a3bb72..65fb634f81502 100644 --- a/drivers/net/ethernet/ti/prueth_core.c +++ b/drivers/net/ethernet/ti/prueth_core.c @@ -2234,6 +2234,68 @@ static void emac_get_ethtool_stats(struct net_device *ndev, prueth_lre_update_stats(emac->prueth, &data[i]); } +static int emac_get_regs_len(struct net_device *ndev) +{ + struct prueth_emac *emac = netdev_priv(ndev); + struct prueth *prueth = emac->prueth; + + /* VLAN Table at the end of the memory map, after MultiCast + * filter region. So VLAN table base + + * size will give the entire size of reg dump in case of + * Dual-EMAC firmware. + */ + if (PRUETH_IS_EMAC(prueth)) { + return ICSS_EMAC_FW_VLAN_FLTR_TBL_BASE_ADDR + + ICSS_EMAC_FW_VLAN_FILTER_TABLE_SIZE_BYTES; + } + + /* MultiCast table and VLAN filter table are in different + * memories in case of HSR/PRP firmware. Therefore add the sizes + * of individual region. + */ + if (PRUETH_IS_LRE(prueth)) { + return ICSS_LRE_FW_VLAN_FLTR_TBL_BASE_ADDR + + ICSS_EMAC_FW_VLAN_FILTER_TABLE_SIZE_BYTES + + ICSS_LRE_FW_MULTICAST_FILTER_TABLE + + ICSS_EMAC_FW_MULTICAST_TABLE_SIZE_BYTES; + } + + return 0; +} + +static void emac_get_regs(struct net_device *ndev, struct ethtool_regs *regs, + void *p) +{ + struct prueth_emac *emac = netdev_priv(ndev); + struct prueth *prueth = emac->prueth; + void __iomem *ram; + u8 *reg = p; + + regs->version = PRUETH_REG_DUMP_GET_VER(prueth); + + /* Dump firmware's VLAN and MC tables */ + if (PRUETH_IS_EMAC(prueth)) { + ram = prueth->mem[emac->dram].va; + memcpy_fromio(reg, ram, emac_get_regs_len(ndev)); + return; + } + + if (PRUETH_IS_LRE(prueth)) { + size_t len = ICSS_LRE_FW_VLAN_FLTR_TBL_BASE_ADDR + + ICSS_EMAC_FW_VLAN_FILTER_TABLE_SIZE_BYTES; + + ram = prueth->mem[PRUETH_MEM_SHARED_RAM].va; + memcpy_fromio(reg, ram, len); + + reg += len; + + ram = prueth->mem[PRUETH_MEM_DRAM1].va; + len = ICSS_LRE_FW_MULTICAST_FILTER_TABLE + + ICSS_EMAC_FW_MULTICAST_TABLE_SIZE_BYTES; + memcpy_fromio(reg, ram, len); + } +} + /* Ethtool support for EMAC adapter */ static const struct ethtool_ops emac_ethtool_ops = { .get_drvinfo = emac_get_drvinfo, @@ -2244,6 +2306,8 @@ static const struct ethtool_ops emac_ethtool_ops = { .get_sset_count = emac_get_sset_count, .get_strings = emac_get_strings, .get_ethtool_stats = emac_get_ethtool_stats, + .get_regs = emac_get_regs, + .get_regs_len = emac_get_regs_len, }; /* get emac_port corresponding to eth_node name */ -- GitLab