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

Merge branch 'hinic-dev_get_stats-fixes'

Qiao Ma says:

====================
net: hinic: fix bugs about dev_get_stats

These patches fixes 2 bugs of hinic driver:
- fix bug that ethtool get wrong stats because of hinic_{txq|rxq}_clean_stats() is called
- avoid kernel hung in hinic_get_stats64()

See every patch for more information.

Changes in v4:
- removed meaningless u64_stats_sync protection in hinic_{txq|rxq}_get_stats
- merged the third patch in v2 into first one

Changes in v3:
- fixes a compile warning reported by kernel test robot <lkp@intel.com>

Changes in v2:
- fixes another 2 bugs. (v1 is a single patch, see: https://lore.kernel.org/all/07736c2b7019b6883076a06129e06e8f7c5f7154.1656487154.git.mqaio@linux.alibaba.com/).
- to fix extra bugs, hinic_dev.tx_stats/rx_stats is removed, so there is no need to use spinlock or semaphore now.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4874fb94 98f9fcde
...@@ -95,9 +95,6 @@ struct hinic_dev { ...@@ -95,9 +95,6 @@ struct hinic_dev {
u16 sq_depth; u16 sq_depth;
u16 rq_depth; u16 rq_depth;
struct hinic_txq_stats tx_stats;
struct hinic_rxq_stats rx_stats;
u8 rss_tmpl_idx; u8 rss_tmpl_idx;
u8 rss_hash_engine; u8 rss_hash_engine;
u16 num_rss; u16 num_rss;
......
...@@ -80,56 +80,44 @@ static int set_features(struct hinic_dev *nic_dev, ...@@ -80,56 +80,44 @@ static int set_features(struct hinic_dev *nic_dev,
netdev_features_t pre_features, netdev_features_t pre_features,
netdev_features_t features, bool force_change); netdev_features_t features, bool force_change);
static void update_rx_stats(struct hinic_dev *nic_dev, struct hinic_rxq *rxq) static void gather_rx_stats(struct hinic_rxq_stats *nic_rx_stats, struct hinic_rxq *rxq)
{ {
struct hinic_rxq_stats *nic_rx_stats = &nic_dev->rx_stats;
struct hinic_rxq_stats rx_stats; struct hinic_rxq_stats rx_stats;
u64_stats_init(&rx_stats.syncp);
hinic_rxq_get_stats(rxq, &rx_stats); hinic_rxq_get_stats(rxq, &rx_stats);
u64_stats_update_begin(&nic_rx_stats->syncp);
nic_rx_stats->bytes += rx_stats.bytes; nic_rx_stats->bytes += rx_stats.bytes;
nic_rx_stats->pkts += rx_stats.pkts; nic_rx_stats->pkts += rx_stats.pkts;
nic_rx_stats->errors += rx_stats.errors; nic_rx_stats->errors += rx_stats.errors;
nic_rx_stats->csum_errors += rx_stats.csum_errors; nic_rx_stats->csum_errors += rx_stats.csum_errors;
nic_rx_stats->other_errors += rx_stats.other_errors; nic_rx_stats->other_errors += rx_stats.other_errors;
u64_stats_update_end(&nic_rx_stats->syncp);
hinic_rxq_clean_stats(rxq);
} }
static void update_tx_stats(struct hinic_dev *nic_dev, struct hinic_txq *txq) static void gather_tx_stats(struct hinic_txq_stats *nic_tx_stats, struct hinic_txq *txq)
{ {
struct hinic_txq_stats *nic_tx_stats = &nic_dev->tx_stats;
struct hinic_txq_stats tx_stats; struct hinic_txq_stats tx_stats;
u64_stats_init(&tx_stats.syncp);
hinic_txq_get_stats(txq, &tx_stats); hinic_txq_get_stats(txq, &tx_stats);
u64_stats_update_begin(&nic_tx_stats->syncp);
nic_tx_stats->bytes += tx_stats.bytes; nic_tx_stats->bytes += tx_stats.bytes;
nic_tx_stats->pkts += tx_stats.pkts; nic_tx_stats->pkts += tx_stats.pkts;
nic_tx_stats->tx_busy += tx_stats.tx_busy; nic_tx_stats->tx_busy += tx_stats.tx_busy;
nic_tx_stats->tx_wake += tx_stats.tx_wake; nic_tx_stats->tx_wake += tx_stats.tx_wake;
nic_tx_stats->tx_dropped += tx_stats.tx_dropped; nic_tx_stats->tx_dropped += tx_stats.tx_dropped;
nic_tx_stats->big_frags_pkts += tx_stats.big_frags_pkts; nic_tx_stats->big_frags_pkts += tx_stats.big_frags_pkts;
u64_stats_update_end(&nic_tx_stats->syncp);
hinic_txq_clean_stats(txq);
} }
static void update_nic_stats(struct hinic_dev *nic_dev) static void gather_nic_stats(struct hinic_dev *nic_dev,
struct hinic_rxq_stats *nic_rx_stats,
struct hinic_txq_stats *nic_tx_stats)
{ {
int i, num_qps = hinic_hwdev_num_qps(nic_dev->hwdev); int i, num_qps = hinic_hwdev_num_qps(nic_dev->hwdev);
for (i = 0; i < num_qps; i++) for (i = 0; i < num_qps; i++)
update_rx_stats(nic_dev, &nic_dev->rxqs[i]); gather_rx_stats(nic_rx_stats, &nic_dev->rxqs[i]);
for (i = 0; i < num_qps; i++) for (i = 0; i < num_qps; i++)
update_tx_stats(nic_dev, &nic_dev->txqs[i]); gather_tx_stats(nic_tx_stats, &nic_dev->txqs[i]);
} }
/** /**
...@@ -558,8 +546,6 @@ int hinic_close(struct net_device *netdev) ...@@ -558,8 +546,6 @@ int hinic_close(struct net_device *netdev)
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_tx_disable(netdev); netif_tx_disable(netdev);
update_nic_stats(nic_dev);
up(&nic_dev->mgmt_lock); up(&nic_dev->mgmt_lock);
if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) if (!HINIC_IS_VF(nic_dev->hwdev->hwif))
...@@ -853,26 +839,19 @@ static void hinic_get_stats64(struct net_device *netdev, ...@@ -853,26 +839,19 @@ static void hinic_get_stats64(struct net_device *netdev,
struct rtnl_link_stats64 *stats) struct rtnl_link_stats64 *stats)
{ {
struct hinic_dev *nic_dev = netdev_priv(netdev); struct hinic_dev *nic_dev = netdev_priv(netdev);
struct hinic_rxq_stats *nic_rx_stats; struct hinic_rxq_stats nic_rx_stats = {};
struct hinic_txq_stats *nic_tx_stats; struct hinic_txq_stats nic_tx_stats = {};
nic_rx_stats = &nic_dev->rx_stats;
nic_tx_stats = &nic_dev->tx_stats;
down(&nic_dev->mgmt_lock);
if (nic_dev->flags & HINIC_INTF_UP) if (nic_dev->flags & HINIC_INTF_UP)
update_nic_stats(nic_dev); gather_nic_stats(nic_dev, &nic_rx_stats, &nic_tx_stats);
up(&nic_dev->mgmt_lock);
stats->rx_bytes = nic_rx_stats->bytes; stats->rx_bytes = nic_rx_stats.bytes;
stats->rx_packets = nic_rx_stats->pkts; stats->rx_packets = nic_rx_stats.pkts;
stats->rx_errors = nic_rx_stats->errors; stats->rx_errors = nic_rx_stats.errors;
stats->tx_bytes = nic_tx_stats->bytes; stats->tx_bytes = nic_tx_stats.bytes;
stats->tx_packets = nic_tx_stats->pkts; stats->tx_packets = nic_tx_stats.pkts;
stats->tx_errors = nic_tx_stats->tx_dropped; stats->tx_errors = nic_tx_stats.tx_dropped;
} }
static int hinic_set_features(struct net_device *netdev, static int hinic_set_features(struct net_device *netdev,
...@@ -1171,8 +1150,6 @@ static void hinic_free_intr_coalesce(struct hinic_dev *nic_dev) ...@@ -1171,8 +1150,6 @@ static void hinic_free_intr_coalesce(struct hinic_dev *nic_dev)
static int nic_dev_init(struct pci_dev *pdev) static int nic_dev_init(struct pci_dev *pdev)
{ {
struct hinic_rx_mode_work *rx_mode_work; struct hinic_rx_mode_work *rx_mode_work;
struct hinic_txq_stats *tx_stats;
struct hinic_rxq_stats *rx_stats;
struct hinic_dev *nic_dev; struct hinic_dev *nic_dev;
struct net_device *netdev; struct net_device *netdev;
struct hinic_hwdev *hwdev; struct hinic_hwdev *hwdev;
...@@ -1234,12 +1211,6 @@ static int nic_dev_init(struct pci_dev *pdev) ...@@ -1234,12 +1211,6 @@ static int nic_dev_init(struct pci_dev *pdev)
sema_init(&nic_dev->mgmt_lock, 1); sema_init(&nic_dev->mgmt_lock, 1);
tx_stats = &nic_dev->tx_stats;
rx_stats = &nic_dev->rx_stats;
u64_stats_init(&tx_stats->syncp);
u64_stats_init(&rx_stats->syncp);
nic_dev->vlan_bitmap = devm_bitmap_zalloc(&pdev->dev, VLAN_N_VID, nic_dev->vlan_bitmap = devm_bitmap_zalloc(&pdev->dev, VLAN_N_VID,
GFP_KERNEL); GFP_KERNEL);
if (!nic_dev->vlan_bitmap) { if (!nic_dev->vlan_bitmap) {
......
...@@ -73,7 +73,6 @@ void hinic_rxq_get_stats(struct hinic_rxq *rxq, struct hinic_rxq_stats *stats) ...@@ -73,7 +73,6 @@ void hinic_rxq_get_stats(struct hinic_rxq *rxq, struct hinic_rxq_stats *stats)
struct hinic_rxq_stats *rxq_stats = &rxq->rxq_stats; struct hinic_rxq_stats *rxq_stats = &rxq->rxq_stats;
unsigned int start; unsigned int start;
u64_stats_update_begin(&stats->syncp);
do { do {
start = u64_stats_fetch_begin(&rxq_stats->syncp); start = u64_stats_fetch_begin(&rxq_stats->syncp);
stats->pkts = rxq_stats->pkts; stats->pkts = rxq_stats->pkts;
...@@ -83,7 +82,6 @@ void hinic_rxq_get_stats(struct hinic_rxq *rxq, struct hinic_rxq_stats *stats) ...@@ -83,7 +82,6 @@ void hinic_rxq_get_stats(struct hinic_rxq *rxq, struct hinic_rxq_stats *stats)
stats->csum_errors = rxq_stats->csum_errors; stats->csum_errors = rxq_stats->csum_errors;
stats->other_errors = rxq_stats->other_errors; stats->other_errors = rxq_stats->other_errors;
} while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); } while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
u64_stats_update_end(&stats->syncp);
} }
/** /**
......
...@@ -98,7 +98,6 @@ void hinic_txq_get_stats(struct hinic_txq *txq, struct hinic_txq_stats *stats) ...@@ -98,7 +98,6 @@ void hinic_txq_get_stats(struct hinic_txq *txq, struct hinic_txq_stats *stats)
struct hinic_txq_stats *txq_stats = &txq->txq_stats; struct hinic_txq_stats *txq_stats = &txq->txq_stats;
unsigned int start; unsigned int start;
u64_stats_update_begin(&stats->syncp);
do { do {
start = u64_stats_fetch_begin(&txq_stats->syncp); start = u64_stats_fetch_begin(&txq_stats->syncp);
stats->pkts = txq_stats->pkts; stats->pkts = txq_stats->pkts;
...@@ -108,7 +107,6 @@ void hinic_txq_get_stats(struct hinic_txq *txq, struct hinic_txq_stats *stats) ...@@ -108,7 +107,6 @@ void hinic_txq_get_stats(struct hinic_txq *txq, struct hinic_txq_stats *stats)
stats->tx_dropped = txq_stats->tx_dropped; stats->tx_dropped = txq_stats->tx_dropped;
stats->big_frags_pkts = txq_stats->big_frags_pkts; stats->big_frags_pkts = txq_stats->big_frags_pkts;
} while (u64_stats_fetch_retry(&txq_stats->syncp, start)); } while (u64_stats_fetch_retry(&txq_stats->syncp, start));
u64_stats_update_end(&stats->syncp);
} }
/** /**
......
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