Commit 093d24a2 authored by Tomasz Nowicki's avatar Tomasz Nowicki Committed by Bjorn Helgaas

arm64: PCI: Manage controller-specific data on per-controller basis

Currently we use one shared global acpi_pci_root_ops structure to keep
controller-specific ops. We pass its pointer to acpi_pci_root_create() and
associate it with a host bridge instance for good.  Such a design implies
serious drawback. Any potential manipulation on the single system-wide
acpi_pci_root_ops leads to kernel crash. The structure content is not
really changing even across multiple host bridges creation; thus it was not
an issue so far.

In preparation for adding ECAM quirks mechanism (where controller-specific
PCI ops may be different for each host bridge) allocate new
acpi_pci_root_ops and fill in with data for each bridge. Now it is safe to
have different controller-specific info. As a consequence free
acpi_pci_root_ops when host bridge is released.

No functional changes in this patch.
Signed-off-by: default avatarTomasz Nowicki <tn@semihalf.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Acked-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
parent 08b1c196
...@@ -168,33 +168,36 @@ static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci) ...@@ -168,33 +168,36 @@ static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci)
ri = container_of(ci, struct acpi_pci_generic_root_info, common); ri = container_of(ci, struct acpi_pci_generic_root_info, common);
pci_ecam_free(ri->cfg); pci_ecam_free(ri->cfg);
kfree(ci->ops);
kfree(ri); kfree(ri);
} }
static struct acpi_pci_root_ops acpi_pci_root_ops = {
.release_info = pci_acpi_generic_release_info,
};
/* Interface called from ACPI code to setup PCI host controller */ /* Interface called from ACPI code to setup PCI host controller */
struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
{ {
int node = acpi_get_node(root->device->handle); int node = acpi_get_node(root->device->handle);
struct acpi_pci_generic_root_info *ri; struct acpi_pci_generic_root_info *ri;
struct pci_bus *bus, *child; struct pci_bus *bus, *child;
struct acpi_pci_root_ops *root_ops;
ri = kzalloc_node(sizeof(*ri), GFP_KERNEL, node); ri = kzalloc_node(sizeof(*ri), GFP_KERNEL, node);
if (!ri) if (!ri)
return NULL; return NULL;
root_ops = kzalloc_node(sizeof(*root_ops), GFP_KERNEL, node);
if (!root_ops)
return NULL;
ri->cfg = pci_acpi_setup_ecam_mapping(root); ri->cfg = pci_acpi_setup_ecam_mapping(root);
if (!ri->cfg) { if (!ri->cfg) {
kfree(ri); kfree(ri);
kfree(root_ops);
return NULL; return NULL;
} }
acpi_pci_root_ops.pci_ops = &ri->cfg->ops->pci_ops; root_ops->release_info = pci_acpi_generic_release_info;
bus = acpi_pci_root_create(root, &acpi_pci_root_ops, &ri->common, root_ops->pci_ops = &ri->cfg->ops->pci_ops;
ri->cfg); bus = acpi_pci_root_create(root, root_ops, &ri->common, ri->cfg);
if (!bus) if (!bus)
return NULL; return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment