octeon_pci_flr() calls __pci_reset_function_locked() from probe-failure and remove paths that already hold the endpoint device lock. Its explicit config-space lock covers only the endpoint. If the reset uses the bus-reset method, the PCI core writes the upstream bridge's Bridge Control register. Without the bridge lock, that access can race with other configuration access and emit the "unlocked secondary bus reset" warning. Take the upstream bridge configuration access lock before the endpoint lock, and hold both locks through pci_restore_state(). This serializes the complete reset and state-restore sequence with PCI configuration access. The PatchProof static-analysis tool identified this issue; manual source inspection confirmed it in v7.1.5 and current mainline. A source-level check found that the original reset path takes the endpoint configuration lock without first taking the upstream bridge lock. The patched source was checked for bridge-first acquisition, restoration while both locks are held, and reverse-order release. A user-space POSIX-thread model held the bridge lock in a concurrent configuration accessor. The original reset proceeded anyway; the fixed reset waited until the accessor released it. No live Liquidio hardware or PCI lockdep test was run. Fixes: 70535350e26f ("liquidio: with embedded f/w, don't reload f/w, issue pf flr at exit") Cc: stable@vger.kernel.org Signed-off-by: Runyu Xiao --- drivers/net/ethernet/cavium/liquidio/lio_main.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index 32dd9b25760e..1d566aec2d75 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -914,12 +914,15 @@ static bool fw_type_is_auto(void) */ static void octeon_pci_flr(struct octeon_device *oct) { + struct pci_dev *bridge = pci_upstream_bridge(oct->pci_dev); int rc; - pci_save_state(oct->pci_dev); - + if (bridge) + pci_cfg_access_lock(bridge); pci_cfg_access_lock(oct->pci_dev); + pci_save_state(oct->pci_dev); + /* Quiesce the device completely */ pci_write_config_word(oct->pci_dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE); @@ -931,6 +934,7 @@ static void octeon_pci_flr(struct octeon_device *oct) rc, oct->pf_num); + pci_restore_state(oct->pci_dev); pci_cfg_access_unlock(oct->pci_dev); + if (bridge) + pci_cfg_access_unlock(bridge); - - pci_restore_state(oct->pci_dev); } -- 2.34.1