Commit 0cca961a authored by Manivannan Sadhasivam's avatar Manivannan Sadhasivam Committed by Krzysztof Wilczyński

PCI: Pass domain number to pci_bus_release_domain_nr() explicitly

The pci_bus_release_domain_nr() API is supposed to free the domain
number allocated by pci_bus_find_domain_nr(). Most of the callers of
pci_bus_find_domain_nr(), store the domain number in pci_bus::domain_nr.

As such, the pci_bus_release_domain_nr() implicitly frees the domain
number by dereferencing 'struct pci_bus'. However, one of the callers
of this API, the PCI endpoint subsystem, doesn't have 'struct pci_bus',
so it only passes NULL. Due to this, the API will end up dereferencing
the NULL pointer.

To fix this issue, pass the domain number to this API explicitly. Since
'struct pci_bus' is not used for anything else other than extracting the
domain number, it makes sense to pass the domain number directly.

Fixes: 0328947c ("PCI: endpoint: Assign PCI domain number for endpoint controllers")
Closes: https://lore.kernel.org/linux-pci/c0c40ddb-bf64-4b22-9dd1-8dbb18aa2813@stanley.mountain
Link: https://lore.kernel.org/linux-pci/20240912053025.25314-1-manivannan.sadhasivam@linaro.orgReported-by: default avatarDan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
[kwilczynski: commit log]
Signed-off-by: default avatarKrzysztof Wilczyński <kwilczynski@kernel.org>
parent d14bc28a
...@@ -840,7 +840,7 @@ void pci_epc_destroy(struct pci_epc *epc) ...@@ -840,7 +840,7 @@ void pci_epc_destroy(struct pci_epc *epc)
device_unregister(&epc->dev); device_unregister(&epc->dev);
#ifdef CONFIG_PCI_DOMAINS_GENERIC #ifdef CONFIG_PCI_DOMAINS_GENERIC
pci_bus_release_domain_nr(NULL, &epc->dev); pci_bus_release_domain_nr(&epc->dev, epc->domain_nr);
#endif #endif
} }
EXPORT_SYMBOL_GPL(pci_epc_destroy); EXPORT_SYMBOL_GPL(pci_epc_destroy);
......
...@@ -6801,16 +6801,16 @@ static int of_pci_bus_find_domain_nr(struct device *parent) ...@@ -6801,16 +6801,16 @@ static int of_pci_bus_find_domain_nr(struct device *parent)
return ida_alloc(&pci_domain_nr_dynamic_ida, GFP_KERNEL); return ida_alloc(&pci_domain_nr_dynamic_ida, GFP_KERNEL);
} }
static void of_pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent) static void of_pci_bus_release_domain_nr(struct device *parent, int domain_nr)
{ {
if (bus->domain_nr < 0) if (domain_nr < 0)
return; return;
/* Release domain from IDA where it was allocated. */ /* Release domain from IDA where it was allocated. */
if (of_get_pci_domain_nr(parent->of_node) == bus->domain_nr) if (of_get_pci_domain_nr(parent->of_node) == domain_nr)
ida_free(&pci_domain_nr_static_ida, bus->domain_nr); ida_free(&pci_domain_nr_static_ida, domain_nr);
else else
ida_free(&pci_domain_nr_dynamic_ida, bus->domain_nr); ida_free(&pci_domain_nr_dynamic_ida, domain_nr);
} }
int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent) int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
...@@ -6819,11 +6819,11 @@ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent) ...@@ -6819,11 +6819,11 @@ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
acpi_pci_bus_find_domain_nr(bus); acpi_pci_bus_find_domain_nr(bus);
} }
void pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent) void pci_bus_release_domain_nr(struct device *parent, int domain_nr)
{ {
if (!acpi_disabled) if (!acpi_disabled)
return; return;
of_pci_bus_release_domain_nr(bus, parent); of_pci_bus_release_domain_nr(parent, domain_nr);
} }
#endif #endif
......
...@@ -1061,7 +1061,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) ...@@ -1061,7 +1061,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
free: free:
#ifdef CONFIG_PCI_DOMAINS_GENERIC #ifdef CONFIG_PCI_DOMAINS_GENERIC
pci_bus_release_domain_nr(bus, parent); pci_bus_release_domain_nr(parent, bus->domain_nr);
#endif #endif
kfree(bus); kfree(bus);
return err; return err;
......
...@@ -163,7 +163,7 @@ void pci_remove_root_bus(struct pci_bus *bus) ...@@ -163,7 +163,7 @@ void pci_remove_root_bus(struct pci_bus *bus)
#ifdef CONFIG_PCI_DOMAINS_GENERIC #ifdef CONFIG_PCI_DOMAINS_GENERIC
/* Release domain_nr if it was dynamically allocated */ /* Release domain_nr if it was dynamically allocated */
if (host_bridge->domain_nr == PCI_DOMAIN_NR_NOT_SET) if (host_bridge->domain_nr == PCI_DOMAIN_NR_NOT_SET)
pci_bus_release_domain_nr(bus, host_bridge->dev.parent); pci_bus_release_domain_nr(host_bridge->dev.parent, bus->domain_nr);
#endif #endif
pci_remove_bus(bus); pci_remove_bus(bus);
......
...@@ -1884,7 +1884,7 @@ static inline int acpi_pci_bus_find_domain_nr(struct pci_bus *bus) ...@@ -1884,7 +1884,7 @@ static inline int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
{ return 0; } { return 0; }
#endif #endif
int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent); int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent);
void pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent); void pci_bus_release_domain_nr(struct device *parent, int domain_nr);
#endif #endif
/* Some architectures require additional setup to direct VGA traffic */ /* Some architectures require additional setup to direct VGA traffic */
......
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