Merge branch 'pci/jiang-bus-lock-v3' into next

* pci/jiang-bus-lock-v3:
  PCI: Return early on allocation failures to unindent mainline code
  PCI: Simplify IOV implementation and fix reference count races
  PCI: Drop redundant setting of bus->is_added in virtfn_add_bus()
  unicore32/PCI: Remove redundant call of pci_bus_add_devices()
  m68k/PCI: Remove redundant call of pci_bus_add_devices()
  PCI: Rename pci_release_bus_bridge_dev() to pci_release_host_bridge_dev()
  PCI: Fix refcount issue in pci_create_root_bus() error recovery path
  ia64/PCI: Clean up pci_scan_root_bus() usage
  PCI: Convert alloc_pci_dev(void) to pci_alloc_dev(bus)
  PCI: Introduce pci_alloc_dev(struct pci_bus*) to replace alloc_pci_dev()
  PCI: Introduce pci_bus_{get|put}() to manage PCI bus reference count

Conflicts:
	drivers/pci/probe.c
This commit is contained in:
Bjorn Helgaas 2013-06-14 17:47:46 -06:00
commit df58f46c0f
12 changed files with 98 additions and 96 deletions

View File

@ -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);
}
/*

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -47,46 +47,36 @@ 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;
}
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;
struct resource *res;
struct pci_sriov *iov = dev->sriov;
virtfn = alloc_pci_dev();
if (!virtfn)
return -ENOMEM;
struct pci_bus *bus;
mutex_lock(&iov->dev->sriov->lock);
virtfn->bus = virtfn_add_bus(dev->bus, virtfn_bus(dev, id));
if (!virtfn->bus) {
kfree(virtfn);
mutex_unlock(&iov->dev->sriov->lock);
return -ENOMEM;
}
bus = virtfn_add_bus(dev->bus, virtfn_bus(dev, id));
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);
@ -134,7 +124,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;
@ -143,20 +135,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);
@ -174,9 +161,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);
}
@ -333,13 +322,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;
}

View File

@ -470,33 +470,46 @@ 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;
}
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;
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;
}
@ -1152,6 +1165,7 @@ static void pci_release_dev(struct device *dev)
pci_release_capabilities(pci_dev);
pci_release_of_node(pci_dev);
pcibios_release_device(pci_dev);
pci_bus_put(pci_dev->bus);
kfree(pci_dev);
}
@ -1208,19 +1222,7 @@ 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 *alloc_pci_dev(void)
struct pci_dev *pci_alloc_dev(struct pci_bus *bus)
{
struct pci_dev *dev;
@ -1230,9 +1232,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,
@ -1283,11 +1292,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;
@ -1295,6 +1303,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;
}
@ -1720,15 +1729,19 @@ 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)
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);
@ -1784,8 +1797,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;

View File

@ -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;

View File

@ -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)
@ -1018,6 +1019,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);