net: stmmac: add ethtool support for get/set channels
Restructure NAPI add and delete process so that we can call them accordingly in open() and ethtool_set_channels() accordingly. Introduced stmmac_reinit_queues() to handle the transition needed for changing Rx & Tx channels accordingly. Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
945c570488
Коммит
0366f7e06a
|
@ -264,6 +264,7 @@ int stmmac_dvr_probe(struct device *device,
|
|||
struct stmmac_resources *res);
|
||||
void stmmac_disable_eee_mode(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)
|
||||
void stmmac_selftest_run(struct net_device *dev,
|
||||
|
|
|
@ -840,6 +840,30 @@ static int stmmac_set_rxfh(struct net_device *dev, const u32 *indir,
|
|||
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,
|
||||
struct ethtool_ts_info *info)
|
||||
{
|
||||
|
@ -941,6 +965,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
|
|||
.get_ts_info = stmmac_get_ts_info,
|
||||
.get_coalesce = stmmac_get_coalesce,
|
||||
.set_coalesce = stmmac_set_coalesce,
|
||||
.get_channels = stmmac_get_channels,
|
||||
.set_channels = stmmac_set_channels,
|
||||
.get_tunable = stmmac_get_tunable,
|
||||
.set_tunable = stmmac_set_tunable,
|
||||
.get_link_ksettings = stmmac_ethtool_get_link_ksettings,
|
||||
|
|
|
@ -4739,6 +4739,69 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
|
|||
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
|
||||
* @device: device pointer
|
||||
|
@ -4755,7 +4818,7 @@ int stmmac_dvr_probe(struct device *device,
|
|||
{
|
||||
struct net_device *ndev = NULL;
|
||||
struct stmmac_priv *priv;
|
||||
u32 queue, rxq, maxq;
|
||||
u32 rxq;
|
||||
int i, ret = 0;
|
||||
|
||||
ndev = devm_alloc_etherdev_mqs(device, sizeof(struct stmmac_priv),
|
||||
|
@ -4920,25 +4983,7 @@ int stmmac_dvr_probe(struct device *device,
|
|||
priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */
|
||||
|
||||
/* Setup channels NAPI */
|
||||
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];
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
stmmac_napi_add(ndev);
|
||||
|
||||
mutex_init(&priv->lock);
|
||||
|
||||
|
@ -5003,14 +5048,7 @@ error_phy_setup:
|
|||
priv->hw->pcs != STMMAC_PCS_RTBI)
|
||||
stmmac_mdio_unregister(ndev);
|
||||
error_mdio_register:
|
||||
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);
|
||||
}
|
||||
stmmac_napi_del(ndev);
|
||||
error_hw_init:
|
||||
destroy_workqueue(priv->wq);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче