16f8d3f33SWingman Kwok /* 290cff9e2SWingman Kwok * Keystone GBE and XGBE subsystem code 36f8d3f33SWingman Kwok * 46f8d3f33SWingman Kwok * Copyright (C) 2014 Texas Instruments Incorporated 56f8d3f33SWingman Kwok * Authors: Sandeep Nair <sandeep_n@ti.com> 66f8d3f33SWingman Kwok * Sandeep Paulraj <s-paulraj@ti.com> 76f8d3f33SWingman Kwok * Cyril Chemparathy <cyril@ti.com> 86f8d3f33SWingman Kwok * Santosh Shilimkar <santosh.shilimkar@ti.com> 96f8d3f33SWingman Kwok * Wingman Kwok <w-kwok2@ti.com> 106f8d3f33SWingman Kwok * 116f8d3f33SWingman Kwok * This program is free software; you can redistribute it and/or 126f8d3f33SWingman Kwok * modify it under the terms of the GNU General Public License as 136f8d3f33SWingman Kwok * published by the Free Software Foundation version 2. 146f8d3f33SWingman Kwok * 156f8d3f33SWingman Kwok * This program is distributed "as is" WITHOUT ANY WARRANTY of any 166f8d3f33SWingman Kwok * kind, whether express or implied; without even the implied warranty 176f8d3f33SWingman Kwok * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 186f8d3f33SWingman Kwok * GNU General Public License for more details. 196f8d3f33SWingman Kwok */ 206f8d3f33SWingman Kwok 216f8d3f33SWingman Kwok #include <linux/io.h> 2258c11b5fSKaricheri, Muralidharan #include <linux/module.h> 236f8d3f33SWingman Kwok #include <linux/of_mdio.h> 246f8d3f33SWingman Kwok #include <linux/of_address.h> 256f8d3f33SWingman Kwok #include <linux/if_vlan.h> 266246168bSWingMan Kwok #include <linux/ptp_classify.h> 276246168bSWingMan Kwok #include <linux/net_tstamp.h> 286f8d3f33SWingman Kwok #include <linux/ethtool.h> 296f8d3f33SWingman Kwok 302733d7b8SGrygorii Strashko #include "cpsw.h" 316f8d3f33SWingman Kwok #include "cpsw_ale.h" 326f8d3f33SWingman Kwok #include "netcp.h" 336246168bSWingMan Kwok #include "cpts.h" 346f8d3f33SWingman Kwok 356f8d3f33SWingman Kwok #define NETCP_DRIVER_NAME "TI KeyStone Ethernet Driver" 366f8d3f33SWingman Kwok #define NETCP_DRIVER_VERSION "v1.0" 376f8d3f33SWingman Kwok 386f8d3f33SWingman Kwok #define GBE_IDENT(reg) ((reg >> 16) & 0xffff) 396f8d3f33SWingman Kwok #define GBE_MAJOR_VERSION(reg) (reg >> 8 & 0x7) 406f8d3f33SWingman Kwok #define GBE_MINOR_VERSION(reg) (reg & 0xff) 416f8d3f33SWingman Kwok #define GBE_RTL_VERSION(reg) ((reg >> 11) & 0x1f) 426f8d3f33SWingman Kwok 436f8d3f33SWingman Kwok /* 1G Ethernet SS defines */ 446f8d3f33SWingman Kwok #define GBE_MODULE_NAME "netcp-gbe" 452953586dSMurali Karicheri #define GBE_SS_VERSION_14 0x4ed2 466f8d3f33SWingman Kwok 4721e0e0ddSKaricheri, Muralidharan #define GBE_SS_REG_INDEX 0 4821e0e0ddSKaricheri, Muralidharan #define GBE_SGMII34_REG_INDEX 1 4921e0e0ddSKaricheri, Muralidharan #define GBE_SM_REG_INDEX 2 5021e0e0ddSKaricheri, Muralidharan /* offset relative to base of GBE_SS_REG_INDEX */ 516f8d3f33SWingman Kwok #define GBE13_SGMII_MODULE_OFFSET 0x100 5221e0e0ddSKaricheri, Muralidharan /* offset relative to base of GBE_SM_REG_INDEX */ 5321e0e0ddSKaricheri, Muralidharan #define GBE13_HOST_PORT_OFFSET 0x34 5421e0e0ddSKaricheri, Muralidharan #define GBE13_SLAVE_PORT_OFFSET 0x60 5521e0e0ddSKaricheri, Muralidharan #define GBE13_EMAC_OFFSET 0x100 5621e0e0ddSKaricheri, Muralidharan #define GBE13_SLAVE_PORT2_OFFSET 0x200 5721e0e0ddSKaricheri, Muralidharan #define GBE13_HW_STATS_OFFSET 0x300 586246168bSWingMan Kwok #define GBE13_CPTS_OFFSET 0x500 5921e0e0ddSKaricheri, Muralidharan #define GBE13_ALE_OFFSET 0x600 606f8d3f33SWingman Kwok #define GBE13_HOST_PORT_NUM 0 616f8d3f33SWingman Kwok #define GBE13_NUM_ALE_ENTRIES 1024 626f8d3f33SWingman Kwok 639a391c7bSWingMan Kwok /* 1G Ethernet NU SS defines */ 649a391c7bSWingMan Kwok #define GBENU_MODULE_NAME "netcp-gbenu" 659a391c7bSWingMan Kwok #define GBE_SS_ID_NU 0x4ee6 669a391c7bSWingMan Kwok #define GBE_SS_ID_2U 0x4ee8 679a391c7bSWingMan Kwok 689a391c7bSWingMan Kwok #define IS_SS_ID_MU(d) \ 699a391c7bSWingMan Kwok ((GBE_IDENT((d)->ss_version) == GBE_SS_ID_NU) || \ 709a391c7bSWingMan Kwok (GBE_IDENT((d)->ss_version) == GBE_SS_ID_2U)) 719a391c7bSWingMan Kwok 729a391c7bSWingMan Kwok #define IS_SS_ID_NU(d) \ 739a391c7bSWingMan Kwok (GBE_IDENT((d)->ss_version) == GBE_SS_ID_NU) 749a391c7bSWingMan Kwok 752953586dSMurali Karicheri #define IS_SS_ID_VER_14(d) \ 762953586dSMurali Karicheri (GBE_IDENT((d)->ss_version) == GBE_SS_VERSION_14) 77775f9535SMurali Karicheri #define IS_SS_ID_2U(d) \ 78775f9535SMurali Karicheri (GBE_IDENT((d)->ss_version) == GBE_SS_ID_2U) 792953586dSMurali Karicheri 809a391c7bSWingMan Kwok #define GBENU_SS_REG_INDEX 0 819a391c7bSWingMan Kwok #define GBENU_SM_REG_INDEX 1 829a391c7bSWingMan Kwok #define GBENU_SGMII_MODULE_OFFSET 0x100 839a391c7bSWingMan Kwok #define GBENU_HOST_PORT_OFFSET 0x1000 849a391c7bSWingMan Kwok #define GBENU_SLAVE_PORT_OFFSET 0x2000 859a391c7bSWingMan Kwok #define GBENU_EMAC_OFFSET 0x2330 869a391c7bSWingMan Kwok #define GBENU_HW_STATS_OFFSET 0x1a000 876246168bSWingMan Kwok #define GBENU_CPTS_OFFSET 0x1d000 889a391c7bSWingMan Kwok #define GBENU_ALE_OFFSET 0x1e000 899a391c7bSWingMan Kwok #define GBENU_HOST_PORT_NUM 0 908c85151dSWingMan Kwok #define GBENU_SGMII_MODULE_SIZE 0x100 919a391c7bSWingMan Kwok 9290cff9e2SWingman Kwok /* 10G Ethernet SS defines */ 9390cff9e2SWingman Kwok #define XGBE_MODULE_NAME "netcp-xgbe" 942953586dSMurali Karicheri #define XGBE_SS_VERSION_10 0x4ee4 9590cff9e2SWingman Kwok 9621e0e0ddSKaricheri, Muralidharan #define XGBE_SS_REG_INDEX 0 9721e0e0ddSKaricheri, Muralidharan #define XGBE_SM_REG_INDEX 1 9821e0e0ddSKaricheri, Muralidharan #define XGBE_SERDES_REG_INDEX 2 9921e0e0ddSKaricheri, Muralidharan 10021e0e0ddSKaricheri, Muralidharan /* offset relative to base of XGBE_SS_REG_INDEX */ 10190cff9e2SWingman Kwok #define XGBE10_SGMII_MODULE_OFFSET 0x100 1024c0ef231SWingMan Kwok #define IS_SS_ID_XGBE(d) ((d)->ss_version == XGBE_SS_VERSION_10) 10321e0e0ddSKaricheri, Muralidharan /* offset relative to base of XGBE_SM_REG_INDEX */ 10421e0e0ddSKaricheri, Muralidharan #define XGBE10_HOST_PORT_OFFSET 0x34 10521e0e0ddSKaricheri, Muralidharan #define XGBE10_SLAVE_PORT_OFFSET 0x64 10621e0e0ddSKaricheri, Muralidharan #define XGBE10_EMAC_OFFSET 0x400 1076246168bSWingMan Kwok #define XGBE10_CPTS_OFFSET 0x600 10821e0e0ddSKaricheri, Muralidharan #define XGBE10_ALE_OFFSET 0x700 10921e0e0ddSKaricheri, Muralidharan #define XGBE10_HW_STATS_OFFSET 0x800 11090cff9e2SWingman Kwok #define XGBE10_HOST_PORT_NUM 0 1117938a0d7SKaricheri, Muralidharan #define XGBE10_NUM_ALE_ENTRIES 2048 11290cff9e2SWingman Kwok 1136f8d3f33SWingman Kwok #define GBE_TIMER_INTERVAL (HZ / 2) 1146f8d3f33SWingman Kwok 1156f8d3f33SWingman Kwok /* Soft reset register values */ 1166f8d3f33SWingman Kwok #define SOFT_RESET_MASK BIT(0) 1176f8d3f33SWingman Kwok #define SOFT_RESET BIT(0) 1186f8d3f33SWingman Kwok #define DEVICE_EMACSL_RESET_POLL_COUNT 100 1196f8d3f33SWingman Kwok #define GMACSL_RET_WARN_RESET_INCOMPLETE -2 1206f8d3f33SWingman Kwok 1216f8d3f33SWingman Kwok #define MACSL_RX_ENABLE_CSF BIT(23) 1226f8d3f33SWingman Kwok #define MACSL_ENABLE_EXT_CTL BIT(18) 12390cff9e2SWingman Kwok #define MACSL_XGMII_ENABLE BIT(13) 12490cff9e2SWingman Kwok #define MACSL_XGIG_MODE BIT(8) 1256f8d3f33SWingman Kwok #define MACSL_GIG_MODE BIT(7) 1266f8d3f33SWingman Kwok #define MACSL_GMII_ENABLE BIT(5) 1276f8d3f33SWingman Kwok #define MACSL_FULLDUPLEX BIT(0) 1286f8d3f33SWingman Kwok 1296f8d3f33SWingman Kwok #define GBE_CTL_P0_ENABLE BIT(2) 1304cd85a61SKaricheri, Muralidharan #define ETH_SW_CTL_P0_TX_CRC_REMOVE BIT(13) 1319a391c7bSWingMan Kwok #define GBE13_REG_VAL_STAT_ENABLE_ALL 0xff 13290cff9e2SWingman Kwok #define XGBE_REG_VAL_STAT_ENABLE_ALL 0xf 1336f8d3f33SWingman Kwok #define GBE_STATS_CD_SEL BIT(28) 1346f8d3f33SWingman Kwok 1356f8d3f33SWingman Kwok #define GBE_PORT_MASK(x) (BIT(x) - 1) 1366f8d3f33SWingman Kwok #define GBE_MASK_NO_PORTS 0 1376f8d3f33SWingman Kwok 1386f8d3f33SWingman Kwok #define GBE_DEF_1G_MAC_CONTROL \ 1396f8d3f33SWingman Kwok (MACSL_GIG_MODE | MACSL_GMII_ENABLE | \ 1406f8d3f33SWingman Kwok MACSL_ENABLE_EXT_CTL | MACSL_RX_ENABLE_CSF) 1416f8d3f33SWingman Kwok 14290cff9e2SWingman Kwok #define GBE_DEF_10G_MAC_CONTROL \ 14390cff9e2SWingman Kwok (MACSL_XGIG_MODE | MACSL_XGMII_ENABLE | \ 14490cff9e2SWingman Kwok MACSL_ENABLE_EXT_CTL | MACSL_RX_ENABLE_CSF) 14590cff9e2SWingman Kwok 1466f8d3f33SWingman Kwok #define GBE_STATSA_MODULE 0 1476f8d3f33SWingman Kwok #define GBE_STATSB_MODULE 1 1486f8d3f33SWingman Kwok #define GBE_STATSC_MODULE 2 1496f8d3f33SWingman Kwok #define GBE_STATSD_MODULE 3 1506f8d3f33SWingman Kwok 1519a391c7bSWingMan Kwok #define GBENU_STATS0_MODULE 0 1529a391c7bSWingMan Kwok #define GBENU_STATS1_MODULE 1 1539a391c7bSWingMan Kwok #define GBENU_STATS2_MODULE 2 1549a391c7bSWingMan Kwok #define GBENU_STATS3_MODULE 3 1559a391c7bSWingMan Kwok #define GBENU_STATS4_MODULE 4 1569a391c7bSWingMan Kwok #define GBENU_STATS5_MODULE 5 1579a391c7bSWingMan Kwok #define GBENU_STATS6_MODULE 6 1589a391c7bSWingMan Kwok #define GBENU_STATS7_MODULE 7 1599a391c7bSWingMan Kwok #define GBENU_STATS8_MODULE 8 1609a391c7bSWingMan Kwok 16190cff9e2SWingman Kwok #define XGBE_STATS0_MODULE 0 16290cff9e2SWingman Kwok #define XGBE_STATS1_MODULE 1 16390cff9e2SWingman Kwok #define XGBE_STATS2_MODULE 2 16490cff9e2SWingman Kwok 1656f8d3f33SWingman Kwok /* s: 0-based slave_port */ 1668c85151dSWingMan Kwok #define SGMII_BASE(d, s) \ 1678c85151dSWingMan Kwok (((s) < 2) ? (d)->sgmii_port_regs : (d)->sgmii_port34_regs) 1686f8d3f33SWingman Kwok 1696f8d3f33SWingman Kwok #define GBE_TX_QUEUE 648 1706f8d3f33SWingman Kwok #define GBE_TXHOOK_ORDER 0 1716246168bSWingMan Kwok #define GBE_RXHOOK_ORDER 0 1726f8d3f33SWingman Kwok #define GBE_DEFAULT_ALE_AGEOUT 30 17390cff9e2SWingman Kwok #define SLAVE_LINK_IS_XGMII(s) ((s)->link_interface >= XGMII_LINK_MAC_PHY) 1747771f2b4SMurali Karicheri #define SLAVE_LINK_IS_RGMII(s) \ 1757771f2b4SMurali Karicheri (((s)->link_interface >= RGMII_LINK_MAC_PHY) && \ 1767771f2b4SMurali Karicheri ((s)->link_interface <= RGMII_LINK_MAC_PHY_NO_MDIO)) 1777771f2b4SMurali Karicheri #define SLAVE_LINK_IS_SGMII(s) \ 1787771f2b4SMurali Karicheri ((s)->link_interface <= SGMII_LINK_MAC_PHY_NO_MDIO) 1796f8d3f33SWingman Kwok #define NETCP_LINK_STATE_INVALID -1 1806f8d3f33SWingman Kwok 1816f8d3f33SWingman Kwok #define GBE_SET_REG_OFS(p, rb, rn) p->rb##_ofs.rn = \ 1826f8d3f33SWingman Kwok offsetof(struct gbe##_##rb, rn) 1839a391c7bSWingMan Kwok #define GBENU_SET_REG_OFS(p, rb, rn) p->rb##_ofs.rn = \ 1849a391c7bSWingMan Kwok offsetof(struct gbenu##_##rb, rn) 18590cff9e2SWingman Kwok #define XGBE_SET_REG_OFS(p, rb, rn) p->rb##_ofs.rn = \ 18690cff9e2SWingman Kwok offsetof(struct xgbe##_##rb, rn) 1876f8d3f33SWingman Kwok #define GBE_REG_ADDR(p, rb, rn) (p->rb + p->rb##_ofs.rn) 1886f8d3f33SWingman Kwok 1899a391c7bSWingMan Kwok #define HOST_TX_PRI_MAP_DEFAULT 0x00000000 1909a391c7bSWingMan Kwok 1916246168bSWingMan Kwok #if IS_ENABLED(CONFIG_TI_CPTS) 1926246168bSWingMan Kwok /* Px_TS_CTL register fields */ 1936246168bSWingMan Kwok #define TS_RX_ANX_F_EN BIT(0) 1946246168bSWingMan Kwok #define TS_RX_VLAN_LT1_EN BIT(1) 1956246168bSWingMan Kwok #define TS_RX_VLAN_LT2_EN BIT(2) 1966246168bSWingMan Kwok #define TS_RX_ANX_D_EN BIT(3) 1976246168bSWingMan Kwok #define TS_TX_ANX_F_EN BIT(4) 1986246168bSWingMan Kwok #define TS_TX_VLAN_LT1_EN BIT(5) 1996246168bSWingMan Kwok #define TS_TX_VLAN_LT2_EN BIT(6) 2006246168bSWingMan Kwok #define TS_TX_ANX_D_EN BIT(7) 2016246168bSWingMan Kwok #define TS_LT2_EN BIT(8) 2026246168bSWingMan Kwok #define TS_RX_ANX_E_EN BIT(9) 2036246168bSWingMan Kwok #define TS_TX_ANX_E_EN BIT(10) 2046246168bSWingMan Kwok #define TS_MSG_TYPE_EN_SHIFT 16 2056246168bSWingMan Kwok #define TS_MSG_TYPE_EN_MASK 0xffff 2066246168bSWingMan Kwok 2076246168bSWingMan Kwok /* Px_TS_SEQ_LTYPE register fields */ 2086246168bSWingMan Kwok #define TS_SEQ_ID_OFS_SHIFT 16 2096246168bSWingMan Kwok #define TS_SEQ_ID_OFS_MASK 0x3f 2106246168bSWingMan Kwok 2116246168bSWingMan Kwok /* Px_TS_CTL_LTYPE2 register fields */ 2126246168bSWingMan Kwok #define TS_107 BIT(16) 2136246168bSWingMan Kwok #define TS_129 BIT(17) 2146246168bSWingMan Kwok #define TS_130 BIT(18) 2156246168bSWingMan Kwok #define TS_131 BIT(19) 2166246168bSWingMan Kwok #define TS_132 BIT(20) 2176246168bSWingMan Kwok #define TS_319 BIT(21) 2186246168bSWingMan Kwok #define TS_320 BIT(22) 2196246168bSWingMan Kwok #define TS_TTL_NONZERO BIT(23) 2206246168bSWingMan Kwok #define TS_UNI_EN BIT(24) 2216246168bSWingMan Kwok #define TS_UNI_EN_SHIFT 24 2226246168bSWingMan Kwok 2236246168bSWingMan Kwok #define TS_TX_ANX_ALL_EN \ 2246246168bSWingMan Kwok (TS_TX_ANX_D_EN | TS_TX_ANX_E_EN | TS_TX_ANX_F_EN) 2256246168bSWingMan Kwok 2266246168bSWingMan Kwok #define TS_RX_ANX_ALL_EN \ 2276246168bSWingMan Kwok (TS_RX_ANX_D_EN | TS_RX_ANX_E_EN | TS_RX_ANX_F_EN) 2286246168bSWingMan Kwok 2296246168bSWingMan Kwok #define TS_CTL_DST_PORT TS_319 2306246168bSWingMan Kwok #define TS_CTL_DST_PORT_SHIFT 21 2316246168bSWingMan Kwok 2326246168bSWingMan Kwok #define TS_CTL_MADDR_ALL \ 2336246168bSWingMan Kwok (TS_107 | TS_129 | TS_130 | TS_131 | TS_132) 2346246168bSWingMan Kwok 2356246168bSWingMan Kwok #define TS_CTL_MADDR_SHIFT 16 2366246168bSWingMan Kwok 2376246168bSWingMan Kwok /* The PTP event messages - Sync, Delay_Req, Pdelay_Req, and Pdelay_Resp. */ 2386246168bSWingMan Kwok #define EVENT_MSG_BITS (BIT(0) | BIT(1) | BIT(2) | BIT(3)) 2396246168bSWingMan Kwok #endif /* CONFIG_TI_CPTS */ 2406246168bSWingMan Kwok 24190cff9e2SWingman Kwok struct xgbe_ss_regs { 24290cff9e2SWingman Kwok u32 id_ver; 24390cff9e2SWingman Kwok u32 synce_count; 24490cff9e2SWingman Kwok u32 synce_mux; 24590cff9e2SWingman Kwok u32 control; 24690cff9e2SWingman Kwok }; 24790cff9e2SWingman Kwok 24890cff9e2SWingman Kwok struct xgbe_switch_regs { 24990cff9e2SWingman Kwok u32 id_ver; 25090cff9e2SWingman Kwok u32 control; 25190cff9e2SWingman Kwok u32 emcontrol; 25290cff9e2SWingman Kwok u32 stat_port_en; 25390cff9e2SWingman Kwok u32 ptype; 25490cff9e2SWingman Kwok u32 soft_idle; 25590cff9e2SWingman Kwok u32 thru_rate; 25690cff9e2SWingman Kwok u32 gap_thresh; 25790cff9e2SWingman Kwok u32 tx_start_wds; 25890cff9e2SWingman Kwok u32 flow_control; 25990cff9e2SWingman Kwok u32 cppi_thresh; 26090cff9e2SWingman Kwok }; 26190cff9e2SWingman Kwok 26290cff9e2SWingman Kwok struct xgbe_port_regs { 26390cff9e2SWingman Kwok u32 blk_cnt; 26490cff9e2SWingman Kwok u32 port_vlan; 26590cff9e2SWingman Kwok u32 tx_pri_map; 26690cff9e2SWingman Kwok u32 sa_lo; 26790cff9e2SWingman Kwok u32 sa_hi; 26890cff9e2SWingman Kwok u32 ts_ctl; 26990cff9e2SWingman Kwok u32 ts_seq_ltype; 27090cff9e2SWingman Kwok u32 ts_vlan; 27190cff9e2SWingman Kwok u32 ts_ctl_ltype2; 27290cff9e2SWingman Kwok u32 ts_ctl2; 27390cff9e2SWingman Kwok u32 control; 27490cff9e2SWingman Kwok }; 27590cff9e2SWingman Kwok 27690cff9e2SWingman Kwok struct xgbe_host_port_regs { 27790cff9e2SWingman Kwok u32 blk_cnt; 27890cff9e2SWingman Kwok u32 port_vlan; 27990cff9e2SWingman Kwok u32 tx_pri_map; 28090cff9e2SWingman Kwok u32 src_id; 28190cff9e2SWingman Kwok u32 rx_pri_map; 28290cff9e2SWingman Kwok u32 rx_maxlen; 28390cff9e2SWingman Kwok }; 28490cff9e2SWingman Kwok 28590cff9e2SWingman Kwok struct xgbe_emac_regs { 28690cff9e2SWingman Kwok u32 id_ver; 28790cff9e2SWingman Kwok u32 mac_control; 28890cff9e2SWingman Kwok u32 mac_status; 28990cff9e2SWingman Kwok u32 soft_reset; 29090cff9e2SWingman Kwok u32 rx_maxlen; 29190cff9e2SWingman Kwok u32 __reserved_0; 29290cff9e2SWingman Kwok u32 rx_pause; 29390cff9e2SWingman Kwok u32 tx_pause; 29490cff9e2SWingman Kwok u32 em_control; 29590cff9e2SWingman Kwok u32 __reserved_1; 29690cff9e2SWingman Kwok u32 tx_gap; 29790cff9e2SWingman Kwok u32 rsvd[4]; 29890cff9e2SWingman Kwok }; 29990cff9e2SWingman Kwok 30090cff9e2SWingman Kwok struct xgbe_host_hw_stats { 30190cff9e2SWingman Kwok u32 rx_good_frames; 30290cff9e2SWingman Kwok u32 rx_broadcast_frames; 30390cff9e2SWingman Kwok u32 rx_multicast_frames; 30490cff9e2SWingman Kwok u32 __rsvd_0[3]; 30590cff9e2SWingman Kwok u32 rx_oversized_frames; 30690cff9e2SWingman Kwok u32 __rsvd_1; 30790cff9e2SWingman Kwok u32 rx_undersized_frames; 30890cff9e2SWingman Kwok u32 __rsvd_2; 30990cff9e2SWingman Kwok u32 overrun_type4; 31090cff9e2SWingman Kwok u32 overrun_type5; 31190cff9e2SWingman Kwok u32 rx_bytes; 31290cff9e2SWingman Kwok u32 tx_good_frames; 31390cff9e2SWingman Kwok u32 tx_broadcast_frames; 31490cff9e2SWingman Kwok u32 tx_multicast_frames; 31590cff9e2SWingman Kwok u32 __rsvd_3[9]; 31690cff9e2SWingman Kwok u32 tx_bytes; 31790cff9e2SWingman Kwok u32 tx_64byte_frames; 31890cff9e2SWingman Kwok u32 tx_65_to_127byte_frames; 31990cff9e2SWingman Kwok u32 tx_128_to_255byte_frames; 32090cff9e2SWingman Kwok u32 tx_256_to_511byte_frames; 32190cff9e2SWingman Kwok u32 tx_512_to_1023byte_frames; 32290cff9e2SWingman Kwok u32 tx_1024byte_frames; 32390cff9e2SWingman Kwok u32 net_bytes; 32490cff9e2SWingman Kwok u32 rx_sof_overruns; 32590cff9e2SWingman Kwok u32 rx_mof_overruns; 32690cff9e2SWingman Kwok u32 rx_dma_overruns; 32790cff9e2SWingman Kwok }; 32890cff9e2SWingman Kwok 32990cff9e2SWingman Kwok struct xgbe_hw_stats { 33090cff9e2SWingman Kwok u32 rx_good_frames; 33190cff9e2SWingman Kwok u32 rx_broadcast_frames; 33290cff9e2SWingman Kwok u32 rx_multicast_frames; 33390cff9e2SWingman Kwok u32 rx_pause_frames; 33490cff9e2SWingman Kwok u32 rx_crc_errors; 33590cff9e2SWingman Kwok u32 rx_align_code_errors; 33690cff9e2SWingman Kwok u32 rx_oversized_frames; 33790cff9e2SWingman Kwok u32 rx_jabber_frames; 33890cff9e2SWingman Kwok u32 rx_undersized_frames; 33990cff9e2SWingman Kwok u32 rx_fragments; 34090cff9e2SWingman Kwok u32 overrun_type4; 34190cff9e2SWingman Kwok u32 overrun_type5; 34290cff9e2SWingman Kwok u32 rx_bytes; 34390cff9e2SWingman Kwok u32 tx_good_frames; 34490cff9e2SWingman Kwok u32 tx_broadcast_frames; 34590cff9e2SWingman Kwok u32 tx_multicast_frames; 34690cff9e2SWingman Kwok u32 tx_pause_frames; 34790cff9e2SWingman Kwok u32 tx_deferred_frames; 34890cff9e2SWingman Kwok u32 tx_collision_frames; 34990cff9e2SWingman Kwok u32 tx_single_coll_frames; 35090cff9e2SWingman Kwok u32 tx_mult_coll_frames; 35190cff9e2SWingman Kwok u32 tx_excessive_collisions; 35290cff9e2SWingman Kwok u32 tx_late_collisions; 35390cff9e2SWingman Kwok u32 tx_underrun; 35490cff9e2SWingman Kwok u32 tx_carrier_sense_errors; 35590cff9e2SWingman Kwok u32 tx_bytes; 35690cff9e2SWingman Kwok u32 tx_64byte_frames; 35790cff9e2SWingman Kwok u32 tx_65_to_127byte_frames; 35890cff9e2SWingman Kwok u32 tx_128_to_255byte_frames; 35990cff9e2SWingman Kwok u32 tx_256_to_511byte_frames; 36090cff9e2SWingman Kwok u32 tx_512_to_1023byte_frames; 36190cff9e2SWingman Kwok u32 tx_1024byte_frames; 36290cff9e2SWingman Kwok u32 net_bytes; 36390cff9e2SWingman Kwok u32 rx_sof_overruns; 36490cff9e2SWingman Kwok u32 rx_mof_overruns; 36590cff9e2SWingman Kwok u32 rx_dma_overruns; 36690cff9e2SWingman Kwok }; 36790cff9e2SWingman Kwok 3689a391c7bSWingMan Kwok struct gbenu_ss_regs { 3699a391c7bSWingMan Kwok u32 id_ver; 3709a391c7bSWingMan Kwok u32 synce_count; /* NU */ 3719a391c7bSWingMan Kwok u32 synce_mux; /* NU */ 3729a391c7bSWingMan Kwok u32 control; /* 2U */ 3739a391c7bSWingMan Kwok u32 __rsvd_0[2]; /* 2U */ 3749a391c7bSWingMan Kwok u32 rgmii_status; /* 2U */ 3759a391c7bSWingMan Kwok u32 ss_status; /* 2U */ 3769a391c7bSWingMan Kwok }; 3779a391c7bSWingMan Kwok 3789a391c7bSWingMan Kwok struct gbenu_switch_regs { 3799a391c7bSWingMan Kwok u32 id_ver; 3809a391c7bSWingMan Kwok u32 control; 3819a391c7bSWingMan Kwok u32 __rsvd_0[2]; 3829a391c7bSWingMan Kwok u32 emcontrol; 3839a391c7bSWingMan Kwok u32 stat_port_en; 3849a391c7bSWingMan Kwok u32 ptype; /* NU */ 3859a391c7bSWingMan Kwok u32 soft_idle; 3869a391c7bSWingMan Kwok u32 thru_rate; /* NU */ 3879a391c7bSWingMan Kwok u32 gap_thresh; /* NU */ 3889a391c7bSWingMan Kwok u32 tx_start_wds; /* NU */ 3899a391c7bSWingMan Kwok u32 eee_prescale; /* 2U */ 3909a391c7bSWingMan Kwok u32 tx_g_oflow_thresh_set; /* NU */ 3919a391c7bSWingMan Kwok u32 tx_g_oflow_thresh_clr; /* NU */ 3929a391c7bSWingMan Kwok u32 tx_g_buf_thresh_set_l; /* NU */ 3939a391c7bSWingMan Kwok u32 tx_g_buf_thresh_set_h; /* NU */ 3949a391c7bSWingMan Kwok u32 tx_g_buf_thresh_clr_l; /* NU */ 3959a391c7bSWingMan Kwok u32 tx_g_buf_thresh_clr_h; /* NU */ 3969a391c7bSWingMan Kwok }; 3979a391c7bSWingMan Kwok 3989a391c7bSWingMan Kwok struct gbenu_port_regs { 3999a391c7bSWingMan Kwok u32 __rsvd_0; 4009a391c7bSWingMan Kwok u32 control; 4019a391c7bSWingMan Kwok u32 max_blks; /* 2U */ 4029a391c7bSWingMan Kwok u32 mem_align1; 4039a391c7bSWingMan Kwok u32 blk_cnt; 4049a391c7bSWingMan Kwok u32 port_vlan; 4059a391c7bSWingMan Kwok u32 tx_pri_map; /* NU */ 4069a391c7bSWingMan Kwok u32 pri_ctl; /* 2U */ 4079a391c7bSWingMan Kwok u32 rx_pri_map; 4089a391c7bSWingMan Kwok u32 rx_maxlen; 4099a391c7bSWingMan Kwok u32 tx_blks_pri; /* NU */ 4109a391c7bSWingMan Kwok u32 __rsvd_1; 4119a391c7bSWingMan Kwok u32 idle2lpi; /* 2U */ 4129a391c7bSWingMan Kwok u32 lpi2idle; /* 2U */ 4139a391c7bSWingMan Kwok u32 eee_status; /* 2U */ 4149a391c7bSWingMan Kwok u32 __rsvd_2; 4159a391c7bSWingMan Kwok u32 __rsvd_3[176]; /* NU: more to add */ 4169a391c7bSWingMan Kwok u32 __rsvd_4[2]; 4179a391c7bSWingMan Kwok u32 sa_lo; 4189a391c7bSWingMan Kwok u32 sa_hi; 4199a391c7bSWingMan Kwok u32 ts_ctl; 4209a391c7bSWingMan Kwok u32 ts_seq_ltype; 4219a391c7bSWingMan Kwok u32 ts_vlan; 4229a391c7bSWingMan Kwok u32 ts_ctl_ltype2; 4239a391c7bSWingMan Kwok u32 ts_ctl2; 4249a391c7bSWingMan Kwok }; 4259a391c7bSWingMan Kwok 4269a391c7bSWingMan Kwok struct gbenu_host_port_regs { 4279a391c7bSWingMan Kwok u32 __rsvd_0; 4289a391c7bSWingMan Kwok u32 control; 4299a391c7bSWingMan Kwok u32 flow_id_offset; /* 2U */ 4309a391c7bSWingMan Kwok u32 __rsvd_1; 4319a391c7bSWingMan Kwok u32 blk_cnt; 4329a391c7bSWingMan Kwok u32 port_vlan; 4339a391c7bSWingMan Kwok u32 tx_pri_map; /* NU */ 4349a391c7bSWingMan Kwok u32 pri_ctl; 4359a391c7bSWingMan Kwok u32 rx_pri_map; 4369a391c7bSWingMan Kwok u32 rx_maxlen; 4379a391c7bSWingMan Kwok u32 tx_blks_pri; /* NU */ 4389a391c7bSWingMan Kwok u32 __rsvd_2; 4399a391c7bSWingMan Kwok u32 idle2lpi; /* 2U */ 4409a391c7bSWingMan Kwok u32 lpi2wake; /* 2U */ 4419a391c7bSWingMan Kwok u32 eee_status; /* 2U */ 4429a391c7bSWingMan Kwok u32 __rsvd_3; 4439a391c7bSWingMan Kwok u32 __rsvd_4[184]; /* NU */ 4449a391c7bSWingMan Kwok u32 host_blks_pri; /* NU */ 4459a391c7bSWingMan Kwok }; 4469a391c7bSWingMan Kwok 4479a391c7bSWingMan Kwok struct gbenu_emac_regs { 4489a391c7bSWingMan Kwok u32 mac_control; 4499a391c7bSWingMan Kwok u32 mac_status; 4509a391c7bSWingMan Kwok u32 soft_reset; 4519a391c7bSWingMan Kwok u32 boff_test; 4529a391c7bSWingMan Kwok u32 rx_pause; 4539a391c7bSWingMan Kwok u32 __rsvd_0[11]; /* NU */ 4549a391c7bSWingMan Kwok u32 tx_pause; 4559a391c7bSWingMan Kwok u32 __rsvd_1[11]; /* NU */ 4569a391c7bSWingMan Kwok u32 em_control; 4579a391c7bSWingMan Kwok u32 tx_gap; 4589a391c7bSWingMan Kwok }; 4599a391c7bSWingMan Kwok 4609a391c7bSWingMan Kwok /* Some hw stat regs are applicable to slave port only. 4619a391c7bSWingMan Kwok * This is handled by gbenu_et_stats struct. Also some 4629a391c7bSWingMan Kwok * are for SS version NU and some are for 2U. 4639a391c7bSWingMan Kwok */ 4649a391c7bSWingMan Kwok struct gbenu_hw_stats { 4659a391c7bSWingMan Kwok u32 rx_good_frames; 4669a391c7bSWingMan Kwok u32 rx_broadcast_frames; 4679a391c7bSWingMan Kwok u32 rx_multicast_frames; 4689a391c7bSWingMan Kwok u32 rx_pause_frames; /* slave */ 4699a391c7bSWingMan Kwok u32 rx_crc_errors; 4709a391c7bSWingMan Kwok u32 rx_align_code_errors; /* slave */ 4719a391c7bSWingMan Kwok u32 rx_oversized_frames; 4729a391c7bSWingMan Kwok u32 rx_jabber_frames; /* slave */ 4739a391c7bSWingMan Kwok u32 rx_undersized_frames; 4749a391c7bSWingMan Kwok u32 rx_fragments; /* slave */ 4759a391c7bSWingMan Kwok u32 ale_drop; 4769a391c7bSWingMan Kwok u32 ale_overrun_drop; 4779a391c7bSWingMan Kwok u32 rx_bytes; 4789a391c7bSWingMan Kwok u32 tx_good_frames; 4799a391c7bSWingMan Kwok u32 tx_broadcast_frames; 4809a391c7bSWingMan Kwok u32 tx_multicast_frames; 4819a391c7bSWingMan Kwok u32 tx_pause_frames; /* slave */ 4829a391c7bSWingMan Kwok u32 tx_deferred_frames; /* slave */ 4839a391c7bSWingMan Kwok u32 tx_collision_frames; /* slave */ 4849a391c7bSWingMan Kwok u32 tx_single_coll_frames; /* slave */ 4859a391c7bSWingMan Kwok u32 tx_mult_coll_frames; /* slave */ 4869a391c7bSWingMan Kwok u32 tx_excessive_collisions; /* slave */ 4879a391c7bSWingMan Kwok u32 tx_late_collisions; /* slave */ 4889a391c7bSWingMan Kwok u32 rx_ipg_error; /* slave 10G only */ 4899a391c7bSWingMan Kwok u32 tx_carrier_sense_errors; /* slave */ 4909a391c7bSWingMan Kwok u32 tx_bytes; 4919a391c7bSWingMan Kwok u32 tx_64B_frames; 4929a391c7bSWingMan Kwok u32 tx_65_to_127B_frames; 4939a391c7bSWingMan Kwok u32 tx_128_to_255B_frames; 4949a391c7bSWingMan Kwok u32 tx_256_to_511B_frames; 4959a391c7bSWingMan Kwok u32 tx_512_to_1023B_frames; 4969a391c7bSWingMan Kwok u32 tx_1024B_frames; 4979a391c7bSWingMan Kwok u32 net_bytes; 4989a391c7bSWingMan Kwok u32 rx_bottom_fifo_drop; 4999a391c7bSWingMan Kwok u32 rx_port_mask_drop; 5009a391c7bSWingMan Kwok u32 rx_top_fifo_drop; 5019a391c7bSWingMan Kwok u32 ale_rate_limit_drop; 5029a391c7bSWingMan Kwok u32 ale_vid_ingress_drop; 5039a391c7bSWingMan Kwok u32 ale_da_eq_sa_drop; 5049a391c7bSWingMan Kwok u32 __rsvd_0[3]; 5059a391c7bSWingMan Kwok u32 ale_unknown_ucast; 5069a391c7bSWingMan Kwok u32 ale_unknown_ucast_bytes; 5079a391c7bSWingMan Kwok u32 ale_unknown_mcast; 5089a391c7bSWingMan Kwok u32 ale_unknown_mcast_bytes; 5099a391c7bSWingMan Kwok u32 ale_unknown_bcast; 5109a391c7bSWingMan Kwok u32 ale_unknown_bcast_bytes; 5119a391c7bSWingMan Kwok u32 ale_pol_match; 5129a391c7bSWingMan Kwok u32 ale_pol_match_red; /* NU */ 5139a391c7bSWingMan Kwok u32 ale_pol_match_yellow; /* NU */ 5149a391c7bSWingMan Kwok u32 __rsvd_1[44]; 5159a391c7bSWingMan Kwok u32 tx_mem_protect_err; 5169a391c7bSWingMan Kwok /* following NU only */ 5179a391c7bSWingMan Kwok u32 tx_pri0; 5189a391c7bSWingMan Kwok u32 tx_pri1; 5199a391c7bSWingMan Kwok u32 tx_pri2; 5209a391c7bSWingMan Kwok u32 tx_pri3; 5219a391c7bSWingMan Kwok u32 tx_pri4; 5229a391c7bSWingMan Kwok u32 tx_pri5; 5239a391c7bSWingMan Kwok u32 tx_pri6; 5249a391c7bSWingMan Kwok u32 tx_pri7; 5259a391c7bSWingMan Kwok u32 tx_pri0_bcnt; 5269a391c7bSWingMan Kwok u32 tx_pri1_bcnt; 5279a391c7bSWingMan Kwok u32 tx_pri2_bcnt; 5289a391c7bSWingMan Kwok u32 tx_pri3_bcnt; 5299a391c7bSWingMan Kwok u32 tx_pri4_bcnt; 5309a391c7bSWingMan Kwok u32 tx_pri5_bcnt; 5319a391c7bSWingMan Kwok u32 tx_pri6_bcnt; 5329a391c7bSWingMan Kwok u32 tx_pri7_bcnt; 5339a391c7bSWingMan Kwok u32 tx_pri0_drop; 5349a391c7bSWingMan Kwok u32 tx_pri1_drop; 5359a391c7bSWingMan Kwok u32 tx_pri2_drop; 5369a391c7bSWingMan Kwok u32 tx_pri3_drop; 5379a391c7bSWingMan Kwok u32 tx_pri4_drop; 5389a391c7bSWingMan Kwok u32 tx_pri5_drop; 5399a391c7bSWingMan Kwok u32 tx_pri6_drop; 5409a391c7bSWingMan Kwok u32 tx_pri7_drop; 5419a391c7bSWingMan Kwok u32 tx_pri0_drop_bcnt; 5429a391c7bSWingMan Kwok u32 tx_pri1_drop_bcnt; 5439a391c7bSWingMan Kwok u32 tx_pri2_drop_bcnt; 5449a391c7bSWingMan Kwok u32 tx_pri3_drop_bcnt; 5459a391c7bSWingMan Kwok u32 tx_pri4_drop_bcnt; 5469a391c7bSWingMan Kwok u32 tx_pri5_drop_bcnt; 5479a391c7bSWingMan Kwok u32 tx_pri6_drop_bcnt; 5489a391c7bSWingMan Kwok u32 tx_pri7_drop_bcnt; 5499a391c7bSWingMan Kwok }; 5509a391c7bSWingMan Kwok 5519a391c7bSWingMan Kwok #define GBENU_HW_STATS_REG_MAP_SZ 0x200 5529a391c7bSWingMan Kwok 5536f8d3f33SWingman Kwok struct gbe_ss_regs { 5546f8d3f33SWingman Kwok u32 id_ver; 5556f8d3f33SWingman Kwok u32 synce_count; 5566f8d3f33SWingman Kwok u32 synce_mux; 5576f8d3f33SWingman Kwok }; 5586f8d3f33SWingman Kwok 5596f8d3f33SWingman Kwok struct gbe_ss_regs_ofs { 5606f8d3f33SWingman Kwok u16 id_ver; 5616f8d3f33SWingman Kwok u16 control; 5627771f2b4SMurali Karicheri u16 rgmii_status; /* 2U */ 5636f8d3f33SWingman Kwok }; 5646f8d3f33SWingman Kwok 5656f8d3f33SWingman Kwok struct gbe_switch_regs { 5666f8d3f33SWingman Kwok u32 id_ver; 5676f8d3f33SWingman Kwok u32 control; 5686f8d3f33SWingman Kwok u32 soft_reset; 5696f8d3f33SWingman Kwok u32 stat_port_en; 5706f8d3f33SWingman Kwok u32 ptype; 5716f8d3f33SWingman Kwok u32 soft_idle; 5726f8d3f33SWingman Kwok u32 thru_rate; 5736f8d3f33SWingman Kwok u32 gap_thresh; 5746f8d3f33SWingman Kwok u32 tx_start_wds; 5756f8d3f33SWingman Kwok u32 flow_control; 5766f8d3f33SWingman Kwok }; 5776f8d3f33SWingman Kwok 5786f8d3f33SWingman Kwok struct gbe_switch_regs_ofs { 5796f8d3f33SWingman Kwok u16 id_ver; 5806f8d3f33SWingman Kwok u16 control; 5816f8d3f33SWingman Kwok u16 soft_reset; 5826f8d3f33SWingman Kwok u16 emcontrol; 5836f8d3f33SWingman Kwok u16 stat_port_en; 5846f8d3f33SWingman Kwok u16 ptype; 5856f8d3f33SWingman Kwok u16 flow_control; 5866f8d3f33SWingman Kwok }; 5876f8d3f33SWingman Kwok 5886f8d3f33SWingman Kwok struct gbe_port_regs { 5896f8d3f33SWingman Kwok u32 max_blks; 5906f8d3f33SWingman Kwok u32 blk_cnt; 5916f8d3f33SWingman Kwok u32 port_vlan; 5926f8d3f33SWingman Kwok u32 tx_pri_map; 5936f8d3f33SWingman Kwok u32 sa_lo; 5946f8d3f33SWingman Kwok u32 sa_hi; 5956f8d3f33SWingman Kwok u32 ts_ctl; 5966f8d3f33SWingman Kwok u32 ts_seq_ltype; 5976f8d3f33SWingman Kwok u32 ts_vlan; 5986f8d3f33SWingman Kwok u32 ts_ctl_ltype2; 5996f8d3f33SWingman Kwok u32 ts_ctl2; 6006f8d3f33SWingman Kwok }; 6016f8d3f33SWingman Kwok 6026f8d3f33SWingman Kwok struct gbe_port_regs_ofs { 6036f8d3f33SWingman Kwok u16 port_vlan; 6046f8d3f33SWingman Kwok u16 tx_pri_map; 60565c45064SMurali Karicheri u16 rx_pri_map; 6066f8d3f33SWingman Kwok u16 sa_lo; 6076f8d3f33SWingman Kwok u16 sa_hi; 6086f8d3f33SWingman Kwok u16 ts_ctl; 6096f8d3f33SWingman Kwok u16 ts_seq_ltype; 6106f8d3f33SWingman Kwok u16 ts_vlan; 6116f8d3f33SWingman Kwok u16 ts_ctl_ltype2; 6126f8d3f33SWingman Kwok u16 ts_ctl2; 6139a391c7bSWingMan Kwok u16 rx_maxlen; /* 2U, NU */ 6146f8d3f33SWingman Kwok }; 6156f8d3f33SWingman Kwok 6166f8d3f33SWingman Kwok struct gbe_host_port_regs { 6176f8d3f33SWingman Kwok u32 src_id; 6186f8d3f33SWingman Kwok u32 port_vlan; 6196f8d3f33SWingman Kwok u32 rx_pri_map; 6206f8d3f33SWingman Kwok u32 rx_maxlen; 6216f8d3f33SWingman Kwok }; 6226f8d3f33SWingman Kwok 6236f8d3f33SWingman Kwok struct gbe_host_port_regs_ofs { 6246f8d3f33SWingman Kwok u16 port_vlan; 6256f8d3f33SWingman Kwok u16 tx_pri_map; 6266f8d3f33SWingman Kwok u16 rx_maxlen; 6276f8d3f33SWingman Kwok }; 6286f8d3f33SWingman Kwok 6296f8d3f33SWingman Kwok struct gbe_emac_regs { 6306f8d3f33SWingman Kwok u32 id_ver; 6316f8d3f33SWingman Kwok u32 mac_control; 6326f8d3f33SWingman Kwok u32 mac_status; 6336f8d3f33SWingman Kwok u32 soft_reset; 6346f8d3f33SWingman Kwok u32 rx_maxlen; 6356f8d3f33SWingman Kwok u32 __reserved_0; 6366f8d3f33SWingman Kwok u32 rx_pause; 6376f8d3f33SWingman Kwok u32 tx_pause; 6386f8d3f33SWingman Kwok u32 __reserved_1; 6396f8d3f33SWingman Kwok u32 rx_pri_map; 6406f8d3f33SWingman Kwok u32 rsvd[6]; 6416f8d3f33SWingman Kwok }; 6426f8d3f33SWingman Kwok 6436f8d3f33SWingman Kwok struct gbe_emac_regs_ofs { 6446f8d3f33SWingman Kwok u16 mac_control; 6456f8d3f33SWingman Kwok u16 soft_reset; 6466f8d3f33SWingman Kwok u16 rx_maxlen; 6476f8d3f33SWingman Kwok }; 6486f8d3f33SWingman Kwok 6496f8d3f33SWingman Kwok struct gbe_hw_stats { 6506f8d3f33SWingman Kwok u32 rx_good_frames; 6516f8d3f33SWingman Kwok u32 rx_broadcast_frames; 6526f8d3f33SWingman Kwok u32 rx_multicast_frames; 6536f8d3f33SWingman Kwok u32 rx_pause_frames; 6546f8d3f33SWingman Kwok u32 rx_crc_errors; 6556f8d3f33SWingman Kwok u32 rx_align_code_errors; 6566f8d3f33SWingman Kwok u32 rx_oversized_frames; 6576f8d3f33SWingman Kwok u32 rx_jabber_frames; 6586f8d3f33SWingman Kwok u32 rx_undersized_frames; 6596f8d3f33SWingman Kwok u32 rx_fragments; 6606f8d3f33SWingman Kwok u32 __pad_0[2]; 6616f8d3f33SWingman Kwok u32 rx_bytes; 6626f8d3f33SWingman Kwok u32 tx_good_frames; 6636f8d3f33SWingman Kwok u32 tx_broadcast_frames; 6646f8d3f33SWingman Kwok u32 tx_multicast_frames; 6656f8d3f33SWingman Kwok u32 tx_pause_frames; 6666f8d3f33SWingman Kwok u32 tx_deferred_frames; 6676f8d3f33SWingman Kwok u32 tx_collision_frames; 6686f8d3f33SWingman Kwok u32 tx_single_coll_frames; 6696f8d3f33SWingman Kwok u32 tx_mult_coll_frames; 6706f8d3f33SWingman Kwok u32 tx_excessive_collisions; 6716f8d3f33SWingman Kwok u32 tx_late_collisions; 6726f8d3f33SWingman Kwok u32 tx_underrun; 6736f8d3f33SWingman Kwok u32 tx_carrier_sense_errors; 6746f8d3f33SWingman Kwok u32 tx_bytes; 6756f8d3f33SWingman Kwok u32 tx_64byte_frames; 6766f8d3f33SWingman Kwok u32 tx_65_to_127byte_frames; 6776f8d3f33SWingman Kwok u32 tx_128_to_255byte_frames; 6786f8d3f33SWingman Kwok u32 tx_256_to_511byte_frames; 6796f8d3f33SWingman Kwok u32 tx_512_to_1023byte_frames; 6806f8d3f33SWingman Kwok u32 tx_1024byte_frames; 6816f8d3f33SWingman Kwok u32 net_bytes; 6826f8d3f33SWingman Kwok u32 rx_sof_overruns; 6836f8d3f33SWingman Kwok u32 rx_mof_overruns; 6846f8d3f33SWingman Kwok u32 rx_dma_overruns; 6856f8d3f33SWingman Kwok }; 6866f8d3f33SWingman Kwok 6879a391c7bSWingMan Kwok #define GBE_MAX_HW_STAT_MODS 9 6886f8d3f33SWingman Kwok #define GBE_HW_STATS_REG_MAP_SZ 0x100 6896f8d3f33SWingman Kwok 6906246168bSWingMan Kwok struct ts_ctl { 6916246168bSWingMan Kwok int uni; 6926246168bSWingMan Kwok u8 dst_port_map; 6936246168bSWingMan Kwok u8 maddr_map; 6946246168bSWingMan Kwok u8 ts_mcast_type; 6956246168bSWingMan Kwok }; 6966246168bSWingMan Kwok 6976f8d3f33SWingman Kwok struct gbe_slave { 6986f8d3f33SWingman Kwok void __iomem *port_regs; 6996f8d3f33SWingman Kwok void __iomem *emac_regs; 7006f8d3f33SWingman Kwok struct gbe_port_regs_ofs port_regs_ofs; 7016f8d3f33SWingman Kwok struct gbe_emac_regs_ofs emac_regs_ofs; 7026f8d3f33SWingman Kwok int slave_num; /* 0 based logical number */ 7036f8d3f33SWingman Kwok int port_num; /* actual port number */ 7046f8d3f33SWingman Kwok atomic_t link_state; 7056f8d3f33SWingman Kwok bool open; 7066f8d3f33SWingman Kwok struct phy_device *phy; 7076f8d3f33SWingman Kwok u32 link_interface; 7086f8d3f33SWingman Kwok u32 mac_control; 7096f8d3f33SWingman Kwok u8 phy_port_t; 7106f8d3f33SWingman Kwok struct device_node *phy_node; 7116246168bSWingMan Kwok struct ts_ctl ts_ctl; 7126f8d3f33SWingman Kwok struct list_head slave_list; 7136f8d3f33SWingman Kwok }; 7146f8d3f33SWingman Kwok 7156f8d3f33SWingman Kwok struct gbe_priv { 7166f8d3f33SWingman Kwok struct device *dev; 7176f8d3f33SWingman Kwok struct netcp_device *netcp_device; 7186f8d3f33SWingman Kwok struct timer_list timer; 7196f8d3f33SWingman Kwok u32 num_slaves; 7206f8d3f33SWingman Kwok u32 ale_entries; 7216f8d3f33SWingman Kwok u32 ale_ports; 7226f8d3f33SWingman Kwok bool enable_ale; 7239a391c7bSWingMan Kwok u8 max_num_slaves; 7249a391c7bSWingMan Kwok u8 max_num_ports; /* max_num_slaves + 1 */ 725489e8a2fSWingMan Kwok u8 num_stats_mods; 7266f8d3f33SWingman Kwok struct netcp_tx_pipe tx_pipe; 7276f8d3f33SWingman Kwok 7286f8d3f33SWingman Kwok int host_port; 7296f8d3f33SWingman Kwok u32 rx_packet_max; 7306f8d3f33SWingman Kwok u32 ss_version; 7319a391c7bSWingMan Kwok u32 stats_en_mask; 7326f8d3f33SWingman Kwok 7336f8d3f33SWingman Kwok void __iomem *ss_regs; 7346f8d3f33SWingman Kwok void __iomem *switch_regs; 7356f8d3f33SWingman Kwok void __iomem *host_port_regs; 7366f8d3f33SWingman Kwok void __iomem *ale_reg; 7376246168bSWingMan Kwok void __iomem *cpts_reg; 7386f8d3f33SWingman Kwok void __iomem *sgmii_port_regs; 7396f8d3f33SWingman Kwok void __iomem *sgmii_port34_regs; 7406f8d3f33SWingman Kwok void __iomem *xgbe_serdes_regs; 7416f8d3f33SWingman Kwok void __iomem *hw_stats_regs[GBE_MAX_HW_STAT_MODS]; 7426f8d3f33SWingman Kwok 7436f8d3f33SWingman Kwok struct gbe_ss_regs_ofs ss_regs_ofs; 7446f8d3f33SWingman Kwok struct gbe_switch_regs_ofs switch_regs_ofs; 7456f8d3f33SWingman Kwok struct gbe_host_port_regs_ofs host_port_regs_ofs; 7466f8d3f33SWingman Kwok 7476f8d3f33SWingman Kwok struct cpsw_ale *ale; 7486f8d3f33SWingman Kwok unsigned int tx_queue_id; 7496f8d3f33SWingman Kwok const char *dma_chan_name; 7506f8d3f33SWingman Kwok 7516f8d3f33SWingman Kwok struct list_head gbe_intf_head; 7526f8d3f33SWingman Kwok struct list_head secondary_slaves; 7536f8d3f33SWingman Kwok struct net_device *dummy_ndev; 7546f8d3f33SWingman Kwok 7556f8d3f33SWingman Kwok u64 *hw_stats; 756489e8a2fSWingMan Kwok u32 *hw_stats_prev; 7576f8d3f33SWingman Kwok const struct netcp_ethtool_stat *et_stats; 7586f8d3f33SWingman Kwok int num_et_stats; 7596f8d3f33SWingman Kwok /* Lock for updating the hwstats */ 7606f8d3f33SWingman Kwok spinlock_t hw_stats_lock; 7616246168bSWingMan Kwok 7626246168bSWingMan Kwok int cpts_registered; 7636246168bSWingMan Kwok struct cpts *cpts; 7646f8d3f33SWingman Kwok }; 7656f8d3f33SWingman Kwok 7666f8d3f33SWingman Kwok struct gbe_intf { 7676f8d3f33SWingman Kwok struct net_device *ndev; 7686f8d3f33SWingman Kwok struct device *dev; 7696f8d3f33SWingman Kwok struct gbe_priv *gbe_dev; 7706f8d3f33SWingman Kwok struct netcp_tx_pipe tx_pipe; 7716f8d3f33SWingman Kwok struct gbe_slave *slave; 7726f8d3f33SWingman Kwok struct list_head gbe_intf_list; 7736f8d3f33SWingman Kwok unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; 7746f8d3f33SWingman Kwok }; 7756f8d3f33SWingman Kwok 7766f8d3f33SWingman Kwok static struct netcp_module gbe_module; 77790cff9e2SWingman Kwok static struct netcp_module xgbe_module; 7786f8d3f33SWingman Kwok 7796f8d3f33SWingman Kwok /* Statistic management */ 7806f8d3f33SWingman Kwok struct netcp_ethtool_stat { 7816f8d3f33SWingman Kwok char desc[ETH_GSTRING_LEN]; 7826f8d3f33SWingman Kwok int type; 7836f8d3f33SWingman Kwok u32 size; 7846f8d3f33SWingman Kwok int offset; 7856f8d3f33SWingman Kwok }; 7866f8d3f33SWingman Kwok 787da866ba0SKaricheri, Muralidharan #define GBE_STATSA_INFO(field) \ 788da866ba0SKaricheri, Muralidharan { \ 789da866ba0SKaricheri, Muralidharan "GBE_A:"#field, GBE_STATSA_MODULE, \ 7906f8d3f33SWingman Kwok FIELD_SIZEOF(struct gbe_hw_stats, field), \ 791da866ba0SKaricheri, Muralidharan offsetof(struct gbe_hw_stats, field) \ 792da866ba0SKaricheri, Muralidharan } 7936f8d3f33SWingman Kwok 794da866ba0SKaricheri, Muralidharan #define GBE_STATSB_INFO(field) \ 795da866ba0SKaricheri, Muralidharan { \ 796da866ba0SKaricheri, Muralidharan "GBE_B:"#field, GBE_STATSB_MODULE, \ 7976f8d3f33SWingman Kwok FIELD_SIZEOF(struct gbe_hw_stats, field), \ 798da866ba0SKaricheri, Muralidharan offsetof(struct gbe_hw_stats, field) \ 799da866ba0SKaricheri, Muralidharan } 8006f8d3f33SWingman Kwok 801da866ba0SKaricheri, Muralidharan #define GBE_STATSC_INFO(field) \ 802da866ba0SKaricheri, Muralidharan { \ 803da866ba0SKaricheri, Muralidharan "GBE_C:"#field, GBE_STATSC_MODULE, \ 8046f8d3f33SWingman Kwok FIELD_SIZEOF(struct gbe_hw_stats, field), \ 805da866ba0SKaricheri, Muralidharan offsetof(struct gbe_hw_stats, field) \ 806da866ba0SKaricheri, Muralidharan } 8076f8d3f33SWingman Kwok 808da866ba0SKaricheri, Muralidharan #define GBE_STATSD_INFO(field) \ 809da866ba0SKaricheri, Muralidharan { \ 810da866ba0SKaricheri, Muralidharan "GBE_D:"#field, GBE_STATSD_MODULE, \ 8116f8d3f33SWingman Kwok FIELD_SIZEOF(struct gbe_hw_stats, field), \ 812da866ba0SKaricheri, Muralidharan offsetof(struct gbe_hw_stats, field) \ 813da866ba0SKaricheri, Muralidharan } 8146f8d3f33SWingman Kwok 8156f8d3f33SWingman Kwok static const struct netcp_ethtool_stat gbe13_et_stats[] = { 8166f8d3f33SWingman Kwok /* GBE module A */ 817da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(rx_good_frames), 818da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(rx_broadcast_frames), 819da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(rx_multicast_frames), 820da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(rx_pause_frames), 821da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(rx_crc_errors), 822da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(rx_align_code_errors), 823da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(rx_oversized_frames), 824da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(rx_jabber_frames), 825da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(rx_undersized_frames), 826da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(rx_fragments), 827da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(rx_bytes), 828da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_good_frames), 829da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_broadcast_frames), 830da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_multicast_frames), 831da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_pause_frames), 832da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_deferred_frames), 833da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_collision_frames), 834da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_single_coll_frames), 835da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_mult_coll_frames), 836da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_excessive_collisions), 837da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_late_collisions), 838da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_underrun), 839da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_carrier_sense_errors), 840da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_bytes), 841da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_64byte_frames), 842da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_65_to_127byte_frames), 843da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_128_to_255byte_frames), 844da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_256_to_511byte_frames), 845da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_512_to_1023byte_frames), 846da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(tx_1024byte_frames), 847da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(net_bytes), 848da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(rx_sof_overruns), 849da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(rx_mof_overruns), 850da866ba0SKaricheri, Muralidharan GBE_STATSA_INFO(rx_dma_overruns), 8516f8d3f33SWingman Kwok /* GBE module B */ 852da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(rx_good_frames), 853da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(rx_broadcast_frames), 854da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(rx_multicast_frames), 855da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(rx_pause_frames), 856da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(rx_crc_errors), 857da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(rx_align_code_errors), 858da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(rx_oversized_frames), 859da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(rx_jabber_frames), 860da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(rx_undersized_frames), 861da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(rx_fragments), 862da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(rx_bytes), 863da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_good_frames), 864da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_broadcast_frames), 865da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_multicast_frames), 866da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_pause_frames), 867da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_deferred_frames), 868da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_collision_frames), 869da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_single_coll_frames), 870da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_mult_coll_frames), 871da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_excessive_collisions), 872da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_late_collisions), 873da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_underrun), 874da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_carrier_sense_errors), 875da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_bytes), 876da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_64byte_frames), 877da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_65_to_127byte_frames), 878da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_128_to_255byte_frames), 879da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_256_to_511byte_frames), 880da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_512_to_1023byte_frames), 881da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(tx_1024byte_frames), 882da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(net_bytes), 883da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(rx_sof_overruns), 884da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(rx_mof_overruns), 885da866ba0SKaricheri, Muralidharan GBE_STATSB_INFO(rx_dma_overruns), 8866f8d3f33SWingman Kwok /* GBE module C */ 887da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(rx_good_frames), 888da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(rx_broadcast_frames), 889da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(rx_multicast_frames), 890da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(rx_pause_frames), 891da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(rx_crc_errors), 892da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(rx_align_code_errors), 893da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(rx_oversized_frames), 894da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(rx_jabber_frames), 895da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(rx_undersized_frames), 896da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(rx_fragments), 897da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(rx_bytes), 898da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_good_frames), 899da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_broadcast_frames), 900da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_multicast_frames), 901da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_pause_frames), 902da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_deferred_frames), 903da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_collision_frames), 904da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_single_coll_frames), 905da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_mult_coll_frames), 906da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_excessive_collisions), 907da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_late_collisions), 908da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_underrun), 909da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_carrier_sense_errors), 910da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_bytes), 911da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_64byte_frames), 912da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_65_to_127byte_frames), 913da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_128_to_255byte_frames), 914da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_256_to_511byte_frames), 915da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_512_to_1023byte_frames), 916da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(tx_1024byte_frames), 917da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(net_bytes), 918da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(rx_sof_overruns), 919da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(rx_mof_overruns), 920da866ba0SKaricheri, Muralidharan GBE_STATSC_INFO(rx_dma_overruns), 9216f8d3f33SWingman Kwok /* GBE module D */ 922da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(rx_good_frames), 923da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(rx_broadcast_frames), 924da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(rx_multicast_frames), 925da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(rx_pause_frames), 926da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(rx_crc_errors), 927da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(rx_align_code_errors), 928da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(rx_oversized_frames), 929da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(rx_jabber_frames), 930da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(rx_undersized_frames), 931da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(rx_fragments), 932da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(rx_bytes), 933da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_good_frames), 934da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_broadcast_frames), 935da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_multicast_frames), 936da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_pause_frames), 937da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_deferred_frames), 938da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_collision_frames), 939da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_single_coll_frames), 940da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_mult_coll_frames), 941da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_excessive_collisions), 942da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_late_collisions), 943da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_underrun), 944da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_carrier_sense_errors), 945da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_bytes), 946da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_64byte_frames), 947da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_65_to_127byte_frames), 948da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_128_to_255byte_frames), 949da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_256_to_511byte_frames), 950da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_512_to_1023byte_frames), 951da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(tx_1024byte_frames), 952da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(net_bytes), 953da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(rx_sof_overruns), 954da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(rx_mof_overruns), 955da866ba0SKaricheri, Muralidharan GBE_STATSD_INFO(rx_dma_overruns), 9566f8d3f33SWingman Kwok }; 9576f8d3f33SWingman Kwok 9589a391c7bSWingMan Kwok /* This is the size of entries in GBENU_STATS_HOST */ 9595be4001eSWingMan Kwok #define GBENU_ET_STATS_HOST_SIZE 52 9609a391c7bSWingMan Kwok 9619a391c7bSWingMan Kwok #define GBENU_STATS_HOST(field) \ 9629a391c7bSWingMan Kwok { \ 9639a391c7bSWingMan Kwok "GBE_HOST:"#field, GBENU_STATS0_MODULE, \ 9649a391c7bSWingMan Kwok FIELD_SIZEOF(struct gbenu_hw_stats, field), \ 9659a391c7bSWingMan Kwok offsetof(struct gbenu_hw_stats, field) \ 9669a391c7bSWingMan Kwok } 9679a391c7bSWingMan Kwok 9685be4001eSWingMan Kwok /* This is the size of entries in GBENU_STATS_PORT */ 9695be4001eSWingMan Kwok #define GBENU_ET_STATS_PORT_SIZE 65 9709a391c7bSWingMan Kwok 9719a391c7bSWingMan Kwok #define GBENU_STATS_P1(field) \ 9729a391c7bSWingMan Kwok { \ 9739a391c7bSWingMan Kwok "GBE_P1:"#field, GBENU_STATS1_MODULE, \ 9749a391c7bSWingMan Kwok FIELD_SIZEOF(struct gbenu_hw_stats, field), \ 9759a391c7bSWingMan Kwok offsetof(struct gbenu_hw_stats, field) \ 9769a391c7bSWingMan Kwok } 9779a391c7bSWingMan Kwok 9789a391c7bSWingMan Kwok #define GBENU_STATS_P2(field) \ 9799a391c7bSWingMan Kwok { \ 9809a391c7bSWingMan Kwok "GBE_P2:"#field, GBENU_STATS2_MODULE, \ 9819a391c7bSWingMan Kwok FIELD_SIZEOF(struct gbenu_hw_stats, field), \ 9829a391c7bSWingMan Kwok offsetof(struct gbenu_hw_stats, field) \ 9839a391c7bSWingMan Kwok } 9849a391c7bSWingMan Kwok 9859a391c7bSWingMan Kwok #define GBENU_STATS_P3(field) \ 9869a391c7bSWingMan Kwok { \ 9879a391c7bSWingMan Kwok "GBE_P3:"#field, GBENU_STATS3_MODULE, \ 9889a391c7bSWingMan Kwok FIELD_SIZEOF(struct gbenu_hw_stats, field), \ 9899a391c7bSWingMan Kwok offsetof(struct gbenu_hw_stats, field) \ 9909a391c7bSWingMan Kwok } 9919a391c7bSWingMan Kwok 9929a391c7bSWingMan Kwok #define GBENU_STATS_P4(field) \ 9939a391c7bSWingMan Kwok { \ 9949a391c7bSWingMan Kwok "GBE_P4:"#field, GBENU_STATS4_MODULE, \ 9959a391c7bSWingMan Kwok FIELD_SIZEOF(struct gbenu_hw_stats, field), \ 9969a391c7bSWingMan Kwok offsetof(struct gbenu_hw_stats, field) \ 9979a391c7bSWingMan Kwok } 9989a391c7bSWingMan Kwok 9999a391c7bSWingMan Kwok #define GBENU_STATS_P5(field) \ 10009a391c7bSWingMan Kwok { \ 10019a391c7bSWingMan Kwok "GBE_P5:"#field, GBENU_STATS5_MODULE, \ 10029a391c7bSWingMan Kwok FIELD_SIZEOF(struct gbenu_hw_stats, field), \ 10039a391c7bSWingMan Kwok offsetof(struct gbenu_hw_stats, field) \ 10049a391c7bSWingMan Kwok } 10059a391c7bSWingMan Kwok 10069a391c7bSWingMan Kwok #define GBENU_STATS_P6(field) \ 10079a391c7bSWingMan Kwok { \ 10089a391c7bSWingMan Kwok "GBE_P6:"#field, GBENU_STATS6_MODULE, \ 10099a391c7bSWingMan Kwok FIELD_SIZEOF(struct gbenu_hw_stats, field), \ 10109a391c7bSWingMan Kwok offsetof(struct gbenu_hw_stats, field) \ 10119a391c7bSWingMan Kwok } 10129a391c7bSWingMan Kwok 10139a391c7bSWingMan Kwok #define GBENU_STATS_P7(field) \ 10149a391c7bSWingMan Kwok { \ 10159a391c7bSWingMan Kwok "GBE_P7:"#field, GBENU_STATS7_MODULE, \ 10169a391c7bSWingMan Kwok FIELD_SIZEOF(struct gbenu_hw_stats, field), \ 10179a391c7bSWingMan Kwok offsetof(struct gbenu_hw_stats, field) \ 10189a391c7bSWingMan Kwok } 10199a391c7bSWingMan Kwok 10209a391c7bSWingMan Kwok #define GBENU_STATS_P8(field) \ 10219a391c7bSWingMan Kwok { \ 10229a391c7bSWingMan Kwok "GBE_P8:"#field, GBENU_STATS8_MODULE, \ 10239a391c7bSWingMan Kwok FIELD_SIZEOF(struct gbenu_hw_stats, field), \ 10249a391c7bSWingMan Kwok offsetof(struct gbenu_hw_stats, field) \ 10259a391c7bSWingMan Kwok } 10269a391c7bSWingMan Kwok 10279a391c7bSWingMan Kwok static const struct netcp_ethtool_stat gbenu_et_stats[] = { 10289a391c7bSWingMan Kwok /* GBENU Host Module */ 10299a391c7bSWingMan Kwok GBENU_STATS_HOST(rx_good_frames), 10309a391c7bSWingMan Kwok GBENU_STATS_HOST(rx_broadcast_frames), 10319a391c7bSWingMan Kwok GBENU_STATS_HOST(rx_multicast_frames), 10329a391c7bSWingMan Kwok GBENU_STATS_HOST(rx_crc_errors), 10339a391c7bSWingMan Kwok GBENU_STATS_HOST(rx_oversized_frames), 10349a391c7bSWingMan Kwok GBENU_STATS_HOST(rx_undersized_frames), 10359a391c7bSWingMan Kwok GBENU_STATS_HOST(ale_drop), 10369a391c7bSWingMan Kwok GBENU_STATS_HOST(ale_overrun_drop), 10379a391c7bSWingMan Kwok GBENU_STATS_HOST(rx_bytes), 10389a391c7bSWingMan Kwok GBENU_STATS_HOST(tx_good_frames), 10399a391c7bSWingMan Kwok GBENU_STATS_HOST(tx_broadcast_frames), 10409a391c7bSWingMan Kwok GBENU_STATS_HOST(tx_multicast_frames), 10419a391c7bSWingMan Kwok GBENU_STATS_HOST(tx_bytes), 10429a391c7bSWingMan Kwok GBENU_STATS_HOST(tx_64B_frames), 10439a391c7bSWingMan Kwok GBENU_STATS_HOST(tx_65_to_127B_frames), 10449a391c7bSWingMan Kwok GBENU_STATS_HOST(tx_128_to_255B_frames), 10459a391c7bSWingMan Kwok GBENU_STATS_HOST(tx_256_to_511B_frames), 10469a391c7bSWingMan Kwok GBENU_STATS_HOST(tx_512_to_1023B_frames), 10479a391c7bSWingMan Kwok GBENU_STATS_HOST(tx_1024B_frames), 10489a391c7bSWingMan Kwok GBENU_STATS_HOST(net_bytes), 10499a391c7bSWingMan Kwok GBENU_STATS_HOST(rx_bottom_fifo_drop), 10509a391c7bSWingMan Kwok GBENU_STATS_HOST(rx_port_mask_drop), 10519a391c7bSWingMan Kwok GBENU_STATS_HOST(rx_top_fifo_drop), 10529a391c7bSWingMan Kwok GBENU_STATS_HOST(ale_rate_limit_drop), 10539a391c7bSWingMan Kwok GBENU_STATS_HOST(ale_vid_ingress_drop), 10549a391c7bSWingMan Kwok GBENU_STATS_HOST(ale_da_eq_sa_drop), 10559a391c7bSWingMan Kwok GBENU_STATS_HOST(ale_unknown_ucast), 10569a391c7bSWingMan Kwok GBENU_STATS_HOST(ale_unknown_ucast_bytes), 10579a391c7bSWingMan Kwok GBENU_STATS_HOST(ale_unknown_mcast), 10589a391c7bSWingMan Kwok GBENU_STATS_HOST(ale_unknown_mcast_bytes), 10599a391c7bSWingMan Kwok GBENU_STATS_HOST(ale_unknown_bcast), 10609a391c7bSWingMan Kwok GBENU_STATS_HOST(ale_unknown_bcast_bytes), 10615be4001eSWingMan Kwok GBENU_STATS_HOST(ale_pol_match), 10625be4001eSWingMan Kwok GBENU_STATS_HOST(ale_pol_match_red), 10635be4001eSWingMan Kwok GBENU_STATS_HOST(ale_pol_match_yellow), 10649a391c7bSWingMan Kwok GBENU_STATS_HOST(tx_mem_protect_err), 10655be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri0_drop), 10665be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri1_drop), 10675be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri2_drop), 10685be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri3_drop), 10695be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri4_drop), 10705be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri5_drop), 10715be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri6_drop), 10725be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri7_drop), 10735be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri0_drop_bcnt), 10745be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri1_drop_bcnt), 10755be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri2_drop_bcnt), 10765be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri3_drop_bcnt), 10775be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri4_drop_bcnt), 10785be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri5_drop_bcnt), 10795be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri6_drop_bcnt), 10805be4001eSWingMan Kwok GBENU_STATS_HOST(tx_pri7_drop_bcnt), 10819a391c7bSWingMan Kwok /* GBENU Module 1 */ 10829a391c7bSWingMan Kwok GBENU_STATS_P1(rx_good_frames), 10839a391c7bSWingMan Kwok GBENU_STATS_P1(rx_broadcast_frames), 10849a391c7bSWingMan Kwok GBENU_STATS_P1(rx_multicast_frames), 10859a391c7bSWingMan Kwok GBENU_STATS_P1(rx_pause_frames), 10869a391c7bSWingMan Kwok GBENU_STATS_P1(rx_crc_errors), 10879a391c7bSWingMan Kwok GBENU_STATS_P1(rx_align_code_errors), 10889a391c7bSWingMan Kwok GBENU_STATS_P1(rx_oversized_frames), 10899a391c7bSWingMan Kwok GBENU_STATS_P1(rx_jabber_frames), 10909a391c7bSWingMan Kwok GBENU_STATS_P1(rx_undersized_frames), 10919a391c7bSWingMan Kwok GBENU_STATS_P1(rx_fragments), 10929a391c7bSWingMan Kwok GBENU_STATS_P1(ale_drop), 10939a391c7bSWingMan Kwok GBENU_STATS_P1(ale_overrun_drop), 10949a391c7bSWingMan Kwok GBENU_STATS_P1(rx_bytes), 10959a391c7bSWingMan Kwok GBENU_STATS_P1(tx_good_frames), 10969a391c7bSWingMan Kwok GBENU_STATS_P1(tx_broadcast_frames), 10979a391c7bSWingMan Kwok GBENU_STATS_P1(tx_multicast_frames), 10989a391c7bSWingMan Kwok GBENU_STATS_P1(tx_pause_frames), 10999a391c7bSWingMan Kwok GBENU_STATS_P1(tx_deferred_frames), 11009a391c7bSWingMan Kwok GBENU_STATS_P1(tx_collision_frames), 11019a391c7bSWingMan Kwok GBENU_STATS_P1(tx_single_coll_frames), 11029a391c7bSWingMan Kwok GBENU_STATS_P1(tx_mult_coll_frames), 11039a391c7bSWingMan Kwok GBENU_STATS_P1(tx_excessive_collisions), 11049a391c7bSWingMan Kwok GBENU_STATS_P1(tx_late_collisions), 11059a391c7bSWingMan Kwok GBENU_STATS_P1(rx_ipg_error), 11069a391c7bSWingMan Kwok GBENU_STATS_P1(tx_carrier_sense_errors), 11079a391c7bSWingMan Kwok GBENU_STATS_P1(tx_bytes), 11089a391c7bSWingMan Kwok GBENU_STATS_P1(tx_64B_frames), 11099a391c7bSWingMan Kwok GBENU_STATS_P1(tx_65_to_127B_frames), 11109a391c7bSWingMan Kwok GBENU_STATS_P1(tx_128_to_255B_frames), 11119a391c7bSWingMan Kwok GBENU_STATS_P1(tx_256_to_511B_frames), 11129a391c7bSWingMan Kwok GBENU_STATS_P1(tx_512_to_1023B_frames), 11139a391c7bSWingMan Kwok GBENU_STATS_P1(tx_1024B_frames), 11149a391c7bSWingMan Kwok GBENU_STATS_P1(net_bytes), 11159a391c7bSWingMan Kwok GBENU_STATS_P1(rx_bottom_fifo_drop), 11169a391c7bSWingMan Kwok GBENU_STATS_P1(rx_port_mask_drop), 11179a391c7bSWingMan Kwok GBENU_STATS_P1(rx_top_fifo_drop), 11189a391c7bSWingMan Kwok GBENU_STATS_P1(ale_rate_limit_drop), 11199a391c7bSWingMan Kwok GBENU_STATS_P1(ale_vid_ingress_drop), 11209a391c7bSWingMan Kwok GBENU_STATS_P1(ale_da_eq_sa_drop), 11219a391c7bSWingMan Kwok GBENU_STATS_P1(ale_unknown_ucast), 11229a391c7bSWingMan Kwok GBENU_STATS_P1(ale_unknown_ucast_bytes), 11239a391c7bSWingMan Kwok GBENU_STATS_P1(ale_unknown_mcast), 11249a391c7bSWingMan Kwok GBENU_STATS_P1(ale_unknown_mcast_bytes), 11259a391c7bSWingMan Kwok GBENU_STATS_P1(ale_unknown_bcast), 11269a391c7bSWingMan Kwok GBENU_STATS_P1(ale_unknown_bcast_bytes), 11275be4001eSWingMan Kwok GBENU_STATS_P1(ale_pol_match), 11285be4001eSWingMan Kwok GBENU_STATS_P1(ale_pol_match_red), 11295be4001eSWingMan Kwok GBENU_STATS_P1(ale_pol_match_yellow), 11309a391c7bSWingMan Kwok GBENU_STATS_P1(tx_mem_protect_err), 11315be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri0_drop), 11325be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri1_drop), 11335be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri2_drop), 11345be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri3_drop), 11355be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri4_drop), 11365be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri5_drop), 11375be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri6_drop), 11385be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri7_drop), 11395be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri0_drop_bcnt), 11405be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri1_drop_bcnt), 11415be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri2_drop_bcnt), 11425be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri3_drop_bcnt), 11435be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri4_drop_bcnt), 11445be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri5_drop_bcnt), 11455be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri6_drop_bcnt), 11465be4001eSWingMan Kwok GBENU_STATS_P1(tx_pri7_drop_bcnt), 11479a391c7bSWingMan Kwok /* GBENU Module 2 */ 11489a391c7bSWingMan Kwok GBENU_STATS_P2(rx_good_frames), 11499a391c7bSWingMan Kwok GBENU_STATS_P2(rx_broadcast_frames), 11509a391c7bSWingMan Kwok GBENU_STATS_P2(rx_multicast_frames), 11519a391c7bSWingMan Kwok GBENU_STATS_P2(rx_pause_frames), 11529a391c7bSWingMan Kwok GBENU_STATS_P2(rx_crc_errors), 11539a391c7bSWingMan Kwok GBENU_STATS_P2(rx_align_code_errors), 11549a391c7bSWingMan Kwok GBENU_STATS_P2(rx_oversized_frames), 11559a391c7bSWingMan Kwok GBENU_STATS_P2(rx_jabber_frames), 11569a391c7bSWingMan Kwok GBENU_STATS_P2(rx_undersized_frames), 11579a391c7bSWingMan Kwok GBENU_STATS_P2(rx_fragments), 11589a391c7bSWingMan Kwok GBENU_STATS_P2(ale_drop), 11599a391c7bSWingMan Kwok GBENU_STATS_P2(ale_overrun_drop), 11609a391c7bSWingMan Kwok GBENU_STATS_P2(rx_bytes), 11619a391c7bSWingMan Kwok GBENU_STATS_P2(tx_good_frames), 11629a391c7bSWingMan Kwok GBENU_STATS_P2(tx_broadcast_frames), 11639a391c7bSWingMan Kwok GBENU_STATS_P2(tx_multicast_frames), 11649a391c7bSWingMan Kwok GBENU_STATS_P2(tx_pause_frames), 11659a391c7bSWingMan Kwok GBENU_STATS_P2(tx_deferred_frames), 11669a391c7bSWingMan Kwok GBENU_STATS_P2(tx_collision_frames), 11679a391c7bSWingMan Kwok GBENU_STATS_P2(tx_single_coll_frames), 11689a391c7bSWingMan Kwok GBENU_STATS_P2(tx_mult_coll_frames), 11699a391c7bSWingMan Kwok GBENU_STATS_P2(tx_excessive_collisions), 11709a391c7bSWingMan Kwok GBENU_STATS_P2(tx_late_collisions), 11719a391c7bSWingMan Kwok GBENU_STATS_P2(rx_ipg_error), 11729a391c7bSWingMan Kwok GBENU_STATS_P2(tx_carrier_sense_errors), 11739a391c7bSWingMan Kwok GBENU_STATS_P2(tx_bytes), 11749a391c7bSWingMan Kwok GBENU_STATS_P2(tx_64B_frames), 11759a391c7bSWingMan Kwok GBENU_STATS_P2(tx_65_to_127B_frames), 11769a391c7bSWingMan Kwok GBENU_STATS_P2(tx_128_to_255B_frames), 11779a391c7bSWingMan Kwok GBENU_STATS_P2(tx_256_to_511B_frames), 11789a391c7bSWingMan Kwok GBENU_STATS_P2(tx_512_to_1023B_frames), 11799a391c7bSWingMan Kwok GBENU_STATS_P2(tx_1024B_frames), 11809a391c7bSWingMan Kwok GBENU_STATS_P2(net_bytes), 11819a391c7bSWingMan Kwok GBENU_STATS_P2(rx_bottom_fifo_drop), 11829a391c7bSWingMan Kwok GBENU_STATS_P2(rx_port_mask_drop), 11839a391c7bSWingMan Kwok GBENU_STATS_P2(rx_top_fifo_drop), 11849a391c7bSWingMan Kwok GBENU_STATS_P2(ale_rate_limit_drop), 11859a391c7bSWingMan Kwok GBENU_STATS_P2(ale_vid_ingress_drop), 11869a391c7bSWingMan Kwok GBENU_STATS_P2(ale_da_eq_sa_drop), 11879a391c7bSWingMan Kwok GBENU_STATS_P2(ale_unknown_ucast), 11889a391c7bSWingMan Kwok GBENU_STATS_P2(ale_unknown_ucast_bytes), 11899a391c7bSWingMan Kwok GBENU_STATS_P2(ale_unknown_mcast), 11909a391c7bSWingMan Kwok GBENU_STATS_P2(ale_unknown_mcast_bytes), 11919a391c7bSWingMan Kwok GBENU_STATS_P2(ale_unknown_bcast), 11929a391c7bSWingMan Kwok GBENU_STATS_P2(ale_unknown_bcast_bytes), 11935be4001eSWingMan Kwok GBENU_STATS_P2(ale_pol_match), 11945be4001eSWingMan Kwok GBENU_STATS_P2(ale_pol_match_red), 11955be4001eSWingMan Kwok GBENU_STATS_P2(ale_pol_match_yellow), 11969a391c7bSWingMan Kwok GBENU_STATS_P2(tx_mem_protect_err), 11975be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri0_drop), 11985be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri1_drop), 11995be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri2_drop), 12005be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri3_drop), 12015be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri4_drop), 12025be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri5_drop), 12035be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri6_drop), 12045be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri7_drop), 12055be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri0_drop_bcnt), 12065be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri1_drop_bcnt), 12075be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri2_drop_bcnt), 12085be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri3_drop_bcnt), 12095be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri4_drop_bcnt), 12105be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri5_drop_bcnt), 12115be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri6_drop_bcnt), 12125be4001eSWingMan Kwok GBENU_STATS_P2(tx_pri7_drop_bcnt), 12139a391c7bSWingMan Kwok /* GBENU Module 3 */ 12149a391c7bSWingMan Kwok GBENU_STATS_P3(rx_good_frames), 12159a391c7bSWingMan Kwok GBENU_STATS_P3(rx_broadcast_frames), 12169a391c7bSWingMan Kwok GBENU_STATS_P3(rx_multicast_frames), 12179a391c7bSWingMan Kwok GBENU_STATS_P3(rx_pause_frames), 12189a391c7bSWingMan Kwok GBENU_STATS_P3(rx_crc_errors), 12199a391c7bSWingMan Kwok GBENU_STATS_P3(rx_align_code_errors), 12209a391c7bSWingMan Kwok GBENU_STATS_P3(rx_oversized_frames), 12219a391c7bSWingMan Kwok GBENU_STATS_P3(rx_jabber_frames), 12229a391c7bSWingMan Kwok GBENU_STATS_P3(rx_undersized_frames), 12239a391c7bSWingMan Kwok GBENU_STATS_P3(rx_fragments), 12249a391c7bSWingMan Kwok GBENU_STATS_P3(ale_drop), 12259a391c7bSWingMan Kwok GBENU_STATS_P3(ale_overrun_drop), 12269a391c7bSWingMan Kwok GBENU_STATS_P3(rx_bytes), 12279a391c7bSWingMan Kwok GBENU_STATS_P3(tx_good_frames), 12289a391c7bSWingMan Kwok GBENU_STATS_P3(tx_broadcast_frames), 12299a391c7bSWingMan Kwok GBENU_STATS_P3(tx_multicast_frames), 12309a391c7bSWingMan Kwok GBENU_STATS_P3(tx_pause_frames), 12319a391c7bSWingMan Kwok GBENU_STATS_P3(tx_deferred_frames), 12329a391c7bSWingMan Kwok GBENU_STATS_P3(tx_collision_frames), 12339a391c7bSWingMan Kwok GBENU_STATS_P3(tx_single_coll_frames), 12349a391c7bSWingMan Kwok GBENU_STATS_P3(tx_mult_coll_frames), 12359a391c7bSWingMan Kwok GBENU_STATS_P3(tx_excessive_collisions), 12369a391c7bSWingMan Kwok GBENU_STATS_P3(tx_late_collisions), 12379a391c7bSWingMan Kwok GBENU_STATS_P3(rx_ipg_error), 12389a391c7bSWingMan Kwok GBENU_STATS_P3(tx_carrier_sense_errors), 12399a391c7bSWingMan Kwok GBENU_STATS_P3(tx_bytes), 12409a391c7bSWingMan Kwok GBENU_STATS_P3(tx_64B_frames), 12419a391c7bSWingMan Kwok GBENU_STATS_P3(tx_65_to_127B_frames), 12429a391c7bSWingMan Kwok GBENU_STATS_P3(tx_128_to_255B_frames), 12439a391c7bSWingMan Kwok GBENU_STATS_P3(tx_256_to_511B_frames), 12449a391c7bSWingMan Kwok GBENU_STATS_P3(tx_512_to_1023B_frames), 12459a391c7bSWingMan Kwok GBENU_STATS_P3(tx_1024B_frames), 12469a391c7bSWingMan Kwok GBENU_STATS_P3(net_bytes), 12479a391c7bSWingMan Kwok GBENU_STATS_P3(rx_bottom_fifo_drop), 12489a391c7bSWingMan Kwok GBENU_STATS_P3(rx_port_mask_drop), 12499a391c7bSWingMan Kwok GBENU_STATS_P3(rx_top_fifo_drop), 12509a391c7bSWingMan Kwok GBENU_STATS_P3(ale_rate_limit_drop), 12519a391c7bSWingMan Kwok GBENU_STATS_P3(ale_vid_ingress_drop), 12529a391c7bSWingMan Kwok GBENU_STATS_P3(ale_da_eq_sa_drop), 12539a391c7bSWingMan Kwok GBENU_STATS_P3(ale_unknown_ucast), 12549a391c7bSWingMan Kwok GBENU_STATS_P3(ale_unknown_ucast_bytes), 12559a391c7bSWingMan Kwok GBENU_STATS_P3(ale_unknown_mcast), 12569a391c7bSWingMan Kwok GBENU_STATS_P3(ale_unknown_mcast_bytes), 12579a391c7bSWingMan Kwok GBENU_STATS_P3(ale_unknown_bcast), 12589a391c7bSWingMan Kwok GBENU_STATS_P3(ale_unknown_bcast_bytes), 12595be4001eSWingMan Kwok GBENU_STATS_P3(ale_pol_match), 12605be4001eSWingMan Kwok GBENU_STATS_P3(ale_pol_match_red), 12615be4001eSWingMan Kwok GBENU_STATS_P3(ale_pol_match_yellow), 12629a391c7bSWingMan Kwok GBENU_STATS_P3(tx_mem_protect_err), 12635be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri0_drop), 12645be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri1_drop), 12655be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri2_drop), 12665be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri3_drop), 12675be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri4_drop), 12685be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri5_drop), 12695be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri6_drop), 12705be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri7_drop), 12715be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri0_drop_bcnt), 12725be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri1_drop_bcnt), 12735be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri2_drop_bcnt), 12745be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri3_drop_bcnt), 12755be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri4_drop_bcnt), 12765be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri5_drop_bcnt), 12775be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri6_drop_bcnt), 12785be4001eSWingMan Kwok GBENU_STATS_P3(tx_pri7_drop_bcnt), 12799a391c7bSWingMan Kwok /* GBENU Module 4 */ 12809a391c7bSWingMan Kwok GBENU_STATS_P4(rx_good_frames), 12819a391c7bSWingMan Kwok GBENU_STATS_P4(rx_broadcast_frames), 12829a391c7bSWingMan Kwok GBENU_STATS_P4(rx_multicast_frames), 12839a391c7bSWingMan Kwok GBENU_STATS_P4(rx_pause_frames), 12849a391c7bSWingMan Kwok GBENU_STATS_P4(rx_crc_errors), 12859a391c7bSWingMan Kwok GBENU_STATS_P4(rx_align_code_errors), 12869a391c7bSWingMan Kwok GBENU_STATS_P4(rx_oversized_frames), 12879a391c7bSWingMan Kwok GBENU_STATS_P4(rx_jabber_frames), 12889a391c7bSWingMan Kwok GBENU_STATS_P4(rx_undersized_frames), 12899a391c7bSWingMan Kwok GBENU_STATS_P4(rx_fragments), 12909a391c7bSWingMan Kwok GBENU_STATS_P4(ale_drop), 12919a391c7bSWingMan Kwok GBENU_STATS_P4(ale_overrun_drop), 12929a391c7bSWingMan Kwok GBENU_STATS_P4(rx_bytes), 12939a391c7bSWingMan Kwok GBENU_STATS_P4(tx_good_frames), 12949a391c7bSWingMan Kwok GBENU_STATS_P4(tx_broadcast_frames), 12959a391c7bSWingMan Kwok GBENU_STATS_P4(tx_multicast_frames), 12969a391c7bSWingMan Kwok GBENU_STATS_P4(tx_pause_frames), 12979a391c7bSWingMan Kwok GBENU_STATS_P4(tx_deferred_frames), 12989a391c7bSWingMan Kwok GBENU_STATS_P4(tx_collision_frames), 12999a391c7bSWingMan Kwok GBENU_STATS_P4(tx_single_coll_frames), 13009a391c7bSWingMan Kwok GBENU_STATS_P4(tx_mult_coll_frames), 13019a391c7bSWingMan Kwok GBENU_STATS_P4(tx_excessive_collisions), 13029a391c7bSWingMan Kwok GBENU_STATS_P4(tx_late_collisions), 13039a391c7bSWingMan Kwok GBENU_STATS_P4(rx_ipg_error), 13049a391c7bSWingMan Kwok GBENU_STATS_P4(tx_carrier_sense_errors), 13059a391c7bSWingMan Kwok GBENU_STATS_P4(tx_bytes), 13069a391c7bSWingMan Kwok GBENU_STATS_P4(tx_64B_frames), 13079a391c7bSWingMan Kwok GBENU_STATS_P4(tx_65_to_127B_frames), 13089a391c7bSWingMan Kwok GBENU_STATS_P4(tx_128_to_255B_frames), 13099a391c7bSWingMan Kwok GBENU_STATS_P4(tx_256_to_511B_frames), 13109a391c7bSWingMan Kwok GBENU_STATS_P4(tx_512_to_1023B_frames), 13119a391c7bSWingMan Kwok GBENU_STATS_P4(tx_1024B_frames), 13129a391c7bSWingMan Kwok GBENU_STATS_P4(net_bytes), 13139a391c7bSWingMan Kwok GBENU_STATS_P4(rx_bottom_fifo_drop), 13149a391c7bSWingMan Kwok GBENU_STATS_P4(rx_port_mask_drop), 13159a391c7bSWingMan Kwok GBENU_STATS_P4(rx_top_fifo_drop), 13169a391c7bSWingMan Kwok GBENU_STATS_P4(ale_rate_limit_drop), 13179a391c7bSWingMan Kwok GBENU_STATS_P4(ale_vid_ingress_drop), 13189a391c7bSWingMan Kwok GBENU_STATS_P4(ale_da_eq_sa_drop), 13199a391c7bSWingMan Kwok GBENU_STATS_P4(ale_unknown_ucast), 13209a391c7bSWingMan Kwok GBENU_STATS_P4(ale_unknown_ucast_bytes), 13219a391c7bSWingMan Kwok GBENU_STATS_P4(ale_unknown_mcast), 13229a391c7bSWingMan Kwok GBENU_STATS_P4(ale_unknown_mcast_bytes), 13239a391c7bSWingMan Kwok GBENU_STATS_P4(ale_unknown_bcast), 13249a391c7bSWingMan Kwok GBENU_STATS_P4(ale_unknown_bcast_bytes), 13255be4001eSWingMan Kwok GBENU_STATS_P4(ale_pol_match), 13265be4001eSWingMan Kwok GBENU_STATS_P4(ale_pol_match_red), 13275be4001eSWingMan Kwok GBENU_STATS_P4(ale_pol_match_yellow), 13289a391c7bSWingMan Kwok GBENU_STATS_P4(tx_mem_protect_err), 13295be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri0_drop), 13305be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri1_drop), 13315be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri2_drop), 13325be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri3_drop), 13335be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri4_drop), 13345be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri5_drop), 13355be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri6_drop), 13365be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri7_drop), 13375be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri0_drop_bcnt), 13385be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri1_drop_bcnt), 13395be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri2_drop_bcnt), 13405be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri3_drop_bcnt), 13415be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri4_drop_bcnt), 13425be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri5_drop_bcnt), 13435be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri6_drop_bcnt), 13445be4001eSWingMan Kwok GBENU_STATS_P4(tx_pri7_drop_bcnt), 13459a391c7bSWingMan Kwok /* GBENU Module 5 */ 13469a391c7bSWingMan Kwok GBENU_STATS_P5(rx_good_frames), 13479a391c7bSWingMan Kwok GBENU_STATS_P5(rx_broadcast_frames), 13489a391c7bSWingMan Kwok GBENU_STATS_P5(rx_multicast_frames), 13499a391c7bSWingMan Kwok GBENU_STATS_P5(rx_pause_frames), 13509a391c7bSWingMan Kwok GBENU_STATS_P5(rx_crc_errors), 13519a391c7bSWingMan Kwok GBENU_STATS_P5(rx_align_code_errors), 13529a391c7bSWingMan Kwok GBENU_STATS_P5(rx_oversized_frames), 13539a391c7bSWingMan Kwok GBENU_STATS_P5(rx_jabber_frames), 13549a391c7bSWingMan Kwok GBENU_STATS_P5(rx_undersized_frames), 13559a391c7bSWingMan Kwok GBENU_STATS_P5(rx_fragments), 13569a391c7bSWingMan Kwok GBENU_STATS_P5(ale_drop), 13579a391c7bSWingMan Kwok GBENU_STATS_P5(ale_overrun_drop), 13589a391c7bSWingMan Kwok GBENU_STATS_P5(rx_bytes), 13599a391c7bSWingMan Kwok GBENU_STATS_P5(tx_good_frames), 13609a391c7bSWingMan Kwok GBENU_STATS_P5(tx_broadcast_frames), 13619a391c7bSWingMan Kwok GBENU_STATS_P5(tx_multicast_frames), 13629a391c7bSWingMan Kwok GBENU_STATS_P5(tx_pause_frames), 13639a391c7bSWingMan Kwok GBENU_STATS_P5(tx_deferred_frames), 13649a391c7bSWingMan Kwok GBENU_STATS_P5(tx_collision_frames), 13659a391c7bSWingMan Kwok GBENU_STATS_P5(tx_single_coll_frames), 13669a391c7bSWingMan Kwok GBENU_STATS_P5(tx_mult_coll_frames), 13679a391c7bSWingMan Kwok GBENU_STATS_P5(tx_excessive_collisions), 13689a391c7bSWingMan Kwok GBENU_STATS_P5(tx_late_collisions), 13699a391c7bSWingMan Kwok GBENU_STATS_P5(rx_ipg_error), 13709a391c7bSWingMan Kwok GBENU_STATS_P5(tx_carrier_sense_errors), 13719a391c7bSWingMan Kwok GBENU_STATS_P5(tx_bytes), 13729a391c7bSWingMan Kwok GBENU_STATS_P5(tx_64B_frames), 13739a391c7bSWingMan Kwok GBENU_STATS_P5(tx_65_to_127B_frames), 13749a391c7bSWingMan Kwok GBENU_STATS_P5(tx_128_to_255B_frames), 13759a391c7bSWingMan Kwok GBENU_STATS_P5(tx_256_to_511B_frames), 13769a391c7bSWingMan Kwok GBENU_STATS_P5(tx_512_to_1023B_frames), 13779a391c7bSWingMan Kwok GBENU_STATS_P5(tx_1024B_frames), 13789a391c7bSWingMan Kwok GBENU_STATS_P5(net_bytes), 13799a391c7bSWingMan Kwok GBENU_STATS_P5(rx_bottom_fifo_drop), 13809a391c7bSWingMan Kwok GBENU_STATS_P5(rx_port_mask_drop), 13819a391c7bSWingMan Kwok GBENU_STATS_P5(rx_top_fifo_drop), 13829a391c7bSWingMan Kwok GBENU_STATS_P5(ale_rate_limit_drop), 13839a391c7bSWingMan Kwok GBENU_STATS_P5(ale_vid_ingress_drop), 13849a391c7bSWingMan Kwok GBENU_STATS_P5(ale_da_eq_sa_drop), 13859a391c7bSWingMan Kwok GBENU_STATS_P5(ale_unknown_ucast), 13869a391c7bSWingMan Kwok GBENU_STATS_P5(ale_unknown_ucast_bytes), 13879a391c7bSWingMan Kwok GBENU_STATS_P5(ale_unknown_mcast), 13889a391c7bSWingMan Kwok GBENU_STATS_P5(ale_unknown_mcast_bytes), 13899a391c7bSWingMan Kwok GBENU_STATS_P5(ale_unknown_bcast), 13909a391c7bSWingMan Kwok GBENU_STATS_P5(ale_unknown_bcast_bytes), 13915be4001eSWingMan Kwok GBENU_STATS_P5(ale_pol_match), 13925be4001eSWingMan Kwok GBENU_STATS_P5(ale_pol_match_red), 13935be4001eSWingMan Kwok GBENU_STATS_P5(ale_pol_match_yellow), 13949a391c7bSWingMan Kwok GBENU_STATS_P5(tx_mem_protect_err), 13955be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri0_drop), 13965be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri1_drop), 13975be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri2_drop), 13985be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri3_drop), 13995be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri4_drop), 14005be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri5_drop), 14015be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri6_drop), 14025be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri7_drop), 14035be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri0_drop_bcnt), 14045be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri1_drop_bcnt), 14055be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri2_drop_bcnt), 14065be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri3_drop_bcnt), 14075be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri4_drop_bcnt), 14085be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri5_drop_bcnt), 14095be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri6_drop_bcnt), 14105be4001eSWingMan Kwok GBENU_STATS_P5(tx_pri7_drop_bcnt), 14119a391c7bSWingMan Kwok /* GBENU Module 6 */ 14129a391c7bSWingMan Kwok GBENU_STATS_P6(rx_good_frames), 14139a391c7bSWingMan Kwok GBENU_STATS_P6(rx_broadcast_frames), 14149a391c7bSWingMan Kwok GBENU_STATS_P6(rx_multicast_frames), 14159a391c7bSWingMan Kwok GBENU_STATS_P6(rx_pause_frames), 14169a391c7bSWingMan Kwok GBENU_STATS_P6(rx_crc_errors), 14179a391c7bSWingMan Kwok GBENU_STATS_P6(rx_align_code_errors), 14189a391c7bSWingMan Kwok GBENU_STATS_P6(rx_oversized_frames), 14199a391c7bSWingMan Kwok GBENU_STATS_P6(rx_jabber_frames), 14209a391c7bSWingMan Kwok GBENU_STATS_P6(rx_undersized_frames), 14219a391c7bSWingMan Kwok GBENU_STATS_P6(rx_fragments), 14229a391c7bSWingMan Kwok GBENU_STATS_P6(ale_drop), 14239a391c7bSWingMan Kwok GBENU_STATS_P6(ale_overrun_drop), 14249a391c7bSWingMan Kwok GBENU_STATS_P6(rx_bytes), 14259a391c7bSWingMan Kwok GBENU_STATS_P6(tx_good_frames), 14269a391c7bSWingMan Kwok GBENU_STATS_P6(tx_broadcast_frames), 14279a391c7bSWingMan Kwok GBENU_STATS_P6(tx_multicast_frames), 14289a391c7bSWingMan Kwok GBENU_STATS_P6(tx_pause_frames), 14299a391c7bSWingMan Kwok GBENU_STATS_P6(tx_deferred_frames), 14309a391c7bSWingMan Kwok GBENU_STATS_P6(tx_collision_frames), 14319a391c7bSWingMan Kwok GBENU_STATS_P6(tx_single_coll_frames), 14329a391c7bSWingMan Kwok GBENU_STATS_P6(tx_mult_coll_frames), 14339a391c7bSWingMan Kwok GBENU_STATS_P6(tx_excessive_collisions), 14349a391c7bSWingMan Kwok GBENU_STATS_P6(tx_late_collisions), 14359a391c7bSWingMan Kwok GBENU_STATS_P6(rx_ipg_error), 14369a391c7bSWingMan Kwok GBENU_STATS_P6(tx_carrier_sense_errors), 14379a391c7bSWingMan Kwok GBENU_STATS_P6(tx_bytes), 14389a391c7bSWingMan Kwok GBENU_STATS_P6(tx_64B_frames), 14399a391c7bSWingMan Kwok GBENU_STATS_P6(tx_65_to_127B_frames), 14409a391c7bSWingMan Kwok GBENU_STATS_P6(tx_128_to_255B_frames), 14419a391c7bSWingMan Kwok GBENU_STATS_P6(tx_256_to_511B_frames), 14429a391c7bSWingMan Kwok GBENU_STATS_P6(tx_512_to_1023B_frames), 14439a391c7bSWingMan Kwok GBENU_STATS_P6(tx_1024B_frames), 14449a391c7bSWingMan Kwok GBENU_STATS_P6(net_bytes), 14459a391c7bSWingMan Kwok GBENU_STATS_P6(rx_bottom_fifo_drop), 14469a391c7bSWingMan Kwok GBENU_STATS_P6(rx_port_mask_drop), 14479a391c7bSWingMan Kwok GBENU_STATS_P6(rx_top_fifo_drop), 14489a391c7bSWingMan Kwok GBENU_STATS_P6(ale_rate_limit_drop), 14499a391c7bSWingMan Kwok GBENU_STATS_P6(ale_vid_ingress_drop), 14509a391c7bSWingMan Kwok GBENU_STATS_P6(ale_da_eq_sa_drop), 14519a391c7bSWingMan Kwok GBENU_STATS_P6(ale_unknown_ucast), 14529a391c7bSWingMan Kwok GBENU_STATS_P6(ale_unknown_ucast_bytes), 14539a391c7bSWingMan Kwok GBENU_STATS_P6(ale_unknown_mcast), 14549a391c7bSWingMan Kwok GBENU_STATS_P6(ale_unknown_mcast_bytes), 14559a391c7bSWingMan Kwok GBENU_STATS_P6(ale_unknown_bcast), 14569a391c7bSWingMan Kwok GBENU_STATS_P6(ale_unknown_bcast_bytes), 14575be4001eSWingMan Kwok GBENU_STATS_P6(ale_pol_match), 14585be4001eSWingMan Kwok GBENU_STATS_P6(ale_pol_match_red), 14595be4001eSWingMan Kwok GBENU_STATS_P6(ale_pol_match_yellow), 14609a391c7bSWingMan Kwok GBENU_STATS_P6(tx_mem_protect_err), 14615be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri0_drop), 14625be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri1_drop), 14635be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri2_drop), 14645be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri3_drop), 14655be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri4_drop), 14665be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri5_drop), 14675be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri6_drop), 14685be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri7_drop), 14695be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri0_drop_bcnt), 14705be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri1_drop_bcnt), 14715be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri2_drop_bcnt), 14725be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri3_drop_bcnt), 14735be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri4_drop_bcnt), 14745be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri5_drop_bcnt), 14755be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri6_drop_bcnt), 14765be4001eSWingMan Kwok GBENU_STATS_P6(tx_pri7_drop_bcnt), 14779a391c7bSWingMan Kwok /* GBENU Module 7 */ 14789a391c7bSWingMan Kwok GBENU_STATS_P7(rx_good_frames), 14799a391c7bSWingMan Kwok GBENU_STATS_P7(rx_broadcast_frames), 14809a391c7bSWingMan Kwok GBENU_STATS_P7(rx_multicast_frames), 14819a391c7bSWingMan Kwok GBENU_STATS_P7(rx_pause_frames), 14829a391c7bSWingMan Kwok GBENU_STATS_P7(rx_crc_errors), 14839a391c7bSWingMan Kwok GBENU_STATS_P7(rx_align_code_errors), 14849a391c7bSWingMan Kwok GBENU_STATS_P7(rx_oversized_frames), 14859a391c7bSWingMan Kwok GBENU_STATS_P7(rx_jabber_frames), 14869a391c7bSWingMan Kwok GBENU_STATS_P7(rx_undersized_frames), 14879a391c7bSWingMan Kwok GBENU_STATS_P7(rx_fragments), 14889a391c7bSWingMan Kwok GBENU_STATS_P7(ale_drop), 14899a391c7bSWingMan Kwok GBENU_STATS_P7(ale_overrun_drop), 14909a391c7bSWingMan Kwok GBENU_STATS_P7(rx_bytes), 14919a391c7bSWingMan Kwok GBENU_STATS_P7(tx_good_frames), 14929a391c7bSWingMan Kwok GBENU_STATS_P7(tx_broadcast_frames), 14939a391c7bSWingMan Kwok GBENU_STATS_P7(tx_multicast_frames), 14949a391c7bSWingMan Kwok GBENU_STATS_P7(tx_pause_frames), 14959a391c7bSWingMan Kwok GBENU_STATS_P7(tx_deferred_frames), 14969a391c7bSWingMan Kwok GBENU_STATS_P7(tx_collision_frames), 14979a391c7bSWingMan Kwok GBENU_STATS_P7(tx_single_coll_frames), 14989a391c7bSWingMan Kwok GBENU_STATS_P7(tx_mult_coll_frames), 14999a391c7bSWingMan Kwok GBENU_STATS_P7(tx_excessive_collisions), 15009a391c7bSWingMan Kwok GBENU_STATS_P7(tx_late_collisions), 15019a391c7bSWingMan Kwok GBENU_STATS_P7(rx_ipg_error), 15029a391c7bSWingMan Kwok GBENU_STATS_P7(tx_carrier_sense_errors), 15039a391c7bSWingMan Kwok GBENU_STATS_P7(tx_bytes), 15049a391c7bSWingMan Kwok GBENU_STATS_P7(tx_64B_frames), 15059a391c7bSWingMan Kwok GBENU_STATS_P7(tx_65_to_127B_frames), 15069a391c7bSWingMan Kwok GBENU_STATS_P7(tx_128_to_255B_frames), 15079a391c7bSWingMan Kwok GBENU_STATS_P7(tx_256_to_511B_frames), 15089a391c7bSWingMan Kwok GBENU_STATS_P7(tx_512_to_1023B_frames), 15099a391c7bSWingMan Kwok GBENU_STATS_P7(tx_1024B_frames), 15109a391c7bSWingMan Kwok GBENU_STATS_P7(net_bytes), 15119a391c7bSWingMan Kwok GBENU_STATS_P7(rx_bottom_fifo_drop), 15129a391c7bSWingMan Kwok GBENU_STATS_P7(rx_port_mask_drop), 15139a391c7bSWingMan Kwok GBENU_STATS_P7(rx_top_fifo_drop), 15149a391c7bSWingMan Kwok GBENU_STATS_P7(ale_rate_limit_drop), 15159a391c7bSWingMan Kwok GBENU_STATS_P7(ale_vid_ingress_drop), 15169a391c7bSWingMan Kwok GBENU_STATS_P7(ale_da_eq_sa_drop), 15179a391c7bSWingMan Kwok GBENU_STATS_P7(ale_unknown_ucast), 15189a391c7bSWingMan Kwok GBENU_STATS_P7(ale_unknown_ucast_bytes), 15199a391c7bSWingMan Kwok GBENU_STATS_P7(ale_unknown_mcast), 15209a391c7bSWingMan Kwok GBENU_STATS_P7(ale_unknown_mcast_bytes), 15219a391c7bSWingMan Kwok GBENU_STATS_P7(ale_unknown_bcast), 15229a391c7bSWingMan Kwok GBENU_STATS_P7(ale_unknown_bcast_bytes), 15235be4001eSWingMan Kwok GBENU_STATS_P7(ale_pol_match), 15245be4001eSWingMan Kwok GBENU_STATS_P7(ale_pol_match_red), 15255be4001eSWingMan Kwok GBENU_STATS_P7(ale_pol_match_yellow), 15269a391c7bSWingMan Kwok GBENU_STATS_P7(tx_mem_protect_err), 15275be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri0_drop), 15285be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri1_drop), 15295be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri2_drop), 15305be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri3_drop), 15315be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri4_drop), 15325be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri5_drop), 15335be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri6_drop), 15345be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri7_drop), 15355be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri0_drop_bcnt), 15365be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri1_drop_bcnt), 15375be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri2_drop_bcnt), 15385be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri3_drop_bcnt), 15395be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri4_drop_bcnt), 15405be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri5_drop_bcnt), 15415be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri6_drop_bcnt), 15425be4001eSWingMan Kwok GBENU_STATS_P7(tx_pri7_drop_bcnt), 15439a391c7bSWingMan Kwok /* GBENU Module 8 */ 15449a391c7bSWingMan Kwok GBENU_STATS_P8(rx_good_frames), 15459a391c7bSWingMan Kwok GBENU_STATS_P8(rx_broadcast_frames), 15469a391c7bSWingMan Kwok GBENU_STATS_P8(rx_multicast_frames), 15479a391c7bSWingMan Kwok GBENU_STATS_P8(rx_pause_frames), 15489a391c7bSWingMan Kwok GBENU_STATS_P8(rx_crc_errors), 15499a391c7bSWingMan Kwok GBENU_STATS_P8(rx_align_code_errors), 15509a391c7bSWingMan Kwok GBENU_STATS_P8(rx_oversized_frames), 15519a391c7bSWingMan Kwok GBENU_STATS_P8(rx_jabber_frames), 15529a391c7bSWingMan Kwok GBENU_STATS_P8(rx_undersized_frames), 15539a391c7bSWingMan Kwok GBENU_STATS_P8(rx_fragments), 15549a391c7bSWingMan Kwok GBENU_STATS_P8(ale_drop), 15559a391c7bSWingMan Kwok GBENU_STATS_P8(ale_overrun_drop), 15569a391c7bSWingMan Kwok GBENU_STATS_P8(rx_bytes), 15579a391c7bSWingMan Kwok GBENU_STATS_P8(tx_good_frames), 15589a391c7bSWingMan Kwok GBENU_STATS_P8(tx_broadcast_frames), 15599a391c7bSWingMan Kwok GBENU_STATS_P8(tx_multicast_frames), 15609a391c7bSWingMan Kwok GBENU_STATS_P8(tx_pause_frames), 15619a391c7bSWingMan Kwok GBENU_STATS_P8(tx_deferred_frames), 15629a391c7bSWingMan Kwok GBENU_STATS_P8(tx_collision_frames), 15639a391c7bSWingMan Kwok GBENU_STATS_P8(tx_single_coll_frames), 15649a391c7bSWingMan Kwok GBENU_STATS_P8(tx_mult_coll_frames), 15659a391c7bSWingMan Kwok GBENU_STATS_P8(tx_excessive_collisions), 15669a391c7bSWingMan Kwok GBENU_STATS_P8(tx_late_collisions), 15679a391c7bSWingMan Kwok GBENU_STATS_P8(rx_ipg_error), 15689a391c7bSWingMan Kwok GBENU_STATS_P8(tx_carrier_sense_errors), 15699a391c7bSWingMan Kwok GBENU_STATS_P8(tx_bytes), 15709a391c7bSWingMan Kwok GBENU_STATS_P8(tx_64B_frames), 15719a391c7bSWingMan Kwok GBENU_STATS_P8(tx_65_to_127B_frames), 15729a391c7bSWingMan Kwok GBENU_STATS_P8(tx_128_to_255B_frames), 15739a391c7bSWingMan Kwok GBENU_STATS_P8(tx_256_to_511B_frames), 15749a391c7bSWingMan Kwok GBENU_STATS_P8(tx_512_to_1023B_frames), 15759a391c7bSWingMan Kwok GBENU_STATS_P8(tx_1024B_frames), 15769a391c7bSWingMan Kwok GBENU_STATS_P8(net_bytes), 15779a391c7bSWingMan Kwok GBENU_STATS_P8(rx_bottom_fifo_drop), 15789a391c7bSWingMan Kwok GBENU_STATS_P8(rx_port_mask_drop), 15799a391c7bSWingMan Kwok GBENU_STATS_P8(rx_top_fifo_drop), 15809a391c7bSWingMan Kwok GBENU_STATS_P8(ale_rate_limit_drop), 15819a391c7bSWingMan Kwok GBENU_STATS_P8(ale_vid_ingress_drop), 15829a391c7bSWingMan Kwok GBENU_STATS_P8(ale_da_eq_sa_drop), 15839a391c7bSWingMan Kwok GBENU_STATS_P8(ale_unknown_ucast), 15849a391c7bSWingMan Kwok GBENU_STATS_P8(ale_unknown_ucast_bytes), 15859a391c7bSWingMan Kwok GBENU_STATS_P8(ale_unknown_mcast), 15869a391c7bSWingMan Kwok GBENU_STATS_P8(ale_unknown_mcast_bytes), 15879a391c7bSWingMan Kwok GBENU_STATS_P8(ale_unknown_bcast), 15889a391c7bSWingMan Kwok GBENU_STATS_P8(ale_unknown_bcast_bytes), 15895be4001eSWingMan Kwok GBENU_STATS_P8(ale_pol_match), 15905be4001eSWingMan Kwok GBENU_STATS_P8(ale_pol_match_red), 15915be4001eSWingMan Kwok GBENU_STATS_P8(ale_pol_match_yellow), 15929a391c7bSWingMan Kwok GBENU_STATS_P8(tx_mem_protect_err), 15935be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri0_drop), 15945be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri1_drop), 15955be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri2_drop), 15965be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri3_drop), 15975be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri4_drop), 15985be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri5_drop), 15995be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri6_drop), 16005be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri7_drop), 16015be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri0_drop_bcnt), 16025be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri1_drop_bcnt), 16035be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri2_drop_bcnt), 16045be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri3_drop_bcnt), 16055be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri4_drop_bcnt), 16065be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri5_drop_bcnt), 16075be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri6_drop_bcnt), 16085be4001eSWingMan Kwok GBENU_STATS_P8(tx_pri7_drop_bcnt), 16099a391c7bSWingMan Kwok }; 16109a391c7bSWingMan Kwok 1611da866ba0SKaricheri, Muralidharan #define XGBE_STATS0_INFO(field) \ 1612da866ba0SKaricheri, Muralidharan { \ 1613da866ba0SKaricheri, Muralidharan "GBE_0:"#field, XGBE_STATS0_MODULE, \ 161490cff9e2SWingman Kwok FIELD_SIZEOF(struct xgbe_hw_stats, field), \ 1615da866ba0SKaricheri, Muralidharan offsetof(struct xgbe_hw_stats, field) \ 1616da866ba0SKaricheri, Muralidharan } 161790cff9e2SWingman Kwok 1618da866ba0SKaricheri, Muralidharan #define XGBE_STATS1_INFO(field) \ 1619da866ba0SKaricheri, Muralidharan { \ 1620da866ba0SKaricheri, Muralidharan "GBE_1:"#field, XGBE_STATS1_MODULE, \ 162190cff9e2SWingman Kwok FIELD_SIZEOF(struct xgbe_hw_stats, field), \ 1622da866ba0SKaricheri, Muralidharan offsetof(struct xgbe_hw_stats, field) \ 1623da866ba0SKaricheri, Muralidharan } 162490cff9e2SWingman Kwok 1625da866ba0SKaricheri, Muralidharan #define XGBE_STATS2_INFO(field) \ 1626da866ba0SKaricheri, Muralidharan { \ 1627da866ba0SKaricheri, Muralidharan "GBE_2:"#field, XGBE_STATS2_MODULE, \ 162890cff9e2SWingman Kwok FIELD_SIZEOF(struct xgbe_hw_stats, field), \ 1629da866ba0SKaricheri, Muralidharan offsetof(struct xgbe_hw_stats, field) \ 1630da866ba0SKaricheri, Muralidharan } 163190cff9e2SWingman Kwok 163290cff9e2SWingman Kwok static const struct netcp_ethtool_stat xgbe10_et_stats[] = { 163390cff9e2SWingman Kwok /* GBE module 0 */ 1634da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(rx_good_frames), 1635da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(rx_broadcast_frames), 1636da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(rx_multicast_frames), 1637da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(rx_oversized_frames), 1638da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(rx_undersized_frames), 1639da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(overrun_type4), 1640da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(overrun_type5), 1641da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(rx_bytes), 1642da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(tx_good_frames), 1643da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(tx_broadcast_frames), 1644da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(tx_multicast_frames), 1645da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(tx_bytes), 1646da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(tx_64byte_frames), 1647da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(tx_65_to_127byte_frames), 1648da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(tx_128_to_255byte_frames), 1649da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(tx_256_to_511byte_frames), 1650da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(tx_512_to_1023byte_frames), 1651da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(tx_1024byte_frames), 1652da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(net_bytes), 1653da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(rx_sof_overruns), 1654da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(rx_mof_overruns), 1655da866ba0SKaricheri, Muralidharan XGBE_STATS0_INFO(rx_dma_overruns), 165690cff9e2SWingman Kwok /* XGBE module 1 */ 1657da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(rx_good_frames), 1658da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(rx_broadcast_frames), 1659da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(rx_multicast_frames), 1660da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(rx_pause_frames), 1661da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(rx_crc_errors), 1662da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(rx_align_code_errors), 1663da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(rx_oversized_frames), 1664da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(rx_jabber_frames), 1665da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(rx_undersized_frames), 1666da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(rx_fragments), 1667da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(overrun_type4), 1668da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(overrun_type5), 1669da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(rx_bytes), 1670da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_good_frames), 1671da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_broadcast_frames), 1672da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_multicast_frames), 1673da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_pause_frames), 1674da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_deferred_frames), 1675da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_collision_frames), 1676da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_single_coll_frames), 1677da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_mult_coll_frames), 1678da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_excessive_collisions), 1679da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_late_collisions), 1680da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_underrun), 1681da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_carrier_sense_errors), 1682da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_bytes), 1683da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_64byte_frames), 1684da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_65_to_127byte_frames), 1685da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_128_to_255byte_frames), 1686da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_256_to_511byte_frames), 1687da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_512_to_1023byte_frames), 1688da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(tx_1024byte_frames), 1689da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(net_bytes), 1690da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(rx_sof_overruns), 1691da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(rx_mof_overruns), 1692da866ba0SKaricheri, Muralidharan XGBE_STATS1_INFO(rx_dma_overruns), 169390cff9e2SWingman Kwok /* XGBE module 2 */ 1694da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(rx_good_frames), 1695da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(rx_broadcast_frames), 1696da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(rx_multicast_frames), 1697da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(rx_pause_frames), 1698da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(rx_crc_errors), 1699da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(rx_align_code_errors), 1700da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(rx_oversized_frames), 1701da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(rx_jabber_frames), 1702da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(rx_undersized_frames), 1703da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(rx_fragments), 1704da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(overrun_type4), 1705da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(overrun_type5), 1706da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(rx_bytes), 1707da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_good_frames), 1708da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_broadcast_frames), 1709da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_multicast_frames), 1710da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_pause_frames), 1711da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_deferred_frames), 1712da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_collision_frames), 1713da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_single_coll_frames), 1714da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_mult_coll_frames), 1715da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_excessive_collisions), 1716da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_late_collisions), 1717da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_underrun), 1718da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_carrier_sense_errors), 1719da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_bytes), 1720da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_64byte_frames), 1721da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_65_to_127byte_frames), 1722da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_128_to_255byte_frames), 1723da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_256_to_511byte_frames), 1724da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_512_to_1023byte_frames), 1725da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(tx_1024byte_frames), 1726da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(net_bytes), 1727da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(rx_sof_overruns), 1728da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(rx_mof_overruns), 1729da866ba0SKaricheri, Muralidharan XGBE_STATS2_INFO(rx_dma_overruns), 173090cff9e2SWingman Kwok }; 173190cff9e2SWingman Kwok 17326f8d3f33SWingman Kwok #define for_each_intf(i, priv) \ 17336f8d3f33SWingman Kwok list_for_each_entry((i), &(priv)->gbe_intf_head, gbe_intf_list) 17346f8d3f33SWingman Kwok 17356f8d3f33SWingman Kwok #define for_each_sec_slave(slave, priv) \ 17366f8d3f33SWingman Kwok list_for_each_entry((slave), &(priv)->secondary_slaves, slave_list) 17376f8d3f33SWingman Kwok 17386f8d3f33SWingman Kwok #define first_sec_slave(priv) \ 17396f8d3f33SWingman Kwok list_first_entry(&priv->secondary_slaves, \ 17406f8d3f33SWingman Kwok struct gbe_slave, slave_list) 17416f8d3f33SWingman Kwok 17426f8d3f33SWingman Kwok static void keystone_get_drvinfo(struct net_device *ndev, 17436f8d3f33SWingman Kwok struct ethtool_drvinfo *info) 17446f8d3f33SWingman Kwok { 17456f8d3f33SWingman Kwok strncpy(info->driver, NETCP_DRIVER_NAME, sizeof(info->driver)); 17466f8d3f33SWingman Kwok strncpy(info->version, NETCP_DRIVER_VERSION, sizeof(info->version)); 17476f8d3f33SWingman Kwok } 17486f8d3f33SWingman Kwok 17496f8d3f33SWingman Kwok static u32 keystone_get_msglevel(struct net_device *ndev) 17506f8d3f33SWingman Kwok { 17516f8d3f33SWingman Kwok struct netcp_intf *netcp = netdev_priv(ndev); 17526f8d3f33SWingman Kwok 17536f8d3f33SWingman Kwok return netcp->msg_enable; 17546f8d3f33SWingman Kwok } 17556f8d3f33SWingman Kwok 17566f8d3f33SWingman Kwok static void keystone_set_msglevel(struct net_device *ndev, u32 value) 17576f8d3f33SWingman Kwok { 17586f8d3f33SWingman Kwok struct netcp_intf *netcp = netdev_priv(ndev); 17596f8d3f33SWingman Kwok 17606f8d3f33SWingman Kwok netcp->msg_enable = value; 17616f8d3f33SWingman Kwok } 17626f8d3f33SWingman Kwok 1763e9838ef2SWingMan Kwok static struct gbe_intf *keystone_get_intf_data(struct netcp_intf *netcp) 1764e9838ef2SWingMan Kwok { 1765e9838ef2SWingMan Kwok struct gbe_intf *gbe_intf; 1766e9838ef2SWingMan Kwok 1767e9838ef2SWingMan Kwok gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp); 1768e9838ef2SWingMan Kwok if (!gbe_intf) 1769e9838ef2SWingMan Kwok gbe_intf = netcp_module_get_intf_data(&xgbe_module, netcp); 1770e9838ef2SWingMan Kwok 1771e9838ef2SWingMan Kwok return gbe_intf; 1772e9838ef2SWingMan Kwok } 1773e9838ef2SWingMan Kwok 17746f8d3f33SWingman Kwok static void keystone_get_stat_strings(struct net_device *ndev, 17756f8d3f33SWingman Kwok uint32_t stringset, uint8_t *data) 17766f8d3f33SWingman Kwok { 17776f8d3f33SWingman Kwok struct netcp_intf *netcp = netdev_priv(ndev); 17786f8d3f33SWingman Kwok struct gbe_intf *gbe_intf; 17796f8d3f33SWingman Kwok struct gbe_priv *gbe_dev; 17806f8d3f33SWingman Kwok int i; 17816f8d3f33SWingman Kwok 1782e9838ef2SWingMan Kwok gbe_intf = keystone_get_intf_data(netcp); 17836f8d3f33SWingman Kwok if (!gbe_intf) 17846f8d3f33SWingman Kwok return; 17856f8d3f33SWingman Kwok gbe_dev = gbe_intf->gbe_dev; 17866f8d3f33SWingman Kwok 17876f8d3f33SWingman Kwok switch (stringset) { 17886f8d3f33SWingman Kwok case ETH_SS_STATS: 17896f8d3f33SWingman Kwok for (i = 0; i < gbe_dev->num_et_stats; i++) { 17906f8d3f33SWingman Kwok memcpy(data, gbe_dev->et_stats[i].desc, 17916f8d3f33SWingman Kwok ETH_GSTRING_LEN); 17926f8d3f33SWingman Kwok data += ETH_GSTRING_LEN; 17936f8d3f33SWingman Kwok } 17946f8d3f33SWingman Kwok break; 17956f8d3f33SWingman Kwok case ETH_SS_TEST: 17966f8d3f33SWingman Kwok break; 17976f8d3f33SWingman Kwok } 17986f8d3f33SWingman Kwok } 17996f8d3f33SWingman Kwok 18006f8d3f33SWingman Kwok static int keystone_get_sset_count(struct net_device *ndev, int stringset) 18016f8d3f33SWingman Kwok { 18026f8d3f33SWingman Kwok struct netcp_intf *netcp = netdev_priv(ndev); 18036f8d3f33SWingman Kwok struct gbe_intf *gbe_intf; 18046f8d3f33SWingman Kwok struct gbe_priv *gbe_dev; 18056f8d3f33SWingman Kwok 1806e9838ef2SWingMan Kwok gbe_intf = keystone_get_intf_data(netcp); 18076f8d3f33SWingman Kwok if (!gbe_intf) 18086f8d3f33SWingman Kwok return -EINVAL; 18096f8d3f33SWingman Kwok gbe_dev = gbe_intf->gbe_dev; 18106f8d3f33SWingman Kwok 18116f8d3f33SWingman Kwok switch (stringset) { 18126f8d3f33SWingman Kwok case ETH_SS_TEST: 18136f8d3f33SWingman Kwok return 0; 18146f8d3f33SWingman Kwok case ETH_SS_STATS: 18156f8d3f33SWingman Kwok return gbe_dev->num_et_stats; 18166f8d3f33SWingman Kwok default: 18176f8d3f33SWingman Kwok return -EINVAL; 18186f8d3f33SWingman Kwok } 18196f8d3f33SWingman Kwok } 18206f8d3f33SWingman Kwok 1821489e8a2fSWingMan Kwok static void gbe_reset_mod_stats(struct gbe_priv *gbe_dev, int stats_mod) 1822489e8a2fSWingMan Kwok { 1823489e8a2fSWingMan Kwok void __iomem *base = gbe_dev->hw_stats_regs[stats_mod]; 1824489e8a2fSWingMan Kwok u32 __iomem *p_stats_entry; 1825489e8a2fSWingMan Kwok int i; 1826489e8a2fSWingMan Kwok 1827489e8a2fSWingMan Kwok for (i = 0; i < gbe_dev->num_et_stats; i++) { 1828489e8a2fSWingMan Kwok if (gbe_dev->et_stats[i].type == stats_mod) { 1829489e8a2fSWingMan Kwok p_stats_entry = base + gbe_dev->et_stats[i].offset; 1830489e8a2fSWingMan Kwok gbe_dev->hw_stats[i] = 0; 1831489e8a2fSWingMan Kwok gbe_dev->hw_stats_prev[i] = readl(p_stats_entry); 1832489e8a2fSWingMan Kwok } 1833489e8a2fSWingMan Kwok } 1834489e8a2fSWingMan Kwok } 1835489e8a2fSWingMan Kwok 1836fbf64c19SWingMan Kwok static inline void gbe_update_hw_stats_entry(struct gbe_priv *gbe_dev, 1837fbf64c19SWingMan Kwok int et_stats_entry) 18386f8d3f33SWingman Kwok { 18396f8d3f33SWingman Kwok void __iomem *base = NULL; 1840489e8a2fSWingMan Kwok u32 __iomem *p_stats_entry; 1841489e8a2fSWingMan Kwok u32 curr, delta; 18426f8d3f33SWingman Kwok 1843fbf64c19SWingMan Kwok /* The hw_stats_regs pointers are already 1844fbf64c19SWingMan Kwok * properly set to point to the right base: 1845fbf64c19SWingMan Kwok */ 1846fbf64c19SWingMan Kwok base = gbe_dev->hw_stats_regs[gbe_dev->et_stats[et_stats_entry].type]; 1847489e8a2fSWingMan Kwok p_stats_entry = base + gbe_dev->et_stats[et_stats_entry].offset; 1848489e8a2fSWingMan Kwok curr = readl(p_stats_entry); 1849489e8a2fSWingMan Kwok delta = curr - gbe_dev->hw_stats_prev[et_stats_entry]; 1850489e8a2fSWingMan Kwok gbe_dev->hw_stats_prev[et_stats_entry] = curr; 1851489e8a2fSWingMan Kwok gbe_dev->hw_stats[et_stats_entry] += delta; 18526f8d3f33SWingman Kwok } 1853fbf64c19SWingMan Kwok 1854fbf64c19SWingMan Kwok static void gbe_update_stats(struct gbe_priv *gbe_dev, uint64_t *data) 1855fbf64c19SWingMan Kwok { 1856fbf64c19SWingMan Kwok int i; 1857fbf64c19SWingMan Kwok 1858fbf64c19SWingMan Kwok for (i = 0; i < gbe_dev->num_et_stats; i++) { 1859fbf64c19SWingMan Kwok gbe_update_hw_stats_entry(gbe_dev, i); 1860fbf64c19SWingMan Kwok 1861fbf64c19SWingMan Kwok if (data) 1862fbf64c19SWingMan Kwok data[i] = gbe_dev->hw_stats[i]; 1863fbf64c19SWingMan Kwok } 1864fbf64c19SWingMan Kwok } 1865fbf64c19SWingMan Kwok 1866fbf64c19SWingMan Kwok static inline void gbe_stats_mod_visible_ver14(struct gbe_priv *gbe_dev, 1867fbf64c19SWingMan Kwok int stats_mod) 1868fbf64c19SWingMan Kwok { 1869fbf64c19SWingMan Kwok u32 val; 1870fbf64c19SWingMan Kwok 1871fbf64c19SWingMan Kwok val = readl(GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en)); 1872fbf64c19SWingMan Kwok 1873fbf64c19SWingMan Kwok switch (stats_mod) { 1874fbf64c19SWingMan Kwok case GBE_STATSA_MODULE: 1875fbf64c19SWingMan Kwok case GBE_STATSB_MODULE: 1876fbf64c19SWingMan Kwok val &= ~GBE_STATS_CD_SEL; 1877fbf64c19SWingMan Kwok break; 1878fbf64c19SWingMan Kwok case GBE_STATSC_MODULE: 1879fbf64c19SWingMan Kwok case GBE_STATSD_MODULE: 1880fbf64c19SWingMan Kwok val |= GBE_STATS_CD_SEL; 1881fbf64c19SWingMan Kwok break; 1882fbf64c19SWingMan Kwok default: 1883fbf64c19SWingMan Kwok return; 1884fbf64c19SWingMan Kwok } 1885fbf64c19SWingMan Kwok 1886fbf64c19SWingMan Kwok /* make the stat module visible */ 1887fbf64c19SWingMan Kwok writel(val, GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en)); 18886f8d3f33SWingman Kwok } 18896f8d3f33SWingman Kwok 1890489e8a2fSWingMan Kwok static void gbe_reset_mod_stats_ver14(struct gbe_priv *gbe_dev, int stats_mod) 1891489e8a2fSWingMan Kwok { 1892489e8a2fSWingMan Kwok gbe_stats_mod_visible_ver14(gbe_dev, stats_mod); 1893489e8a2fSWingMan Kwok gbe_reset_mod_stats(gbe_dev, stats_mod); 1894489e8a2fSWingMan Kwok } 1895489e8a2fSWingMan Kwok 18966f8d3f33SWingman Kwok static void gbe_update_stats_ver14(struct gbe_priv *gbe_dev, uint64_t *data) 18976f8d3f33SWingman Kwok { 1898fbf64c19SWingMan Kwok u32 half_num_et_stats = (gbe_dev->num_et_stats / 2); 1899fbf64c19SWingMan Kwok int et_entry, j, pair; 19006f8d3f33SWingman Kwok 19016f8d3f33SWingman Kwok for (pair = 0; pair < 2; pair++) { 1902fbf64c19SWingMan Kwok gbe_stats_mod_visible_ver14(gbe_dev, (pair ? 1903fbf64c19SWingMan Kwok GBE_STATSC_MODULE : 1904fbf64c19SWingMan Kwok GBE_STATSA_MODULE)); 19056f8d3f33SWingman Kwok 1906fbf64c19SWingMan Kwok for (j = 0; j < half_num_et_stats; j++) { 1907fbf64c19SWingMan Kwok et_entry = pair * half_num_et_stats + j; 1908fbf64c19SWingMan Kwok gbe_update_hw_stats_entry(gbe_dev, et_entry); 19096f8d3f33SWingman Kwok 19106f8d3f33SWingman Kwok if (data) 1911fbf64c19SWingMan Kwok data[et_entry] = gbe_dev->hw_stats[et_entry]; 19126f8d3f33SWingman Kwok } 19136f8d3f33SWingman Kwok } 19146f8d3f33SWingman Kwok } 19156f8d3f33SWingman Kwok 19166f8d3f33SWingman Kwok static void keystone_get_ethtool_stats(struct net_device *ndev, 19176f8d3f33SWingman Kwok struct ethtool_stats *stats, 19186f8d3f33SWingman Kwok uint64_t *data) 19196f8d3f33SWingman Kwok { 19206f8d3f33SWingman Kwok struct netcp_intf *netcp = netdev_priv(ndev); 19216f8d3f33SWingman Kwok struct gbe_intf *gbe_intf; 19226f8d3f33SWingman Kwok struct gbe_priv *gbe_dev; 19236f8d3f33SWingman Kwok 1924e9838ef2SWingMan Kwok gbe_intf = keystone_get_intf_data(netcp); 19256f8d3f33SWingman Kwok if (!gbe_intf) 19266f8d3f33SWingman Kwok return; 19276f8d3f33SWingman Kwok 19286f8d3f33SWingman Kwok gbe_dev = gbe_intf->gbe_dev; 19296f8d3f33SWingman Kwok spin_lock_bh(&gbe_dev->hw_stats_lock); 19302953586dSMurali Karicheri if (IS_SS_ID_VER_14(gbe_dev)) 19316f8d3f33SWingman Kwok gbe_update_stats_ver14(gbe_dev, data); 193290cff9e2SWingman Kwok else 193390cff9e2SWingman Kwok gbe_update_stats(gbe_dev, data); 19346f8d3f33SWingman Kwok spin_unlock_bh(&gbe_dev->hw_stats_lock); 19356f8d3f33SWingman Kwok } 19366f8d3f33SWingman Kwok 193786e3a040SPhilippe Reynes static int keystone_get_link_ksettings(struct net_device *ndev, 193886e3a040SPhilippe Reynes struct ethtool_link_ksettings *cmd) 19396f8d3f33SWingman Kwok { 19406f8d3f33SWingman Kwok struct netcp_intf *netcp = netdev_priv(ndev); 19416f8d3f33SWingman Kwok struct phy_device *phy = ndev->phydev; 19426f8d3f33SWingman Kwok struct gbe_intf *gbe_intf; 19436f8d3f33SWingman Kwok 19446f8d3f33SWingman Kwok if (!phy) 19456f8d3f33SWingman Kwok return -EINVAL; 19466f8d3f33SWingman Kwok 1947e9838ef2SWingMan Kwok gbe_intf = keystone_get_intf_data(netcp); 19486f8d3f33SWingman Kwok if (!gbe_intf) 19496f8d3f33SWingman Kwok return -EINVAL; 19506f8d3f33SWingman Kwok 19516f8d3f33SWingman Kwok if (!gbe_intf->slave) 19526f8d3f33SWingman Kwok return -EINVAL; 19536f8d3f33SWingman Kwok 19545514174fSyuval.shaia@oracle.com phy_ethtool_ksettings_get(phy, cmd); 195586e3a040SPhilippe Reynes cmd->base.port = gbe_intf->slave->phy_port_t; 19566f8d3f33SWingman Kwok 19575514174fSyuval.shaia@oracle.com return 0; 19586f8d3f33SWingman Kwok } 19596f8d3f33SWingman Kwok 196086e3a040SPhilippe Reynes static int keystone_set_link_ksettings(struct net_device *ndev, 196186e3a040SPhilippe Reynes const struct ethtool_link_ksettings *cmd) 19626f8d3f33SWingman Kwok { 19636f8d3f33SWingman Kwok struct netcp_intf *netcp = netdev_priv(ndev); 19646f8d3f33SWingman Kwok struct phy_device *phy = ndev->phydev; 19656f8d3f33SWingman Kwok struct gbe_intf *gbe_intf; 196686e3a040SPhilippe Reynes u8 port = cmd->base.port; 196786e3a040SPhilippe Reynes u32 advertising, supported; 196886e3a040SPhilippe Reynes u32 features; 196986e3a040SPhilippe Reynes 197086e3a040SPhilippe Reynes ethtool_convert_link_mode_to_legacy_u32(&advertising, 197186e3a040SPhilippe Reynes cmd->link_modes.advertising); 197286e3a040SPhilippe Reynes ethtool_convert_link_mode_to_legacy_u32(&supported, 197386e3a040SPhilippe Reynes cmd->link_modes.supported); 197486e3a040SPhilippe Reynes features = advertising & supported; 19756f8d3f33SWingman Kwok 19766f8d3f33SWingman Kwok if (!phy) 19776f8d3f33SWingman Kwok return -EINVAL; 19786f8d3f33SWingman Kwok 1979e9838ef2SWingMan Kwok gbe_intf = keystone_get_intf_data(netcp); 19806f8d3f33SWingman Kwok if (!gbe_intf) 19816f8d3f33SWingman Kwok return -EINVAL; 19826f8d3f33SWingman Kwok 19836f8d3f33SWingman Kwok if (!gbe_intf->slave) 19846f8d3f33SWingman Kwok return -EINVAL; 19856f8d3f33SWingman Kwok 198686e3a040SPhilippe Reynes if (port != gbe_intf->slave->phy_port_t) { 198786e3a040SPhilippe Reynes if ((port == PORT_TP) && !(features & ADVERTISED_TP)) 19886f8d3f33SWingman Kwok return -EINVAL; 19896f8d3f33SWingman Kwok 199086e3a040SPhilippe Reynes if ((port == PORT_AUI) && !(features & ADVERTISED_AUI)) 19916f8d3f33SWingman Kwok return -EINVAL; 19926f8d3f33SWingman Kwok 199386e3a040SPhilippe Reynes if ((port == PORT_BNC) && !(features & ADVERTISED_BNC)) 19946f8d3f33SWingman Kwok return -EINVAL; 19956f8d3f33SWingman Kwok 199686e3a040SPhilippe Reynes if ((port == PORT_MII) && !(features & ADVERTISED_MII)) 19976f8d3f33SWingman Kwok return -EINVAL; 19986f8d3f33SWingman Kwok 199986e3a040SPhilippe Reynes if ((port == PORT_FIBRE) && !(features & ADVERTISED_FIBRE)) 20006f8d3f33SWingman Kwok return -EINVAL; 20016f8d3f33SWingman Kwok } 20026f8d3f33SWingman Kwok 200386e3a040SPhilippe Reynes gbe_intf->slave->phy_port_t = port; 200486e3a040SPhilippe Reynes return phy_ethtool_ksettings_set(phy, cmd); 20056f8d3f33SWingman Kwok } 20066f8d3f33SWingman Kwok 20076246168bSWingMan Kwok #if IS_ENABLED(CONFIG_TI_CPTS) 20086246168bSWingMan Kwok static int keystone_get_ts_info(struct net_device *ndev, 20096246168bSWingMan Kwok struct ethtool_ts_info *info) 20106246168bSWingMan Kwok { 20116246168bSWingMan Kwok struct netcp_intf *netcp = netdev_priv(ndev); 20126246168bSWingMan Kwok struct gbe_intf *gbe_intf; 20136246168bSWingMan Kwok 20146246168bSWingMan Kwok gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp); 20156246168bSWingMan Kwok if (!gbe_intf || !gbe_intf->gbe_dev->cpts) 20166246168bSWingMan Kwok return -EINVAL; 20176246168bSWingMan Kwok 20186246168bSWingMan Kwok info->so_timestamping = 20196246168bSWingMan Kwok SOF_TIMESTAMPING_TX_HARDWARE | 20206246168bSWingMan Kwok SOF_TIMESTAMPING_TX_SOFTWARE | 20216246168bSWingMan Kwok SOF_TIMESTAMPING_RX_HARDWARE | 20226246168bSWingMan Kwok SOF_TIMESTAMPING_RX_SOFTWARE | 20236246168bSWingMan Kwok SOF_TIMESTAMPING_SOFTWARE | 20246246168bSWingMan Kwok SOF_TIMESTAMPING_RAW_HARDWARE; 20256246168bSWingMan Kwok info->phc_index = gbe_intf->gbe_dev->cpts->phc_index; 20266246168bSWingMan Kwok info->tx_types = 20276246168bSWingMan Kwok (1 << HWTSTAMP_TX_OFF) | 20286246168bSWingMan Kwok (1 << HWTSTAMP_TX_ON); 20296246168bSWingMan Kwok info->rx_filters = 20306246168bSWingMan Kwok (1 << HWTSTAMP_FILTER_NONE) | 20316246168bSWingMan Kwok (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) | 20326246168bSWingMan Kwok (1 << HWTSTAMP_FILTER_PTP_V2_EVENT); 20336246168bSWingMan Kwok return 0; 20346246168bSWingMan Kwok } 20356246168bSWingMan Kwok #else 20366246168bSWingMan Kwok static int keystone_get_ts_info(struct net_device *ndev, 20376246168bSWingMan Kwok struct ethtool_ts_info *info) 20386246168bSWingMan Kwok { 20396246168bSWingMan Kwok info->so_timestamping = 20406246168bSWingMan Kwok SOF_TIMESTAMPING_TX_SOFTWARE | 20416246168bSWingMan Kwok SOF_TIMESTAMPING_RX_SOFTWARE | 20426246168bSWingMan Kwok SOF_TIMESTAMPING_SOFTWARE; 20436246168bSWingMan Kwok info->phc_index = -1; 20446246168bSWingMan Kwok info->tx_types = 0; 20456246168bSWingMan Kwok info->rx_filters = 0; 20466246168bSWingMan Kwok return 0; 20476246168bSWingMan Kwok } 20486246168bSWingMan Kwok #endif /* CONFIG_TI_CPTS */ 20496246168bSWingMan Kwok 20506f8d3f33SWingman Kwok static const struct ethtool_ops keystone_ethtool_ops = { 20516f8d3f33SWingman Kwok .get_drvinfo = keystone_get_drvinfo, 20526f8d3f33SWingman Kwok .get_link = ethtool_op_get_link, 20536f8d3f33SWingman Kwok .get_msglevel = keystone_get_msglevel, 20546f8d3f33SWingman Kwok .set_msglevel = keystone_set_msglevel, 20556f8d3f33SWingman Kwok .get_strings = keystone_get_stat_strings, 20566f8d3f33SWingman Kwok .get_sset_count = keystone_get_sset_count, 20576f8d3f33SWingman Kwok .get_ethtool_stats = keystone_get_ethtool_stats, 205886e3a040SPhilippe Reynes .get_link_ksettings = keystone_get_link_ksettings, 205986e3a040SPhilippe Reynes .set_link_ksettings = keystone_set_link_ksettings, 20606246168bSWingMan Kwok .get_ts_info = keystone_get_ts_info, 20616f8d3f33SWingman Kwok }; 20626f8d3f33SWingman Kwok 20636f8d3f33SWingman Kwok static void gbe_set_slave_mac(struct gbe_slave *slave, 20646f8d3f33SWingman Kwok struct gbe_intf *gbe_intf) 20656f8d3f33SWingman Kwok { 20666f8d3f33SWingman Kwok struct net_device *ndev = gbe_intf->ndev; 20676f8d3f33SWingman Kwok 20686f8d3f33SWingman Kwok writel(mac_hi(ndev->dev_addr), GBE_REG_ADDR(slave, port_regs, sa_hi)); 20696f8d3f33SWingman Kwok writel(mac_lo(ndev->dev_addr), GBE_REG_ADDR(slave, port_regs, sa_lo)); 20706f8d3f33SWingman Kwok } 20716f8d3f33SWingman Kwok 20726f8d3f33SWingman Kwok static int gbe_get_slave_port(struct gbe_priv *priv, u32 slave_num) 20736f8d3f33SWingman Kwok { 20746f8d3f33SWingman Kwok if (priv->host_port == 0) 20756f8d3f33SWingman Kwok return slave_num + 1; 20766f8d3f33SWingman Kwok 20776f8d3f33SWingman Kwok return slave_num; 20786f8d3f33SWingman Kwok } 20796f8d3f33SWingman Kwok 20806f8d3f33SWingman Kwok static void netcp_ethss_link_state_action(struct gbe_priv *gbe_dev, 20816f8d3f33SWingman Kwok struct net_device *ndev, 20826f8d3f33SWingman Kwok struct gbe_slave *slave, 20836f8d3f33SWingman Kwok int up) 20846f8d3f33SWingman Kwok { 20856f8d3f33SWingman Kwok struct phy_device *phy = slave->phy; 20866f8d3f33SWingman Kwok u32 mac_control = 0; 20876f8d3f33SWingman Kwok 20886f8d3f33SWingman Kwok if (up) { 20896f8d3f33SWingman Kwok mac_control = slave->mac_control; 209090cff9e2SWingman Kwok if (phy && (phy->speed == SPEED_1000)) { 20916f8d3f33SWingman Kwok mac_control |= MACSL_GIG_MODE; 209290cff9e2SWingman Kwok mac_control &= ~MACSL_XGIG_MODE; 209390cff9e2SWingman Kwok } else if (phy && (phy->speed == SPEED_10000)) { 209490cff9e2SWingman Kwok mac_control |= MACSL_XGIG_MODE; 209590cff9e2SWingman Kwok mac_control &= ~MACSL_GIG_MODE; 209690cff9e2SWingman Kwok } 20976f8d3f33SWingman Kwok 20986f8d3f33SWingman Kwok writel(mac_control, GBE_REG_ADDR(slave, emac_regs, 20996f8d3f33SWingman Kwok mac_control)); 21006f8d3f33SWingman Kwok 21016f8d3f33SWingman Kwok cpsw_ale_control_set(gbe_dev->ale, slave->port_num, 21026f8d3f33SWingman Kwok ALE_PORT_STATE, 21036f8d3f33SWingman Kwok ALE_PORT_STATE_FORWARD); 21046f8d3f33SWingman Kwok 21058e046d68SKaricheri, Muralidharan if (ndev && slave->open && 2106478e9a5fSMurali Karicheri ((slave->link_interface != SGMII_LINK_MAC_PHY) && 2107478e9a5fSMurali Karicheri (slave->link_interface != RGMII_LINK_MAC_PHY) && 2108478e9a5fSMurali Karicheri (slave->link_interface != XGMII_LINK_MAC_PHY))) 21096f8d3f33SWingman Kwok netif_carrier_on(ndev); 21106f8d3f33SWingman Kwok } else { 21116f8d3f33SWingman Kwok writel(mac_control, GBE_REG_ADDR(slave, emac_regs, 21126f8d3f33SWingman Kwok mac_control)); 21136f8d3f33SWingman Kwok cpsw_ale_control_set(gbe_dev->ale, slave->port_num, 21146f8d3f33SWingman Kwok ALE_PORT_STATE, 21156f8d3f33SWingman Kwok ALE_PORT_STATE_DISABLE); 21168e046d68SKaricheri, Muralidharan if (ndev && 2117478e9a5fSMurali Karicheri ((slave->link_interface != SGMII_LINK_MAC_PHY) && 2118478e9a5fSMurali Karicheri (slave->link_interface != RGMII_LINK_MAC_PHY) && 2119478e9a5fSMurali Karicheri (slave->link_interface != XGMII_LINK_MAC_PHY))) 21206f8d3f33SWingman Kwok netif_carrier_off(ndev); 21216f8d3f33SWingman Kwok } 21226f8d3f33SWingman Kwok 21236f8d3f33SWingman Kwok if (phy) 21246f8d3f33SWingman Kwok phy_print_status(phy); 21256f8d3f33SWingman Kwok } 21266f8d3f33SWingman Kwok 21276f8d3f33SWingman Kwok static bool gbe_phy_link_status(struct gbe_slave *slave) 21286f8d3f33SWingman Kwok { 21296f8d3f33SWingman Kwok return !slave->phy || slave->phy->link; 21306f8d3f33SWingman Kwok } 21316f8d3f33SWingman Kwok 21327771f2b4SMurali Karicheri #define RGMII_REG_STATUS_LINK BIT(0) 21337771f2b4SMurali Karicheri 21347771f2b4SMurali Karicheri static void netcp_2u_rgmii_get_port_link(struct gbe_priv *gbe_dev, bool *status) 21357771f2b4SMurali Karicheri { 21367771f2b4SMurali Karicheri u32 val = 0; 21377771f2b4SMurali Karicheri 21387771f2b4SMurali Karicheri val = readl(GBE_REG_ADDR(gbe_dev, ss_regs, rgmii_status)); 21397771f2b4SMurali Karicheri *status = !!(val & RGMII_REG_STATUS_LINK); 21407771f2b4SMurali Karicheri } 21417771f2b4SMurali Karicheri 21426f8d3f33SWingman Kwok static void netcp_ethss_update_link_state(struct gbe_priv *gbe_dev, 21436f8d3f33SWingman Kwok struct gbe_slave *slave, 21446f8d3f33SWingman Kwok struct net_device *ndev) 21456f8d3f33SWingman Kwok { 21467771f2b4SMurali Karicheri bool sw_link_state = true, phy_link_state; 21477771f2b4SMurali Karicheri int sp = slave->slave_num, link_state; 21486f8d3f33SWingman Kwok 21496f8d3f33SWingman Kwok if (!slave->open) 21506f8d3f33SWingman Kwok return; 21516f8d3f33SWingman Kwok 21527771f2b4SMurali Karicheri if (SLAVE_LINK_IS_RGMII(slave)) 21537771f2b4SMurali Karicheri netcp_2u_rgmii_get_port_link(gbe_dev, 21547771f2b4SMurali Karicheri &sw_link_state); 21557771f2b4SMurali Karicheri if (SLAVE_LINK_IS_SGMII(slave)) 21567771f2b4SMurali Karicheri sw_link_state = 21578c85151dSWingMan Kwok netcp_sgmii_get_port_link(SGMII_BASE(gbe_dev, sp), sp); 21589a391c7bSWingMan Kwok 21596f8d3f33SWingman Kwok phy_link_state = gbe_phy_link_status(slave); 21607771f2b4SMurali Karicheri link_state = phy_link_state & sw_link_state; 21616f8d3f33SWingman Kwok 21626f8d3f33SWingman Kwok if (atomic_xchg(&slave->link_state, link_state) != link_state) 21636f8d3f33SWingman Kwok netcp_ethss_link_state_action(gbe_dev, ndev, slave, 21646f8d3f33SWingman Kwok link_state); 21656f8d3f33SWingman Kwok } 21666f8d3f33SWingman Kwok 216790cff9e2SWingman Kwok static void xgbe_adjust_link(struct net_device *ndev) 216890cff9e2SWingman Kwok { 216990cff9e2SWingman Kwok struct netcp_intf *netcp = netdev_priv(ndev); 217090cff9e2SWingman Kwok struct gbe_intf *gbe_intf; 217190cff9e2SWingman Kwok 217290cff9e2SWingman Kwok gbe_intf = netcp_module_get_intf_data(&xgbe_module, netcp); 217390cff9e2SWingman Kwok if (!gbe_intf) 217490cff9e2SWingman Kwok return; 217590cff9e2SWingman Kwok 217690cff9e2SWingman Kwok netcp_ethss_update_link_state(gbe_intf->gbe_dev, gbe_intf->slave, 217790cff9e2SWingman Kwok ndev); 217890cff9e2SWingman Kwok } 217990cff9e2SWingman Kwok 21806f8d3f33SWingman Kwok static void gbe_adjust_link(struct net_device *ndev) 21816f8d3f33SWingman Kwok { 21826f8d3f33SWingman Kwok struct netcp_intf *netcp = netdev_priv(ndev); 21836f8d3f33SWingman Kwok struct gbe_intf *gbe_intf; 21846f8d3f33SWingman Kwok 21856f8d3f33SWingman Kwok gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp); 21866f8d3f33SWingman Kwok if (!gbe_intf) 21876f8d3f33SWingman Kwok return; 21886f8d3f33SWingman Kwok 21896f8d3f33SWingman Kwok netcp_ethss_update_link_state(gbe_intf->gbe_dev, gbe_intf->slave, 21906f8d3f33SWingman Kwok ndev); 21916f8d3f33SWingman Kwok } 21926f8d3f33SWingman Kwok 21936f8d3f33SWingman Kwok static void gbe_adjust_link_sec_slaves(struct net_device *ndev) 21946f8d3f33SWingman Kwok { 21956f8d3f33SWingman Kwok struct gbe_priv *gbe_dev = netdev_priv(ndev); 21966f8d3f33SWingman Kwok struct gbe_slave *slave; 21976f8d3f33SWingman Kwok 21986f8d3f33SWingman Kwok for_each_sec_slave(slave, gbe_dev) 21996f8d3f33SWingman Kwok netcp_ethss_update_link_state(gbe_dev, slave, NULL); 22006f8d3f33SWingman Kwok } 22016f8d3f33SWingman Kwok 22026f8d3f33SWingman Kwok /* Reset EMAC 22036f8d3f33SWingman Kwok * Soft reset is set and polled until clear, or until a timeout occurs 22046f8d3f33SWingman Kwok */ 22056f8d3f33SWingman Kwok static int gbe_port_reset(struct gbe_slave *slave) 22066f8d3f33SWingman Kwok { 22076f8d3f33SWingman Kwok u32 i, v; 22086f8d3f33SWingman Kwok 22096f8d3f33SWingman Kwok /* Set the soft reset bit */ 22106f8d3f33SWingman Kwok writel(SOFT_RESET, GBE_REG_ADDR(slave, emac_regs, soft_reset)); 22116f8d3f33SWingman Kwok 22126f8d3f33SWingman Kwok /* Wait for the bit to clear */ 22136f8d3f33SWingman Kwok for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) { 22146f8d3f33SWingman Kwok v = readl(GBE_REG_ADDR(slave, emac_regs, soft_reset)); 22156f8d3f33SWingman Kwok if ((v & SOFT_RESET_MASK) != SOFT_RESET) 22166f8d3f33SWingman Kwok return 0; 22176f8d3f33SWingman Kwok } 22186f8d3f33SWingman Kwok 22196f8d3f33SWingman Kwok /* Timeout on the reset */ 22206f8d3f33SWingman Kwok return GMACSL_RET_WARN_RESET_INCOMPLETE; 22216f8d3f33SWingman Kwok } 22226f8d3f33SWingman Kwok 22236f8d3f33SWingman Kwok /* Configure EMAC */ 22246f8d3f33SWingman Kwok static void gbe_port_config(struct gbe_priv *gbe_dev, struct gbe_slave *slave, 22256f8d3f33SWingman Kwok int max_rx_len) 22266f8d3f33SWingman Kwok { 22279a391c7bSWingMan Kwok void __iomem *rx_maxlen_reg; 222890cff9e2SWingman Kwok u32 xgmii_mode; 222990cff9e2SWingman Kwok 22306f8d3f33SWingman Kwok if (max_rx_len > NETCP_MAX_FRAME_SIZE) 22316f8d3f33SWingman Kwok max_rx_len = NETCP_MAX_FRAME_SIZE; 22326f8d3f33SWingman Kwok 223390cff9e2SWingman Kwok /* Enable correct MII mode at SS level */ 22342953586dSMurali Karicheri if (IS_SS_ID_XGBE(gbe_dev) && 223590cff9e2SWingman Kwok (slave->link_interface >= XGMII_LINK_MAC_PHY)) { 223690cff9e2SWingman Kwok xgmii_mode = readl(GBE_REG_ADDR(gbe_dev, ss_regs, control)); 223790cff9e2SWingman Kwok xgmii_mode |= (1 << slave->slave_num); 223890cff9e2SWingman Kwok writel(xgmii_mode, GBE_REG_ADDR(gbe_dev, ss_regs, control)); 223990cff9e2SWingman Kwok } 224090cff9e2SWingman Kwok 22419a391c7bSWingMan Kwok if (IS_SS_ID_MU(gbe_dev)) 22429a391c7bSWingMan Kwok rx_maxlen_reg = GBE_REG_ADDR(slave, port_regs, rx_maxlen); 22439a391c7bSWingMan Kwok else 22449a391c7bSWingMan Kwok rx_maxlen_reg = GBE_REG_ADDR(slave, emac_regs, rx_maxlen); 22459a391c7bSWingMan Kwok 22469a391c7bSWingMan Kwok writel(max_rx_len, rx_maxlen_reg); 22476f8d3f33SWingman Kwok writel(slave->mac_control, GBE_REG_ADDR(slave, emac_regs, mac_control)); 22486f8d3f33SWingman Kwok } 22496f8d3f33SWingman Kwok 22507025e88aSWingMan Kwok static void gbe_sgmii_rtreset(struct gbe_priv *priv, 22517025e88aSWingMan Kwok struct gbe_slave *slave, bool set) 22527025e88aSWingMan Kwok { 22537025e88aSWingMan Kwok if (SLAVE_LINK_IS_XGMII(slave)) 22547025e88aSWingMan Kwok return; 22557025e88aSWingMan Kwok 22568c85151dSWingMan Kwok netcp_sgmii_rtreset(SGMII_BASE(priv, slave->slave_num), 22578c85151dSWingMan Kwok slave->slave_num, set); 22587025e88aSWingMan Kwok } 22597025e88aSWingMan Kwok 22606f8d3f33SWingman Kwok static void gbe_slave_stop(struct gbe_intf *intf) 22616f8d3f33SWingman Kwok { 22626f8d3f33SWingman Kwok struct gbe_priv *gbe_dev = intf->gbe_dev; 22636f8d3f33SWingman Kwok struct gbe_slave *slave = intf->slave; 22646f8d3f33SWingman Kwok 2265775f9535SMurali Karicheri if (!IS_SS_ID_2U(gbe_dev)) 22667025e88aSWingMan Kwok gbe_sgmii_rtreset(gbe_dev, slave, true); 22676f8d3f33SWingman Kwok gbe_port_reset(slave); 22686f8d3f33SWingman Kwok /* Disable forwarding */ 22696f8d3f33SWingman Kwok cpsw_ale_control_set(gbe_dev->ale, slave->port_num, 22706f8d3f33SWingman Kwok ALE_PORT_STATE, ALE_PORT_STATE_DISABLE); 22716f8d3f33SWingman Kwok cpsw_ale_del_mcast(gbe_dev->ale, intf->ndev->broadcast, 22726f8d3f33SWingman Kwok 1 << slave->port_num, 0, 0); 22736f8d3f33SWingman Kwok 22746f8d3f33SWingman Kwok if (!slave->phy) 22756f8d3f33SWingman Kwok return; 22766f8d3f33SWingman Kwok 22776f8d3f33SWingman Kwok phy_stop(slave->phy); 22786f8d3f33SWingman Kwok phy_disconnect(slave->phy); 22796f8d3f33SWingman Kwok slave->phy = NULL; 22806f8d3f33SWingman Kwok } 22816f8d3f33SWingman Kwok 22826f8d3f33SWingman Kwok static void gbe_sgmii_config(struct gbe_priv *priv, struct gbe_slave *slave) 22836f8d3f33SWingman Kwok { 22848c85151dSWingMan Kwok if (SLAVE_LINK_IS_XGMII(slave)) 22858c85151dSWingMan Kwok return; 22866f8d3f33SWingman Kwok 22878c85151dSWingMan Kwok netcp_sgmii_reset(SGMII_BASE(priv, slave->slave_num), slave->slave_num); 22888c85151dSWingMan Kwok netcp_sgmii_config(SGMII_BASE(priv, slave->slave_num), slave->slave_num, 22896f8d3f33SWingman Kwok slave->link_interface); 22906f8d3f33SWingman Kwok } 22916f8d3f33SWingman Kwok 22926f8d3f33SWingman Kwok static int gbe_slave_open(struct gbe_intf *gbe_intf) 22936f8d3f33SWingman Kwok { 22946f8d3f33SWingman Kwok struct gbe_priv *priv = gbe_intf->gbe_dev; 22956f8d3f33SWingman Kwok struct gbe_slave *slave = gbe_intf->slave; 22966f8d3f33SWingman Kwok phy_interface_t phy_mode; 22976f8d3f33SWingman Kwok bool has_phy = false; 22986f8d3f33SWingman Kwok 22996f8d3f33SWingman Kwok void (*hndlr)(struct net_device *) = gbe_adjust_link; 23006f8d3f33SWingman Kwok 2301775f9535SMurali Karicheri if (!IS_SS_ID_2U(priv)) 23026f8d3f33SWingman Kwok gbe_sgmii_config(priv, slave); 23036f8d3f33SWingman Kwok gbe_port_reset(slave); 2304775f9535SMurali Karicheri if (!IS_SS_ID_2U(priv)) 23057025e88aSWingMan Kwok gbe_sgmii_rtreset(priv, slave, false); 23066f8d3f33SWingman Kwok gbe_port_config(priv, slave, priv->rx_packet_max); 23076f8d3f33SWingman Kwok gbe_set_slave_mac(slave, gbe_intf); 230865c45064SMurali Karicheri /* For NU & 2U switch, map the vlan priorities to zero 230965c45064SMurali Karicheri * as we only configure to use priority 0 231065c45064SMurali Karicheri */ 231165c45064SMurali Karicheri if (IS_SS_ID_MU(priv)) 231265c45064SMurali Karicheri writel(HOST_TX_PRI_MAP_DEFAULT, 231365c45064SMurali Karicheri GBE_REG_ADDR(slave, port_regs, rx_pri_map)); 231465c45064SMurali Karicheri 23156f8d3f33SWingman Kwok /* enable forwarding */ 23166f8d3f33SWingman Kwok cpsw_ale_control_set(priv->ale, slave->port_num, 23176f8d3f33SWingman Kwok ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); 23186f8d3f33SWingman Kwok cpsw_ale_add_mcast(priv->ale, gbe_intf->ndev->broadcast, 23196f8d3f33SWingman Kwok 1 << slave->port_num, 0, 0, ALE_MCAST_FWD_2); 23206f8d3f33SWingman Kwok 23216f8d3f33SWingman Kwok if (slave->link_interface == SGMII_LINK_MAC_PHY) { 23226f8d3f33SWingman Kwok has_phy = true; 23236f8d3f33SWingman Kwok phy_mode = PHY_INTERFACE_MODE_SGMII; 23246f8d3f33SWingman Kwok slave->phy_port_t = PORT_MII; 23256f8d3f33SWingman Kwok } else if (slave->link_interface == XGMII_LINK_MAC_PHY) { 23266f8d3f33SWingman Kwok has_phy = true; 23276f8d3f33SWingman Kwok phy_mode = PHY_INTERFACE_MODE_NA; 23286f8d3f33SWingman Kwok slave->phy_port_t = PORT_FIBRE; 23296f8d3f33SWingman Kwok } 23306f8d3f33SWingman Kwok 23316f8d3f33SWingman Kwok if (has_phy) { 23322953586dSMurali Karicheri if (IS_SS_ID_XGBE(priv)) 233390cff9e2SWingman Kwok hndlr = xgbe_adjust_link; 233490cff9e2SWingman Kwok 23356f8d3f33SWingman Kwok slave->phy = of_phy_connect(gbe_intf->ndev, 23366f8d3f33SWingman Kwok slave->phy_node, 23376f8d3f33SWingman Kwok hndlr, 0, 23386f8d3f33SWingman Kwok phy_mode); 23396f8d3f33SWingman Kwok if (!slave->phy) { 23406f8d3f33SWingman Kwok dev_err(priv->dev, "phy not found on slave %d\n", 23416f8d3f33SWingman Kwok slave->slave_num); 23426f8d3f33SWingman Kwok return -ENODEV; 23436f8d3f33SWingman Kwok } 23446f8d3f33SWingman Kwok dev_dbg(priv->dev, "phy found: id is: 0x%s\n", 234584eff6d1SAndrew Lunn phydev_name(slave->phy)); 23466f8d3f33SWingman Kwok phy_start(slave->phy); 23476f8d3f33SWingman Kwok } 23486f8d3f33SWingman Kwok return 0; 23496f8d3f33SWingman Kwok } 23506f8d3f33SWingman Kwok 23516f8d3f33SWingman Kwok static void gbe_init_host_port(struct gbe_priv *priv) 23526f8d3f33SWingman Kwok { 23536f8d3f33SWingman Kwok int bypass_en = 1; 23549a391c7bSWingMan Kwok 23559a391c7bSWingMan Kwok /* Host Tx Pri */ 23564c0ef231SWingMan Kwok if (IS_SS_ID_NU(priv) || IS_SS_ID_XGBE(priv)) 23579a391c7bSWingMan Kwok writel(HOST_TX_PRI_MAP_DEFAULT, 23589a391c7bSWingMan Kwok GBE_REG_ADDR(priv, host_port_regs, tx_pri_map)); 23599a391c7bSWingMan Kwok 23606f8d3f33SWingman Kwok /* Max length register */ 23616f8d3f33SWingman Kwok writel(NETCP_MAX_FRAME_SIZE, GBE_REG_ADDR(priv, host_port_regs, 23626f8d3f33SWingman Kwok rx_maxlen)); 23636f8d3f33SWingman Kwok 23646f8d3f33SWingman Kwok cpsw_ale_start(priv->ale); 23656f8d3f33SWingman Kwok 23666f8d3f33SWingman Kwok if (priv->enable_ale) 23676f8d3f33SWingman Kwok bypass_en = 0; 23686f8d3f33SWingman Kwok 23696f8d3f33SWingman Kwok cpsw_ale_control_set(priv->ale, 0, ALE_BYPASS, bypass_en); 23706f8d3f33SWingman Kwok 23716f8d3f33SWingman Kwok cpsw_ale_control_set(priv->ale, 0, ALE_NO_PORT_VLAN, 1); 23726f8d3f33SWingman Kwok 23736f8d3f33SWingman Kwok cpsw_ale_control_set(priv->ale, priv->host_port, 23746f8d3f33SWingman Kwok ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); 23756f8d3f33SWingman Kwok 23766f8d3f33SWingman Kwok cpsw_ale_control_set(priv->ale, 0, 23776f8d3f33SWingman Kwok ALE_PORT_UNKNOWN_VLAN_MEMBER, 23786f8d3f33SWingman Kwok GBE_PORT_MASK(priv->ale_ports)); 23796f8d3f33SWingman Kwok 23806f8d3f33SWingman Kwok cpsw_ale_control_set(priv->ale, 0, 23816f8d3f33SWingman Kwok ALE_PORT_UNKNOWN_MCAST_FLOOD, 23826f8d3f33SWingman Kwok GBE_PORT_MASK(priv->ale_ports - 1)); 23836f8d3f33SWingman Kwok 23846f8d3f33SWingman Kwok cpsw_ale_control_set(priv->ale, 0, 23856f8d3f33SWingman Kwok ALE_PORT_UNKNOWN_REG_MCAST_FLOOD, 23866f8d3f33SWingman Kwok GBE_PORT_MASK(priv->ale_ports)); 23876f8d3f33SWingman Kwok 23886f8d3f33SWingman Kwok cpsw_ale_control_set(priv->ale, 0, 23896f8d3f33SWingman Kwok ALE_PORT_UNTAGGED_EGRESS, 23906f8d3f33SWingman Kwok GBE_PORT_MASK(priv->ale_ports)); 23916f8d3f33SWingman Kwok } 23926f8d3f33SWingman Kwok 23936f8d3f33SWingman Kwok static void gbe_add_mcast_addr(struct gbe_intf *gbe_intf, u8 *addr) 23946f8d3f33SWingman Kwok { 23956f8d3f33SWingman Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 23966f8d3f33SWingman Kwok u16 vlan_id; 23976f8d3f33SWingman Kwok 23986f8d3f33SWingman Kwok cpsw_ale_add_mcast(gbe_dev->ale, addr, 23996f8d3f33SWingman Kwok GBE_PORT_MASK(gbe_dev->ale_ports), 0, 0, 24006f8d3f33SWingman Kwok ALE_MCAST_FWD_2); 24016f8d3f33SWingman Kwok for_each_set_bit(vlan_id, gbe_intf->active_vlans, VLAN_N_VID) { 24026f8d3f33SWingman Kwok cpsw_ale_add_mcast(gbe_dev->ale, addr, 24036f8d3f33SWingman Kwok GBE_PORT_MASK(gbe_dev->ale_ports), 24046f8d3f33SWingman Kwok ALE_VLAN, vlan_id, ALE_MCAST_FWD_2); 24056f8d3f33SWingman Kwok } 24066f8d3f33SWingman Kwok } 24076f8d3f33SWingman Kwok 24086f8d3f33SWingman Kwok static void gbe_add_ucast_addr(struct gbe_intf *gbe_intf, u8 *addr) 24096f8d3f33SWingman Kwok { 24106f8d3f33SWingman Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 24116f8d3f33SWingman Kwok u16 vlan_id; 24126f8d3f33SWingman Kwok 24136f8d3f33SWingman Kwok cpsw_ale_add_ucast(gbe_dev->ale, addr, gbe_dev->host_port, 0, 0); 24146f8d3f33SWingman Kwok 24156f8d3f33SWingman Kwok for_each_set_bit(vlan_id, gbe_intf->active_vlans, VLAN_N_VID) 24166f8d3f33SWingman Kwok cpsw_ale_add_ucast(gbe_dev->ale, addr, gbe_dev->host_port, 24176f8d3f33SWingman Kwok ALE_VLAN, vlan_id); 24186f8d3f33SWingman Kwok } 24196f8d3f33SWingman Kwok 24206f8d3f33SWingman Kwok static void gbe_del_mcast_addr(struct gbe_intf *gbe_intf, u8 *addr) 24216f8d3f33SWingman Kwok { 24226f8d3f33SWingman Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 24236f8d3f33SWingman Kwok u16 vlan_id; 24246f8d3f33SWingman Kwok 24256f8d3f33SWingman Kwok cpsw_ale_del_mcast(gbe_dev->ale, addr, 0, 0, 0); 24266f8d3f33SWingman Kwok 24276f8d3f33SWingman Kwok for_each_set_bit(vlan_id, gbe_intf->active_vlans, VLAN_N_VID) { 24286f8d3f33SWingman Kwok cpsw_ale_del_mcast(gbe_dev->ale, addr, 0, ALE_VLAN, vlan_id); 24296f8d3f33SWingman Kwok } 24306f8d3f33SWingman Kwok } 24316f8d3f33SWingman Kwok 24326f8d3f33SWingman Kwok static void gbe_del_ucast_addr(struct gbe_intf *gbe_intf, u8 *addr) 24336f8d3f33SWingman Kwok { 24346f8d3f33SWingman Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 24356f8d3f33SWingman Kwok u16 vlan_id; 24366f8d3f33SWingman Kwok 24376f8d3f33SWingman Kwok cpsw_ale_del_ucast(gbe_dev->ale, addr, gbe_dev->host_port, 0, 0); 24386f8d3f33SWingman Kwok 24396f8d3f33SWingman Kwok for_each_set_bit(vlan_id, gbe_intf->active_vlans, VLAN_N_VID) { 24406f8d3f33SWingman Kwok cpsw_ale_del_ucast(gbe_dev->ale, addr, gbe_dev->host_port, 24416f8d3f33SWingman Kwok ALE_VLAN, vlan_id); 24426f8d3f33SWingman Kwok } 24436f8d3f33SWingman Kwok } 24446f8d3f33SWingman Kwok 24456f8d3f33SWingman Kwok static int gbe_add_addr(void *intf_priv, struct netcp_addr *naddr) 24466f8d3f33SWingman Kwok { 24476f8d3f33SWingman Kwok struct gbe_intf *gbe_intf = intf_priv; 24486f8d3f33SWingman Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 24496f8d3f33SWingman Kwok 24506f8d3f33SWingman Kwok dev_dbg(gbe_dev->dev, "ethss adding address %pM, type %d\n", 24516f8d3f33SWingman Kwok naddr->addr, naddr->type); 24526f8d3f33SWingman Kwok 24536f8d3f33SWingman Kwok switch (naddr->type) { 24546f8d3f33SWingman Kwok case ADDR_MCAST: 24556f8d3f33SWingman Kwok case ADDR_BCAST: 24566f8d3f33SWingman Kwok gbe_add_mcast_addr(gbe_intf, naddr->addr); 24576f8d3f33SWingman Kwok break; 24586f8d3f33SWingman Kwok case ADDR_UCAST: 24596f8d3f33SWingman Kwok case ADDR_DEV: 24606f8d3f33SWingman Kwok gbe_add_ucast_addr(gbe_intf, naddr->addr); 24616f8d3f33SWingman Kwok break; 24626f8d3f33SWingman Kwok case ADDR_ANY: 24636f8d3f33SWingman Kwok /* nothing to do for promiscuous */ 24646f8d3f33SWingman Kwok default: 24656f8d3f33SWingman Kwok break; 24666f8d3f33SWingman Kwok } 24676f8d3f33SWingman Kwok 24686f8d3f33SWingman Kwok return 0; 24696f8d3f33SWingman Kwok } 24706f8d3f33SWingman Kwok 24716f8d3f33SWingman Kwok static int gbe_del_addr(void *intf_priv, struct netcp_addr *naddr) 24726f8d3f33SWingman Kwok { 24736f8d3f33SWingman Kwok struct gbe_intf *gbe_intf = intf_priv; 24746f8d3f33SWingman Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 24756f8d3f33SWingman Kwok 24766f8d3f33SWingman Kwok dev_dbg(gbe_dev->dev, "ethss deleting address %pM, type %d\n", 24776f8d3f33SWingman Kwok naddr->addr, naddr->type); 24786f8d3f33SWingman Kwok 24796f8d3f33SWingman Kwok switch (naddr->type) { 24806f8d3f33SWingman Kwok case ADDR_MCAST: 24816f8d3f33SWingman Kwok case ADDR_BCAST: 24826f8d3f33SWingman Kwok gbe_del_mcast_addr(gbe_intf, naddr->addr); 24836f8d3f33SWingman Kwok break; 24846f8d3f33SWingman Kwok case ADDR_UCAST: 24856f8d3f33SWingman Kwok case ADDR_DEV: 24866f8d3f33SWingman Kwok gbe_del_ucast_addr(gbe_intf, naddr->addr); 24876f8d3f33SWingman Kwok break; 24886f8d3f33SWingman Kwok case ADDR_ANY: 24896f8d3f33SWingman Kwok /* nothing to do for promiscuous */ 24906f8d3f33SWingman Kwok default: 24916f8d3f33SWingman Kwok break; 24926f8d3f33SWingman Kwok } 24936f8d3f33SWingman Kwok 24946f8d3f33SWingman Kwok return 0; 24956f8d3f33SWingman Kwok } 24966f8d3f33SWingman Kwok 24976f8d3f33SWingman Kwok static int gbe_add_vid(void *intf_priv, int vid) 24986f8d3f33SWingman Kwok { 24996f8d3f33SWingman Kwok struct gbe_intf *gbe_intf = intf_priv; 25006f8d3f33SWingman Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 25016f8d3f33SWingman Kwok 25026f8d3f33SWingman Kwok set_bit(vid, gbe_intf->active_vlans); 25036f8d3f33SWingman Kwok 25046f8d3f33SWingman Kwok cpsw_ale_add_vlan(gbe_dev->ale, vid, 25056f8d3f33SWingman Kwok GBE_PORT_MASK(gbe_dev->ale_ports), 25066f8d3f33SWingman Kwok GBE_MASK_NO_PORTS, 25076f8d3f33SWingman Kwok GBE_PORT_MASK(gbe_dev->ale_ports), 25086f8d3f33SWingman Kwok GBE_PORT_MASK(gbe_dev->ale_ports - 1)); 25096f8d3f33SWingman Kwok 25106f8d3f33SWingman Kwok return 0; 25116f8d3f33SWingman Kwok } 25126f8d3f33SWingman Kwok 25136f8d3f33SWingman Kwok static int gbe_del_vid(void *intf_priv, int vid) 25146f8d3f33SWingman Kwok { 25156f8d3f33SWingman Kwok struct gbe_intf *gbe_intf = intf_priv; 25166f8d3f33SWingman Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 25176f8d3f33SWingman Kwok 25186f8d3f33SWingman Kwok cpsw_ale_del_vlan(gbe_dev->ale, vid, 0); 25196f8d3f33SWingman Kwok clear_bit(vid, gbe_intf->active_vlans); 25206f8d3f33SWingman Kwok return 0; 25216f8d3f33SWingman Kwok } 25226f8d3f33SWingman Kwok 25236246168bSWingMan Kwok #if IS_ENABLED(CONFIG_TI_CPTS) 25246246168bSWingMan Kwok #define HAS_PHY_TXTSTAMP(p) ((p)->drv && (p)->drv->txtstamp) 25256246168bSWingMan Kwok #define HAS_PHY_RXTSTAMP(p) ((p)->drv && (p)->drv->rxtstamp) 25266246168bSWingMan Kwok 25276246168bSWingMan Kwok static void gbe_txtstamp(void *context, struct sk_buff *skb) 25286246168bSWingMan Kwok { 25296246168bSWingMan Kwok struct gbe_intf *gbe_intf = context; 25306246168bSWingMan Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 25316246168bSWingMan Kwok 25326246168bSWingMan Kwok cpts_tx_timestamp(gbe_dev->cpts, skb); 25336246168bSWingMan Kwok } 25346246168bSWingMan Kwok 25356246168bSWingMan Kwok static bool gbe_need_txtstamp(struct gbe_intf *gbe_intf, 25366246168bSWingMan Kwok const struct netcp_packet *p_info) 25376246168bSWingMan Kwok { 25386246168bSWingMan Kwok struct sk_buff *skb = p_info->skb; 25396246168bSWingMan Kwok 25400ccf59baSIvan Khoronzhuk return cpts_can_timestamp(gbe_intf->gbe_dev->cpts, skb); 25416246168bSWingMan Kwok } 25426246168bSWingMan Kwok 25436246168bSWingMan Kwok static int gbe_txtstamp_mark_pkt(struct gbe_intf *gbe_intf, 25446246168bSWingMan Kwok struct netcp_packet *p_info) 25456246168bSWingMan Kwok { 25466246168bSWingMan Kwok struct phy_device *phydev = p_info->skb->dev->phydev; 25476246168bSWingMan Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 25486246168bSWingMan Kwok 25496246168bSWingMan Kwok if (!(skb_shinfo(p_info->skb)->tx_flags & SKBTX_HW_TSTAMP) || 25506246168bSWingMan Kwok !cpts_is_tx_enabled(gbe_dev->cpts)) 25516246168bSWingMan Kwok return 0; 25526246168bSWingMan Kwok 25536246168bSWingMan Kwok /* If phy has the txtstamp api, assume it will do it. 25546246168bSWingMan Kwok * We mark it here because skb_tx_timestamp() is called 25556246168bSWingMan Kwok * after all the txhooks are called. 25566246168bSWingMan Kwok */ 25576246168bSWingMan Kwok if (phydev && HAS_PHY_TXTSTAMP(phydev)) { 25586246168bSWingMan Kwok skb_shinfo(p_info->skb)->tx_flags |= SKBTX_IN_PROGRESS; 25596246168bSWingMan Kwok return 0; 25606246168bSWingMan Kwok } 25616246168bSWingMan Kwok 25626246168bSWingMan Kwok if (gbe_need_txtstamp(gbe_intf, p_info)) { 25636246168bSWingMan Kwok p_info->txtstamp = gbe_txtstamp; 25646246168bSWingMan Kwok p_info->ts_context = (void *)gbe_intf; 25656246168bSWingMan Kwok skb_shinfo(p_info->skb)->tx_flags |= SKBTX_IN_PROGRESS; 25666246168bSWingMan Kwok } 25676246168bSWingMan Kwok 25686246168bSWingMan Kwok return 0; 25696246168bSWingMan Kwok } 25706246168bSWingMan Kwok 25716246168bSWingMan Kwok static int gbe_rxtstamp(struct gbe_intf *gbe_intf, struct netcp_packet *p_info) 25726246168bSWingMan Kwok { 25736246168bSWingMan Kwok struct phy_device *phydev = p_info->skb->dev->phydev; 25746246168bSWingMan Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 25756246168bSWingMan Kwok 25766246168bSWingMan Kwok if (p_info->rxtstamp_complete) 25776246168bSWingMan Kwok return 0; 25786246168bSWingMan Kwok 25796246168bSWingMan Kwok if (phydev && HAS_PHY_RXTSTAMP(phydev)) { 25806246168bSWingMan Kwok p_info->rxtstamp_complete = true; 25816246168bSWingMan Kwok return 0; 25826246168bSWingMan Kwok } 25836246168bSWingMan Kwok 25846246168bSWingMan Kwok cpts_rx_timestamp(gbe_dev->cpts, p_info->skb); 25856246168bSWingMan Kwok p_info->rxtstamp_complete = true; 25866246168bSWingMan Kwok 25876246168bSWingMan Kwok return 0; 25886246168bSWingMan Kwok } 25896246168bSWingMan Kwok 25906246168bSWingMan Kwok static int gbe_hwtstamp_get(struct gbe_intf *gbe_intf, struct ifreq *ifr) 25916246168bSWingMan Kwok { 25926246168bSWingMan Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 25936246168bSWingMan Kwok struct cpts *cpts = gbe_dev->cpts; 25946246168bSWingMan Kwok struct hwtstamp_config cfg; 25956246168bSWingMan Kwok 25966246168bSWingMan Kwok if (!cpts) 25976246168bSWingMan Kwok return -EOPNOTSUPP; 25986246168bSWingMan Kwok 25996246168bSWingMan Kwok cfg.flags = 0; 26006246168bSWingMan Kwok cfg.tx_type = cpts_is_tx_enabled(cpts) ? 26016246168bSWingMan Kwok HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; 26026246168bSWingMan Kwok cfg.rx_filter = (cpts_is_rx_enabled(cpts) ? 26036246168bSWingMan Kwok cpts->rx_enable : HWTSTAMP_FILTER_NONE); 26046246168bSWingMan Kwok 26056246168bSWingMan Kwok return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; 26066246168bSWingMan Kwok } 26076246168bSWingMan Kwok 26086246168bSWingMan Kwok static void gbe_hwtstamp(struct gbe_intf *gbe_intf) 26096246168bSWingMan Kwok { 26106246168bSWingMan Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 26116246168bSWingMan Kwok struct gbe_slave *slave = gbe_intf->slave; 26126246168bSWingMan Kwok u32 ts_en, seq_id, ctl; 26136246168bSWingMan Kwok 26146246168bSWingMan Kwok if (!cpts_is_rx_enabled(gbe_dev->cpts) && 26156246168bSWingMan Kwok !cpts_is_tx_enabled(gbe_dev->cpts)) { 26166246168bSWingMan Kwok writel(0, GBE_REG_ADDR(slave, port_regs, ts_ctl)); 26176246168bSWingMan Kwok return; 26186246168bSWingMan Kwok } 26196246168bSWingMan Kwok 26206246168bSWingMan Kwok seq_id = (30 << TS_SEQ_ID_OFS_SHIFT) | ETH_P_1588; 26216246168bSWingMan Kwok ts_en = EVENT_MSG_BITS << TS_MSG_TYPE_EN_SHIFT; 26226246168bSWingMan Kwok ctl = ETH_P_1588 | TS_TTL_NONZERO | 26236246168bSWingMan Kwok (slave->ts_ctl.dst_port_map << TS_CTL_DST_PORT_SHIFT) | 26246246168bSWingMan Kwok (slave->ts_ctl.uni ? TS_UNI_EN : 26256246168bSWingMan Kwok slave->ts_ctl.maddr_map << TS_CTL_MADDR_SHIFT); 26266246168bSWingMan Kwok 26276246168bSWingMan Kwok if (cpts_is_tx_enabled(gbe_dev->cpts)) 26286246168bSWingMan Kwok ts_en |= (TS_TX_ANX_ALL_EN | TS_TX_VLAN_LT1_EN); 26296246168bSWingMan Kwok 26306246168bSWingMan Kwok if (cpts_is_rx_enabled(gbe_dev->cpts)) 26316246168bSWingMan Kwok ts_en |= (TS_RX_ANX_ALL_EN | TS_RX_VLAN_LT1_EN); 26326246168bSWingMan Kwok 26336246168bSWingMan Kwok writel(ts_en, GBE_REG_ADDR(slave, port_regs, ts_ctl)); 26346246168bSWingMan Kwok writel(seq_id, GBE_REG_ADDR(slave, port_regs, ts_seq_ltype)); 26356246168bSWingMan Kwok writel(ctl, GBE_REG_ADDR(slave, port_regs, ts_ctl_ltype2)); 26366246168bSWingMan Kwok } 26376246168bSWingMan Kwok 26386246168bSWingMan Kwok static int gbe_hwtstamp_set(struct gbe_intf *gbe_intf, struct ifreq *ifr) 26396246168bSWingMan Kwok { 26406246168bSWingMan Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 26416246168bSWingMan Kwok struct cpts *cpts = gbe_dev->cpts; 26426246168bSWingMan Kwok struct hwtstamp_config cfg; 26436246168bSWingMan Kwok 26446246168bSWingMan Kwok if (!cpts) 26456246168bSWingMan Kwok return -EOPNOTSUPP; 26466246168bSWingMan Kwok 26476246168bSWingMan Kwok if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) 26486246168bSWingMan Kwok return -EFAULT; 26496246168bSWingMan Kwok 26506246168bSWingMan Kwok /* reserved for future extensions */ 26516246168bSWingMan Kwok if (cfg.flags) 26526246168bSWingMan Kwok return -EINVAL; 26536246168bSWingMan Kwok 26546246168bSWingMan Kwok switch (cfg.tx_type) { 26556246168bSWingMan Kwok case HWTSTAMP_TX_OFF: 26566246168bSWingMan Kwok cpts_tx_enable(cpts, 0); 26576246168bSWingMan Kwok break; 26586246168bSWingMan Kwok case HWTSTAMP_TX_ON: 26596246168bSWingMan Kwok cpts_tx_enable(cpts, 1); 26606246168bSWingMan Kwok break; 26616246168bSWingMan Kwok default: 26626246168bSWingMan Kwok return -ERANGE; 26636246168bSWingMan Kwok } 26646246168bSWingMan Kwok 26656246168bSWingMan Kwok switch (cfg.rx_filter) { 26666246168bSWingMan Kwok case HWTSTAMP_FILTER_NONE: 26676246168bSWingMan Kwok cpts_rx_enable(cpts, 0); 26686246168bSWingMan Kwok break; 26696246168bSWingMan Kwok case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: 26706246168bSWingMan Kwok case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: 26716246168bSWingMan Kwok case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: 26726246168bSWingMan Kwok cpts_rx_enable(cpts, HWTSTAMP_FILTER_PTP_V1_L4_EVENT); 26736246168bSWingMan Kwok cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; 26746246168bSWingMan Kwok break; 26756246168bSWingMan Kwok case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 26766246168bSWingMan Kwok case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: 26776246168bSWingMan Kwok case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: 26786246168bSWingMan Kwok case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 26796246168bSWingMan Kwok case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: 26806246168bSWingMan Kwok case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: 26816246168bSWingMan Kwok case HWTSTAMP_FILTER_PTP_V2_EVENT: 26826246168bSWingMan Kwok case HWTSTAMP_FILTER_PTP_V2_SYNC: 26836246168bSWingMan Kwok case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 26846246168bSWingMan Kwok cpts_rx_enable(cpts, HWTSTAMP_FILTER_PTP_V2_EVENT); 26856246168bSWingMan Kwok cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 26866246168bSWingMan Kwok break; 26876246168bSWingMan Kwok default: 26886246168bSWingMan Kwok return -ERANGE; 26896246168bSWingMan Kwok } 26906246168bSWingMan Kwok 26916246168bSWingMan Kwok gbe_hwtstamp(gbe_intf); 26926246168bSWingMan Kwok 26936246168bSWingMan Kwok return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; 26946246168bSWingMan Kwok } 26956246168bSWingMan Kwok 26966246168bSWingMan Kwok static void gbe_register_cpts(struct gbe_priv *gbe_dev) 26976246168bSWingMan Kwok { 26986246168bSWingMan Kwok if (!gbe_dev->cpts) 26996246168bSWingMan Kwok return; 27006246168bSWingMan Kwok 27016246168bSWingMan Kwok if (gbe_dev->cpts_registered > 0) 27026246168bSWingMan Kwok goto done; 27036246168bSWingMan Kwok 27046246168bSWingMan Kwok if (cpts_register(gbe_dev->cpts)) { 27056246168bSWingMan Kwok dev_err(gbe_dev->dev, "error registering cpts device\n"); 27066246168bSWingMan Kwok return; 27076246168bSWingMan Kwok } 27086246168bSWingMan Kwok 27096246168bSWingMan Kwok done: 27106246168bSWingMan Kwok ++gbe_dev->cpts_registered; 27116246168bSWingMan Kwok } 27126246168bSWingMan Kwok 27136246168bSWingMan Kwok static void gbe_unregister_cpts(struct gbe_priv *gbe_dev) 27146246168bSWingMan Kwok { 27156246168bSWingMan Kwok if (!gbe_dev->cpts || (gbe_dev->cpts_registered <= 0)) 27166246168bSWingMan Kwok return; 27176246168bSWingMan Kwok 27186246168bSWingMan Kwok if (--gbe_dev->cpts_registered) 27196246168bSWingMan Kwok return; 27206246168bSWingMan Kwok 27216246168bSWingMan Kwok cpts_unregister(gbe_dev->cpts); 27226246168bSWingMan Kwok } 27236246168bSWingMan Kwok #else 27246246168bSWingMan Kwok static inline int gbe_txtstamp_mark_pkt(struct gbe_intf *gbe_intf, 27256246168bSWingMan Kwok struct netcp_packet *p_info) 27266246168bSWingMan Kwok { 27276246168bSWingMan Kwok return 0; 27286246168bSWingMan Kwok } 27296246168bSWingMan Kwok 27306246168bSWingMan Kwok static inline int gbe_rxtstamp(struct gbe_intf *gbe_intf, 27316246168bSWingMan Kwok struct netcp_packet *p_info) 27326246168bSWingMan Kwok { 27336246168bSWingMan Kwok return 0; 27346246168bSWingMan Kwok } 27356246168bSWingMan Kwok 27366246168bSWingMan Kwok static inline int gbe_hwtstamp(struct gbe_intf *gbe_intf, 27376246168bSWingMan Kwok struct ifreq *ifr, int cmd) 27386246168bSWingMan Kwok { 27396246168bSWingMan Kwok return -EOPNOTSUPP; 27406246168bSWingMan Kwok } 27416246168bSWingMan Kwok 27426246168bSWingMan Kwok static inline void gbe_register_cpts(struct gbe_priv *gbe_dev) 27436246168bSWingMan Kwok { 27446246168bSWingMan Kwok } 27456246168bSWingMan Kwok 27466246168bSWingMan Kwok static inline void gbe_unregister_cpts(struct gbe_priv *gbe_dev) 27476246168bSWingMan Kwok { 27486246168bSWingMan Kwok } 27496246168bSWingMan Kwok 27506246168bSWingMan Kwok static inline int gbe_hwtstamp_get(struct gbe_intf *gbe_intf, struct ifreq *req) 27516246168bSWingMan Kwok { 27526246168bSWingMan Kwok return -EOPNOTSUPP; 27536246168bSWingMan Kwok } 27546246168bSWingMan Kwok 27556246168bSWingMan Kwok static inline int gbe_hwtstamp_set(struct gbe_intf *gbe_intf, struct ifreq *req) 27566246168bSWingMan Kwok { 27576246168bSWingMan Kwok return -EOPNOTSUPP; 27586246168bSWingMan Kwok } 27596246168bSWingMan Kwok #endif /* CONFIG_TI_CPTS */ 27606246168bSWingMan Kwok 27616f8d3f33SWingman Kwok static int gbe_ioctl(void *intf_priv, struct ifreq *req, int cmd) 27626f8d3f33SWingman Kwok { 27636f8d3f33SWingman Kwok struct gbe_intf *gbe_intf = intf_priv; 27646f8d3f33SWingman Kwok struct phy_device *phy = gbe_intf->slave->phy; 27656246168bSWingMan Kwok 27666246168bSWingMan Kwok if (!phy || !phy->drv->hwtstamp) { 27676246168bSWingMan Kwok switch (cmd) { 27686246168bSWingMan Kwok case SIOCGHWTSTAMP: 27696246168bSWingMan Kwok return gbe_hwtstamp_get(gbe_intf, req); 27706246168bSWingMan Kwok case SIOCSHWTSTAMP: 27716246168bSWingMan Kwok return gbe_hwtstamp_set(gbe_intf, req); 27726246168bSWingMan Kwok } 27736246168bSWingMan Kwok } 27746f8d3f33SWingman Kwok 27756f8d3f33SWingman Kwok if (phy) 27766246168bSWingMan Kwok return phy_mii_ioctl(phy, req, cmd); 27776f8d3f33SWingman Kwok 27786246168bSWingMan Kwok return -EOPNOTSUPP; 27796f8d3f33SWingman Kwok } 27806f8d3f33SWingman Kwok 2781e99e88a9SKees Cook static void netcp_ethss_timer(struct timer_list *t) 27826f8d3f33SWingman Kwok { 2783e99e88a9SKees Cook struct gbe_priv *gbe_dev = from_timer(gbe_dev, t, timer); 27846f8d3f33SWingman Kwok struct gbe_intf *gbe_intf; 27856f8d3f33SWingman Kwok struct gbe_slave *slave; 27866f8d3f33SWingman Kwok 27876f8d3f33SWingman Kwok /* Check & update SGMII link state of interfaces */ 27886f8d3f33SWingman Kwok for_each_intf(gbe_intf, gbe_dev) { 27896f8d3f33SWingman Kwok if (!gbe_intf->slave->open) 27906f8d3f33SWingman Kwok continue; 27916f8d3f33SWingman Kwok netcp_ethss_update_link_state(gbe_dev, gbe_intf->slave, 27926f8d3f33SWingman Kwok gbe_intf->ndev); 27936f8d3f33SWingman Kwok } 27946f8d3f33SWingman Kwok 27956f8d3f33SWingman Kwok /* Check & update SGMII link state of secondary ports */ 27966f8d3f33SWingman Kwok for_each_sec_slave(slave, gbe_dev) { 27976f8d3f33SWingman Kwok netcp_ethss_update_link_state(gbe_dev, slave, NULL); 27986f8d3f33SWingman Kwok } 27996f8d3f33SWingman Kwok 2800c0f54edbSWingMan Kwok /* A timer runs as a BH, no need to block them */ 2801c0f54edbSWingMan Kwok spin_lock(&gbe_dev->hw_stats_lock); 28026f8d3f33SWingman Kwok 28032953586dSMurali Karicheri if (IS_SS_ID_VER_14(gbe_dev)) 28046f8d3f33SWingman Kwok gbe_update_stats_ver14(gbe_dev, NULL); 28056f8d3f33SWingman Kwok else 28066f8d3f33SWingman Kwok gbe_update_stats(gbe_dev, NULL); 28076f8d3f33SWingman Kwok 2808c0f54edbSWingMan Kwok spin_unlock(&gbe_dev->hw_stats_lock); 28096f8d3f33SWingman Kwok 28106f8d3f33SWingman Kwok gbe_dev->timer.expires = jiffies + GBE_TIMER_INTERVAL; 28116f8d3f33SWingman Kwok add_timer(&gbe_dev->timer); 28126f8d3f33SWingman Kwok } 28136f8d3f33SWingman Kwok 28146246168bSWingMan Kwok static int gbe_txhook(int order, void *data, struct netcp_packet *p_info) 28156f8d3f33SWingman Kwok { 28166f8d3f33SWingman Kwok struct gbe_intf *gbe_intf = data; 28176f8d3f33SWingman Kwok 28186f8d3f33SWingman Kwok p_info->tx_pipe = &gbe_intf->tx_pipe; 28196246168bSWingMan Kwok 28206246168bSWingMan Kwok return gbe_txtstamp_mark_pkt(gbe_intf, p_info); 28216246168bSWingMan Kwok } 28226246168bSWingMan Kwok 28236246168bSWingMan Kwok static int gbe_rxhook(int order, void *data, struct netcp_packet *p_info) 28246246168bSWingMan Kwok { 28256246168bSWingMan Kwok struct gbe_intf *gbe_intf = data; 28266246168bSWingMan Kwok 28276246168bSWingMan Kwok return gbe_rxtstamp(gbe_intf, p_info); 28286f8d3f33SWingman Kwok } 28296f8d3f33SWingman Kwok 28306f8d3f33SWingman Kwok static int gbe_open(void *intf_priv, struct net_device *ndev) 28316f8d3f33SWingman Kwok { 28326f8d3f33SWingman Kwok struct gbe_intf *gbe_intf = intf_priv; 28336f8d3f33SWingman Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 28346f8d3f33SWingman Kwok struct netcp_intf *netcp = netdev_priv(ndev); 28356f8d3f33SWingman Kwok struct gbe_slave *slave = gbe_intf->slave; 28366f8d3f33SWingman Kwok int port_num = slave->port_num; 28374cd85a61SKaricheri, Muralidharan u32 reg, val; 28386f8d3f33SWingman Kwok int ret; 28396f8d3f33SWingman Kwok 28406f8d3f33SWingman Kwok reg = readl(GBE_REG_ADDR(gbe_dev, switch_regs, id_ver)); 28416f8d3f33SWingman Kwok dev_dbg(gbe_dev->dev, "initializing gbe version %d.%d (%d) GBE identification value 0x%x\n", 28426f8d3f33SWingman Kwok GBE_MAJOR_VERSION(reg), GBE_MINOR_VERSION(reg), 28436f8d3f33SWingman Kwok GBE_RTL_VERSION(reg), GBE_IDENT(reg)); 28446f8d3f33SWingman Kwok 28459a391c7bSWingMan Kwok /* For 10G and on NetCP 1.5, use directed to port */ 28462953586dSMurali Karicheri if (IS_SS_ID_XGBE(gbe_dev) || IS_SS_ID_MU(gbe_dev)) 2847e170f409SKaricheri, Muralidharan gbe_intf->tx_pipe.flags = SWITCH_TO_PORT_IN_TAGINFO; 28486f8d3f33SWingman Kwok 2849e170f409SKaricheri, Muralidharan if (gbe_dev->enable_ale) 2850e170f409SKaricheri, Muralidharan gbe_intf->tx_pipe.switch_to_port = 0; 2851e170f409SKaricheri, Muralidharan else 2852e170f409SKaricheri, Muralidharan gbe_intf->tx_pipe.switch_to_port = port_num; 2853e170f409SKaricheri, Muralidharan 2854e170f409SKaricheri, Muralidharan dev_dbg(gbe_dev->dev, 2855e170f409SKaricheri, Muralidharan "opened TX channel %s: %p with to port %d, flags %d\n", 28566f8d3f33SWingman Kwok gbe_intf->tx_pipe.dma_chan_name, 28576f8d3f33SWingman Kwok gbe_intf->tx_pipe.dma_channel, 2858e170f409SKaricheri, Muralidharan gbe_intf->tx_pipe.switch_to_port, 2859e170f409SKaricheri, Muralidharan gbe_intf->tx_pipe.flags); 28606f8d3f33SWingman Kwok 28616f8d3f33SWingman Kwok gbe_slave_stop(gbe_intf); 28626f8d3f33SWingman Kwok 28636f8d3f33SWingman Kwok /* disable priority elevation and enable statistics on all ports */ 28646f8d3f33SWingman Kwok writel(0, GBE_REG_ADDR(gbe_dev, switch_regs, ptype)); 28656f8d3f33SWingman Kwok 28666f8d3f33SWingman Kwok /* Control register */ 28674cd85a61SKaricheri, Muralidharan val = GBE_CTL_P0_ENABLE; 28684cd85a61SKaricheri, Muralidharan if (IS_SS_ID_MU(gbe_dev)) { 28694cd85a61SKaricheri, Muralidharan val |= ETH_SW_CTL_P0_TX_CRC_REMOVE; 28704cd85a61SKaricheri, Muralidharan netcp->hw_cap = ETH_SW_CAN_REMOVE_ETH_FCS; 28714cd85a61SKaricheri, Muralidharan } 28724cd85a61SKaricheri, Muralidharan writel(val, GBE_REG_ADDR(gbe_dev, switch_regs, control)); 28736f8d3f33SWingman Kwok 28746f8d3f33SWingman Kwok /* All statistics enabled and STAT AB visible by default */ 28759a391c7bSWingMan Kwok writel(gbe_dev->stats_en_mask, GBE_REG_ADDR(gbe_dev, switch_regs, 28766f8d3f33SWingman Kwok stat_port_en)); 28776f8d3f33SWingman Kwok 28786f8d3f33SWingman Kwok ret = gbe_slave_open(gbe_intf); 28796f8d3f33SWingman Kwok if (ret) 28806f8d3f33SWingman Kwok goto fail; 28816f8d3f33SWingman Kwok 28826246168bSWingMan Kwok netcp_register_txhook(netcp, GBE_TXHOOK_ORDER, gbe_txhook, gbe_intf); 28836246168bSWingMan Kwok netcp_register_rxhook(netcp, GBE_RXHOOK_ORDER, gbe_rxhook, gbe_intf); 28846f8d3f33SWingman Kwok 28856f8d3f33SWingman Kwok slave->open = true; 28866f8d3f33SWingman Kwok netcp_ethss_update_link_state(gbe_dev, slave, ndev); 28876246168bSWingMan Kwok 28886246168bSWingMan Kwok gbe_register_cpts(gbe_dev); 28896246168bSWingMan Kwok 28906f8d3f33SWingman Kwok return 0; 28916f8d3f33SWingman Kwok 28926f8d3f33SWingman Kwok fail: 28936f8d3f33SWingman Kwok gbe_slave_stop(gbe_intf); 28946f8d3f33SWingman Kwok return ret; 28956f8d3f33SWingman Kwok } 28966f8d3f33SWingman Kwok 28976f8d3f33SWingman Kwok static int gbe_close(void *intf_priv, struct net_device *ndev) 28986f8d3f33SWingman Kwok { 28996f8d3f33SWingman Kwok struct gbe_intf *gbe_intf = intf_priv; 29006f8d3f33SWingman Kwok struct netcp_intf *netcp = netdev_priv(ndev); 29016246168bSWingMan Kwok struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; 29026246168bSWingMan Kwok 29036246168bSWingMan Kwok gbe_unregister_cpts(gbe_dev); 29046f8d3f33SWingman Kwok 29056f8d3f33SWingman Kwok gbe_slave_stop(gbe_intf); 29066246168bSWingMan Kwok 29076246168bSWingMan Kwok netcp_unregister_rxhook(netcp, GBE_RXHOOK_ORDER, gbe_rxhook, gbe_intf); 29086246168bSWingMan Kwok netcp_unregister_txhook(netcp, GBE_TXHOOK_ORDER, gbe_txhook, gbe_intf); 29096f8d3f33SWingman Kwok 29106f8d3f33SWingman Kwok gbe_intf->slave->open = false; 29116f8d3f33SWingman Kwok atomic_set(&gbe_intf->slave->link_state, NETCP_LINK_STATE_INVALID); 29126f8d3f33SWingman Kwok return 0; 29136f8d3f33SWingman Kwok } 29146f8d3f33SWingman Kwok 29156246168bSWingMan Kwok #if IS_ENABLED(CONFIG_TI_CPTS) 29166246168bSWingMan Kwok static void init_slave_ts_ctl(struct gbe_slave *slave) 29176246168bSWingMan Kwok { 29186246168bSWingMan Kwok slave->ts_ctl.uni = 1; 29196246168bSWingMan Kwok slave->ts_ctl.dst_port_map = 29206246168bSWingMan Kwok (TS_CTL_DST_PORT >> TS_CTL_DST_PORT_SHIFT) & 0x3; 29216246168bSWingMan Kwok slave->ts_ctl.maddr_map = 29226246168bSWingMan Kwok (TS_CTL_MADDR_ALL >> TS_CTL_MADDR_SHIFT) & 0x1f; 29236246168bSWingMan Kwok } 29246246168bSWingMan Kwok 29256246168bSWingMan Kwok #else 29266246168bSWingMan Kwok static void init_slave_ts_ctl(struct gbe_slave *slave) 29276246168bSWingMan Kwok { 29286246168bSWingMan Kwok } 29296246168bSWingMan Kwok #endif /* CONFIG_TI_CPTS */ 29306246168bSWingMan Kwok 29316f8d3f33SWingman Kwok static int init_slave(struct gbe_priv *gbe_dev, struct gbe_slave *slave, 29326f8d3f33SWingman Kwok struct device_node *node) 29336f8d3f33SWingman Kwok { 29346f8d3f33SWingman Kwok int port_reg_num; 29356f8d3f33SWingman Kwok u32 port_reg_ofs, emac_reg_ofs; 29369a391c7bSWingMan Kwok u32 port_reg_blk_sz, emac_reg_blk_sz; 29376f8d3f33SWingman Kwok 29386f8d3f33SWingman Kwok if (of_property_read_u32(node, "slave-port", &slave->slave_num)) { 29396f8d3f33SWingman Kwok dev_err(gbe_dev->dev, "missing slave-port parameter\n"); 29406f8d3f33SWingman Kwok return -EINVAL; 29416f8d3f33SWingman Kwok } 29426f8d3f33SWingman Kwok 29436f8d3f33SWingman Kwok if (of_property_read_u32(node, "link-interface", 29446f8d3f33SWingman Kwok &slave->link_interface)) { 29456f8d3f33SWingman Kwok dev_warn(gbe_dev->dev, 29466f8d3f33SWingman Kwok "missing link-interface value defaulting to 1G mac-phy link\n"); 29476f8d3f33SWingman Kwok slave->link_interface = SGMII_LINK_MAC_PHY; 29486f8d3f33SWingman Kwok } 29496f8d3f33SWingman Kwok 29506f8d3f33SWingman Kwok slave->open = false; 29510cead3a6SKaricheri, Muralidharan if ((slave->link_interface == SGMII_LINK_MAC_PHY) || 2952478e9a5fSMurali Karicheri (slave->link_interface == RGMII_LINK_MAC_PHY) || 29530cead3a6SKaricheri, Muralidharan (slave->link_interface == XGMII_LINK_MAC_PHY)) 29546f8d3f33SWingman Kwok slave->phy_node = of_parse_phandle(node, "phy-handle", 0); 29556f8d3f33SWingman Kwok slave->port_num = gbe_get_slave_port(gbe_dev, slave->slave_num); 29566f8d3f33SWingman Kwok 295790cff9e2SWingman Kwok if (slave->link_interface >= XGMII_LINK_MAC_PHY) 295890cff9e2SWingman Kwok slave->mac_control = GBE_DEF_10G_MAC_CONTROL; 295990cff9e2SWingman Kwok else 29606f8d3f33SWingman Kwok slave->mac_control = GBE_DEF_1G_MAC_CONTROL; 29616f8d3f33SWingman Kwok 29626f8d3f33SWingman Kwok /* Emac regs memmap are contiguous but port regs are not */ 29636f8d3f33SWingman Kwok port_reg_num = slave->slave_num; 29642953586dSMurali Karicheri if (IS_SS_ID_VER_14(gbe_dev)) { 29656f8d3f33SWingman Kwok if (slave->slave_num > 1) { 29666f8d3f33SWingman Kwok port_reg_ofs = GBE13_SLAVE_PORT2_OFFSET; 29676f8d3f33SWingman Kwok port_reg_num -= 2; 29686f8d3f33SWingman Kwok } else { 29696f8d3f33SWingman Kwok port_reg_ofs = GBE13_SLAVE_PORT_OFFSET; 29706f8d3f33SWingman Kwok } 29719a391c7bSWingMan Kwok emac_reg_ofs = GBE13_EMAC_OFFSET; 29729a391c7bSWingMan Kwok port_reg_blk_sz = 0x30; 29739a391c7bSWingMan Kwok emac_reg_blk_sz = 0x40; 29749a391c7bSWingMan Kwok } else if (IS_SS_ID_MU(gbe_dev)) { 29759a391c7bSWingMan Kwok port_reg_ofs = GBENU_SLAVE_PORT_OFFSET; 29769a391c7bSWingMan Kwok emac_reg_ofs = GBENU_EMAC_OFFSET; 29779a391c7bSWingMan Kwok port_reg_blk_sz = 0x1000; 29789a391c7bSWingMan Kwok emac_reg_blk_sz = 0x1000; 29792953586dSMurali Karicheri } else if (IS_SS_ID_XGBE(gbe_dev)) { 298090cff9e2SWingman Kwok port_reg_ofs = XGBE10_SLAVE_PORT_OFFSET; 29819a391c7bSWingMan Kwok emac_reg_ofs = XGBE10_EMAC_OFFSET; 29829a391c7bSWingMan Kwok port_reg_blk_sz = 0x30; 29839a391c7bSWingMan Kwok emac_reg_blk_sz = 0x40; 29846f8d3f33SWingman Kwok } else { 29856f8d3f33SWingman Kwok dev_err(gbe_dev->dev, "unknown ethss(0x%x)\n", 29866f8d3f33SWingman Kwok gbe_dev->ss_version); 29876f8d3f33SWingman Kwok return -EINVAL; 29886f8d3f33SWingman Kwok } 29896f8d3f33SWingman Kwok 299021e0e0ddSKaricheri, Muralidharan slave->port_regs = gbe_dev->switch_regs + port_reg_ofs + 29919a391c7bSWingMan Kwok (port_reg_blk_sz * port_reg_num); 299221e0e0ddSKaricheri, Muralidharan slave->emac_regs = gbe_dev->switch_regs + emac_reg_ofs + 29939a391c7bSWingMan Kwok (emac_reg_blk_sz * slave->slave_num); 29946f8d3f33SWingman Kwok 29952953586dSMurali Karicheri if (IS_SS_ID_VER_14(gbe_dev)) { 29966f8d3f33SWingman Kwok /* Initialize slave port register offsets */ 29976f8d3f33SWingman Kwok GBE_SET_REG_OFS(slave, port_regs, port_vlan); 29986f8d3f33SWingman Kwok GBE_SET_REG_OFS(slave, port_regs, tx_pri_map); 29996f8d3f33SWingman Kwok GBE_SET_REG_OFS(slave, port_regs, sa_lo); 30006f8d3f33SWingman Kwok GBE_SET_REG_OFS(slave, port_regs, sa_hi); 30016f8d3f33SWingman Kwok GBE_SET_REG_OFS(slave, port_regs, ts_ctl); 30026f8d3f33SWingman Kwok GBE_SET_REG_OFS(slave, port_regs, ts_seq_ltype); 30036f8d3f33SWingman Kwok GBE_SET_REG_OFS(slave, port_regs, ts_vlan); 30046f8d3f33SWingman Kwok GBE_SET_REG_OFS(slave, port_regs, ts_ctl_ltype2); 30056f8d3f33SWingman Kwok GBE_SET_REG_OFS(slave, port_regs, ts_ctl2); 30066f8d3f33SWingman Kwok 30076f8d3f33SWingman Kwok /* Initialize EMAC register offsets */ 30086f8d3f33SWingman Kwok GBE_SET_REG_OFS(slave, emac_regs, mac_control); 30096f8d3f33SWingman Kwok GBE_SET_REG_OFS(slave, emac_regs, soft_reset); 30106f8d3f33SWingman Kwok GBE_SET_REG_OFS(slave, emac_regs, rx_maxlen); 30116f8d3f33SWingman Kwok 30129a391c7bSWingMan Kwok } else if (IS_SS_ID_MU(gbe_dev)) { 30139a391c7bSWingMan Kwok /* Initialize slave port register offsets */ 30149a391c7bSWingMan Kwok GBENU_SET_REG_OFS(slave, port_regs, port_vlan); 30159a391c7bSWingMan Kwok GBENU_SET_REG_OFS(slave, port_regs, tx_pri_map); 301665c45064SMurali Karicheri GBENU_SET_REG_OFS(slave, port_regs, rx_pri_map); 30179a391c7bSWingMan Kwok GBENU_SET_REG_OFS(slave, port_regs, sa_lo); 30189a391c7bSWingMan Kwok GBENU_SET_REG_OFS(slave, port_regs, sa_hi); 30199a391c7bSWingMan Kwok GBENU_SET_REG_OFS(slave, port_regs, ts_ctl); 30209a391c7bSWingMan Kwok GBENU_SET_REG_OFS(slave, port_regs, ts_seq_ltype); 30219a391c7bSWingMan Kwok GBENU_SET_REG_OFS(slave, port_regs, ts_vlan); 30229a391c7bSWingMan Kwok GBENU_SET_REG_OFS(slave, port_regs, ts_ctl_ltype2); 30239a391c7bSWingMan Kwok GBENU_SET_REG_OFS(slave, port_regs, ts_ctl2); 30249a391c7bSWingMan Kwok GBENU_SET_REG_OFS(slave, port_regs, rx_maxlen); 30259a391c7bSWingMan Kwok 30269a391c7bSWingMan Kwok /* Initialize EMAC register offsets */ 30279a391c7bSWingMan Kwok GBENU_SET_REG_OFS(slave, emac_regs, mac_control); 30289a391c7bSWingMan Kwok GBENU_SET_REG_OFS(slave, emac_regs, soft_reset); 30299a391c7bSWingMan Kwok 30302953586dSMurali Karicheri } else if (IS_SS_ID_XGBE(gbe_dev)) { 303190cff9e2SWingman Kwok /* Initialize slave port register offsets */ 303290cff9e2SWingman Kwok XGBE_SET_REG_OFS(slave, port_regs, port_vlan); 303390cff9e2SWingman Kwok XGBE_SET_REG_OFS(slave, port_regs, tx_pri_map); 303490cff9e2SWingman Kwok XGBE_SET_REG_OFS(slave, port_regs, sa_lo); 303590cff9e2SWingman Kwok XGBE_SET_REG_OFS(slave, port_regs, sa_hi); 303690cff9e2SWingman Kwok XGBE_SET_REG_OFS(slave, port_regs, ts_ctl); 303790cff9e2SWingman Kwok XGBE_SET_REG_OFS(slave, port_regs, ts_seq_ltype); 303890cff9e2SWingman Kwok XGBE_SET_REG_OFS(slave, port_regs, ts_vlan); 303990cff9e2SWingman Kwok XGBE_SET_REG_OFS(slave, port_regs, ts_ctl_ltype2); 304090cff9e2SWingman Kwok XGBE_SET_REG_OFS(slave, port_regs, ts_ctl2); 304190cff9e2SWingman Kwok 304290cff9e2SWingman Kwok /* Initialize EMAC register offsets */ 304390cff9e2SWingman Kwok XGBE_SET_REG_OFS(slave, emac_regs, mac_control); 304490cff9e2SWingman Kwok XGBE_SET_REG_OFS(slave, emac_regs, soft_reset); 304590cff9e2SWingman Kwok XGBE_SET_REG_OFS(slave, emac_regs, rx_maxlen); 30466f8d3f33SWingman Kwok } 30476f8d3f33SWingman Kwok 30486f8d3f33SWingman Kwok atomic_set(&slave->link_state, NETCP_LINK_STATE_INVALID); 30496246168bSWingMan Kwok 30506246168bSWingMan Kwok init_slave_ts_ctl(slave); 30516f8d3f33SWingman Kwok return 0; 30526f8d3f33SWingman Kwok } 30536f8d3f33SWingman Kwok 30546f8d3f33SWingman Kwok static void init_secondary_ports(struct gbe_priv *gbe_dev, 30556f8d3f33SWingman Kwok struct device_node *node) 30566f8d3f33SWingman Kwok { 30576f8d3f33SWingman Kwok struct device *dev = gbe_dev->dev; 30586f8d3f33SWingman Kwok phy_interface_t phy_mode; 30596f8d3f33SWingman Kwok struct gbe_priv **priv; 30606f8d3f33SWingman Kwok struct device_node *port; 30616f8d3f33SWingman Kwok struct gbe_slave *slave; 30626f8d3f33SWingman Kwok bool mac_phy_link = false; 30636f8d3f33SWingman Kwok 30646f8d3f33SWingman Kwok for_each_child_of_node(node, port) { 30656f8d3f33SWingman Kwok slave = devm_kzalloc(dev, sizeof(*slave), GFP_KERNEL); 30666f8d3f33SWingman Kwok if (!slave) { 306711a9ec43SColin Ian King dev_err(dev, "memory alloc failed for secondary port(%s), skipping...\n", 30686f8d3f33SWingman Kwok port->name); 30696f8d3f33SWingman Kwok continue; 30706f8d3f33SWingman Kwok } 30716f8d3f33SWingman Kwok 30726f8d3f33SWingman Kwok if (init_slave(gbe_dev, slave, port)) { 30736f8d3f33SWingman Kwok dev_err(dev, 30746f8d3f33SWingman Kwok "Failed to initialize secondary port(%s), skipping...\n", 30756f8d3f33SWingman Kwok port->name); 30766f8d3f33SWingman Kwok devm_kfree(dev, slave); 30776f8d3f33SWingman Kwok continue; 30786f8d3f33SWingman Kwok } 30796f8d3f33SWingman Kwok 3080775f9535SMurali Karicheri if (!IS_SS_ID_2U(gbe_dev)) 30816f8d3f33SWingman Kwok gbe_sgmii_config(gbe_dev, slave); 30826f8d3f33SWingman Kwok gbe_port_reset(slave); 30836f8d3f33SWingman Kwok gbe_port_config(gbe_dev, slave, gbe_dev->rx_packet_max); 30846f8d3f33SWingman Kwok list_add_tail(&slave->slave_list, &gbe_dev->secondary_slaves); 30856f8d3f33SWingman Kwok gbe_dev->num_slaves++; 308690cff9e2SWingman Kwok if ((slave->link_interface == SGMII_LINK_MAC_PHY) || 308790cff9e2SWingman Kwok (slave->link_interface == XGMII_LINK_MAC_PHY)) 30886f8d3f33SWingman Kwok mac_phy_link = true; 30896f8d3f33SWingman Kwok 30906f8d3f33SWingman Kwok slave->open = true; 3091bd252796SJulia Lawall if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) { 3092bd252796SJulia Lawall of_node_put(port); 30939a391c7bSWingMan Kwok break; 30946f8d3f33SWingman Kwok } 3095bd252796SJulia Lawall } 30966f8d3f33SWingman Kwok 30976f8d3f33SWingman Kwok /* of_phy_connect() is needed only for MAC-PHY interface */ 30986f8d3f33SWingman Kwok if (!mac_phy_link) 30996f8d3f33SWingman Kwok return; 31006f8d3f33SWingman Kwok 31016f8d3f33SWingman Kwok /* Allocate dummy netdev device for attaching to phy device */ 31026f8d3f33SWingman Kwok gbe_dev->dummy_ndev = alloc_netdev(sizeof(gbe_dev), "dummy", 31036f8d3f33SWingman Kwok NET_NAME_UNKNOWN, ether_setup); 31046f8d3f33SWingman Kwok if (!gbe_dev->dummy_ndev) { 31056f8d3f33SWingman Kwok dev_err(dev, 31066f8d3f33SWingman Kwok "Failed to allocate dummy netdev for secondary ports, skipping phy_connect()...\n"); 31076f8d3f33SWingman Kwok return; 31086f8d3f33SWingman Kwok } 31096f8d3f33SWingman Kwok priv = netdev_priv(gbe_dev->dummy_ndev); 31106f8d3f33SWingman Kwok *priv = gbe_dev; 31116f8d3f33SWingman Kwok 31126f8d3f33SWingman Kwok if (slave->link_interface == SGMII_LINK_MAC_PHY) { 31136f8d3f33SWingman Kwok phy_mode = PHY_INTERFACE_MODE_SGMII; 31146f8d3f33SWingman Kwok slave->phy_port_t = PORT_MII; 3115478e9a5fSMurali Karicheri } else if (slave->link_interface == RGMII_LINK_MAC_PHY) { 3116478e9a5fSMurali Karicheri phy_mode = PHY_INTERFACE_MODE_RGMII; 3117478e9a5fSMurali Karicheri slave->phy_port_t = PORT_MII; 31186f8d3f33SWingman Kwok } else { 31196f8d3f33SWingman Kwok phy_mode = PHY_INTERFACE_MODE_NA; 31206f8d3f33SWingman Kwok slave->phy_port_t = PORT_FIBRE; 31216f8d3f33SWingman Kwok } 31226f8d3f33SWingman Kwok 31236f8d3f33SWingman Kwok for_each_sec_slave(slave, gbe_dev) { 312490cff9e2SWingman Kwok if ((slave->link_interface != SGMII_LINK_MAC_PHY) && 3125478e9a5fSMurali Karicheri (slave->link_interface != RGMII_LINK_MAC_PHY) && 312690cff9e2SWingman Kwok (slave->link_interface != XGMII_LINK_MAC_PHY)) 31276f8d3f33SWingman Kwok continue; 31286f8d3f33SWingman Kwok slave->phy = 31296f8d3f33SWingman Kwok of_phy_connect(gbe_dev->dummy_ndev, 31306f8d3f33SWingman Kwok slave->phy_node, 31316f8d3f33SWingman Kwok gbe_adjust_link_sec_slaves, 31326f8d3f33SWingman Kwok 0, phy_mode); 31336f8d3f33SWingman Kwok if (!slave->phy) { 31346f8d3f33SWingman Kwok dev_err(dev, "phy not found for slave %d\n", 31356f8d3f33SWingman Kwok slave->slave_num); 31366f8d3f33SWingman Kwok slave->phy = NULL; 31376f8d3f33SWingman Kwok } else { 31386f8d3f33SWingman Kwok dev_dbg(dev, "phy found: id is: 0x%s\n", 313984eff6d1SAndrew Lunn phydev_name(slave->phy)); 31406f8d3f33SWingman Kwok phy_start(slave->phy); 31416f8d3f33SWingman Kwok } 31426f8d3f33SWingman Kwok } 31436f8d3f33SWingman Kwok } 31446f8d3f33SWingman Kwok 31456f8d3f33SWingman Kwok static void free_secondary_ports(struct gbe_priv *gbe_dev) 31466f8d3f33SWingman Kwok { 31476f8d3f33SWingman Kwok struct gbe_slave *slave; 31486f8d3f33SWingman Kwok 3149c20afae7SKaricheri, Muralidharan while (!list_empty(&gbe_dev->secondary_slaves)) { 31506f8d3f33SWingman Kwok slave = first_sec_slave(gbe_dev); 3151c20afae7SKaricheri, Muralidharan 31526f8d3f33SWingman Kwok if (slave->phy) 31536f8d3f33SWingman Kwok phy_disconnect(slave->phy); 31546f8d3f33SWingman Kwok list_del(&slave->slave_list); 31556f8d3f33SWingman Kwok } 31566f8d3f33SWingman Kwok if (gbe_dev->dummy_ndev) 31576f8d3f33SWingman Kwok free_netdev(gbe_dev->dummy_ndev); 31586f8d3f33SWingman Kwok } 31596f8d3f33SWingman Kwok 316090cff9e2SWingman Kwok static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev, 316190cff9e2SWingman Kwok struct device_node *node) 316290cff9e2SWingman Kwok { 316390cff9e2SWingman Kwok struct resource res; 316490cff9e2SWingman Kwok void __iomem *regs; 316590cff9e2SWingman Kwok int ret, i; 316690cff9e2SWingman Kwok 31679a391c7bSWingMan Kwok ret = of_address_to_resource(node, XGBE_SS_REG_INDEX, &res); 316890cff9e2SWingman Kwok if (ret) { 316921e0e0ddSKaricheri, Muralidharan dev_err(gbe_dev->dev, 317021e0e0ddSKaricheri, Muralidharan "Can't xlate xgbe of node(%s) ss address at %d\n", 317121e0e0ddSKaricheri, Muralidharan node->name, XGBE_SS_REG_INDEX); 317290cff9e2SWingman Kwok return ret; 317390cff9e2SWingman Kwok } 317490cff9e2SWingman Kwok 317590cff9e2SWingman Kwok regs = devm_ioremap_resource(gbe_dev->dev, &res); 317690cff9e2SWingman Kwok if (IS_ERR(regs)) { 317721e0e0ddSKaricheri, Muralidharan dev_err(gbe_dev->dev, "Failed to map xgbe ss register base\n"); 317890cff9e2SWingman Kwok return PTR_ERR(regs); 317990cff9e2SWingman Kwok } 318090cff9e2SWingman Kwok gbe_dev->ss_regs = regs; 318190cff9e2SWingman Kwok 318221e0e0ddSKaricheri, Muralidharan ret = of_address_to_resource(node, XGBE_SM_REG_INDEX, &res); 318321e0e0ddSKaricheri, Muralidharan if (ret) { 318421e0e0ddSKaricheri, Muralidharan dev_err(gbe_dev->dev, 318521e0e0ddSKaricheri, Muralidharan "Can't xlate xgbe of node(%s) sm address at %d\n", 318621e0e0ddSKaricheri, Muralidharan node->name, XGBE_SM_REG_INDEX); 318721e0e0ddSKaricheri, Muralidharan return ret; 318821e0e0ddSKaricheri, Muralidharan } 318921e0e0ddSKaricheri, Muralidharan 319021e0e0ddSKaricheri, Muralidharan regs = devm_ioremap_resource(gbe_dev->dev, &res); 319121e0e0ddSKaricheri, Muralidharan if (IS_ERR(regs)) { 319221e0e0ddSKaricheri, Muralidharan dev_err(gbe_dev->dev, "Failed to map xgbe sm register base\n"); 319321e0e0ddSKaricheri, Muralidharan return PTR_ERR(regs); 319421e0e0ddSKaricheri, Muralidharan } 319521e0e0ddSKaricheri, Muralidharan gbe_dev->switch_regs = regs; 319621e0e0ddSKaricheri, Muralidharan 319790cff9e2SWingman Kwok ret = of_address_to_resource(node, XGBE_SERDES_REG_INDEX, &res); 319890cff9e2SWingman Kwok if (ret) { 319921e0e0ddSKaricheri, Muralidharan dev_err(gbe_dev->dev, 320021e0e0ddSKaricheri, Muralidharan "Can't xlate xgbe serdes of node(%s) address at %d\n", 320121e0e0ddSKaricheri, Muralidharan node->name, XGBE_SERDES_REG_INDEX); 320290cff9e2SWingman Kwok return ret; 320390cff9e2SWingman Kwok } 320490cff9e2SWingman Kwok 320590cff9e2SWingman Kwok regs = devm_ioremap_resource(gbe_dev->dev, &res); 320690cff9e2SWingman Kwok if (IS_ERR(regs)) { 320790cff9e2SWingman Kwok dev_err(gbe_dev->dev, "Failed to map xgbe serdes register base\n"); 320890cff9e2SWingman Kwok return PTR_ERR(regs); 320990cff9e2SWingman Kwok } 321090cff9e2SWingman Kwok gbe_dev->xgbe_serdes_regs = regs; 321190cff9e2SWingman Kwok 3212489e8a2fSWingMan Kwok gbe_dev->num_stats_mods = gbe_dev->max_num_ports; 3213208c6b9aSWingMan Kwok gbe_dev->et_stats = xgbe10_et_stats; 3214208c6b9aSWingMan Kwok gbe_dev->num_et_stats = ARRAY_SIZE(xgbe10_et_stats); 3215208c6b9aSWingMan Kwok 321690cff9e2SWingman Kwok gbe_dev->hw_stats = devm_kzalloc(gbe_dev->dev, 3217208c6b9aSWingMan Kwok gbe_dev->num_et_stats * sizeof(u64), 321890cff9e2SWingman Kwok GFP_KERNEL); 321990cff9e2SWingman Kwok if (!gbe_dev->hw_stats) { 322090cff9e2SWingman Kwok dev_err(gbe_dev->dev, "hw_stats memory allocation failed\n"); 322190cff9e2SWingman Kwok return -ENOMEM; 322290cff9e2SWingman Kwok } 322390cff9e2SWingman Kwok 3224489e8a2fSWingMan Kwok gbe_dev->hw_stats_prev = 3225489e8a2fSWingMan Kwok devm_kzalloc(gbe_dev->dev, 3226489e8a2fSWingMan Kwok gbe_dev->num_et_stats * sizeof(u32), 3227489e8a2fSWingMan Kwok GFP_KERNEL); 3228489e8a2fSWingMan Kwok if (!gbe_dev->hw_stats_prev) { 3229489e8a2fSWingMan Kwok dev_err(gbe_dev->dev, 3230489e8a2fSWingMan Kwok "hw_stats_prev memory allocation failed\n"); 3231489e8a2fSWingMan Kwok return -ENOMEM; 3232489e8a2fSWingMan Kwok } 3233489e8a2fSWingMan Kwok 323490cff9e2SWingman Kwok gbe_dev->ss_version = XGBE_SS_VERSION_10; 323590cff9e2SWingman Kwok gbe_dev->sgmii_port_regs = gbe_dev->ss_regs + 323690cff9e2SWingman Kwok XGBE10_SGMII_MODULE_OFFSET; 323790cff9e2SWingman Kwok gbe_dev->host_port_regs = gbe_dev->ss_regs + XGBE10_HOST_PORT_OFFSET; 323890cff9e2SWingman Kwok 32399a391c7bSWingMan Kwok for (i = 0; i < gbe_dev->max_num_ports; i++) 324021e0e0ddSKaricheri, Muralidharan gbe_dev->hw_stats_regs[i] = gbe_dev->switch_regs + 324190cff9e2SWingman Kwok XGBE10_HW_STATS_OFFSET + (GBE_HW_STATS_REG_MAP_SZ * i); 324290cff9e2SWingman Kwok 32439a391c7bSWingMan Kwok gbe_dev->ale_reg = gbe_dev->switch_regs + XGBE10_ALE_OFFSET; 32446246168bSWingMan Kwok gbe_dev->cpts_reg = gbe_dev->switch_regs + XGBE10_CPTS_OFFSET; 32459a391c7bSWingMan Kwok gbe_dev->ale_ports = gbe_dev->max_num_ports; 324690cff9e2SWingman Kwok gbe_dev->host_port = XGBE10_HOST_PORT_NUM; 324790cff9e2SWingman Kwok gbe_dev->ale_entries = XGBE10_NUM_ALE_ENTRIES; 32489a391c7bSWingMan Kwok gbe_dev->stats_en_mask = (1 << (gbe_dev->max_num_ports)) - 1; 324990cff9e2SWingman Kwok 325090cff9e2SWingman Kwok /* Subsystem registers */ 325190cff9e2SWingman Kwok XGBE_SET_REG_OFS(gbe_dev, ss_regs, id_ver); 325290cff9e2SWingman Kwok XGBE_SET_REG_OFS(gbe_dev, ss_regs, control); 325390cff9e2SWingman Kwok 325490cff9e2SWingman Kwok /* Switch module registers */ 325590cff9e2SWingman Kwok XGBE_SET_REG_OFS(gbe_dev, switch_regs, id_ver); 325690cff9e2SWingman Kwok XGBE_SET_REG_OFS(gbe_dev, switch_regs, control); 325790cff9e2SWingman Kwok XGBE_SET_REG_OFS(gbe_dev, switch_regs, ptype); 325890cff9e2SWingman Kwok XGBE_SET_REG_OFS(gbe_dev, switch_regs, stat_port_en); 325990cff9e2SWingman Kwok XGBE_SET_REG_OFS(gbe_dev, switch_regs, flow_control); 326090cff9e2SWingman Kwok 326190cff9e2SWingman Kwok /* Host port registers */ 326290cff9e2SWingman Kwok XGBE_SET_REG_OFS(gbe_dev, host_port_regs, port_vlan); 326390cff9e2SWingman Kwok XGBE_SET_REG_OFS(gbe_dev, host_port_regs, tx_pri_map); 326490cff9e2SWingman Kwok XGBE_SET_REG_OFS(gbe_dev, host_port_regs, rx_maxlen); 326590cff9e2SWingman Kwok return 0; 326690cff9e2SWingman Kwok } 326790cff9e2SWingman Kwok 32686f8d3f33SWingman Kwok static int get_gbe_resource_version(struct gbe_priv *gbe_dev, 32696f8d3f33SWingman Kwok struct device_node *node) 32706f8d3f33SWingman Kwok { 32716f8d3f33SWingman Kwok struct resource res; 32726f8d3f33SWingman Kwok void __iomem *regs; 32736f8d3f33SWingman Kwok int ret; 32746f8d3f33SWingman Kwok 327521e0e0ddSKaricheri, Muralidharan ret = of_address_to_resource(node, GBE_SS_REG_INDEX, &res); 32766f8d3f33SWingman Kwok if (ret) { 327721e0e0ddSKaricheri, Muralidharan dev_err(gbe_dev->dev, 327821e0e0ddSKaricheri, Muralidharan "Can't translate of node(%s) of gbe ss address at %d\n", 327921e0e0ddSKaricheri, Muralidharan node->name, GBE_SS_REG_INDEX); 32806f8d3f33SWingman Kwok return ret; 32816f8d3f33SWingman Kwok } 32826f8d3f33SWingman Kwok 32836f8d3f33SWingman Kwok regs = devm_ioremap_resource(gbe_dev->dev, &res); 32846f8d3f33SWingman Kwok if (IS_ERR(regs)) { 32856f8d3f33SWingman Kwok dev_err(gbe_dev->dev, "Failed to map gbe register base\n"); 32866f8d3f33SWingman Kwok return PTR_ERR(regs); 32876f8d3f33SWingman Kwok } 32886f8d3f33SWingman Kwok gbe_dev->ss_regs = regs; 32896f8d3f33SWingman Kwok gbe_dev->ss_version = readl(gbe_dev->ss_regs); 32906f8d3f33SWingman Kwok return 0; 32916f8d3f33SWingman Kwok } 32926f8d3f33SWingman Kwok 32936f8d3f33SWingman Kwok static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev, 32946f8d3f33SWingman Kwok struct device_node *node) 32956f8d3f33SWingman Kwok { 329621e0e0ddSKaricheri, Muralidharan struct resource res; 32976f8d3f33SWingman Kwok void __iomem *regs; 329821e0e0ddSKaricheri, Muralidharan int i, ret; 329921e0e0ddSKaricheri, Muralidharan 330021e0e0ddSKaricheri, Muralidharan ret = of_address_to_resource(node, GBE_SGMII34_REG_INDEX, &res); 330121e0e0ddSKaricheri, Muralidharan if (ret) { 330221e0e0ddSKaricheri, Muralidharan dev_err(gbe_dev->dev, 330321e0e0ddSKaricheri, Muralidharan "Can't translate of gbe node(%s) address at index %d\n", 330421e0e0ddSKaricheri, Muralidharan node->name, GBE_SGMII34_REG_INDEX); 330521e0e0ddSKaricheri, Muralidharan return ret; 330621e0e0ddSKaricheri, Muralidharan } 330721e0e0ddSKaricheri, Muralidharan 330821e0e0ddSKaricheri, Muralidharan regs = devm_ioremap_resource(gbe_dev->dev, &res); 330921e0e0ddSKaricheri, Muralidharan if (IS_ERR(regs)) { 331021e0e0ddSKaricheri, Muralidharan dev_err(gbe_dev->dev, 331121e0e0ddSKaricheri, Muralidharan "Failed to map gbe sgmii port34 register base\n"); 331221e0e0ddSKaricheri, Muralidharan return PTR_ERR(regs); 331321e0e0ddSKaricheri, Muralidharan } 331421e0e0ddSKaricheri, Muralidharan gbe_dev->sgmii_port34_regs = regs; 331521e0e0ddSKaricheri, Muralidharan 331621e0e0ddSKaricheri, Muralidharan ret = of_address_to_resource(node, GBE_SM_REG_INDEX, &res); 331721e0e0ddSKaricheri, Muralidharan if (ret) { 331821e0e0ddSKaricheri, Muralidharan dev_err(gbe_dev->dev, 331921e0e0ddSKaricheri, Muralidharan "Can't translate of gbe node(%s) address at index %d\n", 332021e0e0ddSKaricheri, Muralidharan node->name, GBE_SM_REG_INDEX); 332121e0e0ddSKaricheri, Muralidharan return ret; 332221e0e0ddSKaricheri, Muralidharan } 332321e0e0ddSKaricheri, Muralidharan 332421e0e0ddSKaricheri, Muralidharan regs = devm_ioremap_resource(gbe_dev->dev, &res); 332521e0e0ddSKaricheri, Muralidharan if (IS_ERR(regs)) { 332621e0e0ddSKaricheri, Muralidharan dev_err(gbe_dev->dev, 332721e0e0ddSKaricheri, Muralidharan "Failed to map gbe switch module register base\n"); 332821e0e0ddSKaricheri, Muralidharan return PTR_ERR(regs); 332921e0e0ddSKaricheri, Muralidharan } 333021e0e0ddSKaricheri, Muralidharan gbe_dev->switch_regs = regs; 33316f8d3f33SWingman Kwok 3332489e8a2fSWingMan Kwok gbe_dev->num_stats_mods = gbe_dev->max_num_slaves; 3333208c6b9aSWingMan Kwok gbe_dev->et_stats = gbe13_et_stats; 3334208c6b9aSWingMan Kwok gbe_dev->num_et_stats = ARRAY_SIZE(gbe13_et_stats); 3335208c6b9aSWingMan Kwok 33366f8d3f33SWingman Kwok gbe_dev->hw_stats = devm_kzalloc(gbe_dev->dev, 3337208c6b9aSWingMan Kwok gbe_dev->num_et_stats * sizeof(u64), 33386f8d3f33SWingman Kwok GFP_KERNEL); 33396f8d3f33SWingman Kwok if (!gbe_dev->hw_stats) { 33406f8d3f33SWingman Kwok dev_err(gbe_dev->dev, "hw_stats memory allocation failed\n"); 33416f8d3f33SWingman Kwok return -ENOMEM; 33426f8d3f33SWingman Kwok } 33436f8d3f33SWingman Kwok 3344489e8a2fSWingMan Kwok gbe_dev->hw_stats_prev = 3345489e8a2fSWingMan Kwok devm_kzalloc(gbe_dev->dev, 3346489e8a2fSWingMan Kwok gbe_dev->num_et_stats * sizeof(u32), 3347489e8a2fSWingMan Kwok GFP_KERNEL); 3348489e8a2fSWingMan Kwok if (!gbe_dev->hw_stats_prev) { 3349489e8a2fSWingMan Kwok dev_err(gbe_dev->dev, 3350489e8a2fSWingMan Kwok "hw_stats_prev memory allocation failed\n"); 3351489e8a2fSWingMan Kwok return -ENOMEM; 3352489e8a2fSWingMan Kwok } 3353489e8a2fSWingMan Kwok 335421e0e0ddSKaricheri, Muralidharan gbe_dev->sgmii_port_regs = gbe_dev->ss_regs + GBE13_SGMII_MODULE_OFFSET; 335521e0e0ddSKaricheri, Muralidharan gbe_dev->host_port_regs = gbe_dev->switch_regs + GBE13_HOST_PORT_OFFSET; 33566f8d3f33SWingman Kwok 3357a94bcd09SWingMan Kwok /* K2HK has only 2 hw stats modules visible at a time, so 3358a94bcd09SWingMan Kwok * module 0 & 2 points to one base and 3359a94bcd09SWingMan Kwok * module 1 & 3 points to the other base 3360a94bcd09SWingMan Kwok */ 33619a391c7bSWingMan Kwok for (i = 0; i < gbe_dev->max_num_slaves; i++) { 336221e0e0ddSKaricheri, Muralidharan gbe_dev->hw_stats_regs[i] = 336321e0e0ddSKaricheri, Muralidharan gbe_dev->switch_regs + GBE13_HW_STATS_OFFSET + 3364a94bcd09SWingMan Kwok (GBE_HW_STATS_REG_MAP_SZ * (i & 0x1)); 336521e0e0ddSKaricheri, Muralidharan } 33666f8d3f33SWingman Kwok 33676246168bSWingMan Kwok gbe_dev->cpts_reg = gbe_dev->switch_regs + GBE13_CPTS_OFFSET; 336821e0e0ddSKaricheri, Muralidharan gbe_dev->ale_reg = gbe_dev->switch_regs + GBE13_ALE_OFFSET; 33699a391c7bSWingMan Kwok gbe_dev->ale_ports = gbe_dev->max_num_ports; 33706f8d3f33SWingman Kwok gbe_dev->host_port = GBE13_HOST_PORT_NUM; 33716f8d3f33SWingman Kwok gbe_dev->ale_entries = GBE13_NUM_ALE_ENTRIES; 33729a391c7bSWingMan Kwok gbe_dev->stats_en_mask = GBE13_REG_VAL_STAT_ENABLE_ALL; 33736f8d3f33SWingman Kwok 33746f8d3f33SWingman Kwok /* Subsystem registers */ 33756f8d3f33SWingman Kwok GBE_SET_REG_OFS(gbe_dev, ss_regs, id_ver); 33766f8d3f33SWingman Kwok 33776f8d3f33SWingman Kwok /* Switch module registers */ 33786f8d3f33SWingman Kwok GBE_SET_REG_OFS(gbe_dev, switch_regs, id_ver); 33796f8d3f33SWingman Kwok GBE_SET_REG_OFS(gbe_dev, switch_regs, control); 33806f8d3f33SWingman Kwok GBE_SET_REG_OFS(gbe_dev, switch_regs, soft_reset); 33816f8d3f33SWingman Kwok GBE_SET_REG_OFS(gbe_dev, switch_regs, stat_port_en); 33826f8d3f33SWingman Kwok GBE_SET_REG_OFS(gbe_dev, switch_regs, ptype); 33836f8d3f33SWingman Kwok GBE_SET_REG_OFS(gbe_dev, switch_regs, flow_control); 33846f8d3f33SWingman Kwok 33856f8d3f33SWingman Kwok /* Host port registers */ 33866f8d3f33SWingman Kwok GBE_SET_REG_OFS(gbe_dev, host_port_regs, port_vlan); 33876f8d3f33SWingman Kwok GBE_SET_REG_OFS(gbe_dev, host_port_regs, rx_maxlen); 33886f8d3f33SWingman Kwok return 0; 33896f8d3f33SWingman Kwok } 33906f8d3f33SWingman Kwok 33919a391c7bSWingMan Kwok static int set_gbenu_ethss_priv(struct gbe_priv *gbe_dev, 33929a391c7bSWingMan Kwok struct device_node *node) 33939a391c7bSWingMan Kwok { 33949a391c7bSWingMan Kwok struct resource res; 33959a391c7bSWingMan Kwok void __iomem *regs; 33969a391c7bSWingMan Kwok int i, ret; 33979a391c7bSWingMan Kwok 3398489e8a2fSWingMan Kwok gbe_dev->num_stats_mods = gbe_dev->max_num_ports; 3399208c6b9aSWingMan Kwok gbe_dev->et_stats = gbenu_et_stats; 3400208c6b9aSWingMan Kwok 3401208c6b9aSWingMan Kwok if (IS_SS_ID_NU(gbe_dev)) 3402208c6b9aSWingMan Kwok gbe_dev->num_et_stats = GBENU_ET_STATS_HOST_SIZE + 3403208c6b9aSWingMan Kwok (gbe_dev->max_num_slaves * GBENU_ET_STATS_PORT_SIZE); 3404208c6b9aSWingMan Kwok else 3405208c6b9aSWingMan Kwok gbe_dev->num_et_stats = GBENU_ET_STATS_HOST_SIZE + 3406208c6b9aSWingMan Kwok GBENU_ET_STATS_PORT_SIZE; 3407208c6b9aSWingMan Kwok 34089a391c7bSWingMan Kwok gbe_dev->hw_stats = devm_kzalloc(gbe_dev->dev, 3409208c6b9aSWingMan Kwok gbe_dev->num_et_stats * sizeof(u64), 34109a391c7bSWingMan Kwok GFP_KERNEL); 34119a391c7bSWingMan Kwok if (!gbe_dev->hw_stats) { 34129a391c7bSWingMan Kwok dev_err(gbe_dev->dev, "hw_stats memory allocation failed\n"); 34139a391c7bSWingMan Kwok return -ENOMEM; 34149a391c7bSWingMan Kwok } 34159a391c7bSWingMan Kwok 3416489e8a2fSWingMan Kwok gbe_dev->hw_stats_prev = 3417489e8a2fSWingMan Kwok devm_kzalloc(gbe_dev->dev, 3418489e8a2fSWingMan Kwok gbe_dev->num_et_stats * sizeof(u32), 3419489e8a2fSWingMan Kwok GFP_KERNEL); 3420489e8a2fSWingMan Kwok if (!gbe_dev->hw_stats_prev) { 3421489e8a2fSWingMan Kwok dev_err(gbe_dev->dev, 3422489e8a2fSWingMan Kwok "hw_stats_prev memory allocation failed\n"); 3423489e8a2fSWingMan Kwok return -ENOMEM; 3424489e8a2fSWingMan Kwok } 3425489e8a2fSWingMan Kwok 34269a391c7bSWingMan Kwok ret = of_address_to_resource(node, GBENU_SM_REG_INDEX, &res); 34279a391c7bSWingMan Kwok if (ret) { 34289a391c7bSWingMan Kwok dev_err(gbe_dev->dev, 34299a391c7bSWingMan Kwok "Can't translate of gbenu node(%s) addr at index %d\n", 34309a391c7bSWingMan Kwok node->name, GBENU_SM_REG_INDEX); 34319a391c7bSWingMan Kwok return ret; 34329a391c7bSWingMan Kwok } 34339a391c7bSWingMan Kwok 34349a391c7bSWingMan Kwok regs = devm_ioremap_resource(gbe_dev->dev, &res); 34359a391c7bSWingMan Kwok if (IS_ERR(regs)) { 34369a391c7bSWingMan Kwok dev_err(gbe_dev->dev, 34379a391c7bSWingMan Kwok "Failed to map gbenu switch module register base\n"); 34389a391c7bSWingMan Kwok return PTR_ERR(regs); 34399a391c7bSWingMan Kwok } 34409a391c7bSWingMan Kwok gbe_dev->switch_regs = regs; 34419a391c7bSWingMan Kwok 3442775f9535SMurali Karicheri if (!IS_SS_ID_2U(gbe_dev)) 3443775f9535SMurali Karicheri gbe_dev->sgmii_port_regs = 3444775f9535SMurali Karicheri gbe_dev->ss_regs + GBENU_SGMII_MODULE_OFFSET; 34458c85151dSWingMan Kwok 34468c85151dSWingMan Kwok /* Although sgmii modules are mem mapped to one contiguous 34478c85151dSWingMan Kwok * region on GBENU devices, setting sgmii_port34_regs allows 34488c85151dSWingMan Kwok * consistent code when accessing sgmii api 34498c85151dSWingMan Kwok */ 34508c85151dSWingMan Kwok gbe_dev->sgmii_port34_regs = gbe_dev->sgmii_port_regs + 34518c85151dSWingMan Kwok (2 * GBENU_SGMII_MODULE_SIZE); 34528c85151dSWingMan Kwok 34539a391c7bSWingMan Kwok gbe_dev->host_port_regs = gbe_dev->switch_regs + GBENU_HOST_PORT_OFFSET; 34549a391c7bSWingMan Kwok 34559a391c7bSWingMan Kwok for (i = 0; i < (gbe_dev->max_num_ports); i++) 34569a391c7bSWingMan Kwok gbe_dev->hw_stats_regs[i] = gbe_dev->switch_regs + 34579a391c7bSWingMan Kwok GBENU_HW_STATS_OFFSET + (GBENU_HW_STATS_REG_MAP_SZ * i); 34589a391c7bSWingMan Kwok 34596246168bSWingMan Kwok gbe_dev->cpts_reg = gbe_dev->switch_regs + GBENU_CPTS_OFFSET; 34609a391c7bSWingMan Kwok gbe_dev->ale_reg = gbe_dev->switch_regs + GBENU_ALE_OFFSET; 34619a391c7bSWingMan Kwok gbe_dev->ale_ports = gbe_dev->max_num_ports; 34629a391c7bSWingMan Kwok gbe_dev->host_port = GBENU_HOST_PORT_NUM; 34639a391c7bSWingMan Kwok gbe_dev->stats_en_mask = (1 << (gbe_dev->max_num_ports)) - 1; 34649a391c7bSWingMan Kwok 34659a391c7bSWingMan Kwok /* Subsystem registers */ 34669a391c7bSWingMan Kwok GBENU_SET_REG_OFS(gbe_dev, ss_regs, id_ver); 34677771f2b4SMurali Karicheri /* ok to set for MU, but used by 2U only */ 34687771f2b4SMurali Karicheri GBENU_SET_REG_OFS(gbe_dev, ss_regs, rgmii_status); 34699a391c7bSWingMan Kwok 34709a391c7bSWingMan Kwok /* Switch module registers */ 34719a391c7bSWingMan Kwok GBENU_SET_REG_OFS(gbe_dev, switch_regs, id_ver); 34729a391c7bSWingMan Kwok GBENU_SET_REG_OFS(gbe_dev, switch_regs, control); 34739a391c7bSWingMan Kwok GBENU_SET_REG_OFS(gbe_dev, switch_regs, stat_port_en); 34749a391c7bSWingMan Kwok GBENU_SET_REG_OFS(gbe_dev, switch_regs, ptype); 34759a391c7bSWingMan Kwok 34769a391c7bSWingMan Kwok /* Host port registers */ 34779a391c7bSWingMan Kwok GBENU_SET_REG_OFS(gbe_dev, host_port_regs, port_vlan); 34789a391c7bSWingMan Kwok GBENU_SET_REG_OFS(gbe_dev, host_port_regs, rx_maxlen); 34799a391c7bSWingMan Kwok 34809a391c7bSWingMan Kwok /* For NU only. 2U does not need tx_pri_map. 34819a391c7bSWingMan Kwok * NU cppi port 0 tx pkt streaming interface has (n-1)*8 egress threads 34829a391c7bSWingMan Kwok * while 2U has only 1 such thread 34839a391c7bSWingMan Kwok */ 34849a391c7bSWingMan Kwok GBENU_SET_REG_OFS(gbe_dev, host_port_regs, tx_pri_map); 34859a391c7bSWingMan Kwok return 0; 34869a391c7bSWingMan Kwok } 34879a391c7bSWingMan Kwok 34886f8d3f33SWingman Kwok static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, 34896f8d3f33SWingman Kwok struct device_node *node, void **inst_priv) 34906f8d3f33SWingman Kwok { 34916f8d3f33SWingman Kwok struct device_node *interfaces, *interface; 34926f8d3f33SWingman Kwok struct device_node *secondary_ports; 34936f8d3f33SWingman Kwok struct cpsw_ale_params ale_params; 34946f8d3f33SWingman Kwok struct gbe_priv *gbe_dev; 34956f8d3f33SWingman Kwok u32 slave_num; 3496489e8a2fSWingMan Kwok int i, ret = 0; 34976f8d3f33SWingman Kwok 34986f8d3f33SWingman Kwok if (!node) { 34996f8d3f33SWingman Kwok dev_err(dev, "device tree info unavailable\n"); 35006f8d3f33SWingman Kwok return -ENODEV; 35016f8d3f33SWingman Kwok } 35026f8d3f33SWingman Kwok 35036f8d3f33SWingman Kwok gbe_dev = devm_kzalloc(dev, sizeof(struct gbe_priv), GFP_KERNEL); 35046f8d3f33SWingman Kwok if (!gbe_dev) 35056f8d3f33SWingman Kwok return -ENOMEM; 35066f8d3f33SWingman Kwok 35079a391c7bSWingMan Kwok if (of_device_is_compatible(node, "ti,netcp-gbe-5") || 35089a391c7bSWingMan Kwok of_device_is_compatible(node, "ti,netcp-gbe")) { 35099a391c7bSWingMan Kwok gbe_dev->max_num_slaves = 4; 35109a391c7bSWingMan Kwok } else if (of_device_is_compatible(node, "ti,netcp-gbe-9")) { 35119a391c7bSWingMan Kwok gbe_dev->max_num_slaves = 8; 35129a391c7bSWingMan Kwok } else if (of_device_is_compatible(node, "ti,netcp-gbe-2")) { 35139a391c7bSWingMan Kwok gbe_dev->max_num_slaves = 1; 35149a391c7bSWingMan Kwok } else if (of_device_is_compatible(node, "ti,netcp-xgbe")) { 35159a391c7bSWingMan Kwok gbe_dev->max_num_slaves = 2; 35169a391c7bSWingMan Kwok } else { 35179a391c7bSWingMan Kwok dev_err(dev, "device tree node for unknown device\n"); 35189a391c7bSWingMan Kwok return -EINVAL; 35199a391c7bSWingMan Kwok } 35209a391c7bSWingMan Kwok gbe_dev->max_num_ports = gbe_dev->max_num_slaves + 1; 35219a391c7bSWingMan Kwok 35226f8d3f33SWingman Kwok gbe_dev->dev = dev; 35236f8d3f33SWingman Kwok gbe_dev->netcp_device = netcp_device; 35246f8d3f33SWingman Kwok gbe_dev->rx_packet_max = NETCP_MAX_FRAME_SIZE; 35256f8d3f33SWingman Kwok 35266f8d3f33SWingman Kwok /* init the hw stats lock */ 35276f8d3f33SWingman Kwok spin_lock_init(&gbe_dev->hw_stats_lock); 35286f8d3f33SWingman Kwok 35296f8d3f33SWingman Kwok if (of_find_property(node, "enable-ale", NULL)) { 35306f8d3f33SWingman Kwok gbe_dev->enable_ale = true; 35316f8d3f33SWingman Kwok dev_info(dev, "ALE enabled\n"); 35326f8d3f33SWingman Kwok } else { 35336f8d3f33SWingman Kwok gbe_dev->enable_ale = false; 35346f8d3f33SWingman Kwok dev_dbg(dev, "ALE bypass enabled*\n"); 35356f8d3f33SWingman Kwok } 35366f8d3f33SWingman Kwok 35376f8d3f33SWingman Kwok ret = of_property_read_u32(node, "tx-queue", 35386f8d3f33SWingman Kwok &gbe_dev->tx_queue_id); 35396f8d3f33SWingman Kwok if (ret < 0) { 35406f8d3f33SWingman Kwok dev_err(dev, "missing tx_queue parameter\n"); 35416f8d3f33SWingman Kwok gbe_dev->tx_queue_id = GBE_TX_QUEUE; 35426f8d3f33SWingman Kwok } 35436f8d3f33SWingman Kwok 35446f8d3f33SWingman Kwok ret = of_property_read_string(node, "tx-channel", 35456f8d3f33SWingman Kwok &gbe_dev->dma_chan_name); 35466f8d3f33SWingman Kwok if (ret < 0) { 35476f8d3f33SWingman Kwok dev_err(dev, "missing \"tx-channel\" parameter\n"); 354831a184b7SKaricheri, Muralidharan return -EINVAL; 35496f8d3f33SWingman Kwok } 35506f8d3f33SWingman Kwok 35516f8d3f33SWingman Kwok if (!strcmp(node->name, "gbe")) { 35526f8d3f33SWingman Kwok ret = get_gbe_resource_version(gbe_dev, node); 35536f8d3f33SWingman Kwok if (ret) 355431a184b7SKaricheri, Muralidharan return ret; 35556f8d3f33SWingman Kwok 35569a391c7bSWingMan Kwok dev_dbg(dev, "ss_version: 0x%08x\n", gbe_dev->ss_version); 35579a391c7bSWingMan Kwok 35582953586dSMurali Karicheri if (IS_SS_ID_VER_14(gbe_dev)) 35596f8d3f33SWingman Kwok ret = set_gbe_ethss14_priv(gbe_dev, node); 35609a391c7bSWingMan Kwok else if (IS_SS_ID_MU(gbe_dev)) 35619a391c7bSWingMan Kwok ret = set_gbenu_ethss_priv(gbe_dev, node); 35629a391c7bSWingMan Kwok else 35639a391c7bSWingMan Kwok ret = -ENODEV; 35649a391c7bSWingMan Kwok 356590cff9e2SWingman Kwok } else if (!strcmp(node->name, "xgbe")) { 356690cff9e2SWingman Kwok ret = set_xgbe_ethss10_priv(gbe_dev, node); 356790cff9e2SWingman Kwok if (ret) 356831a184b7SKaricheri, Muralidharan return ret; 356990cff9e2SWingman Kwok ret = netcp_xgbe_serdes_init(gbe_dev->xgbe_serdes_regs, 357090cff9e2SWingman Kwok gbe_dev->ss_regs); 35716f8d3f33SWingman Kwok } else { 35726f8d3f33SWingman Kwok dev_err(dev, "unknown GBE node(%s)\n", node->name); 35736f8d3f33SWingman Kwok ret = -ENODEV; 35746f8d3f33SWingman Kwok } 35756f8d3f33SWingman Kwok 357631a184b7SKaricheri, Muralidharan if (ret) 357731a184b7SKaricheri, Muralidharan return ret; 357831a184b7SKaricheri, Muralidharan 35796f8d3f33SWingman Kwok interfaces = of_get_child_by_name(node, "interfaces"); 35806f8d3f33SWingman Kwok if (!interfaces) 35816f8d3f33SWingman Kwok dev_err(dev, "could not find interfaces\n"); 35826f8d3f33SWingman Kwok 35836f8d3f33SWingman Kwok ret = netcp_txpipe_init(&gbe_dev->tx_pipe, netcp_device, 35846f8d3f33SWingman Kwok gbe_dev->dma_chan_name, gbe_dev->tx_queue_id); 35856f8d3f33SWingman Kwok if (ret) 358631a184b7SKaricheri, Muralidharan return ret; 35876f8d3f33SWingman Kwok 35886f8d3f33SWingman Kwok ret = netcp_txpipe_open(&gbe_dev->tx_pipe); 35896f8d3f33SWingman Kwok if (ret) 359031a184b7SKaricheri, Muralidharan return ret; 35916f8d3f33SWingman Kwok 35926f8d3f33SWingman Kwok /* Create network interfaces */ 35936f8d3f33SWingman Kwok INIT_LIST_HEAD(&gbe_dev->gbe_intf_head); 35946f8d3f33SWingman Kwok for_each_child_of_node(interfaces, interface) { 35956f8d3f33SWingman Kwok ret = of_property_read_u32(interface, "slave-port", &slave_num); 35966f8d3f33SWingman Kwok if (ret) { 35976f8d3f33SWingman Kwok dev_err(dev, "missing slave-port parameter, skipping interface configuration for %s\n", 35986f8d3f33SWingman Kwok interface->name); 35996f8d3f33SWingman Kwok continue; 36006f8d3f33SWingman Kwok } 36016f8d3f33SWingman Kwok gbe_dev->num_slaves++; 3602bd252796SJulia Lawall if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) { 3603bd252796SJulia Lawall of_node_put(interface); 36049a391c7bSWingMan Kwok break; 36056f8d3f33SWingman Kwok } 3606bd252796SJulia Lawall } 360731a184b7SKaricheri, Muralidharan of_node_put(interfaces); 36086f8d3f33SWingman Kwok 36096f8d3f33SWingman Kwok if (!gbe_dev->num_slaves) 36106f8d3f33SWingman Kwok dev_warn(dev, "No network interface configured\n"); 36116f8d3f33SWingman Kwok 36126f8d3f33SWingman Kwok /* Initialize Secondary slave ports */ 36136f8d3f33SWingman Kwok secondary_ports = of_get_child_by_name(node, "secondary-slave-ports"); 36146f8d3f33SWingman Kwok INIT_LIST_HEAD(&gbe_dev->secondary_slaves); 36159a391c7bSWingMan Kwok if (secondary_ports && (gbe_dev->num_slaves < gbe_dev->max_num_slaves)) 36166f8d3f33SWingman Kwok init_secondary_ports(gbe_dev, secondary_ports); 36176f8d3f33SWingman Kwok of_node_put(secondary_ports); 36186f8d3f33SWingman Kwok 36196f8d3f33SWingman Kwok if (!gbe_dev->num_slaves) { 362031a184b7SKaricheri, Muralidharan dev_err(dev, 362131a184b7SKaricheri, Muralidharan "No network interface or secondary ports configured\n"); 36226f8d3f33SWingman Kwok ret = -ENODEV; 362331a184b7SKaricheri, Muralidharan goto free_sec_ports; 36246f8d3f33SWingman Kwok } 36256f8d3f33SWingman Kwok 36266f8d3f33SWingman Kwok memset(&ale_params, 0, sizeof(ale_params)); 36276f8d3f33SWingman Kwok ale_params.dev = gbe_dev->dev; 36286f8d3f33SWingman Kwok ale_params.ale_regs = gbe_dev->ale_reg; 36296f8d3f33SWingman Kwok ale_params.ale_ageout = GBE_DEFAULT_ALE_AGEOUT; 36306f8d3f33SWingman Kwok ale_params.ale_entries = gbe_dev->ale_entries; 36316f8d3f33SWingman Kwok ale_params.ale_ports = gbe_dev->ale_ports; 3632ca47130aSKaricheri, Muralidharan if (IS_SS_ID_MU(gbe_dev)) { 3633ca47130aSKaricheri, Muralidharan ale_params.major_ver_mask = 0x7; 3634ca47130aSKaricheri, Muralidharan ale_params.nu_switch_ale = true; 3635ca47130aSKaricheri, Muralidharan } 36366f8d3f33SWingman Kwok gbe_dev->ale = cpsw_ale_create(&ale_params); 36376f8d3f33SWingman Kwok if (!gbe_dev->ale) { 36386f8d3f33SWingman Kwok dev_err(gbe_dev->dev, "error initializing ale engine\n"); 36396f8d3f33SWingman Kwok ret = -ENODEV; 364031a184b7SKaricheri, Muralidharan goto free_sec_ports; 36416f8d3f33SWingman Kwok } else { 36426f8d3f33SWingman Kwok dev_dbg(gbe_dev->dev, "Created a gbe ale engine\n"); 36436f8d3f33SWingman Kwok } 36446f8d3f33SWingman Kwok 36456246168bSWingMan Kwok gbe_dev->cpts = cpts_create(gbe_dev->dev, gbe_dev->cpts_reg, node); 36466246168bSWingMan Kwok if (IS_ENABLED(CONFIG_TI_CPTS) && IS_ERR(gbe_dev->cpts)) { 36476246168bSWingMan Kwok ret = PTR_ERR(gbe_dev->cpts); 36486246168bSWingMan Kwok goto free_sec_ports; 36496246168bSWingMan Kwok } 36506246168bSWingMan Kwok 36516f8d3f33SWingman Kwok /* initialize host port */ 36526f8d3f33SWingman Kwok gbe_init_host_port(gbe_dev); 36536f8d3f33SWingman Kwok 3654489e8a2fSWingMan Kwok spin_lock_bh(&gbe_dev->hw_stats_lock); 3655489e8a2fSWingMan Kwok for (i = 0; i < gbe_dev->num_stats_mods; i++) { 36562953586dSMurali Karicheri if (IS_SS_ID_VER_14(gbe_dev)) 3657489e8a2fSWingMan Kwok gbe_reset_mod_stats_ver14(gbe_dev, i); 3658489e8a2fSWingMan Kwok else 3659489e8a2fSWingMan Kwok gbe_reset_mod_stats(gbe_dev, i); 3660489e8a2fSWingMan Kwok } 3661489e8a2fSWingMan Kwok spin_unlock_bh(&gbe_dev->hw_stats_lock); 3662489e8a2fSWingMan Kwok 3663e99e88a9SKees Cook timer_setup(&gbe_dev->timer, netcp_ethss_timer, 0); 36646f8d3f33SWingman Kwok gbe_dev->timer.expires = jiffies + GBE_TIMER_INTERVAL; 36656f8d3f33SWingman Kwok add_timer(&gbe_dev->timer); 36666f8d3f33SWingman Kwok *inst_priv = gbe_dev; 36676f8d3f33SWingman Kwok return 0; 36686f8d3f33SWingman Kwok 366931a184b7SKaricheri, Muralidharan free_sec_ports: 367031a184b7SKaricheri, Muralidharan free_secondary_ports(gbe_dev); 36716f8d3f33SWingman Kwok return ret; 36726f8d3f33SWingman Kwok } 36736f8d3f33SWingman Kwok 36746f8d3f33SWingman Kwok static int gbe_attach(void *inst_priv, struct net_device *ndev, 36756f8d3f33SWingman Kwok struct device_node *node, void **intf_priv) 36766f8d3f33SWingman Kwok { 36776f8d3f33SWingman Kwok struct gbe_priv *gbe_dev = inst_priv; 36786f8d3f33SWingman Kwok struct gbe_intf *gbe_intf; 36796f8d3f33SWingman Kwok int ret; 36806f8d3f33SWingman Kwok 36816f8d3f33SWingman Kwok if (!node) { 36826f8d3f33SWingman Kwok dev_err(gbe_dev->dev, "interface node not available\n"); 36836f8d3f33SWingman Kwok return -ENODEV; 36846f8d3f33SWingman Kwok } 36856f8d3f33SWingman Kwok 36866f8d3f33SWingman Kwok gbe_intf = devm_kzalloc(gbe_dev->dev, sizeof(*gbe_intf), GFP_KERNEL); 36876f8d3f33SWingman Kwok if (!gbe_intf) 36886f8d3f33SWingman Kwok return -ENOMEM; 36896f8d3f33SWingman Kwok 36906f8d3f33SWingman Kwok gbe_intf->ndev = ndev; 36916f8d3f33SWingman Kwok gbe_intf->dev = gbe_dev->dev; 36926f8d3f33SWingman Kwok gbe_intf->gbe_dev = gbe_dev; 36936f8d3f33SWingman Kwok 36946f8d3f33SWingman Kwok gbe_intf->slave = devm_kzalloc(gbe_dev->dev, 36956f8d3f33SWingman Kwok sizeof(*gbe_intf->slave), 36966f8d3f33SWingman Kwok GFP_KERNEL); 36976f8d3f33SWingman Kwok if (!gbe_intf->slave) { 36986f8d3f33SWingman Kwok ret = -ENOMEM; 36996f8d3f33SWingman Kwok goto fail; 37006f8d3f33SWingman Kwok } 37016f8d3f33SWingman Kwok 37026f8d3f33SWingman Kwok if (init_slave(gbe_dev, gbe_intf->slave, node)) { 37036f8d3f33SWingman Kwok ret = -ENODEV; 37046f8d3f33SWingman Kwok goto fail; 37056f8d3f33SWingman Kwok } 37066f8d3f33SWingman Kwok 37076f8d3f33SWingman Kwok gbe_intf->tx_pipe = gbe_dev->tx_pipe; 37086f8d3f33SWingman Kwok ndev->ethtool_ops = &keystone_ethtool_ops; 37096f8d3f33SWingman Kwok list_add_tail(&gbe_intf->gbe_intf_list, &gbe_dev->gbe_intf_head); 37106f8d3f33SWingman Kwok *intf_priv = gbe_intf; 37116f8d3f33SWingman Kwok return 0; 37126f8d3f33SWingman Kwok 37136f8d3f33SWingman Kwok fail: 37146f8d3f33SWingman Kwok if (gbe_intf->slave) 37156f8d3f33SWingman Kwok devm_kfree(gbe_dev->dev, gbe_intf->slave); 37166f8d3f33SWingman Kwok if (gbe_intf) 37176f8d3f33SWingman Kwok devm_kfree(gbe_dev->dev, gbe_intf); 37186f8d3f33SWingman Kwok return ret; 37196f8d3f33SWingman Kwok } 37206f8d3f33SWingman Kwok 37216f8d3f33SWingman Kwok static int gbe_release(void *intf_priv) 37226f8d3f33SWingman Kwok { 37236f8d3f33SWingman Kwok struct gbe_intf *gbe_intf = intf_priv; 37246f8d3f33SWingman Kwok 37256f8d3f33SWingman Kwok gbe_intf->ndev->ethtool_ops = NULL; 37266f8d3f33SWingman Kwok list_del(&gbe_intf->gbe_intf_list); 37276f8d3f33SWingman Kwok devm_kfree(gbe_intf->dev, gbe_intf->slave); 37286f8d3f33SWingman Kwok devm_kfree(gbe_intf->dev, gbe_intf); 37296f8d3f33SWingman Kwok return 0; 37306f8d3f33SWingman Kwok } 37316f8d3f33SWingman Kwok 37326f8d3f33SWingman Kwok static int gbe_remove(struct netcp_device *netcp_device, void *inst_priv) 37336f8d3f33SWingman Kwok { 37346f8d3f33SWingman Kwok struct gbe_priv *gbe_dev = inst_priv; 37356f8d3f33SWingman Kwok 37366f8d3f33SWingman Kwok del_timer_sync(&gbe_dev->timer); 37376246168bSWingMan Kwok cpts_release(gbe_dev->cpts); 37386f8d3f33SWingman Kwok cpsw_ale_stop(gbe_dev->ale); 37396f8d3f33SWingman Kwok netcp_txpipe_close(&gbe_dev->tx_pipe); 37406f8d3f33SWingman Kwok free_secondary_ports(gbe_dev); 37416f8d3f33SWingman Kwok 37426f8d3f33SWingman Kwok if (!list_empty(&gbe_dev->gbe_intf_head)) 374331a184b7SKaricheri, Muralidharan dev_alert(gbe_dev->dev, 374431a184b7SKaricheri, Muralidharan "unreleased ethss interfaces present\n"); 37456f8d3f33SWingman Kwok 37466f8d3f33SWingman Kwok return 0; 37476f8d3f33SWingman Kwok } 37486f8d3f33SWingman Kwok 37496f8d3f33SWingman Kwok static struct netcp_module gbe_module = { 37506f8d3f33SWingman Kwok .name = GBE_MODULE_NAME, 37516f8d3f33SWingman Kwok .owner = THIS_MODULE, 37526f8d3f33SWingman Kwok .primary = true, 37536f8d3f33SWingman Kwok .probe = gbe_probe, 37546f8d3f33SWingman Kwok .open = gbe_open, 37556f8d3f33SWingman Kwok .close = gbe_close, 37566f8d3f33SWingman Kwok .remove = gbe_remove, 37576f8d3f33SWingman Kwok .attach = gbe_attach, 37586f8d3f33SWingman Kwok .release = gbe_release, 37596f8d3f33SWingman Kwok .add_addr = gbe_add_addr, 37606f8d3f33SWingman Kwok .del_addr = gbe_del_addr, 37616f8d3f33SWingman Kwok .add_vid = gbe_add_vid, 37626f8d3f33SWingman Kwok .del_vid = gbe_del_vid, 37636f8d3f33SWingman Kwok .ioctl = gbe_ioctl, 37646f8d3f33SWingman Kwok }; 37656f8d3f33SWingman Kwok 376690cff9e2SWingman Kwok static struct netcp_module xgbe_module = { 376790cff9e2SWingman Kwok .name = XGBE_MODULE_NAME, 376890cff9e2SWingman Kwok .owner = THIS_MODULE, 376990cff9e2SWingman Kwok .primary = true, 377090cff9e2SWingman Kwok .probe = gbe_probe, 377190cff9e2SWingman Kwok .open = gbe_open, 377290cff9e2SWingman Kwok .close = gbe_close, 377390cff9e2SWingman Kwok .remove = gbe_remove, 377490cff9e2SWingman Kwok .attach = gbe_attach, 377590cff9e2SWingman Kwok .release = gbe_release, 377690cff9e2SWingman Kwok .add_addr = gbe_add_addr, 377790cff9e2SWingman Kwok .del_addr = gbe_del_addr, 377890cff9e2SWingman Kwok .add_vid = gbe_add_vid, 377990cff9e2SWingman Kwok .del_vid = gbe_del_vid, 378090cff9e2SWingman Kwok .ioctl = gbe_ioctl, 378190cff9e2SWingman Kwok }; 378290cff9e2SWingman Kwok 37836f8d3f33SWingman Kwok static int __init keystone_gbe_init(void) 37846f8d3f33SWingman Kwok { 37856f8d3f33SWingman Kwok int ret; 37866f8d3f33SWingman Kwok 37876f8d3f33SWingman Kwok ret = netcp_register_module(&gbe_module); 37886f8d3f33SWingman Kwok if (ret) 37896f8d3f33SWingman Kwok return ret; 37906f8d3f33SWingman Kwok 379190cff9e2SWingman Kwok ret = netcp_register_module(&xgbe_module); 379290cff9e2SWingman Kwok if (ret) 379390cff9e2SWingman Kwok return ret; 379490cff9e2SWingman Kwok 37956f8d3f33SWingman Kwok return 0; 37966f8d3f33SWingman Kwok } 37976f8d3f33SWingman Kwok module_init(keystone_gbe_init); 37986f8d3f33SWingman Kwok 37996f8d3f33SWingman Kwok static void __exit keystone_gbe_exit(void) 38006f8d3f33SWingman Kwok { 38016f8d3f33SWingman Kwok netcp_unregister_module(&gbe_module); 380290cff9e2SWingman Kwok netcp_unregister_module(&xgbe_module); 38036f8d3f33SWingman Kwok } 38046f8d3f33SWingman Kwok module_exit(keystone_gbe_exit); 380558c11b5fSKaricheri, Muralidharan 380658c11b5fSKaricheri, Muralidharan MODULE_LICENSE("GPL v2"); 380758c11b5fSKaricheri, Muralidharan MODULE_DESCRIPTION("TI NETCP ETHSS driver for Keystone SOCs"); 380858c11b5fSKaricheri, Muralidharan MODULE_AUTHOR("Sandeep Nair <sandeep_n@ti.com"); 3809