Commit c62cd3c4 authored by Sunil Goutham's avatar Sunil Goutham Committed by David S. Miller

net: thunderx: Fix memory leak when changing queue count

Fix for memory leak when changing queue/channel count via ethtool
Signed-off-by: default avatarSunil Goutham <sgoutham@cavium.com>
Signed-off-by: default avatarAleksey Makarov <aleksey.makarov@caviumnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 32c1b965
...@@ -126,6 +126,7 @@ static void nicvf_set_msglevel(struct net_device *netdev, u32 lvl) ...@@ -126,6 +126,7 @@ static void nicvf_set_msglevel(struct net_device *netdev, u32 lvl)
static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data) static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
{ {
struct nicvf *nic = netdev_priv(netdev);
int stats, qidx; int stats, qidx;
if (sset != ETH_SS_STATS) if (sset != ETH_SS_STATS)
...@@ -141,7 +142,7 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data) ...@@ -141,7 +142,7 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
data += ETH_GSTRING_LEN; data += ETH_GSTRING_LEN;
} }
for (qidx = 0; qidx < MAX_RCV_QUEUES_PER_QS; qidx++) { for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
for (stats = 0; stats < nicvf_n_queue_stats; stats++) { for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
sprintf(data, "rxq%d: %s", qidx, sprintf(data, "rxq%d: %s", qidx,
nicvf_queue_stats[stats].name); nicvf_queue_stats[stats].name);
...@@ -149,7 +150,7 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data) ...@@ -149,7 +150,7 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
} }
} }
for (qidx = 0; qidx < MAX_SND_QUEUES_PER_QS; qidx++) { for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
for (stats = 0; stats < nicvf_n_queue_stats; stats++) { for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
sprintf(data, "txq%d: %s", qidx, sprintf(data, "txq%d: %s", qidx,
nicvf_queue_stats[stats].name); nicvf_queue_stats[stats].name);
...@@ -170,12 +171,14 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data) ...@@ -170,12 +171,14 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
static int nicvf_get_sset_count(struct net_device *netdev, int sset) static int nicvf_get_sset_count(struct net_device *netdev, int sset)
{ {
struct nicvf *nic = netdev_priv(netdev);
if (sset != ETH_SS_STATS) if (sset != ETH_SS_STATS)
return -EINVAL; return -EINVAL;
return nicvf_n_hw_stats + nicvf_n_drv_stats + return nicvf_n_hw_stats + nicvf_n_drv_stats +
(nicvf_n_queue_stats * (nicvf_n_queue_stats *
(MAX_RCV_QUEUES_PER_QS + MAX_SND_QUEUES_PER_QS)) + (nic->qs->rq_cnt + nic->qs->sq_cnt)) +
BGX_RX_STATS_COUNT + BGX_TX_STATS_COUNT; BGX_RX_STATS_COUNT + BGX_TX_STATS_COUNT;
} }
...@@ -197,13 +200,13 @@ static void nicvf_get_ethtool_stats(struct net_device *netdev, ...@@ -197,13 +200,13 @@ static void nicvf_get_ethtool_stats(struct net_device *netdev,
*(data++) = ((u64 *)&nic->drv_stats) *(data++) = ((u64 *)&nic->drv_stats)
[nicvf_drv_stats[stat].index]; [nicvf_drv_stats[stat].index];
for (qidx = 0; qidx < MAX_RCV_QUEUES_PER_QS; qidx++) { for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
for (stat = 0; stat < nicvf_n_queue_stats; stat++) for (stat = 0; stat < nicvf_n_queue_stats; stat++)
*(data++) = ((u64 *)&nic->qs->rq[qidx].stats) *(data++) = ((u64 *)&nic->qs->rq[qidx].stats)
[nicvf_queue_stats[stat].index]; [nicvf_queue_stats[stat].index];
} }
for (qidx = 0; qidx < MAX_SND_QUEUES_PER_QS; qidx++) { for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
for (stat = 0; stat < nicvf_n_queue_stats; stat++) for (stat = 0; stat < nicvf_n_queue_stats; stat++)
*(data++) = ((u64 *)&nic->qs->sq[qidx].stats) *(data++) = ((u64 *)&nic->qs->sq[qidx].stats)
[nicvf_queue_stats[stat].index]; [nicvf_queue_stats[stat].index];
...@@ -543,6 +546,7 @@ static int nicvf_set_channels(struct net_device *dev, ...@@ -543,6 +546,7 @@ static int nicvf_set_channels(struct net_device *dev,
{ {
struct nicvf *nic = netdev_priv(dev); struct nicvf *nic = netdev_priv(dev);
int err = 0; int err = 0;
bool if_up = netif_running(dev);
if (!channel->rx_count || !channel->tx_count) if (!channel->rx_count || !channel->tx_count)
return -EINVAL; return -EINVAL;
...@@ -551,6 +555,9 @@ static int nicvf_set_channels(struct net_device *dev, ...@@ -551,6 +555,9 @@ static int nicvf_set_channels(struct net_device *dev,
if (channel->tx_count > MAX_SND_QUEUES_PER_QS) if (channel->tx_count > MAX_SND_QUEUES_PER_QS)
return -EINVAL; return -EINVAL;
if (if_up)
nicvf_stop(dev);
nic->qs->rq_cnt = channel->rx_count; nic->qs->rq_cnt = channel->rx_count;
nic->qs->sq_cnt = channel->tx_count; nic->qs->sq_cnt = channel->tx_count;
nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt); nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt);
...@@ -559,11 +566,9 @@ static int nicvf_set_channels(struct net_device *dev, ...@@ -559,11 +566,9 @@ static int nicvf_set_channels(struct net_device *dev,
if (err) if (err)
return err; return err;
if (!netif_running(dev)) if (if_up)
return err; nicvf_open(dev);
nicvf_stop(dev);
nicvf_open(dev);
netdev_info(dev, "Setting num Tx rings to %d, Rx rings to %d success\n", netdev_info(dev, "Setting num Tx rings to %d, Rx rings to %d success\n",
nic->qs->sq_cnt, nic->qs->rq_cnt); nic->qs->sq_cnt, nic->qs->rq_cnt);
......
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