s390/pci: use mutex not spinlock for zbus list
authorNiklas Schnelle <schnelle@linux.ibm.com>
Fri, 12 Feb 2021 09:16:46 +0000 (10:16 +0100)
committerHeiko Carstens <hca@linux.ibm.com>
Mon, 12 Apr 2021 10:46:42 +0000 (12:46 +0200)
In a later change we will first collect all PCI functions from the CLP
List PCI functions call, then register them to/creating the relevant
zbus. Then only after we've created our virtual bus structure will we
scan all zbusses iterating over the zbus list. Since scanning is
relatively slow a spinlock is a bad fit for protecting the
loop over the devices on the zbus. Furthermore doing the probing on the
bus we need to use pci_lock_rescan_remove() as devices are added to
the PCI subsystem and that is a mutex which can't be locked nested
inside a spinlock section. Note that the contention of this lock should
be very low either way as zbusses are only added/removed concurrently on
hotplug events.

Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
Reviewed-by: Pierre Morel <pmorel@linux.ibm.com>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/pci/pci_bus.c

index d200e75..9bc869a 100644 (file)
@@ -27,7 +27,7 @@
 #include "pci_iov.h"
 
 static LIST_HEAD(zbus_list);
-static DEFINE_SPINLOCK(zbus_list_lock);
+static DEFINE_MUTEX(zbus_list_lock);
 static int zpci_nb_devices;
 
 /* zpci_bus_prepare_device - Prepare a zPCI function for scanning
@@ -214,9 +214,9 @@ static void zpci_bus_release(struct kref *kref)
                pci_unlock_rescan_remove();
        }
 
-       spin_lock(&zbus_list_lock);
+       mutex_lock(&zbus_list_lock);
        list_del(&zbus->bus_next);
-       spin_unlock(&zbus_list_lock);
+       mutex_unlock(&zbus_list_lock);
        kfree(zbus);
 }
 
@@ -229,7 +229,7 @@ static struct zpci_bus *zpci_bus_get(int pchid)
 {
        struct zpci_bus *zbus;
 
-       spin_lock(&zbus_list_lock);
+       mutex_lock(&zbus_list_lock);
        list_for_each_entry(zbus, &zbus_list, bus_next) {
                if (pchid == zbus->pchid) {
                        kref_get(&zbus->kref);
@@ -238,7 +238,7 @@ static struct zpci_bus *zpci_bus_get(int pchid)
        }
        zbus = NULL;
 out_unlock:
-       spin_unlock(&zbus_list_lock);
+       mutex_unlock(&zbus_list_lock);
        return zbus;
 }
 
@@ -252,9 +252,9 @@ static struct zpci_bus *zpci_bus_alloc(int pchid)
 
        zbus->pchid = pchid;
        INIT_LIST_HEAD(&zbus->bus_next);
-       spin_lock(&zbus_list_lock);
+       mutex_lock(&zbus_list_lock);
        list_add_tail(&zbus->bus_next, &zbus_list);
-       spin_unlock(&zbus_list_lock);
+       mutex_unlock(&zbus_list_lock);
 
        kref_init(&zbus->kref);
        INIT_LIST_HEAD(&zbus->resources);