From: Mohsin Bashir Date: Thu, 10 Apr 2025 07:08:55 +0000 (-0700) Subject: eth: fbnic: add locking support for hw stats X-Git-Tag: v6.16-rc1~132^2~305^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9f61eb2d185b06d49ef8c25af994d6fc571433cc;p=thirdparty%2Fkernel%2Flinux.git eth: fbnic: add locking support for hw stats This patch adds lock protection for the hardware statistics for fbnic. The hardware statistics access via ndo_get_stats64 is not protected by the rtnl_lock(). Since these stats can be accessed from different places in the code such as service task, ethtool, Q-API, and net_device_ops, a lock-less approach can lead to races. Note that this patch is not a fix rather, just a prep for the subsequent changes in this series. Signed-off-by: Jakub Kicinski Signed-off-by: Mohsin Bashir Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250410070859.4160768-2-mohsin.bashr@gmail.com Signed-off-by: Paolo Abeni --- diff --git a/drivers/net/ethernet/meta/fbnic/fbnic.h b/drivers/net/ethernet/meta/fbnic/fbnic.h index 4ca7b99ef1315..80d54edaac557 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic.h @@ -81,6 +81,9 @@ struct fbnic_dev { /* Local copy of hardware statistics */ struct fbnic_hw_stats hw_stats; + + /* Lock protecting access to hw_stats */ + spinlock_t hw_stats_lock; }; /* Reserve entry 0 in the MSI-X "others" array until we have filled all diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.c b/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.c index 89ac6bc8c7fc3..957138cb841ed 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.c @@ -203,18 +203,28 @@ static void fbnic_get_pcie_stats_asic64(struct fbnic_dev *fbd, void fbnic_reset_hw_stats(struct fbnic_dev *fbd) { + spin_lock(&fbd->hw_stats_lock); fbnic_reset_rpc_stats(fbd, &fbd->hw_stats.rpc); fbnic_reset_pcie_stats_asic(fbd, &fbd->hw_stats.pcie); + spin_unlock(&fbd->hw_stats_lock); } -void fbnic_get_hw_stats32(struct fbnic_dev *fbd) +static void __fbnic_get_hw_stats32(struct fbnic_dev *fbd) { fbnic_get_rpc_stats32(fbd, &fbd->hw_stats.rpc); } -void fbnic_get_hw_stats(struct fbnic_dev *fbd) +void fbnic_get_hw_stats32(struct fbnic_dev *fbd) { - fbnic_get_hw_stats32(fbd); + spin_lock(&fbd->hw_stats_lock); + __fbnic_get_hw_stats32(fbd); + spin_unlock(&fbd->hw_stats_lock); +} +void fbnic_get_hw_stats(struct fbnic_dev *fbd) +{ + spin_lock(&fbd->hw_stats_lock); + __fbnic_get_hw_stats32(fbd); fbnic_get_pcie_stats_asic64(fbd, &fbd->hw_stats.pcie); + spin_unlock(&fbd->hw_stats_lock); } diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c index 6cbbc2ee3e1f9..1f76ebdd6ad18 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c @@ -292,6 +292,7 @@ static int fbnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) fbnic_devlink_register(fbd); fbnic_dbg_fbd_init(fbd); + spin_lock_init(&fbd->hw_stats_lock); /* Capture snapshot of hardware stats so netdev can calculate delta */ fbnic_reset_hw_stats(fbd);