aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0008-amd-xgbe-Add-ethtool-show-set-channels-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0008-amd-xgbe-Add-ethtool-show-set-channels-support.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0008-amd-xgbe-Add-ethtool-show-set-channels-support.patch237
1 files changed, 237 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0008-amd-xgbe-Add-ethtool-show-set-channels-support.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0008-amd-xgbe-Add-ethtool-show-set-channels-support.patch
new file mode 100644
index 00000000..4282cc5e
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71-e3000/0008-amd-xgbe-Add-ethtool-show-set-channels-support.patch
@@ -0,0 +1,237 @@
+From 8ce6e8e4c95dc8c55c49348719668b9b61fc821e Mon Sep 17 00:00:00 2001
+From: Tom Lendacky <thomas.lendacky@amd.com>
+Date: Wed, 23 May 2018 11:39:13 -0500
+Subject: [PATCH 08/95] amd-xgbe: Add ethtool show/set channels support
+
+Add ethtool support to show and set the device channel configuration.
+Changing the channel configuration will result in a device restart.
+
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sudheesh Mavila <sudheesh.mavila@amd.com>
+---
+ drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 25 +++++
+ drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 134 +++++++++++++++++++++++++++
+ drivers/net/ethernet/amd/xgbe/xgbe.h | 4 +
+ 3 files changed, 163 insertions(+)
+
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+index 3c9681a..145b5c0 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+@@ -1331,6 +1331,17 @@ static int xgbe_alloc_memory(struct xgbe_prv_data *pdata)
+ struct net_device *netdev = pdata->netdev;
+ int ret;
+
++ if (pdata->new_tx_ring_count) {
++ pdata->tx_ring_count = pdata->new_tx_ring_count;
++ pdata->tx_q_count = pdata->tx_ring_count;
++ pdata->new_tx_ring_count = 0;
++ }
++
++ if (pdata->new_rx_ring_count) {
++ pdata->rx_ring_count = pdata->new_rx_ring_count;
++ pdata->new_rx_ring_count = 0;
++ }
++
+ /* Calculate the Rx buffer size before allocating rings */
+ pdata->rx_buf_size = xgbe_calc_rx_buf_size(netdev, netdev->mtu);
+
+@@ -1484,6 +1495,20 @@ static void xgbe_stopdev(struct work_struct *work)
+ netdev_alert(pdata->netdev, "device stopped\n");
+ }
+
++void xgbe_full_restart_dev(struct xgbe_prv_data *pdata)
++{
++ /* If not running, "restart" will happen on open */
++ if (!netif_running(pdata->netdev))
++ return;
++
++ xgbe_stop(pdata);
++
++ xgbe_free_memory(pdata);
++ xgbe_alloc_memory(pdata);
++
++ xgbe_start(pdata);
++}
++
+ void xgbe_restart_dev(struct xgbe_prv_data *pdata)
+ {
+ /* If not running, "restart" will happen on open */
+diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+index d12f982..a880f10 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
++++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+@@ -705,6 +705,138 @@ static int xgbe_set_ringparam(struct net_device *netdev,
+ return 0;
+ }
+
++static void xgbe_get_channels(struct net_device *netdev,
++ struct ethtool_channels *channels)
++{
++ struct xgbe_prv_data *pdata = netdev_priv(netdev);
++ unsigned int rx, tx, combined;
++
++ /* Calculate maximums allowed:
++ * - Take into account the number of available IRQs
++ * - Do not take into account the number of online CPUs so that
++ * the user can over-subscribe if desired
++ * - Tx is additionally limited by the number of hardware queues
++ */
++ rx = min(pdata->hw_feat.rx_ch_cnt, pdata->rx_max_channel_count);
++ rx = min(rx, pdata->channel_irq_count);
++ tx = min(pdata->hw_feat.tx_ch_cnt, pdata->tx_max_channel_count);
++ tx = min(tx, pdata->channel_irq_count);
++ tx = min(tx, pdata->tx_max_q_count);
++
++ combined = min(rx, tx);
++
++ channels->max_combined = combined;
++ channels->max_rx = rx ? rx - 1 : 0;
++ channels->max_tx = tx ? tx - 1 : 0;
++
++ /* Get current settings based on device state */
++ rx = pdata->new_rx_ring_count ? : pdata->rx_ring_count;
++ tx = pdata->new_tx_ring_count ? : pdata->tx_ring_count;
++
++ combined = min(rx, tx);
++ rx -= combined;
++ tx -= combined;
++
++ channels->combined_count = combined;
++ channels->rx_count = rx;
++ channels->tx_count = tx;
++}
++
++static void xgbe_print_set_channels_input(struct net_device *netdev,
++ struct ethtool_channels *channels)
++{
++ netdev_err(netdev, "channel inputs: combined=%u, rx-only=%u, tx-only=%u\n",
++ channels->combined_count, channels->rx_count,
++ channels->tx_count);
++}
++
++static int xgbe_set_channels(struct net_device *netdev,
++ struct ethtool_channels *channels)
++{
++ struct xgbe_prv_data *pdata = netdev_priv(netdev);
++ unsigned int rx, rx_curr, tx, tx_curr, combined;
++
++ /* Calculate maximums allowed:
++ * - Take into account the number of available IRQs
++ * - Do not take into account the number of online CPUs so that
++ * the user can over-subscribe if desired
++ * - Tx is additionally limited by the number of hardware queues
++ */
++ rx = min(pdata->hw_feat.rx_ch_cnt, pdata->rx_max_channel_count);
++ rx = min(rx, pdata->channel_irq_count);
++ tx = min(pdata->hw_feat.tx_ch_cnt, pdata->tx_max_channel_count);
++ tx = min(tx, pdata->tx_max_q_count);
++ tx = min(tx, pdata->channel_irq_count);
++
++ combined = min(rx, tx);
++
++ /* Should not be setting other count */
++ if (channels->other_count) {
++ netdev_err(netdev,
++ "other channel count must be zero\n");
++ return -EINVAL;
++ }
++
++ /* Require at least one Combined (Rx and Tx) channel */
++ if (!channels->combined_count) {
++ netdev_err(netdev,
++ "at least one combined Rx/Tx channel is required\n");
++ xgbe_print_set_channels_input(netdev, channels);
++ return -EINVAL;
++ }
++
++ /* Check combined channels */
++ if (channels->combined_count > combined) {
++ netdev_err(netdev,
++ "combined channel count cannot exceed %u\n",
++ combined);
++ xgbe_print_set_channels_input(netdev, channels);
++ return -EINVAL;
++ }
++
++ /* Can have some Rx-only or Tx-only channels, but not both */
++ if (channels->rx_count && channels->tx_count) {
++ netdev_err(netdev,
++ "cannot specify both Rx-only and Tx-only channels\n");
++ xgbe_print_set_channels_input(netdev, channels);
++ return -EINVAL;
++ }
++
++ /* Check that we don't exceed the maximum number of channels */
++ if ((channels->combined_count + channels->rx_count) > rx) {
++ netdev_err(netdev,
++ "total Rx channels (%u) requested exceeds maximum available (%u)\n",
++ channels->combined_count + channels->rx_count, rx);
++ xgbe_print_set_channels_input(netdev, channels);
++ return -EINVAL;
++ }
++
++ if ((channels->combined_count + channels->tx_count) > tx) {
++ netdev_err(netdev,
++ "total Tx channels (%u) requested exceeds maximum available (%u)\n",
++ channels->combined_count + channels->tx_count, tx);
++ xgbe_print_set_channels_input(netdev, channels);
++ return -EINVAL;
++ }
++
++ rx = channels->combined_count + channels->rx_count;
++ tx = channels->combined_count + channels->tx_count;
++
++ rx_curr = pdata->new_rx_ring_count ? : pdata->rx_ring_count;
++ tx_curr = pdata->new_tx_ring_count ? : pdata->tx_ring_count;
++
++ if ((rx == rx_curr) && (tx == tx_curr))
++ goto out;
++
++ pdata->new_rx_ring_count = rx;
++ pdata->new_tx_ring_count = tx;
++
++ xgbe_full_restart_dev(pdata);
++
++out:
++ return 0;
++}
++
+ static const struct ethtool_ops xgbe_ethtool_ops = {
+ .get_drvinfo = xgbe_get_drvinfo,
+ .get_msglevel = xgbe_get_msglevel,
+@@ -729,6 +861,8 @@ static const struct ethtool_ops xgbe_ethtool_ops = {
+ .get_module_eeprom = xgbe_get_module_eeprom,
+ .get_ringparam = xgbe_get_ringparam,
+ .set_ringparam = xgbe_set_ringparam,
++ .get_channels = xgbe_get_channels,
++ .set_channels = xgbe_set_channels,
+ };
+
+ 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 7dc0fac..7a412cf 100644
+--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
++++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
+@@ -1122,6 +1122,9 @@ struct xgbe_prv_data {
+ unsigned int rx_ring_count;
+ unsigned int rx_desc_count;
+
++ unsigned int new_tx_ring_count;
++ unsigned int new_rx_ring_count;
++
+ unsigned int tx_max_q_count;
+ unsigned int rx_max_q_count;
+ unsigned int tx_q_count;
+@@ -1336,6 +1339,7 @@ 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);
++void xgbe_full_restart_dev(struct xgbe_prv_data *pdata);
+
+ #ifdef CONFIG_DEBUG_FS
+ void xgbe_debugfs_init(struct xgbe_prv_data *);
+--
+2.7.4
+