diff options
Diffstat (limited to 'drivers/net/ethernet/ti/am65-cpsw-ethtool.c')
| -rw-r--r-- | drivers/net/ethernet/ti/am65-cpsw-ethtool.c | 382 |
1 files changed, 309 insertions, 73 deletions
diff --git a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c index 8c4690f3ebcb..c57497074ae6 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c +++ b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c @@ -6,11 +6,12 @@ */ #include <linux/net_tstamp.h> -#include <linux/phy.h> +#include <linux/phylink.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include "am65-cpsw-nuss.h" +#include "am65-cpsw-qos.h" #include "cpsw_ale.h" #include "am65-cpts.h" @@ -61,7 +62,7 @@ struct am65_cpsw_regdump_item { #define AM65_CPSW_REGDUMP_REC(mod, start, end) { \ .hdr.module_id = (mod), \ - .hdr.len = (((u32 *)(end)) - ((u32 *)(start)) + 1) * sizeof(u32) * 2 + \ + .hdr.len = (end + 4 - start) * 2 + \ sizeof(struct am65_cpsw_regdump_hdr), \ .start_ofs = (start), \ .end_ofs = end, \ @@ -380,11 +381,9 @@ static int am65_cpsw_ethtool_op_begin(struct net_device *ndev) struct am65_cpsw_common *common = am65_ndev_to_common(ndev); int ret; - ret = pm_runtime_get_sync(common->dev); - if (ret < 0) { + ret = pm_runtime_resume_and_get(common->dev); + if (ret < 0) dev_err(common->dev, "ethtool begin failed %d\n", ret); - pm_runtime_put_noidle(common->dev); - } return ret; } @@ -404,9 +403,9 @@ static void am65_cpsw_get_drvinfo(struct net_device *ndev, { struct am65_cpsw_common *common = am65_ndev_to_common(ndev); - strlcpy(info->driver, dev_driver_string(common->dev), + strscpy(info->driver, dev_driver_string(common->dev), sizeof(info->driver)); - strlcpy(info->bus_info, dev_name(common->dev), sizeof(info->bus_info)); + strscpy(info->bus_info, dev_name(common->dev), sizeof(info->bus_info)); } static u32 am65_cpsw_get_msglevel(struct net_device *ndev) @@ -428,9 +427,9 @@ static void am65_cpsw_get_channels(struct net_device *ndev, { struct am65_cpsw_common *common = am65_ndev_to_common(ndev); - ch->max_rx = AM65_CPSW_MAX_RX_QUEUES; - ch->max_tx = AM65_CPSW_MAX_TX_QUEUES; - ch->rx_count = AM65_CPSW_MAX_RX_QUEUES; + ch->max_rx = AM65_CPSW_MAX_QUEUES; + ch->max_tx = AM65_CPSW_MAX_QUEUES; + ch->rx_count = common->rx_ch_num_flows; ch->tx_count = common->tx_ch_num; } @@ -445,16 +444,18 @@ static int am65_cpsw_set_channels(struct net_device *ndev, /* Check if interface is up. Can change the num queues when * the interface is down. */ - if (netif_running(ndev)) + if (common->usage_count) return -EBUSY; - am65_cpsw_nuss_remove_tx_chns(common); - - return am65_cpsw_nuss_update_tx_chns(common, chs->tx_count); + return am65_cpsw_nuss_update_tx_rx_chns(common, chs->tx_count, + chs->rx_count); } -static void am65_cpsw_get_ringparam(struct net_device *ndev, - struct ethtool_ringparam *ering) +static void +am65_cpsw_get_ringparam(struct net_device *ndev, + struct ethtool_ringparam *ering, + struct kernel_ethtool_ringparam *kernel_ering, + struct netlink_ext_ack *extack) { struct am65_cpsw_common *common = am65_ndev_to_common(ndev); @@ -468,9 +469,7 @@ static void am65_cpsw_get_pauseparam(struct net_device *ndev, { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - pause->autoneg = AUTONEG_DISABLE; - pause->rx_pause = salve->rx_pause ? true : false; - pause->tx_pause = salve->tx_pause ? true : false; + phylink_ethtool_get_pauseparam(salve->phylink, pause); } static int am65_cpsw_set_pauseparam(struct net_device *ndev, @@ -478,18 +477,7 @@ static int am65_cpsw_set_pauseparam(struct net_device *ndev, { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - if (!salve->phy) - return -EINVAL; - - if (!phy_validate_pause(salve->phy, pause)) - return -EINVAL; - - salve->rx_pause = pause->rx_pause ? true : false; - salve->tx_pause = pause->tx_pause ? true : false; - - phy_set_asym_pause(salve->phy, salve->rx_pause, salve->tx_pause); - - return 0; + return phylink_ethtool_set_pauseparam(salve->phylink, pause); } static void am65_cpsw_get_wol(struct net_device *ndev, @@ -497,11 +485,7 @@ static void am65_cpsw_get_wol(struct net_device *ndev, { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - wol->supported = 0; - wol->wolopts = 0; - - if (salve->phy) - phy_ethtool_get_wol(salve->phy, wol); + phylink_ethtool_get_wol(salve->phylink, wol); } static int am65_cpsw_set_wol(struct net_device *ndev, @@ -509,10 +493,7 @@ static int am65_cpsw_set_wol(struct net_device *ndev, { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - if (!salve->phy) - return -EOPNOTSUPP; - - return phy_ethtool_set_wol(salve->phy, wol); + return phylink_ethtool_set_wol(salve->phylink, wol); } static int am65_cpsw_get_link_ksettings(struct net_device *ndev, @@ -520,11 +501,7 @@ static int am65_cpsw_get_link_ksettings(struct net_device *ndev, { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - if (!salve->phy) - return -EOPNOTSUPP; - - phy_ethtool_ksettings_get(salve->phy, ecmd); - return 0; + return phylink_ethtool_ksettings_get(salve->phylink, ecmd); } static int @@ -533,52 +510,41 @@ am65_cpsw_set_link_ksettings(struct net_device *ndev, { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy)) - return -EOPNOTSUPP; - - return phy_ethtool_ksettings_set(salve->phy, ecmd); + return phylink_ethtool_ksettings_set(salve->phylink, ecmd); } -static int am65_cpsw_get_eee(struct net_device *ndev, struct ethtool_eee *edata) +static int am65_cpsw_get_eee(struct net_device *ndev, struct ethtool_keee *edata) { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy)) - return -EOPNOTSUPP; - - return phy_ethtool_get_eee(salve->phy, edata); + return phylink_ethtool_get_eee(salve->phylink, edata); } -static int am65_cpsw_set_eee(struct net_device *ndev, struct ethtool_eee *edata) +static int am65_cpsw_set_eee(struct net_device *ndev, struct ethtool_keee *edata) { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy)) - return -EOPNOTSUPP; - - return phy_ethtool_set_eee(salve->phy, edata); + return phylink_ethtool_set_eee(salve->phylink, edata); } static int am65_cpsw_nway_reset(struct net_device *ndev) { struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev); - if (!salve->phy || phy_is_pseudo_fixed_link(salve->phy)) - return -EOPNOTSUPP; - - return phy_restart_aneg(salve->phy); + return phylink_ethtool_nway_reset(salve->phylink); } static int am65_cpsw_get_regs_len(struct net_device *ndev) { struct am65_cpsw_common *common = am65_ndev_to_common(ndev); - u32 i, regdump_len = 0; + u32 ale_entries, i, regdump_len = 0; + ale_entries = cpsw_ale_get_num_entries(common->ale); for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) { if (am65_cpsw_regdump[i].hdr.module_id == AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL) { regdump_len += sizeof(struct am65_cpsw_regdump_hdr); - regdump_len += common->ale->params.ale_entries * + regdump_len += ale_entries * ALE_ENTRY_WORDS * sizeof(u32); continue; } @@ -592,10 +558,11 @@ static void am65_cpsw_get_regs(struct net_device *ndev, struct ethtool_regs *regs, void *p) { struct am65_cpsw_common *common = am65_ndev_to_common(ndev); - u32 i, j, pos, *reg = p; + u32 ale_entries, i, j, pos, *reg = p; /* update CPSW IP version */ regs->version = AM65_CPSW_REGDUMP_VER; + ale_entries = cpsw_ale_get_num_entries(common->ale); pos = 0; for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) { @@ -603,7 +570,7 @@ static void am65_cpsw_get_regs(struct net_device *ndev, if (am65_cpsw_regdump[i].hdr.module_id == AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL) { - u32 ale_tbl_len = common->ale->params.ale_entries * + u32 ale_tbl_len = ale_entries * ALE_ENTRY_WORDS * sizeof(u32) + sizeof(struct am65_cpsw_regdump_hdr); reg[pos++] = ale_tbl_len; @@ -695,10 +662,52 @@ static void am65_cpsw_get_ethtool_stats(struct net_device *ndev, hw_stats[i].offset); } +static void am65_cpsw_get_eth_mac_stats(struct net_device *ndev, + struct ethtool_eth_mac_stats *s) +{ + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); + struct am65_cpsw_stats_regs __iomem *stats; + + stats = port->stat_base; + + if (s->src != ETHTOOL_MAC_STATS_SRC_AGGREGATE) + return; + + s->FramesTransmittedOK = readl_relaxed(&stats->tx_good_frames); + s->SingleCollisionFrames = readl_relaxed(&stats->tx_single_coll_frames); + s->MultipleCollisionFrames = readl_relaxed(&stats->tx_mult_coll_frames); + s->FramesReceivedOK = readl_relaxed(&stats->rx_good_frames); + s->FrameCheckSequenceErrors = readl_relaxed(&stats->rx_crc_errors); + s->AlignmentErrors = readl_relaxed(&stats->rx_align_code_errors); + s->OctetsTransmittedOK = readl_relaxed(&stats->tx_octets); + s->FramesWithDeferredXmissions = readl_relaxed(&stats->tx_deferred_frames); + s->LateCollisions = readl_relaxed(&stats->tx_late_collisions); + s->CarrierSenseErrors = readl_relaxed(&stats->tx_carrier_sense_errors); + s->OctetsReceivedOK = readl_relaxed(&stats->rx_octets); + s->MulticastFramesXmittedOK = readl_relaxed(&stats->tx_multicast_frames); + s->BroadcastFramesXmittedOK = readl_relaxed(&stats->tx_broadcast_frames); + s->MulticastFramesReceivedOK = readl_relaxed(&stats->rx_multicast_frames); + s->BroadcastFramesReceivedOK = readl_relaxed(&stats->rx_broadcast_frames); +}; + static int am65_cpsw_get_ethtool_ts_info(struct net_device *ndev, - struct ethtool_ts_info *info) + struct kernel_ethtool_ts_info *info) { struct am65_cpsw_common *common = am65_ndev_to_common(ndev); + unsigned int ptp_filter; + + ptp_filter = BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | + BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) | + BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | + BIT(HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) | + BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) | + BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | + BIT(HWTSTAMP_FILTER_PTP_V1_L4_EVENT) | + BIT(HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ); if (!IS_ENABLED(CONFIG_TI_K3_AM65_CPTS)) return ethtool_op_get_ts_info(ndev, info); @@ -707,12 +716,10 @@ static int am65_cpsw_get_ethtool_ts_info(struct net_device *ndev, SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_RX_HARDWARE | - SOF_TIMESTAMPING_RX_SOFTWARE | - SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_RAW_HARDWARE; info->phc_index = am65_cpts_phc_index(common->cpts); info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); - info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL); + info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | ptp_filter; return 0; } @@ -734,6 +741,9 @@ static int am65_cpsw_set_ethtool_priv_flags(struct net_device *ndev, u32 flags) rrobin = !!(flags & AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN); + if (common->usage_count) + return -EBUSY; + if (common->est_enabled && rrobin) { netdev_err(ndev, "p0-rx-ptype-rrobin flag conflicts with QOS\n"); @@ -741,11 +751,228 @@ static int am65_cpsw_set_ethtool_priv_flags(struct net_device *ndev, u32 flags) } common->pf_p0_rx_ptype_rrobin = rrobin; - am65_cpsw_nuss_set_p0_ptype(common); return 0; } +static void am65_cpsw_port_iet_rx_enable(struct am65_cpsw_port *port, bool enable) +{ + u32 val; + + val = readl(port->port_base + AM65_CPSW_PN_REG_CTL); + if (enable) + val |= AM65_CPSW_PN_CTL_IET_PORT_EN; + else + val &= ~AM65_CPSW_PN_CTL_IET_PORT_EN; + + writel(val, port->port_base + AM65_CPSW_PN_REG_CTL); + am65_cpsw_iet_common_enable(port->common); +} + +static void am65_cpsw_port_iet_tx_enable(struct am65_cpsw_port *port, bool enable) +{ + u32 val; + + val = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); + if (enable) + val |= AM65_CPSW_PN_IET_MAC_PENABLE; + else + val &= ~AM65_CPSW_PN_IET_MAC_PENABLE; + + writel(val, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); +} + +static int am65_cpsw_get_mm(struct net_device *ndev, struct ethtool_mm_state *state) +{ + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); + struct am65_cpsw_ndev_priv *priv = netdev_priv(ndev); + u32 port_ctrl, iet_ctrl, iet_status; + u32 add_frag_size; + + if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_QOS)) + return -EOPNOTSUPP; + + mutex_lock(&priv->mm_lock); + + iet_ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); + port_ctrl = readl(port->port_base + AM65_CPSW_PN_REG_CTL); + + state->tx_enabled = !!(iet_ctrl & AM65_CPSW_PN_IET_MAC_PENABLE); + state->pmac_enabled = !!(port_ctrl & AM65_CPSW_PN_CTL_IET_PORT_EN); + + iet_status = readl(port->port_base + AM65_CPSW_PN_REG_IET_STATUS); + + if (iet_ctrl & AM65_CPSW_PN_IET_MAC_DISABLEVERIFY) + state->verify_status = ETHTOOL_MM_VERIFY_STATUS_DISABLED; + else if (iet_status & AM65_CPSW_PN_MAC_VERIFIED) + state->verify_status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED; + else if (iet_status & AM65_CPSW_PN_MAC_VERIFY_FAIL) + state->verify_status = ETHTOOL_MM_VERIFY_STATUS_FAILED; + else + state->verify_status = ETHTOOL_MM_VERIFY_STATUS_UNKNOWN; + + add_frag_size = AM65_CPSW_PN_IET_MAC_GET_ADDFRAGSIZE(iet_ctrl); + state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(add_frag_size); + + /* Errata i2208: RX min fragment size cannot be less than 124 */ + state->rx_min_frag_size = 124; + + /* FPE active if common tx_enabled and verification success or disabled (forced) */ + state->tx_active = state->tx_enabled && + (state->verify_status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED || + state->verify_status == ETHTOOL_MM_VERIFY_STATUS_DISABLED); + state->verify_enabled = !(iet_ctrl & AM65_CPSW_PN_IET_MAC_DISABLEVERIFY); + + state->verify_time = port->qos.iet.verify_time_ms; + + /* 802.3-2018 clause 30.14.1.6, says that the aMACMergeVerifyTime + * variable has a range between 1 and 128 ms inclusive. Limit to that. + */ + state->max_verify_time = 128; + + mutex_unlock(&priv->mm_lock); + + return 0; +} + +static int am65_cpsw_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg, + struct netlink_ext_ack *extack) +{ + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); + struct am65_cpsw_ndev_priv *priv = netdev_priv(ndev); + struct am65_cpsw_iet *iet = &port->qos.iet; + u32 val, add_frag_size; + int err; + + if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_QOS)) + return -EOPNOTSUPP; + + err = ethtool_mm_frag_size_min_to_add(cfg->tx_min_frag_size, &add_frag_size, extack); + if (err) + return err; + + mutex_lock(&priv->mm_lock); + + if (cfg->pmac_enabled) { + /* change TX & RX FIFO MAX_BLKS as per TRM recommendation */ + if (!iet->original_max_blks) + iet->original_max_blks = readl(port->port_base + AM65_CPSW_PN_REG_MAX_BLKS); + + writel(AM65_CPSW_PN_TX_RX_MAX_BLKS_IET, + port->port_base + AM65_CPSW_PN_REG_MAX_BLKS); + } else if (iet->original_max_blks) { + /* restore RX & TX FIFO MAX_BLKS */ + writel(iet->original_max_blks, + port->port_base + AM65_CPSW_PN_REG_MAX_BLKS); + } + + am65_cpsw_port_iet_rx_enable(port, cfg->pmac_enabled); + am65_cpsw_port_iet_tx_enable(port, cfg->tx_enabled); + + val = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); + if (cfg->verify_enabled) { + val &= ~AM65_CPSW_PN_IET_MAC_DISABLEVERIFY; + /* Reset Verify state machine. Verification won't start here. + * Verification will be done once link-up. + */ + val |= AM65_CPSW_PN_IET_MAC_LINKFAIL; + } else { + val |= AM65_CPSW_PN_IET_MAC_DISABLEVERIFY; + /* Clear LINKFAIL to allow verify/response packets */ + val &= ~AM65_CPSW_PN_IET_MAC_LINKFAIL; + } + + val &= ~AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_MASK; + val |= AM65_CPSW_PN_IET_MAC_SET_ADDFRAGSIZE(add_frag_size); + writel(val, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); + + /* verify_timeout_count can only be set at valid link */ + port->qos.iet.verify_time_ms = cfg->verify_time; + + /* enable/disable preemption based on link status */ + am65_cpsw_iet_commit_preemptible_tcs(port); + + mutex_unlock(&priv->mm_lock); + + return 0; +} + +static void am65_cpsw_get_mm_stats(struct net_device *ndev, + struct ethtool_mm_stats *s) +{ + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); + void __iomem *base = port->stat_base; + + s->MACMergeFrameAssOkCount = readl(base + AM65_CPSW_STATN_IET_RX_ASSEMBLY_OK); + s->MACMergeFrameAssErrorCount = readl(base + AM65_CPSW_STATN_IET_RX_ASSEMBLY_ERROR); + s->MACMergeFrameSmdErrorCount = readl(base + AM65_CPSW_STATN_IET_RX_SMD_ERROR); + /* CPSW Functional Spec states: + * "The IET stat aMACMergeFragCountRx is derived by adding the + * Receive Assembly Error count to this value. i.e. AM65_CPSW_STATN_IET_RX_FRAG" + */ + s->MACMergeFragCountRx = readl(base + AM65_CPSW_STATN_IET_RX_FRAG) + s->MACMergeFrameAssErrorCount; + s->MACMergeFragCountTx = readl(base + AM65_CPSW_STATN_IET_TX_FRAG); + s->MACMergeHoldCount = readl(base + AM65_CPSW_STATN_IET_TX_HOLD); +} + +static int am65_cpsw_get_per_queue_coalesce(struct net_device *ndev, u32 queue, + struct ethtool_coalesce *coal) +{ + struct am65_cpsw_common *common = am65_ndev_to_common(ndev); + struct am65_cpsw_rx_flow *rx_flow; + struct am65_cpsw_tx_chn *tx_chn; + + if (queue >= AM65_CPSW_MAX_QUEUES) + return -EINVAL; + + tx_chn = &common->tx_chns[queue]; + coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout / 1000; + + rx_flow = &common->rx_chns.flows[queue]; + coal->rx_coalesce_usecs = rx_flow->rx_pace_timeout / 1000; + + return 0; +} + +static int am65_cpsw_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal, + struct kernel_ethtool_coalesce *kernel_coal, + struct netlink_ext_ack *extack) +{ + return am65_cpsw_get_per_queue_coalesce(ndev, 0, coal); +} + +static int am65_cpsw_set_per_queue_coalesce(struct net_device *ndev, u32 queue, + struct ethtool_coalesce *coal) +{ + struct am65_cpsw_common *common = am65_ndev_to_common(ndev); + struct am65_cpsw_rx_flow *rx_flow; + struct am65_cpsw_tx_chn *tx_chn; + + if (queue >= AM65_CPSW_MAX_QUEUES) + return -EINVAL; + + tx_chn = &common->tx_chns[queue]; + if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20) + return -EINVAL; + + tx_chn->tx_pace_timeout = coal->tx_coalesce_usecs * 1000; + + rx_flow = &common->rx_chns.flows[queue]; + if (coal->rx_coalesce_usecs && coal->rx_coalesce_usecs < 20) + return -EINVAL; + + rx_flow->rx_pace_timeout = coal->rx_coalesce_usecs * 1000; + + return 0; +} + +static int am65_cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal, + struct kernel_ethtool_coalesce *kernel_coal, + struct netlink_ext_ack *extack) +{ + return am65_cpsw_set_per_queue_coalesce(ndev, 0, coal); +} + const struct ethtool_ops am65_cpsw_ethtool_ops_slave = { .begin = am65_cpsw_ethtool_op_begin, .complete = am65_cpsw_ethtool_op_complete, @@ -760,9 +987,15 @@ const struct ethtool_ops am65_cpsw_ethtool_ops_slave = { .get_sset_count = am65_cpsw_get_sset_count, .get_strings = am65_cpsw_get_strings, .get_ethtool_stats = am65_cpsw_get_ethtool_stats, + .get_eth_mac_stats = am65_cpsw_get_eth_mac_stats, .get_ts_info = am65_cpsw_get_ethtool_ts_info, .get_priv_flags = am65_cpsw_get_ethtool_priv_flags, .set_priv_flags = am65_cpsw_set_ethtool_priv_flags, + .supported_coalesce_params = ETHTOOL_COALESCE_USECS, + .get_coalesce = am65_cpsw_get_coalesce, + .set_coalesce = am65_cpsw_set_coalesce, + .get_per_queue_coalesce = am65_cpsw_get_per_queue_coalesce, + .set_per_queue_coalesce = am65_cpsw_set_per_queue_coalesce, .get_link = ethtool_op_get_link, .get_link_ksettings = am65_cpsw_get_link_ksettings, @@ -774,4 +1007,7 @@ const struct ethtool_ops am65_cpsw_ethtool_ops_slave = { .get_eee = am65_cpsw_get_eee, .set_eee = am65_cpsw_set_eee, .nway_reset = am65_cpsw_nway_reset, + .get_mm = am65_cpsw_get_mm, + .set_mm = am65_cpsw_set_mm, + .get_mm_stats = am65_cpsw_get_mm_stats, }; |
