]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
PCI/CXL: Hide SBR from reset_methods if masked by CXL
authorVidya Sagar <vidyas@nvidia.com>
Wed, 25 Feb 2026 13:38:01 +0000 (19:08 +0530)
committerBjorn Helgaas <bhelgaas@google.com>
Tue, 17 Mar 2026 19:53:03 +0000 (14:53 -0500)
Per CXL r3.1, sec 8.1.5.2, the Secondary Bus Reset (SBR) bit in the Bridge
Control register of a CXL port has no effect unless the "Unmask SBR" bit in
the Port Control Extensions Register is set.

After b1956e2d0713 ("PCI/CXL: Fail bus reset if upstream CXL Port has SBR
masked"), Linux checks the "Unmask SBR" bit in pci_reset_bus_function().
But when probe==true, it previously returned 0, incorrectly indicating that
SBR is a viable reset method for the device.

As a result, "bus" is listed in the device's "reset_method" attribute even
though the hardware is incapable of performing it. If a user writes "bus"
to "reset_method" or triggers a reset that falls back to SBR, the operation
fails with "write error: Inappropriate ioctl for device".

If the link is operating in CXL mode (pcie_is_cxl()), return -ENOTTY
immediately unless "Unmask SBR" is set, regardless of the probe argument.
This ensures that "bus" is not advertised in "reset_methods" when the
hardware prevents it, improving clarity for users and aligning the sysfs
capability report with actual hardware behavior.

Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
[bhelgaas: commit log, use pcie_is_cxl()]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Link: https://patch.msgid.link/20260225133801.30231-1-vidyas@nvidia.com
drivers/pci/pci.c

index 0090b4034ec6d44d1984e6143feb369cd9166993..3536c5ab811888272c9c0f569c85c246867a5bc4 100644 (file)
@@ -4914,12 +4914,8 @@ static int pci_reset_bus_function(struct pci_dev *dev, bool probe)
         * If "dev" is below a CXL port that has SBR control masked, SBR
         * won't do anything, so return error.
         */
-       if (bridge && cxl_sbr_masked(bridge)) {
-               if (probe)
-                       return 0;
-
+       if (bridge && pcie_is_cxl(bridge) && cxl_sbr_masked(bridge))
                return -ENOTTY;
-       }
 
        rc = pci_dev_reset_iommu_prepare(dev);
        if (rc) {