Skip to content

Commit 98ff668

Browse files
committed
Merge: qed/qede: Fix scheduling while atomic
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/4930 JIRA: https://issues.redhat.com/browse/RHEL-9751 Statistics read through bond interface via sysfs causes below bug and traces as it triggers the bonding module to collect the slave device statistics while holding the spinlock, beneath that qede->qed driver statistics flow gets scheduled out due to usleep_range() used in PTT acquire logic Fix this by collecting the statistics asynchronously from a periodic delayed work scheduled at default stats coalescing interval and return the recent copy of statisitcs from .ndo_get_stats64(), also add ability to configure/retrieve stats coalescing interval using below commands - ethtool -C ethx stats-block-usecs <val> ethtool -c ethx Signed-off-by: John Meneghini <jmeneghi@redhat.com> Approved-by: Ewan D. Milne <emilne@redhat.com> Approved-by: Maurizio Lombardi <mlombard@redhat.com> Approved-by: Michal Schmidt <mschmidt@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Lucas Zampieri <lzampier@redhat.com>
2 parents 3078152 + 119a7dc commit 98ff668

File tree

4 files changed

+60
-4
lines changed

4 files changed

+60
-4
lines changed

drivers/net/ethernet/qlogic/qed/qed_l2.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1903,7 +1903,7 @@ void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats)
19031903
{
19041904
u32 i;
19051905

1906-
if (!cdev) {
1906+
if (!cdev || cdev->recov_in_prog) {
19071907
memset(stats, 0, sizeof(*stats));
19081908
return;
19091909
}

drivers/net/ethernet/qlogic/qede/qede.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ struct qede_dev {
271271
#define QEDE_ERR_WARN 3
272272

273273
struct qede_dump_info dump_info;
274+
struct delayed_work periodic_task;
275+
unsigned long stats_coal_ticks;
276+
u32 stats_coal_usecs;
277+
spinlock_t stats_lock; /* lock for vport stats access */
274278
};
275279

276280
enum QEDE_STATE {

drivers/net/ethernet/qlogic/qede/qede_ethtool.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,8 @@ static void qede_get_ethtool_stats(struct net_device *dev,
430430
}
431431
}
432432

433+
spin_lock(&edev->stats_lock);
434+
433435
for (i = 0; i < QEDE_NUM_STATS; i++) {
434436
if (qede_is_irrelevant_stat(edev, i))
435437
continue;
@@ -439,6 +441,8 @@ static void qede_get_ethtool_stats(struct net_device *dev,
439441
buf++;
440442
}
441443

444+
spin_unlock(&edev->stats_lock);
445+
442446
__qede_unlock(edev);
443447
}
444448

@@ -830,6 +834,7 @@ static int qede_get_coalesce(struct net_device *dev,
830834

831835
coal->rx_coalesce_usecs = rx_coal;
832836
coal->tx_coalesce_usecs = tx_coal;
837+
coal->stats_block_coalesce_usecs = edev->stats_coal_usecs;
833838

834839
return rc;
835840
}
@@ -843,6 +848,19 @@ int qede_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal,
843848
int i, rc = 0;
844849
u16 rxc, txc;
845850

851+
if (edev->stats_coal_usecs != coal->stats_block_coalesce_usecs) {
852+
edev->stats_coal_usecs = coal->stats_block_coalesce_usecs;
853+
if (edev->stats_coal_usecs) {
854+
edev->stats_coal_ticks = usecs_to_jiffies(edev->stats_coal_usecs);
855+
schedule_delayed_work(&edev->periodic_task, 0);
856+
857+
DP_INFO(edev, "Configured stats coal ticks=%lu jiffies\n",
858+
edev->stats_coal_ticks);
859+
} else {
860+
cancel_delayed_work_sync(&edev->periodic_task);
861+
}
862+
}
863+
846864
if (!netif_running(dev)) {
847865
DP_INFO(edev, "Interface is down\n");
848866
return -EINVAL;
@@ -2255,7 +2273,8 @@ static int qede_get_per_coalesce(struct net_device *dev,
22552273
}
22562274

22572275
static const struct ethtool_ops qede_ethtool_ops = {
2258-
.supported_coalesce_params = ETHTOOL_COALESCE_USECS,
2276+
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
2277+
ETHTOOL_COALESCE_STATS_BLOCK_USECS,
22592278
.get_link_ksettings = qede_get_link_ksettings,
22602279
.set_link_ksettings = qede_set_link_ksettings,
22612280
.get_drvinfo = qede_get_drvinfo,
@@ -2306,7 +2325,8 @@ static const struct ethtool_ops qede_ethtool_ops = {
23062325
};
23072326

23082327
static const struct ethtool_ops qede_vf_ethtool_ops = {
2309-
.supported_coalesce_params = ETHTOOL_COALESCE_USECS,
2328+
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
2329+
ETHTOOL_COALESCE_STATS_BLOCK_USECS,
23102330
.get_link_ksettings = qede_get_link_ksettings,
23112331
.get_drvinfo = qede_get_drvinfo,
23122332
.get_msglevel = qede_get_msglevel,

drivers/net/ethernet/qlogic/qede/qede_main.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ void qede_fill_by_demand_stats(struct qede_dev *edev)
317317

318318
edev->ops->get_vport_stats(edev->cdev, &stats);
319319

320+
spin_lock(&edev->stats_lock);
321+
320322
p_common->no_buff_discards = stats.common.no_buff_discards;
321323
p_common->packet_too_big_discard = stats.common.packet_too_big_discard;
322324
p_common->ttl0_discard = stats.common.ttl0_discard;
@@ -414,6 +416,8 @@ void qede_fill_by_demand_stats(struct qede_dev *edev)
414416
p_ah->tx_1519_to_max_byte_packets =
415417
stats.ah.tx_1519_to_max_byte_packets;
416418
}
419+
420+
spin_unlock(&edev->stats_lock);
417421
}
418422

419423
static void qede_get_stats64(struct net_device *dev,
@@ -422,9 +426,10 @@ static void qede_get_stats64(struct net_device *dev,
422426
struct qede_dev *edev = netdev_priv(dev);
423427
struct qede_stats_common *p_common;
424428

425-
qede_fill_by_demand_stats(edev);
426429
p_common = &edev->stats.common;
427430

431+
spin_lock(&edev->stats_lock);
432+
428433
stats->rx_packets = p_common->rx_ucast_pkts + p_common->rx_mcast_pkts +
429434
p_common->rx_bcast_pkts;
430435
stats->tx_packets = p_common->tx_ucast_pkts + p_common->tx_mcast_pkts +
@@ -444,6 +449,8 @@ static void qede_get_stats64(struct net_device *dev,
444449
stats->collisions = edev->stats.bb.tx_total_collisions;
445450
stats->rx_crc_errors = p_common->rx_crc_errors;
446451
stats->rx_frame_errors = p_common->rx_align_errors;
452+
453+
spin_unlock(&edev->stats_lock);
447454
}
448455

449456
#ifdef CONFIG_QED_SRIOV
@@ -1073,6 +1080,23 @@ static void qede_unlock(struct qede_dev *edev)
10731080
rtnl_unlock();
10741081
}
10751082

1083+
static void qede_periodic_task(struct work_struct *work)
1084+
{
1085+
struct qede_dev *edev = container_of(work, struct qede_dev,
1086+
periodic_task.work);
1087+
1088+
qede_fill_by_demand_stats(edev);
1089+
schedule_delayed_work(&edev->periodic_task, edev->stats_coal_ticks);
1090+
}
1091+
1092+
static void qede_init_periodic_task(struct qede_dev *edev)
1093+
{
1094+
INIT_DELAYED_WORK(&edev->periodic_task, qede_periodic_task);
1095+
spin_lock_init(&edev->stats_lock);
1096+
edev->stats_coal_usecs = USEC_PER_SEC;
1097+
edev->stats_coal_ticks = usecs_to_jiffies(USEC_PER_SEC);
1098+
}
1099+
10761100
static void qede_sp_task(struct work_struct *work)
10771101
{
10781102
struct qede_dev *edev = container_of(work, struct qede_dev,
@@ -1092,6 +1116,7 @@ static void qede_sp_task(struct work_struct *work)
10921116
*/
10931117

10941118
if (test_and_clear_bit(QEDE_SP_RECOVERY, &edev->sp_flags)) {
1119+
cancel_delayed_work_sync(&edev->periodic_task);
10951120
#ifdef CONFIG_QED_SRIOV
10961121
/* SRIOV must be disabled outside the lock to avoid a deadlock.
10971122
* The recovery of the active VFs is currently not supported.
@@ -1282,6 +1307,7 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
12821307
*/
12831308
INIT_DELAYED_WORK(&edev->sp_task, qede_sp_task);
12841309
mutex_init(&edev->qede_lock);
1310+
qede_init_periodic_task(edev);
12851311

12861312
rc = register_netdev(edev->ndev);
12871313
if (rc) {
@@ -1306,6 +1332,11 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
13061332
edev->rx_copybreak = QEDE_RX_HDR_SIZE;
13071333

13081334
qede_log_probe(edev);
1335+
1336+
/* retain user config (for example - after recovery) */
1337+
if (edev->stats_coal_usecs)
1338+
schedule_delayed_work(&edev->periodic_task, 0);
1339+
13091340
return 0;
13101341

13111342
err4:
@@ -1374,6 +1405,7 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode)
13741405
unregister_netdev(ndev);
13751406

13761407
cancel_delayed_work_sync(&edev->sp_task);
1408+
cancel_delayed_work_sync(&edev->periodic_task);
13771409

13781410
edev->ops->common->set_power_state(cdev, PCI_D0);
13791411

0 commit comments

Comments
 (0)