From bab748de986d786cbbef31d550bea3bc616304cb Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Wed, 23 May 2018 11:38:56 -0500 Subject: [PATCH] amd-xgbe: Add ethtool show/set ring parameter support Add ethtool support to show and set the number of the Rx and Tx ring descriptors. Changing the ring configuration will result in a device restart. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 6 +- drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 65 ++++++++++++++++++++ drivers/net/ethernet/amd/xgbe/xgbe.h | 6 ++ 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 7c204f05b418..2646c088452c 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -1426,10 +1426,8 @@ static void xgbe_stopdev(struct work_struct *work) netdev_alert(pdata->netdev, "device stopped\n"); } -static void xgbe_restart_dev(struct xgbe_prv_data *pdata) +void xgbe_restart_dev(struct xgbe_prv_data *pdata) { - DBGPR("-->xgbe_restart_dev\n"); - /* If not running, "restart" will happen on open */ if (!netif_running(pdata->netdev)) return; @@ -1440,8 +1438,6 @@ static void xgbe_restart_dev(struct xgbe_prv_data *pdata) xgbe_free_rx_data(pdata); xgbe_start(pdata); - - DBGPR("<--xgbe_restart_dev\n"); } static void xgbe_restart(struct work_struct *work) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c index 57394b77b2d3..d12f982d73b4 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c @@ -642,6 +642,69 @@ static int xgbe_get_module_eeprom(struct net_device *netdev, return pdata->phy_if.module_eeprom(pdata, eeprom, data); } +static void xgbe_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ringparam) +{ + struct xgbe_prv_data *pdata = netdev_priv(netdev); + + ringparam->rx_max_pending = XGBE_RX_DESC_CNT_MAX; + ringparam->tx_max_pending = XGBE_TX_DESC_CNT_MAX; + ringparam->rx_pending = pdata->rx_desc_count; + ringparam->tx_pending = pdata->tx_desc_count; +} + +static int xgbe_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ringparam) +{ + struct xgbe_prv_data *pdata = netdev_priv(netdev); + unsigned int rx, tx; + + if (ringparam->rx_mini_pending || ringparam->rx_jumbo_pending) { + netdev_err(netdev, "unsupported ring parameter\n"); + return -EINVAL; + } + + if ((ringparam->rx_pending < XGBE_RX_DESC_CNT_MIN) || + (ringparam->rx_pending > XGBE_RX_DESC_CNT_MAX)) { + netdev_err(netdev, + "rx ring parameter must be between %u and %u\n", + XGBE_RX_DESC_CNT_MIN, XGBE_RX_DESC_CNT_MAX); + return -EINVAL; + } + + if ((ringparam->tx_pending < XGBE_TX_DESC_CNT_MIN) || + (ringparam->tx_pending > XGBE_TX_DESC_CNT_MAX)) { + netdev_err(netdev, + "tx ring parameter must be between %u and %u\n", + XGBE_TX_DESC_CNT_MIN, XGBE_TX_DESC_CNT_MAX); + return -EINVAL; + } + + rx = __rounddown_pow_of_two(ringparam->rx_pending); + if (rx != ringparam->rx_pending) + netdev_notice(netdev, + "rx ring parameter rounded to power of two: %u\n", + rx); + + tx = __rounddown_pow_of_two(ringparam->tx_pending); + if (tx != ringparam->tx_pending) + netdev_notice(netdev, + "tx ring parameter rounded to power of two: %u\n", + tx); + + if ((rx == pdata->rx_desc_count) && + (tx == pdata->tx_desc_count)) + goto out; + + pdata->rx_desc_count = rx; + pdata->tx_desc_count = tx; + + xgbe_restart_dev(pdata); + +out: + return 0; +} + static const struct ethtool_ops xgbe_ethtool_ops = { .get_drvinfo = xgbe_get_drvinfo, .get_msglevel = xgbe_get_msglevel, @@ -664,6 +727,8 @@ static const struct ethtool_ops xgbe_ethtool_ops = { .set_link_ksettings = xgbe_set_link_ksettings, .get_module_info = xgbe_get_module_info, .get_module_eeprom = xgbe_get_module_eeprom, + .get_ringparam = xgbe_get_ringparam, + .set_ringparam = xgbe_set_ringparam, }; const struct ethtool_ops *xgbe_get_ethtool_ops(void) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index f0f455b79ff9..7dc0fac560a3 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -144,6 +144,11 @@ #define XGBE_TX_DESC_MAX_PROC (XGBE_TX_DESC_CNT >> 1) #define XGBE_RX_DESC_CNT 512 +#define XGBE_TX_DESC_CNT_MIN 64 +#define XGBE_TX_DESC_CNT_MAX 4096 +#define XGBE_RX_DESC_CNT_MIN 64 +#define XGBE_RX_DESC_CNT_MAX 4096 + #define XGBE_TX_MAX_BUF_SIZE (0x3fff & ~(64 - 1)) /* Descriptors required for maximum contiguous TSO/GSO packet */ @@ -1330,6 +1335,7 @@ int xgbe_powerup(struct net_device *, unsigned int); int xgbe_powerdown(struct net_device *, unsigned int); void xgbe_init_rx_coalesce(struct xgbe_prv_data *); void xgbe_init_tx_coalesce(struct xgbe_prv_data *); +void xgbe_restart_dev(struct xgbe_prv_data *pdata); #ifdef CONFIG_DEBUG_FS void xgbe_debugfs_init(struct xgbe_prv_data *); -- 2.30.2