mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
PCI: Skip Resizable BAR restore on read error
pci_restore_rebar_state() uses the Resizable BAR Control register to decide
how many BARs to restore (nbars) and which BAR each iteration addresses
(bar_idx).
When a device does not respond, config reads typically return
PCI_ERROR_RESPONSE (~0). Both fields are 3 bits wide, so nbars and bar_idx
both evaluate to 7, past the spec's valid ranges for both fields.
pci_resource_n() then returns an unrelated resource slot, whose size is
used to derive a nonsensical value written back to the Resizable BAR
Control register.
Bail out if any Resizable BAR Control read returns PCI_ERROR_RESPONSE. No
further BARs are touched, which is safe because a config read that returns
PCI_ERROR_RESPONSE indicates the device is unreachable and restoration is
pointless.
Fixes: d3252ace0b ("PCI: Restore resized BAR state on resume")
Signed-off-by: Marco Nenciarini <mnencia@kcore.it>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/666cac19b5daa0ab0e0ab64454e76b4d24465dbd.1776429882.git.mnencia@kcore.it
This commit is contained in:
parent
d462c8e89e
commit
ee7471fe96
|
|
@ -231,6 +231,9 @@ void pci_restore_rebar_state(struct pci_dev *pdev)
|
|||
return;
|
||||
|
||||
pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl);
|
||||
if (PCI_POSSIBLE_ERROR(ctrl))
|
||||
return;
|
||||
|
||||
nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, ctrl);
|
||||
|
||||
for (i = 0; i < nbars; i++, pos += 8) {
|
||||
|
|
@ -238,6 +241,9 @@ void pci_restore_rebar_state(struct pci_dev *pdev)
|
|||
int bar_idx, size;
|
||||
|
||||
pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl);
|
||||
if (PCI_POSSIBLE_ERROR(ctrl))
|
||||
return;
|
||||
|
||||
bar_idx = ctrl & PCI_REBAR_CTRL_BAR_IDX;
|
||||
res = pci_resource_n(pdev, bar_idx);
|
||||
size = pci_rebar_bytes_to_size(resource_size(res));
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user