@@ -1508,6 +1508,23 @@ static void vfio_ap_queue_link_mdev(struct vfio_ap_queue *q)
}
}
+
+static void vfio_ap_mdev_hot_plug_queue(struct vfio_ap_queue *q)
+{
+ bool hot_plug = false;
+ unsigned long apid = (unsigned long)AP_QID_CARD(q->apqn);
+ unsigned long apqi = (unsigned long)AP_QID_QUEUE(q->apqn);
+
+ if (q->matrix_mdev == NULL)
+ return;
+
+ hot_plug |= vfio_ap_assign_apid_to_apcb(q->matrix_mdev, apid);
+ hot_plug |= vfio_ap_assign_apqi_to_apcb(q->matrix_mdev, apqi);
+
+ if (hot_plug)
+ vfio_ap_mdev_commit_shadow_apcb(q->matrix_mdev);
+}
+
/**
* vfio_ap_mdev_probe_queue:
*
@@ -1526,11 +1543,30 @@ int vfio_ap_mdev_probe_queue(struct ap_device *apdev)
q->apqn = to_ap_queue(&apdev->device)->qid;
q->saved_isc = VFIO_AP_ISC_INVALID;
vfio_ap_queue_link_mdev(q);
+ vfio_ap_mdev_hot_plug_queue(q);
mutex_unlock(&matrix_dev->lock);
return 0;
}
+static void vfio_ap_mdev_hot_unplug_queue(struct vfio_ap_queue *q)
+{
+ unsigned long apid;
+ unsigned long apqi;
+
+ if (q->matrix_mdev == NULL)
+ return;
+
+ apid = AP_QID_CARD(q->apqn);
+ apqi = AP_QID_QUEUE(q->apqn);
+
+ if (test_bit_inv(apid, q->matrix_mdev->shadow_apcb.apm) &&
+ test_bit_inv(apqi, q->matrix_mdev->shadow_apcb.aqm)) {
+ clear_bit_inv(apid, q->matrix_mdev->shadow_apcb.apm);
+ vfio_ap_mdev_commit_shadow_apcb(q->matrix_mdev);
+ }
+}
+
/**
* vfio_ap_mdev_remove_queue:
*
@@ -1544,6 +1580,7 @@ void vfio_ap_mdev_remove_queue(struct ap_device *apdev)
mutex_lock(&matrix_dev->lock);
q = dev_get_drvdata(&apdev->device);
+ vfio_ap_mdev_hot_unplug_queue(q);
dev_set_drvdata(&apdev->device, NULL);
apid = AP_QID_CARD(q->apqn);
apqi = AP_QID_QUEUE(q->apqn);