Commit ef8e692d authored by David S. Miller's avatar David S. Miller

Merge branch 'net-stmmac-Add-ethtool-support-for-get-set-channels'

Wong Vee Khee says:

====================
net: stmmac: Add ethtool support for get|set channels

This patch set is to add support for user to get or set Tx/Rx channel
via ethtool. There are two patches that fixes bug introduced on upstream
in order to have the feature work.

Tested on Intel Tigerlake Platform.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 945c5704 9f19306d
...@@ -264,6 +264,7 @@ int stmmac_dvr_probe(struct device *device, ...@@ -264,6 +264,7 @@ int stmmac_dvr_probe(struct device *device,
struct stmmac_resources *res); struct stmmac_resources *res);
void stmmac_disable_eee_mode(struct stmmac_priv *priv); void stmmac_disable_eee_mode(struct stmmac_priv *priv);
bool stmmac_eee_init(struct stmmac_priv *priv); bool stmmac_eee_init(struct stmmac_priv *priv);
int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt);
#if IS_ENABLED(CONFIG_STMMAC_SELFTESTS) #if IS_ENABLED(CONFIG_STMMAC_SELFTESTS)
void stmmac_selftest_run(struct net_device *dev, void stmmac_selftest_run(struct net_device *dev,
......
...@@ -840,6 +840,30 @@ static int stmmac_set_rxfh(struct net_device *dev, const u32 *indir, ...@@ -840,6 +840,30 @@ static int stmmac_set_rxfh(struct net_device *dev, const u32 *indir,
priv->plat->rx_queues_to_use); priv->plat->rx_queues_to_use);
} }
static void stmmac_get_channels(struct net_device *dev,
struct ethtool_channels *chan)
{
struct stmmac_priv *priv = netdev_priv(dev);
chan->rx_count = priv->plat->rx_queues_to_use;
chan->tx_count = priv->plat->tx_queues_to_use;
chan->max_rx = priv->dma_cap.number_rx_queues;
chan->max_tx = priv->dma_cap.number_tx_queues;
}
static int stmmac_set_channels(struct net_device *dev,
struct ethtool_channels *chan)
{
struct stmmac_priv *priv = netdev_priv(dev);
if (chan->rx_count > priv->dma_cap.number_rx_queues ||
chan->tx_count > priv->dma_cap.number_tx_queues ||
!chan->rx_count || !chan->tx_count)
return -EINVAL;
return stmmac_reinit_queues(dev, chan->rx_count, chan->tx_count);
}
static int stmmac_get_ts_info(struct net_device *dev, static int stmmac_get_ts_info(struct net_device *dev,
struct ethtool_ts_info *info) struct ethtool_ts_info *info)
{ {
...@@ -941,6 +965,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = { ...@@ -941,6 +965,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
.get_ts_info = stmmac_get_ts_info, .get_ts_info = stmmac_get_ts_info,
.get_coalesce = stmmac_get_coalesce, .get_coalesce = stmmac_get_coalesce,
.set_coalesce = stmmac_set_coalesce, .set_coalesce = stmmac_set_coalesce,
.get_channels = stmmac_get_channels,
.set_channels = stmmac_set_channels,
.get_tunable = stmmac_get_tunable, .get_tunable = stmmac_get_tunable,
.set_tunable = stmmac_set_tunable, .set_tunable = stmmac_set_tunable,
.get_link_ksettings = stmmac_ethtool_get_link_ksettings, .get_link_ksettings = stmmac_ethtool_get_link_ksettings,
......
...@@ -176,32 +176,6 @@ static void stmmac_enable_all_queues(struct stmmac_priv *priv) ...@@ -176,32 +176,6 @@ static void stmmac_enable_all_queues(struct stmmac_priv *priv)
} }
} }
/**
* stmmac_stop_all_queues - Stop all queues
* @priv: driver private structure
*/
static void stmmac_stop_all_queues(struct stmmac_priv *priv)
{
u32 tx_queues_cnt = priv->plat->tx_queues_to_use;
u32 queue;
for (queue = 0; queue < tx_queues_cnt; queue++)
netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue));
}
/**
* stmmac_start_all_queues - Start all queues
* @priv: driver private structure
*/
static void stmmac_start_all_queues(struct stmmac_priv *priv)
{
u32 tx_queues_cnt = priv->plat->tx_queues_to_use;
u32 queue;
for (queue = 0; queue < tx_queues_cnt; queue++)
netif_tx_start_queue(netdev_get_tx_queue(priv->dev, queue));
}
static void stmmac_service_event_schedule(struct stmmac_priv *priv) static void stmmac_service_event_schedule(struct stmmac_priv *priv)
{ {
if (!test_bit(STMMAC_DOWN, &priv->state) && if (!test_bit(STMMAC_DOWN, &priv->state) &&
...@@ -2732,6 +2706,10 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) ...@@ -2732,6 +2706,10 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
stmmac_enable_tbs(priv, priv->ioaddr, enable, chan); stmmac_enable_tbs(priv, priv->ioaddr, enable, chan);
} }
/* Configure real RX and TX queues */
netif_set_real_num_rx_queues(dev, priv->plat->rx_queues_to_use);
netif_set_real_num_tx_queues(dev, priv->plat->tx_queues_to_use);
/* Start the ball rolling... */ /* Start the ball rolling... */
stmmac_start_all_dma(priv); stmmac_start_all_dma(priv);
...@@ -2860,7 +2838,7 @@ static int stmmac_open(struct net_device *dev) ...@@ -2860,7 +2838,7 @@ static int stmmac_open(struct net_device *dev)
} }
stmmac_enable_all_queues(priv); stmmac_enable_all_queues(priv);
stmmac_start_all_queues(priv); netif_tx_start_all_queues(priv->dev);
return 0; return 0;
...@@ -2903,8 +2881,6 @@ static int stmmac_release(struct net_device *dev) ...@@ -2903,8 +2881,6 @@ static int stmmac_release(struct net_device *dev)
phylink_stop(priv->phylink); phylink_stop(priv->phylink);
phylink_disconnect_phy(priv->phylink); phylink_disconnect_phy(priv->phylink);
stmmac_stop_all_queues(priv);
stmmac_disable_all_queues(priv); stmmac_disable_all_queues(priv);
for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++) for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
...@@ -4739,6 +4715,69 @@ static int stmmac_hw_init(struct stmmac_priv *priv) ...@@ -4739,6 +4715,69 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
return 0; return 0;
} }
static void stmmac_napi_add(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
u32 queue, maxq;
maxq = max(priv->plat->rx_queues_to_use, priv->plat->tx_queues_to_use);
for (queue = 0; queue < maxq; queue++) {
struct stmmac_channel *ch = &priv->channel[queue];
ch->priv_data = priv;
ch->index = queue;
if (queue < priv->plat->rx_queues_to_use) {
netif_napi_add(dev, &ch->rx_napi, stmmac_napi_poll_rx,
NAPI_POLL_WEIGHT);
}
if (queue < priv->plat->tx_queues_to_use) {
netif_tx_napi_add(dev, &ch->tx_napi,
stmmac_napi_poll_tx,
NAPI_POLL_WEIGHT);
}
}
}
static void stmmac_napi_del(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
u32 queue, maxq;
maxq = max(priv->plat->rx_queues_to_use, priv->plat->tx_queues_to_use);
for (queue = 0; queue < maxq; queue++) {
struct stmmac_channel *ch = &priv->channel[queue];
if (queue < priv->plat->rx_queues_to_use)
netif_napi_del(&ch->rx_napi);
if (queue < priv->plat->tx_queues_to_use)
netif_napi_del(&ch->tx_napi);
}
}
int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
{
struct stmmac_priv *priv = netdev_priv(dev);
int ret = 0;
if (netif_running(dev))
stmmac_release(dev);
stmmac_napi_del(dev);
priv->plat->rx_queues_to_use = rx_cnt;
priv->plat->tx_queues_to_use = tx_cnt;
stmmac_napi_add(dev);
if (netif_running(dev))
ret = stmmac_open(dev);
return ret;
}
/** /**
* stmmac_dvr_probe * stmmac_dvr_probe
* @device: device pointer * @device: device pointer
...@@ -4755,7 +4794,7 @@ int stmmac_dvr_probe(struct device *device, ...@@ -4755,7 +4794,7 @@ int stmmac_dvr_probe(struct device *device,
{ {
struct net_device *ndev = NULL; struct net_device *ndev = NULL;
struct stmmac_priv *priv; struct stmmac_priv *priv;
u32 queue, rxq, maxq; u32 rxq;
int i, ret = 0; int i, ret = 0;
ndev = devm_alloc_etherdev_mqs(device, sizeof(struct stmmac_priv), ndev = devm_alloc_etherdev_mqs(device, sizeof(struct stmmac_priv),
...@@ -4819,10 +4858,6 @@ int stmmac_dvr_probe(struct device *device, ...@@ -4819,10 +4858,6 @@ int stmmac_dvr_probe(struct device *device,
stmmac_check_ether_addr(priv); stmmac_check_ether_addr(priv);
/* Configure real RX and TX queues */
netif_set_real_num_rx_queues(ndev, priv->plat->rx_queues_to_use);
netif_set_real_num_tx_queues(ndev, priv->plat->tx_queues_to_use);
ndev->netdev_ops = &stmmac_netdev_ops; ndev->netdev_ops = &stmmac_netdev_ops;
ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
...@@ -4920,25 +4955,7 @@ int stmmac_dvr_probe(struct device *device, ...@@ -4920,25 +4955,7 @@ int stmmac_dvr_probe(struct device *device,
priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */ priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */
/* Setup channels NAPI */ /* Setup channels NAPI */
maxq = max(priv->plat->rx_queues_to_use, priv->plat->tx_queues_to_use); stmmac_napi_add(ndev);
for (queue = 0; queue < maxq; queue++) {
struct stmmac_channel *ch = &priv->channel[queue];
spin_lock_init(&ch->lock);
ch->priv_data = priv;
ch->index = queue;
if (queue < priv->plat->rx_queues_to_use) {
netif_napi_add(ndev, &ch->rx_napi, stmmac_napi_poll_rx,
NAPI_POLL_WEIGHT);
}
if (queue < priv->plat->tx_queues_to_use) {
netif_tx_napi_add(ndev, &ch->tx_napi,
stmmac_napi_poll_tx,
NAPI_POLL_WEIGHT);
}
}
mutex_init(&priv->lock); mutex_init(&priv->lock);
...@@ -5003,14 +5020,7 @@ int stmmac_dvr_probe(struct device *device, ...@@ -5003,14 +5020,7 @@ int stmmac_dvr_probe(struct device *device,
priv->hw->pcs != STMMAC_PCS_RTBI) priv->hw->pcs != STMMAC_PCS_RTBI)
stmmac_mdio_unregister(ndev); stmmac_mdio_unregister(ndev);
error_mdio_register: error_mdio_register:
for (queue = 0; queue < maxq; queue++) { stmmac_napi_del(ndev);
struct stmmac_channel *ch = &priv->channel[queue];
if (queue < priv->plat->rx_queues_to_use)
netif_napi_del(&ch->rx_napi);
if (queue < priv->plat->tx_queues_to_use)
netif_napi_del(&ch->tx_napi);
}
error_hw_init: error_hw_init:
destroy_workqueue(priv->wq); destroy_workqueue(priv->wq);
...@@ -5078,7 +5088,6 @@ int stmmac_suspend(struct device *dev) ...@@ -5078,7 +5088,6 @@ int stmmac_suspend(struct device *dev)
mutex_lock(&priv->lock); mutex_lock(&priv->lock);
netif_device_detach(ndev); netif_device_detach(ndev);
stmmac_stop_all_queues(priv);
stmmac_disable_all_queues(priv); stmmac_disable_all_queues(priv);
...@@ -5204,8 +5213,6 @@ int stmmac_resume(struct device *dev) ...@@ -5204,8 +5213,6 @@ int stmmac_resume(struct device *dev)
stmmac_enable_all_queues(priv); stmmac_enable_all_queues(priv);
stmmac_start_all_queues(priv);
mutex_unlock(&priv->lock); mutex_unlock(&priv->lock);
if (!device_may_wakeup(priv->device) || !priv->plat->pmt) { if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment