diff --git a/drivers/s390/crypto/vfio_ap_drv.c b/drivers/s390/crypto/vfio_ap_drv.c
index 1d1746fe50ea..df7528dcf6ed 100644
--- a/drivers/s390/crypto/vfio_ap_drv.c
+++ b/drivers/s390/crypto/vfio_ap_drv.c
@@ -44,6 +44,7 @@ MODULE_DEVICE_TABLE(vfio_ap, ap_queue_ids);
 static struct ap_driver vfio_ap_drv = {
 	.probe = vfio_ap_mdev_probe_queue,
 	.remove = vfio_ap_mdev_remove_queue,
+	.in_use = vfio_ap_mdev_resource_in_use,
 	.ids = ap_queue_ids,
 };
 
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 6b292ed30ada..5386b8635bec 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -635,16 +635,45 @@ static void vfio_ap_mdev_link_adapter(struct ap_matrix_mdev *matrix_mdev,
  * vfio_ap_mdev_get_locks - lock the kvm->lock and matrix_dev->lock mutexes
  *
  * @matrix_mdev: the matrix mediated device object
+ * @check_mdev_lock: indicates whether to check that the matrix_dev->lock mutex
+ *		     is already locked (true = check, false = do not check).
+ *
+ * Return:
+ *	-EAGAIN if the matrix_dev->lock mutex is already locked.
+ *	0 if both locks were acquired.
  */
-static void vfio_ap_mdev_get_locks(struct ap_matrix_mdev *matrix_mdev)
+static int vfio_ap_mdev_get_locks(struct ap_matrix_mdev *matrix_mdev,
+				  bool check_mdev_lock)
 {
+	/*
+	 * If the matrix_dev->lock mutex is to be checked, then there's no
+	 * sense in proceding if it is already locked.
+	 */
+	if (check_mdev_lock && mutex_is_locked(&matrix_dev->lock))
+		return -EAGAIN;
+
 	down_read(&matrix_dev->guests_lock);
 
 	/* The kvm->lock must be must be taken before the matrix_dev->lock */
 	if (matrix_mdev->guest)
 		mutex_lock(&matrix_mdev->guest->kvm->lock);
 
-	mutex_lock(&matrix_dev->lock);
+	/*
+	 * If the matrix_dev-> lock is to be checked, then let's try to acquire
+	 * it. If it can't be acquired, then let's bail out and return
+	 * a value indicating locking should be tried again.
+	 */
+	if (check_mdev_lock) {
+		if (!mutex_trylock(&matrix_dev->lock)) {
+			mutex_unlock(&matrix_mdev->guest->kvm->lock);
+			up_read(&matrix_dev->guests_lock);
+			return -EAGAIN;
+		}
+	} else {
+		mutex_lock(&matrix_dev->lock);
+	}
+
+	return 0;
 }
 
 /**
@@ -654,7 +683,6 @@ static void vfio_ap_mdev_get_locks(struct ap_matrix_mdev *matrix_mdev)
  */
 static void vfio_ap_mdev_put_locks(struct ap_matrix_mdev *matrix_mdev)
 {
-	/* The kvm->lock must be must be taken before the matrix_dev->lock */
 	if (matrix_mdev->guest)
 		mutex_unlock(&matrix_mdev->guest->kvm->lock);
 
@@ -691,6 +719,10 @@ static void vfio_ap_mdev_put_locks(struct ap_matrix_mdev *matrix_mdev)
  *	   An APQN derived from the cross product of the APID being assigned
  *	   and the APQIs previously assigned is being used by another mediated
  *	   matrix device
+ *
+ *     5. -EAGAIN
+ *        The mdev lock could not be acquired which is required in order to
+ *        change the AP configuration for the mdev
  */
 static ssize_t assign_adapter_store(struct device *dev,
 				    struct device_attribute *attr,
@@ -707,7 +739,10 @@ static ssize_t assign_adapter_store(struct device *dev,
 	if (apid > matrix_mdev->matrix.apm_max)
 		return -ENODEV;
 
-	vfio_ap_mdev_get_locks(matrix_mdev);
+	ret = vfio_ap_mdev_get_locks(matrix_mdev, true);
+	if (ret)
+		return ret;
+
 	set_bit_inv(apid, matrix_mdev->matrix.apm);
 
 	ret = vfio_ap_mdev_validate_masks(matrix_mdev);
@@ -815,7 +850,10 @@ static ssize_t unassign_adapter_store(struct device *dev,
 	if (apid > matrix_mdev->matrix.apm_max)
 		return -ENODEV;
 
-	vfio_ap_mdev_get_locks(matrix_mdev);
+	ret = vfio_ap_mdev_get_locks(matrix_mdev, false);
+	if (ret)
+		return ret;
+
 	clear_bit_inv((unsigned long)apid, matrix_mdev->matrix.apm);
 	vfio_ap_mdev_hot_unplug_adapter(matrix_mdev, apid);
 	vfio_ap_mdev_put_locks(matrix_mdev);
@@ -879,7 +917,10 @@ static ssize_t assign_domain_store(struct device *dev,
 	if (apqi > max_apqi)
 		return -ENODEV;
 
-	vfio_ap_mdev_get_locks(matrix_mdev);
+	ret = vfio_ap_mdev_get_locks(matrix_mdev, true);
+	if (ret)
+		return ret;
+
 	set_bit_inv(apqi, matrix_mdev->matrix.aqm);
 
 	ret = vfio_ap_mdev_validate_masks(matrix_mdev);
@@ -962,7 +1003,10 @@ static ssize_t unassign_domain_store(struct device *dev,
 	if (apqi > matrix_mdev->matrix.aqm_max)
 		return -ENODEV;
 
-	vfio_ap_mdev_get_locks(matrix_mdev);
+	ret = vfio_ap_mdev_get_locks(matrix_mdev, false);
+	if (ret)
+		return ret;
+
 	clear_bit_inv((unsigned long)apqi, matrix_mdev->matrix.aqm);
 	vfio_ap_mdev_hot_unplug_domain(matrix_mdev, apqi);
 	vfio_ap_mdev_put_locks(matrix_mdev);
@@ -1000,7 +1044,9 @@ static ssize_t assign_control_domain_store(struct device *dev,
 	if (id > matrix_mdev->matrix.adm_max)
 		return -ENODEV;
 
-	vfio_ap_mdev_get_locks(matrix_mdev);
+	ret = vfio_ap_mdev_get_locks(matrix_mdev, false);
+	if (ret)
+		return ret;
 
 	/* Set the bit in the ADM (bitmask) corresponding to the AP control
 	 * domain number (id). The bits in the mask, from most significant to
@@ -1047,7 +1093,10 @@ static ssize_t unassign_control_domain_store(struct device *dev,
 	if (domid > max_domid)
 		return -ENODEV;
 
-	vfio_ap_mdev_get_locks(matrix_mdev);
+	ret = vfio_ap_mdev_get_locks(matrix_mdev, false);
+	if (ret)
+		return ret;
+
 	clear_bit_inv(domid, matrix_mdev->matrix.adm);
 
 	if (vfio_ap_mdev_filter_cdoms(matrix_mdev))
@@ -1681,3 +1730,16 @@ void vfio_ap_mdev_remove_queue(struct ap_device *apdev)
 	vfio_ap_mdev_put_qlocks(guest);
 	kfree(q);
 }
+
+int vfio_ap_mdev_resource_in_use(unsigned long *apm, unsigned long *aqm)
+{
+	int ret;
+
+	if (!mutex_trylock(&matrix_dev->lock))
+		return -EBUSY;
+
+	ret = vfio_ap_mdev_verify_no_sharing(apm, aqm);
+	mutex_unlock(&matrix_dev->lock);
+
+	return ret;
+}
diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
index 5d59bba8b153..97da41f87c65 100644
--- a/drivers/s390/crypto/vfio_ap_private.h
+++ b/drivers/s390/crypto/vfio_ap_private.h
@@ -149,4 +149,6 @@ void vfio_ap_mdev_unregister(void);
 int vfio_ap_mdev_probe_queue(struct ap_device *queue);
 void vfio_ap_mdev_remove_queue(struct ap_device *queue);
 
+int vfio_ap_mdev_resource_in_use(unsigned long *apm, unsigned long *aqm);
+
 #endif /* _VFIO_AP_PRIVATE_H_ */
