@@ -127,11 +127,16 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
if (bus->number == busnr)
return bus;
+ /*
+ * vf will find existing bus at most case; if not existing, it should
+ * go through slow path to create new bus with locked to support enable SRIOV
+ * concurrently with different PFs in userspace.
+ */
child = pci_find_bus(pci_domain_nr(bus), busnr);
if (child)
return child;
- child = pci_add_new_bus(bus, NULL, busnr);
+ child = pci_add_new_bus_locked(bus, NULL, busnr);
if (!child)
return NULL;
@@ -25,6 +25,8 @@
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
#define CARDBUS_RESERVE_BUSNR 3
+static DEFINE_MUTEX(add_bus_mutex);
+
static struct resource busn_resource = {
.name = "PCI busn",
.start = 0,
@@ -1170,6 +1172,30 @@ struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
}
EXPORT_SYMBOL(pci_add_new_bus);
+struct pci_bus *pci_add_new_bus_locked(struct pci_bus *parent, struct pci_dev *dev,
+ int busnr)
+{
+ struct pci_bus *child;
+
+ mutex_lock(&add_bus_mutex);
+ child = pci_find_bus(pci_domain_nr(parent), busnr);
+ if (child) {
+ mutex_unlock(&add_bus_mutex);
+ return child;
+ }
+
+ child = pci_alloc_child_bus(parent, dev, busnr);
+ if (child) {
+ down_write(&pci_bus_sem);
+ list_add_tail(&child->node, &parent->children);
+ up_write(&pci_bus_sem);
+ }
+ mutex_unlock(&add_bus_mutex);
+
+ return child;
+}
+EXPORT_SYMBOL(pci_add_new_bus_locked);
+
static void pci_enable_crs(struct pci_dev *pdev)
{
u16 root_cap = 0;
@@ -421,6 +421,7 @@ int pci_proc_attach_device(struct pci_dev *dev)
if (!proc_initialized)
return -EACCES;
+ device_lock(&bus->dev);
if (!bus->procdir) {
if (pci_proc_domain(bus)) {
sprintf(name, "%04x:%02x", pci_domain_nr(bus),
@@ -429,9 +430,12 @@ int pci_proc_attach_device(struct pci_dev *dev)
sprintf(name, "%02x", bus->number);
}
bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
- if (!bus->procdir)
+ if (!bus->procdir) {
+ device_unlock(&bus->dev);
return -ENOMEM;
+ }
}
+ device_unlock(&bus->dev);
sprintf(name, "%02x.%x", PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
e = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR, bus->procdir,
@@ -1112,6 +1112,8 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
int pci_scan_root_bus_bridge(struct pci_host_bridge *bridge);
struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
int busnr);
+struct pci_bus *pci_add_new_bus_locked(struct pci_bus *parent, struct pci_dev *dev,
+ int busnr);
struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
const char *name,
struct hotplug_slot *hotplug);