Skip to content

Commit 3cbfa66

Browse files
author
Mete Durlu
committed
s390/pci: Serialize device addition and removal
JIRA: https://issues.redhat.com/browse/RHEL-94944 commit 774a1fa Author: Niklas Schnelle <schnelle@linux.ibm.com> Date: Thu May 22 14:13:15 2025 +0200 s390/pci: Serialize device addition and removal Prior changes ensured that when zpci_release_device() is called and it removed the zdev from the zpci_list this instance can not be found via the zpci_list anymore even while allowing re-add of reserved devices. This only accounts for the overall lifetime and zpci_list addition and removal, it does not yet prevent concurrent add of a new instance for the same underlying device. Such concurrent add would subsequently cause issues such as attempted re-use of the same IOMMU sysfs directory and is generally undesired. Introduce a new zpci_add_remove_lock mutex to serialize adding a new device with removal. Together this ensures that if a struct zpci_dev is not found in the zpci_list it was either already removed and torn down, or its removal and tear down is in progress with the zpci_add_remove_lock held. Cc: stable@vger.kernel.org Fixes: a46044a ("s390/pci: fix zpci_zdev_put() on reserve") Reviewed-by: Gerd Bayer <gbayer@linux.ibm.com> Tested-by: Gerd Bayer <gbayer@linux.ibm.com> Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Mete Durlu <mdurlu@redhat.com>
1 parent e579d6c commit 3cbfa66

File tree

1 file changed

+7
-0
lines changed

1 file changed

+7
-0
lines changed

arch/s390/pci/pci.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
/* list of all detected zpci devices */
4545
static LIST_HEAD(zpci_list);
4646
static DEFINE_SPINLOCK(zpci_list_lock);
47+
static DEFINE_MUTEX(zpci_add_remove_lock);
4748

4849
static DECLARE_BITMAP(zpci_domain, ZPCI_DOMAIN_BITMAP_SIZE);
4950
static DEFINE_SPINLOCK(zpci_domain_lock);
@@ -73,7 +74,9 @@ void zpci_zdev_put(struct zpci_dev *zdev)
7374
{
7475
if (!zdev)
7576
return;
77+
mutex_lock(&zpci_add_remove_lock);
7678
kref_put_lock(&zdev->kref, zpci_release_device, &zpci_list_lock);
79+
mutex_unlock(&zpci_add_remove_lock);
7780
}
7881

7982
struct zpci_dev *get_zdev_by_fid(u32 fid)
@@ -838,6 +841,7 @@ int zpci_add_device(struct zpci_dev *zdev)
838841
{
839842
int rc;
840843

844+
mutex_lock(&zpci_add_remove_lock);
841845
zpci_dbg(1, "add fid:%x, fh:%x, c:%d\n", zdev->fid, zdev->fh, zdev->state);
842846
rc = zpci_init_iommu(zdev);
843847
if (rc)
@@ -851,12 +855,14 @@ int zpci_add_device(struct zpci_dev *zdev)
851855
spin_lock(&zpci_list_lock);
852856
list_add_tail(&zdev->entry, &zpci_list);
853857
spin_unlock(&zpci_list_lock);
858+
mutex_unlock(&zpci_add_remove_lock);
854859
return 0;
855860

856861
error_destroy_iommu:
857862
zpci_destroy_iommu(zdev);
858863
error:
859864
zpci_dbg(0, "add fid:%x, rc:%d\n", zdev->fid, rc);
865+
mutex_unlock(&zpci_add_remove_lock);
860866
return rc;
861867
}
862868

@@ -947,6 +953,7 @@ void zpci_release_device(struct kref *kref)
947953
{
948954
struct zpci_dev *zdev = container_of(kref, struct zpci_dev, kref);
949955

956+
lockdep_assert_held(&zpci_add_remove_lock);
950957
WARN_ON(zdev->state != ZPCI_FN_STATE_RESERVED);
951958
/*
952959
* We already hold zpci_list_lock thanks to kref_put_lock().

0 commit comments

Comments
 (0)