PCI: Pass domain number to pci_bus_release_domain_nr() explicitly
BugLink: https://bugs.launchpad.net/bugs/2102118 commit 0cca961a026177af69044f10d6ae76d8ce043764 upstream. 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: 0328947c5032 ("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.org Reported-by: Dan Carpenter <dan.carpenter@linaro.org> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit a61c55fa3a8af128448a3c09574369d203b6a809 linux-6.11.y) [koichiroden: follow-up fix for a backport for LP#2097301, which acts as a prerequisite here] Signed-off-by: Koichiro Den <koichiro.den@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
This commit is contained in:
committed by
Stefan Bader
parent
58215454fd
commit
aa23eae5b0
@@ -795,7 +795,7 @@ void pci_epc_destroy(struct pci_epc *epc)
|
||||
device_unregister(&epc->dev);
|
||||
|
||||
#ifdef CONFIG_PCI_DOMAINS_GENERIC
|
||||
pci_bus_release_domain_nr(NULL, &epc->dev);
|
||||
pci_bus_release_domain_nr(&epc->dev, epc->domain_nr);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_epc_destroy);
|
||||
|
||||
+7
-7
@@ -7042,16 +7042,16 @@ static int of_pci_bus_find_domain_nr(struct device *parent)
|
||||
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;
|
||||
|
||||
/* Release domain from IDA where it was allocated. */
|
||||
if (of_get_pci_domain_nr(parent->of_node) == bus->domain_nr)
|
||||
ida_free(&pci_domain_nr_static_ida, bus->domain_nr);
|
||||
if (of_get_pci_domain_nr(parent->of_node) == domain_nr)
|
||||
ida_free(&pci_domain_nr_static_ida, domain_nr);
|
||||
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)
|
||||
@@ -7060,11 +7060,11 @@ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
|
||||
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)
|
||||
return;
|
||||
of_pci_bus_release_domain_nr(bus, parent);
|
||||
of_pci_bus_release_domain_nr(parent, domain_nr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+1
-1
@@ -1090,7 +1090,7 @@ unregister:
|
||||
|
||||
free:
|
||||
#ifdef CONFIG_PCI_DOMAINS_GENERIC
|
||||
pci_bus_release_domain_nr(bus, parent);
|
||||
pci_bus_release_domain_nr(parent, bus->domain_nr);
|
||||
#endif
|
||||
kfree(bus);
|
||||
return err;
|
||||
|
||||
@@ -162,7 +162,7 @@ void pci_remove_root_bus(struct pci_bus *bus)
|
||||
#ifdef CONFIG_PCI_DOMAINS_GENERIC
|
||||
/* Release domain_nr if it was dynamically allocated */
|
||||
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
|
||||
|
||||
pci_remove_bus(bus);
|
||||
|
||||
+1
-1
@@ -1891,7 +1891,7 @@ static inline int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
|
||||
{ return 0; }
|
||||
#endif
|
||||
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
|
||||
|
||||
/* Some architectures require additional setup to direct VGA traffic */
|
||||
|
||||
Reference in New Issue
Block a user