diff options
author | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | 2017-06-28 15:13:53 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2017-06-28 15:13:53 -0500 |
commit | 5c3f18cce08364ef68163228c0b42725d64cd353 (patch) | |
tree | 429a2f0838841c1bbaac4f7d028505d7a2428000 | |
parent | dff79b91b8f3279cbe60727368adff1f3a5ab16e (diff) | |
download | lwn-5c3f18cce08364ef68163228c0b42725d64cd353.tar.gz lwn-5c3f18cce08364ef68163228c0b42725d64cd353.zip |
PCI: Add devm_pci_alloc_host_bridge() interface
Struct pci_host_bridge can be allocated by PCI host bridge drivers which
usually allocate and map memory through devm managed interfaces.
Add a devm version for the pci_alloc_host_bridge() interface to simplify
PCI host controller driver porting and simplify the driver failure paths.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | Documentation/driver-model/devres.txt | 1 | ||||
-rw-r--r-- | drivers/pci/probe.c | 24 | ||||
-rw-r--r-- | include/linux/pci.h | 2 |
3 files changed, 25 insertions, 2 deletions
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index e72587fe477d..ffbc8913cc76 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -342,6 +342,7 @@ PER-CPU MEM devm_free_percpu() PCI + devm_pci_alloc_host_bridge() : managed PCI host bridge allocation devm_pci_remap_cfgspace() : ioremap PCI configuration space devm_pci_remap_cfg_resource() : ioremap PCI configuration space resource pcim_enable_device() : after success, all PCI ops become managed diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index cbf0d0c1b009..e3f69655ca87 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -510,14 +510,18 @@ static struct pci_bus *pci_alloc_bus(struct pci_bus *parent) return b; } -static void pci_release_host_bridge_dev(struct device *dev) +static void devm_pci_release_host_bridge_dev(struct device *dev) { struct pci_host_bridge *bridge = to_pci_host_bridge(dev); if (bridge->release_fn) bridge->release_fn(bridge); +} - pci_free_host_bridge(bridge); +static void pci_release_host_bridge_dev(struct device *dev) +{ + devm_pci_release_host_bridge_dev(dev); + pci_free_host_bridge(to_pci_host_bridge(dev)); } struct pci_host_bridge *pci_alloc_host_bridge(size_t priv) @@ -535,6 +539,22 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv) } EXPORT_SYMBOL(pci_alloc_host_bridge); +struct pci_host_bridge *devm_pci_alloc_host_bridge(struct device *dev, + size_t priv) +{ + struct pci_host_bridge *bridge; + + bridge = devm_kzalloc(dev, sizeof(*bridge) + priv, GFP_KERNEL); + if (!bridge) + return NULL; + + INIT_LIST_HEAD(&bridge->windows); + bridge->dev.release = devm_pci_release_host_bridge_dev; + + return bridge; +} +EXPORT_SYMBOL(devm_pci_alloc_host_bridge); + void pci_free_host_bridge(struct pci_host_bridge *bridge) { pci_free_resource_list(&bridge->windows); diff --git a/include/linux/pci.h b/include/linux/pci.h index 9095b38c2fa3..d39a66dc67aa 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -458,6 +458,8 @@ static inline struct pci_host_bridge *pci_host_bridge_from_priv(void *priv) } struct pci_host_bridge *pci_alloc_host_bridge(size_t priv); +struct pci_host_bridge *devm_pci_alloc_host_bridge(struct device *dev, + size_t priv); void pci_free_host_bridge(struct pci_host_bridge *bridge); int pci_register_host_bridge(struct pci_host_bridge *bridge); struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus); |