summaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2018-08-15 21:59:01 +0200
committerBjorn Helgaas <bhelgaas@google.com>2018-08-15 21:59:01 +0200
commit5fc054a54476f9e2b3d6cc3eeb1537aa549d0ba3 (patch)
tree6a0592aa4088435230163ada694c68b839674d60 /drivers/pci/pci.c
parentMerge branch 'pci/peer-to-peer' (diff)
parentPCI: Make pci_get_rom_size() static (diff)
downloadlinux-5fc054a54476f9e2b3d6cc3eeb1537aa549d0ba3.tar.xz
linux-5fc054a54476f9e2b3d6cc3eeb1537aa549d0ba3.zip
Merge branch 'pci/resource'
- Clean up devm_of_pci_get_host_bridge_resources() resource allocation (Jan Kiszka) - Fixup resizable BARs after suspend/resume (Christian König) - Make "pci=earlydump" generic (Sinan Kaya) - Fix ROM BAR access routines to stay in bounds and check for signature correctly (Rex Zhu) * pci/resource: PCI: Make pci_get_rom_size() static PCI: Add check code for last image indicator not set PCI: Avoid accessing memory outside the ROM BAR PCI: Make early dump functionality generic PCI: Cleanup PCI_REBAR_CTRL_BAR_SHIFT handling PCI: Restore resized BAR state on resume PCI: Clean up resource allocation in devm_of_pci_get_host_bridge_resources() # Conflicts: # Documentation/admin-guide/kernel-parameters.txt
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index f68217abc1ef..e6f7ba4378ba 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -114,6 +114,9 @@ static bool pcie_ari_disabled;
/* If set, the PCIe ATS capability will not be used. */
static bool pcie_ats_disabled;
+/* If set, the PCI config space of each device is printed during boot. */
+bool pci_early_dump;
+
bool pci_ats_disabled(void)
{
return pcie_ats_disabled;
@@ -1332,6 +1335,33 @@ static void pci_restore_config_space(struct pci_dev *pdev)
}
}
+static void pci_restore_rebar_state(struct pci_dev *pdev)
+{
+ unsigned int pos, nbars, i;
+ u32 ctrl;
+
+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR);
+ if (!pos)
+ return;
+
+ pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl);
+ nbars = (ctrl & PCI_REBAR_CTRL_NBAR_MASK) >>
+ PCI_REBAR_CTRL_NBAR_SHIFT;
+
+ for (i = 0; i < nbars; i++, pos += 8) {
+ struct resource *res;
+ int bar_idx, size;
+
+ pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl);
+ bar_idx = ctrl & PCI_REBAR_CTRL_BAR_IDX;
+ res = pdev->resource + bar_idx;
+ size = order_base_2((resource_size(res) >> 20) | 1) - 1;
+ ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE;
+ ctrl |= size << PCI_REBAR_CTRL_BAR_SHIFT;
+ pci_write_config_dword(pdev, pos + PCI_REBAR_CTRL, ctrl);
+ }
+}
+
/**
* pci_restore_state - Restore the saved state of a PCI device
* @dev: - PCI device that we're dealing with
@@ -1347,6 +1377,7 @@ void pci_restore_state(struct pci_dev *dev)
pci_restore_pri_state(dev);
pci_restore_ats_state(dev);
pci_restore_vc_state(dev);
+ pci_restore_rebar_state(dev);
pci_cleanup_aer_error_status_regs(dev);
@@ -3311,7 +3342,7 @@ int pci_rebar_get_current_size(struct pci_dev *pdev, int bar)
return pos;
pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl);
- return (ctrl & PCI_REBAR_CTRL_BAR_SIZE) >> 8;
+ return (ctrl & PCI_REBAR_CTRL_BAR_SIZE) >> PCI_REBAR_CTRL_BAR_SHIFT;
}
/**
@@ -3334,7 +3365,7 @@ int pci_rebar_set_size(struct pci_dev *pdev, int bar, int size)
pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl);
ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE;
- ctrl |= size << 8;
+ ctrl |= size << PCI_REBAR_CTRL_BAR_SHIFT;
pci_write_config_dword(pdev, pos + PCI_REBAR_CTRL, ctrl);
return 0;
}
@@ -6060,6 +6091,8 @@ static int __init pci_setup(char *str)
pcie_ats_disabled = true;
} else if (!strcmp(str, "noaer")) {
pci_no_aer();
+ } else if (!strcmp(str, "earlydump")) {
+ pci_early_dump = true;
} else if (!strncmp(str, "realloc=", 8)) {
pci_realloc_get_opt(str + 8);
} else if (!strncmp(str, "realloc", 7)) {