diff options
author | Giuseppe CAVALLARO <peppe.cavallaro@st.com> | 2012-11-25 18:10:44 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-11-26 17:22:12 -0500 |
commit | 48f44da4542d8f91d8b0603e20929b184dc2aa4e (patch) | |
tree | a0789a70089bea5031f75b67a49cf1c937441ca5 | |
parent | 62a2ab935c8d0f8643d02d3696abc401b5da6206 (diff) |
stmmac: get/set coalesce parameters via ethtool
This patch is to get/set the tx/rx coalesce parameters
via ethtool interface.
Tests have been done on several platform with different GMAC chips w/o and w/
RX watchdog feature.
V2: reject coalesce settings that are not supported.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Reviewed-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 7f7ccd217e4..1372ce210b5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | |||
@@ -524,6 +524,87 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev, | |||
524 | return phy_ethtool_set_eee(priv->phydev, edata); | 524 | return phy_ethtool_set_eee(priv->phydev, edata); |
525 | } | 525 | } |
526 | 526 | ||
527 | static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv) | ||
528 | { | ||
529 | unsigned long clk = clk_get_rate(priv->stmmac_clk); | ||
530 | |||
531 | if (!clk) | ||
532 | return 0; | ||
533 | |||
534 | return (usec * (clk / 1000000)) / 256; | ||
535 | } | ||
536 | |||
537 | static u32 stmmac_riwt2usec(u32 riwt, struct stmmac_priv *priv) | ||
538 | { | ||
539 | unsigned long clk = clk_get_rate(priv->stmmac_clk); | ||
540 | |||
541 | if (!clk) | ||
542 | return 0; | ||
543 | |||
544 | return (riwt * 256) / (clk / 1000000); | ||
545 | } | ||
546 | |||
547 | static int stmmac_get_coalesce(struct net_device *dev, | ||
548 | struct ethtool_coalesce *ec) | ||
549 | { | ||
550 | struct stmmac_priv *priv = netdev_priv(dev); | ||
551 | |||
552 | ec->tx_coalesce_usecs = priv->tx_coal_timer; | ||
553 | ec->tx_max_coalesced_frames = priv->tx_coal_frames; | ||
554 | |||
555 | if (priv->use_riwt) | ||
556 | ec->rx_coalesce_usecs = stmmac_riwt2usec(priv->rx_riwt, priv); | ||
557 | |||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | static int stmmac_set_coalesce(struct net_device *dev, | ||
562 | struct ethtool_coalesce *ec) | ||
563 | { | ||
564 | struct stmmac_priv *priv = netdev_priv(dev); | ||
565 | unsigned int rx_riwt; | ||
566 | |||
567 | /* Check not supported parameters */ | ||
568 | if ((ec->rx_max_coalesced_frames) || (ec->rx_coalesce_usecs_irq) || | ||
569 | (ec->rx_max_coalesced_frames_irq) || (ec->tx_coalesce_usecs_irq) || | ||
570 | (ec->use_adaptive_rx_coalesce) || (ec->use_adaptive_tx_coalesce) || | ||
571 | (ec->pkt_rate_low) || (ec->rx_coalesce_usecs_low) || | ||
572 | (ec->rx_max_coalesced_frames_low) || (ec->tx_coalesce_usecs_high) || | ||
573 | (ec->tx_max_coalesced_frames_low) || (ec->pkt_rate_high) || | ||
574 | (ec->tx_coalesce_usecs_low) || (ec->rx_coalesce_usecs_high) || | ||
575 | (ec->rx_max_coalesced_frames_high) || | ||
576 | (ec->tx_max_coalesced_frames_irq) || | ||
577 | (ec->stats_block_coalesce_usecs) || | ||
578 | (ec->tx_max_coalesced_frames_high) || (ec->rate_sample_interval)) | ||
579 | return -EOPNOTSUPP; | ||
580 | |||
581 | if (ec->rx_coalesce_usecs == 0) | ||
582 | return -EINVAL; | ||
583 | |||
584 | if ((ec->tx_coalesce_usecs == 0) && | ||
585 | (ec->tx_max_coalesced_frames == 0)) | ||
586 | return -EINVAL; | ||
587 | |||
588 | if ((ec->tx_coalesce_usecs > STMMAC_COAL_TX_TIMER) || | ||
589 | (ec->tx_max_coalesced_frames > STMMAC_TX_MAX_FRAMES)) | ||
590 | return -EINVAL; | ||
591 | |||
592 | rx_riwt = stmmac_usec2riwt(ec->rx_coalesce_usecs, priv); | ||
593 | |||
594 | if ((rx_riwt > MAX_DMA_RIWT) || (rx_riwt < MIN_DMA_RIWT)) | ||
595 | return -EINVAL; | ||
596 | else if (!priv->use_riwt) | ||
597 | return -EOPNOTSUPP; | ||
598 | |||
599 | /* Only copy relevant parameters, ignore all others. */ | ||
600 | priv->tx_coal_frames = ec->tx_max_coalesced_frames; | ||
601 | priv->tx_coal_timer = ec->tx_coalesce_usecs; | ||
602 | priv->rx_riwt = rx_riwt; | ||
603 | priv->hw->dma->rx_watchdog(priv->ioaddr, priv->rx_riwt); | ||
604 | |||
605 | return 0; | ||
606 | } | ||
607 | |||
527 | static const struct ethtool_ops stmmac_ethtool_ops = { | 608 | static const struct ethtool_ops stmmac_ethtool_ops = { |
528 | .begin = stmmac_check_if_running, | 609 | .begin = stmmac_check_if_running, |
529 | .get_drvinfo = stmmac_ethtool_getdrvinfo, | 610 | .get_drvinfo = stmmac_ethtool_getdrvinfo, |
@@ -544,6 +625,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = { | |||
544 | .set_eee = stmmac_ethtool_op_set_eee, | 625 | .set_eee = stmmac_ethtool_op_set_eee, |
545 | .get_sset_count = stmmac_get_sset_count, | 626 | .get_sset_count = stmmac_get_sset_count, |
546 | .get_ts_info = ethtool_op_get_ts_info, | 627 | .get_ts_info = ethtool_op_get_ts_info, |
628 | .get_coalesce = stmmac_get_coalesce, | ||
629 | .set_coalesce = stmmac_set_coalesce, | ||
547 | }; | 630 | }; |
548 | 631 | ||
549 | void stmmac_set_ethtool_ops(struct net_device *netdev) | 632 | void stmmac_set_ethtool_ops(struct net_device *netdev) |