Message ID | 20231115133414.1221480-11-justinlai0215@realtek.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Add Realtek automotive PCIe driver | expand |
On 15.11.2023 14:34, Justin Lai wrote: > Implement the ethtool function to support users to obtain network card > information, including obtaining various device settings, Report whether > physical link is up, Report pause parameters, Set pause parameters, > Return a set of strings that describe the requested objects, Get number > of strings that @get_strings will write, Return extended statistics > about the device. > > Signed-off-by: Justin Lai <justinlai0215@realtek.com> > --- > .../net/ethernet/realtek/rtase/rtase_main.c | 144 ++++++++++++++++++ > 1 file changed, 144 insertions(+) > > diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c b/drivers/net/ethernet/realtek/rtase/rtase_main.c > index b7679b74cc8a..5ea4d51fcc47 100644 > --- a/drivers/net/ethernet/realtek/rtase/rtase_main.c > +++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c > @@ -1900,9 +1900,153 @@ static void rtase_get_mac_address(struct net_device *dev) > ether_addr_copy(dev->perm_addr, dev->dev_addr); > } > > +static void rtase_get_drvinfo(struct net_device *dev, > + struct ethtool_drvinfo *drvinfo) > +{ > + const struct rtase_private *tp = netdev_priv(dev); > + > + strscpy(drvinfo->driver, KBUILD_MODNAME, 32); > + strscpy(drvinfo->bus_info, pci_name(tp->pdev), 32); > +} > + > +static int rtase_get_settings(struct net_device *dev, > + struct ethtool_link_ksettings *cmd) > +{ > + u32 supported = SUPPORTED_MII | SUPPORTED_Pause | SUPPORTED_Asym_Pause; > + > + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, > + supported); > + cmd->base.speed = SPEED_5000; > + cmd->base.duplex = DUPLEX_FULL; > + cmd->base.port = PORT_MII; > + cmd->base.autoneg = AUTONEG_DISABLE; > + What are you reporting here? Does this refer to the link between MAC and switch CPU port? Because I would assume that the switch ports can do autoneg. > + return 0; > +} > + > +static void rtase_get_pauseparam(struct net_device *dev, > + struct ethtool_pauseparam *pause) > +{ > + const struct rtase_private *tp = netdev_priv(dev); > + u16 value = rtase_r16(tp, RTASE_CPLUS_CMD); > + > + pause->autoneg = AUTONEG_DISABLE; > + > + if ((value & (FORCE_TXFLOW_EN | FORCE_RXFLOW_EN)) == > + (FORCE_TXFLOW_EN | FORCE_RXFLOW_EN)) { > + pause->rx_pause = 1; > + pause->tx_pause = 1; > + } else if ((value & FORCE_TXFLOW_EN)) { > + pause->tx_pause = 1; > + } else if ((value & FORCE_RXFLOW_EN)) { > + pause->rx_pause = 1; > + } > +} > + > +static int rtase_set_pauseparam(struct net_device *dev, > + struct ethtool_pauseparam *pause) > +{ > + const struct rtase_private *tp = netdev_priv(dev); > + u16 value = rtase_r16(tp, RTASE_CPLUS_CMD); > + > + if (pause->autoneg) > + return -EOPNOTSUPP; > + > + value &= ~(FORCE_TXFLOW_EN | FORCE_RXFLOW_EN); > + > + if (pause->tx_pause) > + value |= FORCE_TXFLOW_EN; > + > + if (pause->rx_pause) > + value |= FORCE_RXFLOW_EN; > + > + rtase_w16(tp, RTASE_CPLUS_CMD, value); > + return 0; > +} > + > +static const char rtase_gstrings[][ETH_GSTRING_LEN] = { > + "tx_packets", > + "rx_packets", > + "tx_errors", > + "rx_errors", > + "rx_missed", > + "align_errors", > + "tx_single_collisions", > + "tx_multi_collisions", > + "unicast", > + "broadcast", > + "multicast", > + "tx_aborted", > + "tx_underrun", > +}; > + > +static void rtase_get_strings(struct net_device *dev, u32 stringset, u8 *data) > +{ > + switch (stringset) { > + case ETH_SS_STATS: > + memcpy(data, *rtase_gstrings, sizeof(rtase_gstrings)); > + break; > + } > +} > + > +static int rtase_get_sset_count(struct net_device *dev, int sset) > +{ > + int ret = -EOPNOTSUPP; > + > + switch (sset) { > + case ETH_SS_STATS: > + ret = ARRAY_SIZE(rtase_gstrings); > + break; > + } > + > + return ret; > +} > + > +static void rtase_get_ethtool_stats(struct net_device *dev, > + struct ethtool_stats *stats, u64 *data) > +{ > + struct rtase_private *tp = netdev_priv(dev); > + const struct rtase_counters *counters; > + > + ASSERT_RTNL(); > + > + counters = tp->tally_vaddr; > + if (!counters) > + return; > + > + rtase_dump_tally_counter(tp); > + > + data[0] = le64_to_cpu(counters->tx_packets); > + data[1] = le64_to_cpu(counters->rx_packets); > + data[2] = le64_to_cpu(counters->tx_errors); > + data[3] = le32_to_cpu(counters->rx_errors); > + data[4] = le16_to_cpu(counters->rx_missed); > + data[5] = le16_to_cpu(counters->align_errors); > + data[6] = le32_to_cpu(counters->tx_one_collision); > + data[7] = le32_to_cpu(counters->tx_multi_collision); > + data[8] = le64_to_cpu(counters->rx_unicast); > + data[9] = le64_to_cpu(counters->rx_broadcast); > + data[10] = le32_to_cpu(counters->rx_multicast); > + data[11] = le16_to_cpu(counters->tx_aborted); > + data[12] = le16_to_cpu(counters->tx_underun); > +} > + > +static const struct ethtool_ops rtase_ethtool_ops = { > + .get_drvinfo = rtase_get_drvinfo, > + .get_link = ethtool_op_get_link, > + .get_link_ksettings = rtase_get_settings, > + .get_pauseparam = rtase_get_pauseparam, > + .set_pauseparam = rtase_set_pauseparam, > + .get_strings = rtase_get_strings, > + .get_sset_count = rtase_get_sset_count, > + .get_ethtool_stats = rtase_get_ethtool_stats, > + .get_ts_info = ethtool_op_get_ts_info, > +}; > + > static void rtase_init_netdev_ops(struct net_device *dev) > { > dev->netdev_ops = &rtase_netdev_ops; > + dev->ethtool_ops = &rtase_ethtool_ops; > } > > static void rtase_reset_interrupt(struct pci_dev *pdev,
> On 15.11.2023 14:34, Justin Lai wrote: > > Implement the ethtool function to support users to obtain network card > > information, including obtaining various device settings, Report > > whether physical link is up, Report pause parameters, Set pause > > parameters, Return a set of strings that describe the requested > > objects, Get number of strings that @get_strings will write, Return > > extended statistics about the device. > > > > Signed-off-by: Justin Lai <justinlai0215@realtek.com> > > --- > > .../net/ethernet/realtek/rtase/rtase_main.c | 144 ++++++++++++++++++ > > 1 file changed, 144 insertions(+) > > > > diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c > > b/drivers/net/ethernet/realtek/rtase/rtase_main.c > > index b7679b74cc8a..5ea4d51fcc47 100644 > > --- a/drivers/net/ethernet/realtek/rtase/rtase_main.c > > +++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c > > @@ -1900,9 +1900,153 @@ static void rtase_get_mac_address(struct > net_device *dev) > > ether_addr_copy(dev->perm_addr, dev->dev_addr); } > > > > +static void rtase_get_drvinfo(struct net_device *dev, > > + struct ethtool_drvinfo *drvinfo) { > > + const struct rtase_private *tp = netdev_priv(dev); > > + > > + strscpy(drvinfo->driver, KBUILD_MODNAME, 32); > > + strscpy(drvinfo->bus_info, pci_name(tp->pdev), 32); } > > + > > +static int rtase_get_settings(struct net_device *dev, > > + struct ethtool_link_ksettings *cmd) { > > + u32 supported = SUPPORTED_MII | SUPPORTED_Pause | > > +SUPPORTED_Asym_Pause; > > + > > + > ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, > > + supported); > > + cmd->base.speed = SPEED_5000; > > + cmd->base.duplex = DUPLEX_FULL; > > + cmd->base.port = PORT_MII; > > + cmd->base.autoneg = AUTONEG_DISABLE; > > + > What are you reporting here? Does this refer to the link between MAC and > switch CPU port? Because I would assume that the switch ports can do > autoneg. PATCH 1/13 has our CHIP architecture. The mac and switch are directly connected, and the line seed is fixed at 5G, so there is no need for autoneg. > > > + return 0; > > +} > > + > > +static void rtase_get_pauseparam(struct net_device *dev, > > + struct ethtool_pauseparam *pause) { > > + const struct rtase_private *tp = netdev_priv(dev); > > + u16 value = rtase_r16(tp, RTASE_CPLUS_CMD); > > + > > + pause->autoneg = AUTONEG_DISABLE; > > + > > + if ((value & (FORCE_TXFLOW_EN | FORCE_RXFLOW_EN)) == > > + (FORCE_TXFLOW_EN | FORCE_RXFLOW_EN)) { > > + pause->rx_pause = 1; > > + pause->tx_pause = 1; > > + } else if ((value & FORCE_TXFLOW_EN)) { > > + pause->tx_pause = 1; > > + } else if ((value & FORCE_RXFLOW_EN)) { > > + pause->rx_pause = 1; > > + } > > +} > > + > > +static int rtase_set_pauseparam(struct net_device *dev, > > + struct ethtool_pauseparam *pause) { > > + const struct rtase_private *tp = netdev_priv(dev); > > + u16 value = rtase_r16(tp, RTASE_CPLUS_CMD); > > + > > + if (pause->autoneg) > > + return -EOPNOTSUPP; > > + > > + value &= ~(FORCE_TXFLOW_EN | FORCE_RXFLOW_EN); > > + > > + if (pause->tx_pause) > > + value |= FORCE_TXFLOW_EN; > > + > > + if (pause->rx_pause) > > + value |= FORCE_RXFLOW_EN; > > + > > + rtase_w16(tp, RTASE_CPLUS_CMD, value); > > + return 0; > > +} > > + > > +static const char rtase_gstrings[][ETH_GSTRING_LEN] = { > > + "tx_packets", > > + "rx_packets", > > + "tx_errors", > > + "rx_errors", > > + "rx_missed", > > + "align_errors", > > + "tx_single_collisions", > > + "tx_multi_collisions", > > + "unicast", > > + "broadcast", > > + "multicast", > > + "tx_aborted", > > + "tx_underrun", > > +}; > > + > > +static void rtase_get_strings(struct net_device *dev, u32 stringset, > > +u8 *data) { > > + switch (stringset) { > > + case ETH_SS_STATS: > > + memcpy(data, *rtase_gstrings, sizeof(rtase_gstrings)); > > + break; > > + } > > +} > > + > > +static int rtase_get_sset_count(struct net_device *dev, int sset) { > > + int ret = -EOPNOTSUPP; > > + > > + switch (sset) { > > + case ETH_SS_STATS: > > + ret = ARRAY_SIZE(rtase_gstrings); > > + break; > > + } > > + > > + return ret; > > +} > > + > > +static void rtase_get_ethtool_stats(struct net_device *dev, > > + struct ethtool_stats *stats, u64 > > +*data) { > > + struct rtase_private *tp = netdev_priv(dev); > > + const struct rtase_counters *counters; > > + > > + ASSERT_RTNL(); > > + > > + counters = tp->tally_vaddr; > > + if (!counters) > > + return; > > + > > + rtase_dump_tally_counter(tp); > > + > > + data[0] = le64_to_cpu(counters->tx_packets); > > + data[1] = le64_to_cpu(counters->rx_packets); > > + data[2] = le64_to_cpu(counters->tx_errors); > > + data[3] = le32_to_cpu(counters->rx_errors); > > + data[4] = le16_to_cpu(counters->rx_missed); > > + data[5] = le16_to_cpu(counters->align_errors); > > + data[6] = le32_to_cpu(counters->tx_one_collision); > > + data[7] = le32_to_cpu(counters->tx_multi_collision); > > + data[8] = le64_to_cpu(counters->rx_unicast); > > + data[9] = le64_to_cpu(counters->rx_broadcast); > > + data[10] = le32_to_cpu(counters->rx_multicast); > > + data[11] = le16_to_cpu(counters->tx_aborted); > > + data[12] = le16_to_cpu(counters->tx_underun); > > +} > > + > > +static const struct ethtool_ops rtase_ethtool_ops = { > > + .get_drvinfo = rtase_get_drvinfo, > > + .get_link = ethtool_op_get_link, > > + .get_link_ksettings = rtase_get_settings, > > + .get_pauseparam = rtase_get_pauseparam, > > + .set_pauseparam = rtase_set_pauseparam, > > + .get_strings = rtase_get_strings, > > + .get_sset_count = rtase_get_sset_count, > > + .get_ethtool_stats = rtase_get_ethtool_stats, > > + .get_ts_info = ethtool_op_get_ts_info, }; > > + > > static void rtase_init_netdev_ops(struct net_device *dev) { > > dev->netdev_ops = &rtase_netdev_ops; > > + dev->ethtool_ops = &rtase_ethtool_ops; > > } > > > > static void rtase_reset_interrupt(struct pci_dev *pdev, >
diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c b/drivers/net/ethernet/realtek/rtase/rtase_main.c index b7679b74cc8a..5ea4d51fcc47 100644 --- a/drivers/net/ethernet/realtek/rtase/rtase_main.c +++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c @@ -1900,9 +1900,153 @@ static void rtase_get_mac_address(struct net_device *dev) ether_addr_copy(dev->perm_addr, dev->dev_addr); } +static void rtase_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo) +{ + const struct rtase_private *tp = netdev_priv(dev); + + strscpy(drvinfo->driver, KBUILD_MODNAME, 32); + strscpy(drvinfo->bus_info, pci_name(tp->pdev), 32); +} + +static int rtase_get_settings(struct net_device *dev, + struct ethtool_link_ksettings *cmd) +{ + u32 supported = SUPPORTED_MII | SUPPORTED_Pause | SUPPORTED_Asym_Pause; + + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, + supported); + cmd->base.speed = SPEED_5000; + cmd->base.duplex = DUPLEX_FULL; + cmd->base.port = PORT_MII; + cmd->base.autoneg = AUTONEG_DISABLE; + + return 0; +} + +static void rtase_get_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *pause) +{ + const struct rtase_private *tp = netdev_priv(dev); + u16 value = rtase_r16(tp, RTASE_CPLUS_CMD); + + pause->autoneg = AUTONEG_DISABLE; + + if ((value & (FORCE_TXFLOW_EN | FORCE_RXFLOW_EN)) == + (FORCE_TXFLOW_EN | FORCE_RXFLOW_EN)) { + pause->rx_pause = 1; + pause->tx_pause = 1; + } else if ((value & FORCE_TXFLOW_EN)) { + pause->tx_pause = 1; + } else if ((value & FORCE_RXFLOW_EN)) { + pause->rx_pause = 1; + } +} + +static int rtase_set_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *pause) +{ + const struct rtase_private *tp = netdev_priv(dev); + u16 value = rtase_r16(tp, RTASE_CPLUS_CMD); + + if (pause->autoneg) + return -EOPNOTSUPP; + + value &= ~(FORCE_TXFLOW_EN | FORCE_RXFLOW_EN); + + if (pause->tx_pause) + value |= FORCE_TXFLOW_EN; + + if (pause->rx_pause) + value |= FORCE_RXFLOW_EN; + + rtase_w16(tp, RTASE_CPLUS_CMD, value); + return 0; +} + +static const char rtase_gstrings[][ETH_GSTRING_LEN] = { + "tx_packets", + "rx_packets", + "tx_errors", + "rx_errors", + "rx_missed", + "align_errors", + "tx_single_collisions", + "tx_multi_collisions", + "unicast", + "broadcast", + "multicast", + "tx_aborted", + "tx_underrun", +}; + +static void rtase_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + switch (stringset) { + case ETH_SS_STATS: + memcpy(data, *rtase_gstrings, sizeof(rtase_gstrings)); + break; + } +} + +static int rtase_get_sset_count(struct net_device *dev, int sset) +{ + int ret = -EOPNOTSUPP; + + switch (sset) { + case ETH_SS_STATS: + ret = ARRAY_SIZE(rtase_gstrings); + break; + } + + return ret; +} + +static void rtase_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct rtase_private *tp = netdev_priv(dev); + const struct rtase_counters *counters; + + ASSERT_RTNL(); + + counters = tp->tally_vaddr; + if (!counters) + return; + + rtase_dump_tally_counter(tp); + + data[0] = le64_to_cpu(counters->tx_packets); + data[1] = le64_to_cpu(counters->rx_packets); + data[2] = le64_to_cpu(counters->tx_errors); + data[3] = le32_to_cpu(counters->rx_errors); + data[4] = le16_to_cpu(counters->rx_missed); + data[5] = le16_to_cpu(counters->align_errors); + data[6] = le32_to_cpu(counters->tx_one_collision); + data[7] = le32_to_cpu(counters->tx_multi_collision); + data[8] = le64_to_cpu(counters->rx_unicast); + data[9] = le64_to_cpu(counters->rx_broadcast); + data[10] = le32_to_cpu(counters->rx_multicast); + data[11] = le16_to_cpu(counters->tx_aborted); + data[12] = le16_to_cpu(counters->tx_underun); +} + +static const struct ethtool_ops rtase_ethtool_ops = { + .get_drvinfo = rtase_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_link_ksettings = rtase_get_settings, + .get_pauseparam = rtase_get_pauseparam, + .set_pauseparam = rtase_set_pauseparam, + .get_strings = rtase_get_strings, + .get_sset_count = rtase_get_sset_count, + .get_ethtool_stats = rtase_get_ethtool_stats, + .get_ts_info = ethtool_op_get_ts_info, +}; + static void rtase_init_netdev_ops(struct net_device *dev) { dev->netdev_ops = &rtase_netdev_ops; + dev->ethtool_ops = &rtase_ethtool_ops; } static void rtase_reset_interrupt(struct pci_dev *pdev,
Implement the ethtool function to support users to obtain network card information, including obtaining various device settings, Report whether physical link is up, Report pause parameters, Set pause parameters, Return a set of strings that describe the requested objects, Get number of strings that @get_strings will write, Return extended statistics about the device. Signed-off-by: Justin Lai <justinlai0215@realtek.com> --- .../net/ethernet/realtek/rtase/rtase_main.c | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+)