hisi_acc_vfio_pci: Introduce support for PRE_COPY state transitions
authorShameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Wed, 23 Nov 2022 11:32:34 +0000 (11:32 +0000)
committerAlex Williamson <alex.williamson@redhat.com>
Tue, 6 Dec 2022 19:37:11 +0000 (12:37 -0700)
The saving_migf is open in PRE_COPY state if it is supported and reads
initial device match data. hisi_acc_vf_stop_copy() is refactored to
make use of common code.

Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Link: https://lore.kernel.org/r/20221123113236.896-3-shameerali.kolothum.thodi@huawei.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c

index f3b74a06edb6864d247d84b2f87fe6bfcd75e168..c8658636a84c03b84ea56bacb2adf314fc09876c 100644 (file)
@@ -863,7 +863,7 @@ static const struct file_operations hisi_acc_vf_save_fops = {
 };
 
 static struct hisi_acc_vf_migration_file *
-hisi_acc_vf_stop_copy(struct hisi_acc_vf_core_device *hisi_acc_vdev)
+hisi_acc_open_saving_migf(struct hisi_acc_vf_core_device *hisi_acc_vdev)
 {
        struct hisi_acc_vf_migration_file *migf;
        int ret;
@@ -885,7 +885,7 @@ hisi_acc_vf_stop_copy(struct hisi_acc_vf_core_device *hisi_acc_vdev)
        mutex_init(&migf->lock);
        migf->hisi_acc_vdev = hisi_acc_vdev;
 
-       ret = vf_qm_state_save(hisi_acc_vdev, migf);
+       ret = vf_qm_get_match_data(hisi_acc_vdev, &migf->vf_data);
        if (ret) {
                fput(migf->filp);
                return ERR_PTR(ret);
@@ -894,6 +894,44 @@ hisi_acc_vf_stop_copy(struct hisi_acc_vf_core_device *hisi_acc_vdev)
        return migf;
 }
 
+static struct hisi_acc_vf_migration_file *
+hisi_acc_vf_pre_copy(struct hisi_acc_vf_core_device *hisi_acc_vdev)
+{
+       struct hisi_acc_vf_migration_file *migf;
+
+       migf = hisi_acc_open_saving_migf(hisi_acc_vdev);
+       if (IS_ERR(migf))
+               return migf;
+
+       migf->total_length = QM_MATCH_SIZE;
+       return migf;
+}
+
+static struct hisi_acc_vf_migration_file *
+hisi_acc_vf_stop_copy(struct hisi_acc_vf_core_device *hisi_acc_vdev, bool open)
+{
+       int ret;
+       struct hisi_acc_vf_migration_file *migf = NULL;
+
+       if (open) {
+               /*
+                * Userspace didn't use PRECOPY support. Hence saving_migf
+                * is not opened yet.
+                */
+               migf = hisi_acc_open_saving_migf(hisi_acc_vdev);
+               if (IS_ERR(migf))
+                       return migf;
+       } else {
+               migf = hisi_acc_vdev->saving_migf;
+       }
+
+       ret = vf_qm_state_save(hisi_acc_vdev, migf);
+       if (ret)
+               return ERR_PTR(ret);
+
+       return open ? migf : NULL;
+}
+
 static int hisi_acc_vf_stop_device(struct hisi_acc_vf_core_device *hisi_acc_vdev)
 {
        struct device *dev = &hisi_acc_vdev->vf_dev->dev;
@@ -921,6 +959,31 @@ hisi_acc_vf_set_device_state(struct hisi_acc_vf_core_device *hisi_acc_vdev,
        u32 cur = hisi_acc_vdev->mig_state;
        int ret;
 
+       if (cur == VFIO_DEVICE_STATE_RUNNING && new == VFIO_DEVICE_STATE_PRE_COPY) {
+               struct hisi_acc_vf_migration_file *migf;
+
+               migf = hisi_acc_vf_pre_copy(hisi_acc_vdev);
+               if (IS_ERR(migf))
+                       return ERR_CAST(migf);
+               get_file(migf->filp);
+               hisi_acc_vdev->saving_migf = migf;
+               return migf->filp;
+       }
+
+       if (cur == VFIO_DEVICE_STATE_PRE_COPY && new == VFIO_DEVICE_STATE_STOP_COPY) {
+               struct hisi_acc_vf_migration_file *migf;
+
+               ret = hisi_acc_vf_stop_device(hisi_acc_vdev);
+               if (ret)
+                       return ERR_PTR(ret);
+
+               migf = hisi_acc_vf_stop_copy(hisi_acc_vdev, false);
+               if (IS_ERR(migf))
+                       return ERR_CAST(migf);
+
+               return NULL;
+       }
+
        if (cur == VFIO_DEVICE_STATE_RUNNING && new == VFIO_DEVICE_STATE_STOP) {
                ret = hisi_acc_vf_stop_device(hisi_acc_vdev);
                if (ret)
@@ -931,7 +994,7 @@ hisi_acc_vf_set_device_state(struct hisi_acc_vf_core_device *hisi_acc_vdev,
        if (cur == VFIO_DEVICE_STATE_STOP && new == VFIO_DEVICE_STATE_STOP_COPY) {
                struct hisi_acc_vf_migration_file *migf;
 
-               migf = hisi_acc_vf_stop_copy(hisi_acc_vdev);
+               migf = hisi_acc_vf_stop_copy(hisi_acc_vdev, true);
                if (IS_ERR(migf))
                        return ERR_CAST(migf);
                get_file(migf->filp);
@@ -963,6 +1026,11 @@ hisi_acc_vf_set_device_state(struct hisi_acc_vf_core_device *hisi_acc_vdev,
                return NULL;
        }
 
+       if (cur == VFIO_DEVICE_STATE_PRE_COPY && new == VFIO_DEVICE_STATE_RUNNING) {
+               hisi_acc_vf_disable_fds(hisi_acc_vdev);
+               return NULL;
+       }
+
        if (cur == VFIO_DEVICE_STATE_STOP && new == VFIO_DEVICE_STATE_RUNNING) {
                hisi_acc_vf_start_device(hisi_acc_vdev);
                return NULL;