diff --git a/drivers/net/ethernet/ti/prueth.h b/drivers/net/ethernet/ti/prueth.h index 69ea6affbb1ec848b27a0ed87ff7e5fb88296361..a345f172ac520e84a9a1f82904042e9c53abfa8b 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 3b27345a3bb726f241e642d8ef159fd682674626..65fb634f8150225653067a6e1472946a69d2629b 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 */