pci-v7.3-fixes-2

-----BEGIN PGP SIGNATURE-----
 
 iQJIBAABCgAyFiEEgMe7l+5h9hnxdsnuWYigwDrT+vwFAmq38q4UHGJoZWxnYWFz
 QGdvb2dsZS5jb20ACgkQWYigwDrT+vwVFhAAhO4zr6WHzB/Tx87FGSxYnjrwzOmH
 nS/w0MD0FxPkAzhbkPaXkdgAks10dBNF/umQUXvWBwgZYbR9v0CoZBSm8viuq/8C
 tYOdOm4u4whsHVPU1QJPV5nUSGb2Eiq7vza+2kS1Ll0xy/3/24yVn+IU8sy4EcgX
 IUTwApHfBGq6se88LxtdT5ctAUCRSP8XAeFlKXqfPig9yrrQOZ0cJrA5nhbe4jCL
 jJMFjgH12OvR55ZeKyZianz/lCZ8NcyATblM0EUCVKpx1gv4BcPfbprcycgnyLbw
 R+SoPl0wJDWKGqwuCFYkLMaT4XsLYnJv+6C/aQQ8CJjovAVUzaeDXwlJzPP3hH+N
 iIZp3b5tULHK/c/AykjoRQPq/rVy9ywMvlqmafIeR4+BEJBVYlUGLhum14pnjAQo
 B/wLCSmxrP7K7E+71ODunUdpts6HsH+GbKqSjBS46BAY/Vw+icq0v5RxaIaa6WCv
 BEkVEIfcJ/pnlmxMCoQEVu0bjCrIIaTe7EflO4BDhEIrWTxSq19vCVlXB+XgsHUI
 DWPyCFnAWFG5bZi50PKkrwTOhmcRMRgAjc69DOZ400chbuMAj9PxpomYBEeWvnss
 N+DLTLL2Yp4Y8/tMJIxjNB2eAbiSKql2EoGIpyjQruDRmg1Bcug5gBY90RjRr204
 afoNJYCbtPnd0mY=
 =hhCg
 -----END PGP SIGNATURE-----

Merge tag 'pci-v7.3-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci

Pull PCI fixes from Bjorn Helgaas:

 - Make BAR resize work even for devices where no upstream bridge is
   visible to the OS, which fixes an amdgpu regression on SolidRun
   HoneyComb, which doesn't expose Root Ports to the OS (Liz Fong-Jones)

 - Omit bus properties in dynamic OF nodes when a bridge has no
   subordinate bus, which fixes early boot hangs caused by NULL pointer
   dereferences with CONFIG_PCI_DYNAMIC_OF_NODES enabled (Angel J)

 - Disable enhanced atomics on AMD NBIO 7.7 and 7.11 to avoid silent
   data corruption on 64-bit DMAs (Mario Limonciello)

* tag 'pci-v7.3-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci:
  x86/PCI: Disable enhanced atomics on AMD NBIO 7.7 and 7.11
  PCI: of_property: Omit bus properties without a subordinate bus
  PCI: Fix BAR resize for devices on a root bus
This commit is contained in:
Linus Torvalds 2026-09-26 09:59:59 -07:00
commit fddfc3ec31
3 changed files with 125 additions and 8 deletions

View File

@ -886,6 +886,105 @@ static void quirk_clear_strap_no_soft_reset_dev2_f0(struct pci_dev *dev)
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15b8, quirk_clear_strap_no_soft_reset_dev2_f0);
/*
* Enhanced atomic operations can cause corruption with 64-bit DMA
* on these devices.
*/
#define RX_ENH_ATOMIC_EN BIT(8)
static const u32 nbio_7_7_pcie_smn_addrs[] = {
0x111401d0,
0x111411d0,
0x111421d0,
0x111431d0,
0x111441d0,
0x112401d0,
0x112411d0,
0x112421d0,
0x112431d0,
0x112441d0,
0x112451d0,
0x113401d0,
0x114401d0,
};
static const u32 nbio_7_11_pcie_smn_addrs[] = {
0x112401d0,
0x112411d0,
0x112421d0,
0x112431d0,
0x112441d0,
0x112451d0,
0x113401d0,
0x113411d0,
0x113421d0,
0x113431d0,
0x113441d0,
0x113451d0,
};
static void quirk_amd_nbio_enhanced_atomic(struct pci_dev *host_bridge,
const u32 *smn_addrs,
size_t nr_smn_addrs)
{
bool changed = false;
size_t i;
u32 data;
int ret;
for (i = 0; i < nr_smn_addrs; i++) {
ret = amd_smn_read(0, smn_addrs[i], &data);
if (ret)
continue;
if (!(data & RX_ENH_ATOMIC_EN))
continue;
data = data & ~RX_ENH_ATOMIC_EN;
ret = amd_smn_write(0, smn_addrs[i], data);
if (ret)
continue;
if (changed)
continue;
ret = amd_smn_read(0, smn_addrs[i], &data);
if (ret)
continue;
if (data & RX_ENH_ATOMIC_EN)
continue;
changed = true;
}
if (changed)
pci_info(host_bridge, "enhanced atomics disabled\n");
}
static void quirk_amd_nbio_7_7_disable_enhanced_atomic(struct pci_dev *dev)
{
quirk_amd_nbio_enhanced_atomic(dev, nbio_7_7_pcie_smn_addrs,
ARRAY_SIZE(nbio_7_7_pcie_smn_addrs));
}
static void quirk_amd_nbio_7_11_disable_enhanced_atomic(struct pci_dev *dev)
{
quirk_amd_nbio_enhanced_atomic(dev, nbio_7_11_pcie_smn_addrs,
ARRAY_SIZE(nbio_7_11_pcie_smn_addrs));
}
/* Phoenix, Hawk Point (NBIO 7.7) */
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x14E8,
quirk_amd_nbio_7_7_disable_enhanced_atomic);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x14E8,
quirk_amd_nbio_7_7_disable_enhanced_atomic);
/* Strix, Krackan, Strix Halo (NBIO 7.11) */
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x1507,
quirk_amd_nbio_7_11_disable_enhanced_atomic);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x1507,
quirk_amd_nbio_7_11_disable_enhanced_atomic);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x1122,
quirk_amd_nbio_7_11_disable_enhanced_atomic);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x1122,
quirk_amd_nbio_7_11_disable_enhanced_atomic);
#endif
/*

View File

@ -95,9 +95,13 @@ static int of_pci_prop_bus_range(struct pci_dev *pdev,
struct of_changeset *ocs,
struct device_node *np)
{
u32 bus_range[] = { pdev->subordinate->busn_res.start,
pdev->subordinate->busn_res.end };
u32 bus_range[2];
if (!pdev->subordinate)
return 0;
bus_range[0] = pdev->subordinate->busn_res.start;
bus_range[1] = pdev->subordinate->busn_res.end;
return of_changeset_add_prop_u32_array(ocs, np, "bus-range", bus_range,
ARRAY_SIZE(bus_range));
}
@ -220,6 +224,9 @@ static int of_pci_prop_intr_map(struct pci_dev *pdev, struct of_changeset *ocs,
int ret;
u8 pin;
if (!pdev->subordinate)
return 0;
pnode = pci_device_to_OF_node(pdev->bus->self);
if (!pnode)
pnode = pci_bus_to_OF_node(pdev->bus);

View File

@ -2380,6 +2380,7 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size
struct resource *res = pci_resource_n(pdev, resno);
struct pci_dev_resource *dev_res;
struct pci_bus *bus = pdev->bus;
struct pci_dev *bridge = pci_upstream_bridge(pdev);
struct resource *b_win, *r;
LIST_HEAD(saved);
unsigned int i;
@ -2397,6 +2398,8 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size
if (ret)
return ret;
down_read(&pci_bus_sem);
pci_dev_for_each_resource(pdev, r, i) {
if (i >= PCI_BRIDGE_RESOURCES)
break;
@ -2415,13 +2418,21 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size
pci_resize_resource_set_size(pdev, resno, size);
if (!bus->self)
goto out;
if (bridge) {
ret = pbus_reassign_bridge_resources(bus, res, &saved);
if (ret)
goto restore;
} else {
/* No bridge window to adjust; let the core reassign the bus. */
pci_bus_assign_resources(bus);
down_read(&pci_bus_sem);
ret = pbus_reassign_bridge_resources(bus, res, &saved);
if (ret)
goto restore;
list_for_each_entry(dev_res, &saved, list) {
if (!resource_assigned(dev_res->res)) {
ret = -ENOSPC;
goto restore;
}
}
}
out:
up_read(&pci_bus_sem);