Commit 03502761 authored by Niklas Schnelle's avatar Niklas Schnelle Committed by Heiko Carstens

s390/pci: use mutex not spinlock for zbus list

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: default avatarMatthew Rosato <mjrosato@linux.ibm.com>
Reviewed-by: default avatarPierre Morel <pmorel@linux.ibm.com>
Signed-off-by: default avatarNiklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent a50297cf
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include "pci_iov.h" #include "pci_iov.h"
static LIST_HEAD(zbus_list); static LIST_HEAD(zbus_list);
static DEFINE_SPINLOCK(zbus_list_lock); static DEFINE_MUTEX(zbus_list_lock);
static int zpci_nb_devices; static int zpci_nb_devices;
/* zpci_bus_prepare_device - Prepare a zPCI function for scanning /* zpci_bus_prepare_device - Prepare a zPCI function for scanning
...@@ -214,9 +214,9 @@ static void zpci_bus_release(struct kref *kref) ...@@ -214,9 +214,9 @@ static void zpci_bus_release(struct kref *kref)
pci_unlock_rescan_remove(); pci_unlock_rescan_remove();
} }
spin_lock(&zbus_list_lock); mutex_lock(&zbus_list_lock);
list_del(&zbus->bus_next); list_del(&zbus->bus_next);
spin_unlock(&zbus_list_lock); mutex_unlock(&zbus_list_lock);
kfree(zbus); kfree(zbus);
} }
...@@ -229,7 +229,7 @@ static struct zpci_bus *zpci_bus_get(int pchid) ...@@ -229,7 +229,7 @@ static struct zpci_bus *zpci_bus_get(int pchid)
{ {
struct zpci_bus *zbus; struct zpci_bus *zbus;
spin_lock(&zbus_list_lock); mutex_lock(&zbus_list_lock);
list_for_each_entry(zbus, &zbus_list, bus_next) { list_for_each_entry(zbus, &zbus_list, bus_next) {
if (pchid == zbus->pchid) { if (pchid == zbus->pchid) {
kref_get(&zbus->kref); kref_get(&zbus->kref);
...@@ -238,7 +238,7 @@ static struct zpci_bus *zpci_bus_get(int pchid) ...@@ -238,7 +238,7 @@ static struct zpci_bus *zpci_bus_get(int pchid)
} }
zbus = NULL; zbus = NULL;
out_unlock: out_unlock:
spin_unlock(&zbus_list_lock); mutex_unlock(&zbus_list_lock);
return zbus; return zbus;
} }
...@@ -252,9 +252,9 @@ static struct zpci_bus *zpci_bus_alloc(int pchid) ...@@ -252,9 +252,9 @@ static struct zpci_bus *zpci_bus_alloc(int pchid)
zbus->pchid = pchid; zbus->pchid = pchid;
INIT_LIST_HEAD(&zbus->bus_next); INIT_LIST_HEAD(&zbus->bus_next);
spin_lock(&zbus_list_lock); mutex_lock(&zbus_list_lock);
list_add_tail(&zbus->bus_next, &zbus_list); list_add_tail(&zbus->bus_next, &zbus_list);
spin_unlock(&zbus_list_lock); mutex_unlock(&zbus_list_lock);
kref_init(&zbus->kref); kref_init(&zbus->kref);
INIT_LIST_HEAD(&zbus->resources); INIT_LIST_HEAD(&zbus->resources);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment