From fe830ef62ac6d8814e27b7e2f632848694b0e5c7 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 25 May 2013 21:48:29 +0800 Subject: [PATCH 01/11] PCI: Introduce pci_bus_{get|put}() to manage PCI bus reference count Introduce helper functions pci_bus_{get|put}() to manage PCI bus reference count. Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Gu Zheng Signed-off-by: Bjorn Helgaas --- drivers/pci/bus.c | 15 +++++++++++++++ include/linux/pci.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 32e66a6f12d9..b1ff02ab4f13 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -283,6 +283,21 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), } EXPORT_SYMBOL_GPL(pci_walk_bus); +struct pci_bus *pci_bus_get(struct pci_bus *bus) +{ + if (bus) + get_device(&bus->dev); + return bus; +} +EXPORT_SYMBOL(pci_bus_get); + +void pci_bus_put(struct pci_bus *bus) +{ + if (bus) + put_device(&bus->dev); +} +EXPORT_SYMBOL(pci_bus_put); + EXPORT_SYMBOL(pci_bus_alloc_resource); EXPORT_SYMBOL_GPL(pci_bus_add_device); EXPORT_SYMBOL(pci_bus_add_devices); diff --git a/include/linux/pci.h b/include/linux/pci.h index 3a24e4ff3248..7556c590ddfd 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1018,6 +1018,8 @@ int pci_request_selected_regions_exclusive(struct pci_dev *, int, const char *); void pci_release_selected_regions(struct pci_dev *, int); /* drivers/pci/bus.c */ +struct pci_bus *pci_bus_get(struct pci_bus *bus); +void pci_bus_put(struct pci_bus *bus); void pci_add_resource(struct list_head *resources, struct resource *res); void pci_add_resource_offset(struct list_head *resources, struct resource *res, resource_size_t offset); From 3c6e6ae770f338ef3e54c5823c21063204f53537 Mon Sep 17 00:00:00 2001 From: Gu Zheng Date: Sat, 25 May 2013 21:48:30 +0800 Subject: [PATCH 02/11] PCI: Introduce pci_alloc_dev(struct pci_bus*) to replace alloc_pci_dev() Here we introduce a new interface to replace alloc_pci_dev(): struct pci_dev *pci_alloc_dev(struct pci_bus *bus) It takes a "struct pci_bus *" argument, so we can alloc a PCI device on a target PCI bus, and it acquires a reference on the pci_bus. We use pci_alloc_dev(NULL) to simplify the old alloc_pci_dev(), and keep it for a while but mark it as __deprecated. Holding a reference to the pci_bus ensures that referencing pci_dev->bus is valid as long as the pci_dev is valid. [bhelgaas: keep existing "return error early" structure in pci_alloc_dev()] Signed-off-by: Gu Zheng Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 9 ++++++++- include/linux/pci.h | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 70f10fa3c1b2..d47ce1400c26 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1200,7 +1200,7 @@ static void pci_release_bus_bridge_dev(struct device *dev) kfree(bridge); } -struct pci_dev *alloc_pci_dev(void) +struct pci_dev *pci_alloc_dev(struct pci_bus *bus) { struct pci_dev *dev; @@ -1210,9 +1210,16 @@ struct pci_dev *alloc_pci_dev(void) INIT_LIST_HEAD(&dev->bus_list); dev->dev.type = &pci_dev_type; + dev->bus = pci_bus_get(bus); return dev; } +EXPORT_SYMBOL(pci_alloc_dev); + +struct pci_dev *alloc_pci_dev(void) +{ + return pci_alloc_dev(NULL); +} EXPORT_SYMBOL(alloc_pci_dev); bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l, diff --git a/include/linux/pci.h b/include/linux/pci.h index 7556c590ddfd..b0f4a8264118 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -364,7 +364,8 @@ static inline struct pci_dev *pci_physfn(struct pci_dev *dev) return dev; } -struct pci_dev *alloc_pci_dev(void); +struct pci_dev *pci_alloc_dev(struct pci_bus *bus); +struct pci_dev * __deprecated alloc_pci_dev(void); #define to_pci_dev(n) container_of(n, struct pci_dev, dev) #define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL) From 8b1fce04dc2a2210f050484afa85acc3a81cfbba Mon Sep 17 00:00:00 2001 From: Gu Zheng Date: Sat, 25 May 2013 21:48:31 +0800 Subject: [PATCH 03/11] PCI: Convert alloc_pci_dev(void) to pci_alloc_dev(bus) Use the new pci_alloc_dev(bus) to replace the existing using of alloc_pci_dev(void). [bhelgaas: drop pci_bus ref later in pci_release_dev()] Signed-off-by: Gu Zheng Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: "David S. Miller" Cc: David Airlie Cc: Neela Syam Kolli Cc: "James E.J. Bottomley" Cc: Yinghai Lu Cc: Greg Kroah-Hartman Cc: Andrew Morton --- arch/powerpc/kernel/pci_of_scan.c | 3 +-- arch/sparc/kernel/pci.c | 3 +-- drivers/char/agp/alpha-agp.c | 2 +- drivers/char/agp/parisc-agp.c | 2 +- drivers/pci/iov.c | 8 +++++--- drivers/pci/probe.c | 5 +++-- drivers/scsi/megaraid.c | 2 +- 7 files changed, 13 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index 2a67e9baa59f..24d01c4eac5c 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -128,7 +128,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, const char *type; struct pci_slot *slot; - dev = alloc_pci_dev(); + dev = pci_alloc_dev(bus); if (!dev) return NULL; type = of_get_property(node, "device_type", NULL); @@ -137,7 +137,6 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, pr_debug(" create device, devfn: %x, type: %s\n", devfn, type); - dev->bus = bus; dev->dev.of_node = of_node_get(node); dev->dev.parent = bus->bridge; dev->dev.bus = &pci_bus_type; diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index baf4366e2d6a..e5871fb455b3 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -254,7 +254,7 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, const char *type; u32 class; - dev = alloc_pci_dev(); + dev = pci_alloc_dev(bus); if (!dev) return NULL; @@ -281,7 +281,6 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, printk(" create device, devfn: %x, type: %s\n", devfn, type); - dev->bus = bus; dev->sysdata = node; dev->dev.parent = bus->bridge; dev->dev.bus = &pci_bus_type; diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c index dd84af4d4f7e..199b8e99f7d7 100644 --- a/drivers/char/agp/alpha-agp.c +++ b/drivers/char/agp/alpha-agp.c @@ -174,7 +174,7 @@ alpha_core_agp_setup(void) /* * Build a fake pci_dev struct */ - pdev = alloc_pci_dev(); + pdev = pci_alloc_dev(NULL); if (!pdev) return -ENOMEM; pdev->vendor = 0xffff; diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index 94821ab01c6d..bf5d2477cb77 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c @@ -333,7 +333,7 @@ parisc_agp_setup(void __iomem *ioc_hpa, void __iomem *lba_hpa) struct agp_bridge_data *bridge; int error = 0; - fake_bridge_dev = alloc_pci_dev(); + fake_bridge_dev = pci_alloc_dev(NULL); if (!fake_bridge_dev) { error = -ENOMEM; goto fail; diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index c93071d428f5..2652ca00fae7 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -75,18 +75,20 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset) struct pci_dev *virtfn; struct resource *res; struct pci_sriov *iov = dev->sriov; + struct pci_bus *bus; - virtfn = alloc_pci_dev(); + virtfn = pci_alloc_dev(NULL); if (!virtfn) return -ENOMEM; mutex_lock(&iov->dev->sriov->lock); - virtfn->bus = virtfn_add_bus(dev->bus, virtfn_bus(dev, id)); - if (!virtfn->bus) { + bus = virtfn_add_bus(dev->bus, virtfn_bus(dev, id)); + if (!bus) { kfree(virtfn); mutex_unlock(&iov->dev->sriov->lock); return -ENOMEM; } + virtfn->bus = pci_bus_get(bus); virtfn->devfn = virtfn_devfn(dev, id); virtfn->vendor = dev->vendor; pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_DID, &virtfn->device); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index d47ce1400c26..ed5ce185eed9 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1132,6 +1132,7 @@ static void pci_release_dev(struct device *dev) pci_dev = to_pci_dev(dev); pci_release_capabilities(pci_dev); pci_release_of_node(pci_dev); + pci_bus_put(pci_dev->bus); kfree(pci_dev); } @@ -1270,11 +1271,10 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) if (!pci_bus_read_dev_vendor_id(bus, devfn, &l, 60*1000)) return NULL; - dev = alloc_pci_dev(); + dev = pci_alloc_dev(bus); if (!dev) return NULL; - dev->bus = bus; dev->devfn = devfn; dev->vendor = l & 0xffff; dev->device = (l >> 16) & 0xffff; @@ -1282,6 +1282,7 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) pci_set_of_node(dev); if (pci_setup_device(dev)) { + pci_bus_put(dev->bus); kfree(dev); return NULL; } diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 846f475f62c1..90c95a3385d1 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -2026,7 +2026,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) static inline int make_local_pdev(adapter_t *adapter, struct pci_dev **pdev) { - *pdev = alloc_pci_dev(); + *pdev = pci_alloc_dev(NULL); if( *pdev == NULL ) return -1; From a649dbfea36bdcead7ffddc622c272844b95a13e Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 25 May 2013 21:48:33 +0800 Subject: [PATCH 04/11] ia64/PCI: Clean up pci_scan_root_bus() usage pci_scan_root_bus() already set bus->sysdata, so no need to explicitly set it again in function sn_pci_controller_fixup(). Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Cc: Tony Luck Cc: Fenghua Yu --- arch/ia64/sn/kernel/io_init.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 238e2c511d94..e2c7733e18a7 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -326,16 +326,7 @@ sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, controller, &resources); if (bus == NULL) - goto error_return; /* error, or bus already scanned */ - - bus->sysdata = controller; - - return; - -error_return: - - kfree(controller); - return; + kfree(controller); } /* From 343df771e671d821478dd3ef525a0610b808dbf8 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 7 Jun 2013 01:10:08 +0800 Subject: [PATCH 05/11] PCI: Fix refcount issue in pci_create_root_bus() error recovery path After calling device_register(&bridge->dev), the bridge is reference- counted, and it is illegal to call kfree() on it except in the release function. [bhelgaas: changelog, use put_device() after device_register() failure] Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Cc: stable@vger.kernel.org --- drivers/pci/probe.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ed5ce185eed9..15c39cb09619 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1711,12 +1711,16 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, bridge->dev.release = pci_release_bus_bridge_dev; dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus); error = pcibios_root_bridge_prepare(bridge); - if (error) - goto bridge_dev_reg_err; + if (error) { + kfree(bridge); + goto err_out; + } error = device_register(&bridge->dev); - if (error) - goto bridge_dev_reg_err; + if (error) { + put_device(&bridge->dev); + goto err_out; + } b->bridge = get_device(&bridge->dev); device_enable_async_suspend(b->bridge); pci_set_bus_of_node(b); @@ -1772,8 +1776,6 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, class_dev_reg_err: put_device(&bridge->dev); device_unregister(&bridge->dev); -bridge_dev_reg_err: - kfree(bridge); err_out: kfree(b); return NULL; From 70efde2a2920c12f2b14eb640944ca7e61b2c02d Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 7 Jun 2013 16:16:51 -0600 Subject: [PATCH 06/11] PCI: Rename pci_release_bus_bridge_dev() to pci_release_host_bridge_dev() This renames pci_release_bus_bridge_dev() to pci_release_host_bridge_dev() and moves it next to pci_alloc_host_bridge(). No functional change. [bhelgaas: split rename & move out of create/destroy symmetry patch] Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 15c39cb09619..a723b2b93ab4 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -468,6 +468,18 @@ static struct pci_bus * pci_alloc_bus(void) return b; } +static void 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_resource_list(&bridge->windows); + + kfree(bridge); +} + static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b) { struct pci_host_bridge *bridge; @@ -1189,18 +1201,6 @@ int pci_cfg_space_size(struct pci_dev *dev) return PCI_CFG_SPACE_SIZE; } -static void pci_release_bus_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_resource_list(&bridge->windows); - - kfree(bridge); -} - struct pci_dev *pci_alloc_dev(struct pci_bus *bus) { struct pci_dev *dev; @@ -1708,7 +1708,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, goto err_out; bridge->dev.parent = parent; - bridge->dev.release = pci_release_bus_bridge_dev; + bridge->dev.release = pci_release_host_bridge_dev; dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus); error = pcibios_root_bridge_prepare(bridge); if (error) { From d9e6ba5fed08b64f8dcabcc82d9706fd8ec1f121 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 25 May 2013 21:48:35 +0800 Subject: [PATCH 07/11] m68k/PCI: Remove redundant call of pci_bus_add_devices() pci_scan_bus() has called pci_bus_add_devices() already, so remove the redundant call of pci_bus_add_devices(). subsys_init() callbacks will be invoked before device_init() callbacks, so it should be safe to remove the redundant calls. [bhelgaas: split unicore32 into a separate patch] Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Acked-by: Greg Ungerer --- arch/m68k/platform/coldfire/pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/m68k/platform/coldfire/pci.c b/arch/m68k/platform/coldfire/pci.c index 8572246db84d..b33f97a13e6d 100644 --- a/arch/m68k/platform/coldfire/pci.c +++ b/arch/m68k/platform/coldfire/pci.c @@ -320,7 +320,6 @@ static int __init mcf_pci_init(void) pci_bus_size_bridges(rootbus); pci_bus_assign_resources(rootbus); pci_enable_bridges(rootbus); - pci_bus_add_devices(rootbus); return 0; } From c13e396ebfed48948f3204db0e7def95080cd660 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 27 May 2013 16:42:26 -0600 Subject: [PATCH 08/11] unicore32/PCI: Remove redundant call of pci_bus_add_devices() pci_scan_bus() has called pci_bus_add_devices() already, so remove the redundant call of pci_bus_add_devices(). subsys_init() callbacks will be invoked before device_init() callbacks, so it should be safe to remove the redundant calls. Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- arch/unicore32/kernel/pci.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c index ef69c0c82825..374a055a8e6b 100644 --- a/arch/unicore32/kernel/pci.c +++ b/arch/unicore32/kernel/pci.c @@ -277,11 +277,6 @@ static int __init pci_common_init(void) pci_bus_assign_resources(puv3_bus); } - /* - * Tell drivers about devices found. - */ - pci_bus_add_devices(puv3_bus); - return 0; } subsys_initcall(pci_common_init); From d35329d9f17f05277f2718eb54402dea3e833d19 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 25 May 2013 21:48:36 +0800 Subject: [PATCH 09/11] PCI: Drop redundant setting of bus->is_added in virtfn_add_bus() The flag pci_bus->is_added is used to guard invocation of pcibios_fixup_bus(pci_bus). When virtfn_add_bus() is called, the pci_bus->is_added flag has already been set, so remove the redundant bus->is_added = 1; Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Cc: Donald Dutile Cc: Yinghai Lu Cc: Ram Pai --- drivers/pci/iov.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 2652ca00fae7..8f1e1174b71f 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -47,7 +47,6 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) return NULL; pci_bus_insert_busn_res(child, busnr, busnr); - bus->is_added = 1; return child; } From dc087f2f6a2925e81831f3016b9cbb6e470e7423 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 25 May 2013 21:48:37 +0800 Subject: [PATCH 10/11] PCI: Simplify IOV implementation and fix reference count races Trivial changes to IOV: 1) use new PCI interfaces to simplify IOV implementation 2) fix some reference count related race windows [bhelgaas: fix virtfn_add() add bus/alloc dev error paths] Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Cc: Donald Dutile Cc: Yinghai Lu Cc: Ram Pai --- drivers/pci/iov.c | 59 +++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 8f1e1174b71f..5fffca995a91 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -51,24 +51,16 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) return child; } -static void virtfn_remove_bus(struct pci_bus *bus, int busnr) +static void virtfn_remove_bus(struct pci_bus *physbus, struct pci_bus *virtbus) { - struct pci_bus *child; - - if (bus->number == busnr) - return; - - child = pci_find_bus(pci_domain_nr(bus), busnr); - BUG_ON(!child); - - if (list_empty(&child->devices)) - pci_remove_bus(child); + if (physbus != virtbus && list_empty(&virtbus->devices)) + pci_remove_bus(virtbus); } static int virtfn_add(struct pci_dev *dev, int id, int reset) { int i; - int rc; + int rc = -ENOMEM; u64 size; char buf[VIRTFN_ID_LEN]; struct pci_dev *virtfn; @@ -76,18 +68,15 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset) struct pci_sriov *iov = dev->sriov; struct pci_bus *bus; - virtfn = pci_alloc_dev(NULL); - if (!virtfn) - return -ENOMEM; - mutex_lock(&iov->dev->sriov->lock); bus = virtfn_add_bus(dev->bus, virtfn_bus(dev, id)); - if (!bus) { - kfree(virtfn); - mutex_unlock(&iov->dev->sriov->lock); - return -ENOMEM; - } - virtfn->bus = pci_bus_get(bus); + if (!bus) + goto failed; + + virtfn = pci_alloc_dev(bus); + if (!virtfn) + goto failed0; + virtfn->devfn = virtfn_devfn(dev, id); virtfn->vendor = dev->vendor; pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_DID, &virtfn->device); @@ -136,7 +125,9 @@ failed1: pci_dev_put(dev); mutex_lock(&iov->dev->sriov->lock); pci_stop_and_remove_bus_device(virtfn); - virtfn_remove_bus(dev->bus, virtfn_bus(dev, id)); +failed0: + virtfn_remove_bus(dev->bus, bus); +failed: mutex_unlock(&iov->dev->sriov->lock); return rc; @@ -145,20 +136,15 @@ failed1: static void virtfn_remove(struct pci_dev *dev, int id, int reset) { char buf[VIRTFN_ID_LEN]; - struct pci_bus *bus; struct pci_dev *virtfn; struct pci_sriov *iov = dev->sriov; - bus = pci_find_bus(pci_domain_nr(dev->bus), virtfn_bus(dev, id)); - if (!bus) - return; - - virtfn = pci_get_slot(bus, virtfn_devfn(dev, id)); + virtfn = pci_get_domain_bus_and_slot(pci_domain_nr(dev->bus), + virtfn_bus(dev, id), + virtfn_devfn(dev, id)); if (!virtfn) return; - pci_dev_put(virtfn); - if (reset) { device_release_driver(&virtfn->dev); __pci_reset_function(virtfn); @@ -176,9 +162,11 @@ static void virtfn_remove(struct pci_dev *dev, int id, int reset) mutex_lock(&iov->dev->sriov->lock); pci_stop_and_remove_bus_device(virtfn); - virtfn_remove_bus(dev->bus, virtfn_bus(dev, id)); + virtfn_remove_bus(dev->bus, virtfn->bus); mutex_unlock(&iov->dev->sriov->lock); + /* balance pci_get_domain_bus_and_slot() */ + pci_dev_put(virtfn); pci_dev_put(dev); } @@ -335,13 +323,14 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) if (!pdev) return -ENODEV; - pci_dev_put(pdev); - - if (!pdev->is_physfn) + if (!pdev->is_physfn) { + pci_dev_put(pdev); return -ENODEV; + } rc = sysfs_create_link(&dev->dev.kobj, &pdev->dev.kobj, "dep_link"); + pci_dev_put(pdev); if (rc) return rc; } From 050134864c1c76f49eb86c134a0e02fb3c196382 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 5 Jun 2013 14:22:11 -0600 Subject: [PATCH 11/11] PCI: Return early on allocation failures to unindent mainline code On allocation failure, return early so the main body of the function doesn't have to be indented as the body of an "if" statement. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index a723b2b93ab4..14af6ef4959c 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -451,20 +451,21 @@ void pci_read_bridge_bases(struct pci_bus *child) } } -static struct pci_bus * pci_alloc_bus(void) +static struct pci_bus *pci_alloc_bus(void) { struct pci_bus *b; b = kzalloc(sizeof(*b), GFP_KERNEL); - if (b) { - INIT_LIST_HEAD(&b->node); - INIT_LIST_HEAD(&b->children); - INIT_LIST_HEAD(&b->devices); - INIT_LIST_HEAD(&b->slots); - INIT_LIST_HEAD(&b->resources); - b->max_bus_speed = PCI_SPEED_UNKNOWN; - b->cur_bus_speed = PCI_SPEED_UNKNOWN; - } + if (!b) + return NULL; + + INIT_LIST_HEAD(&b->node); + INIT_LIST_HEAD(&b->children); + INIT_LIST_HEAD(&b->devices); + INIT_LIST_HEAD(&b->slots); + INIT_LIST_HEAD(&b->resources); + b->max_bus_speed = PCI_SPEED_UNKNOWN; + b->cur_bus_speed = PCI_SPEED_UNKNOWN; return b; } @@ -485,11 +486,11 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b) struct pci_host_bridge *bridge; bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); - if (bridge) { - INIT_LIST_HEAD(&bridge->windows); - bridge->bus = b; - } + if (!bridge) + return NULL; + INIT_LIST_HEAD(&bridge->windows); + bridge->bus = b; return bridge; }