[PATCH v12 3/4] hisi_acc_vfio_pci: register debugfs for hisilicon migration driver

Longfang Liu posted 4 patches 1 year, 3 months ago
There is a newer version of this series
[PATCH v12 3/4] hisi_acc_vfio_pci: register debugfs for hisilicon migration driver
Posted by Longfang Liu 1 year, 3 months ago
On the debugfs framework of VFIO, if the CONFIG_VFIO_DEBUGFS macro is
enabled, the debug function is registered for the live migration driver
of the HiSilicon accelerator device.

After registering the HiSilicon accelerator device on the debugfs
framework of live migration of vfio, a directory file "hisi_acc"
of debugfs is created, and then three debug function files are
created in this directory:

   vfio
    |
    +---<dev_name1>
    |    +---migration
    |        +--state
    |        +--hisi_acc
    |            +--dev_data
    |            +--migf_data
    |            +--cmd_state
    |
    +---<dev_name2>
         +---migration
             +--state
             +--hisi_acc
                 +--dev_data
                 +--migf_data
                 +--cmd_state

dev_data file: read device data that needs to be migrated from the
current device in real time
migf_data file: read the migration data of the last live migration
from the current driver.
cmd_state: used to get the cmd channel state for the device.

+----------------+        +--------------+       +---------------+
| migration dev  |        |   src  dev   |       |   dst  dev    |
+-------+--------+        +------+-------+       +-------+-------+
        |                        |                       |
        |                 +------v-------+       +-------v-------+
        |                 |  saving_migf |       | resuming_migf |
  read  |                 |     file     |       |     file      |
        |                 +------+-------+       +-------+-------+
        |                        |          copy         |
        |                        +------------+----------+
        |                                     |
+-------v--------+                    +-------v--------+
|   data buffer  |                    |   debug_migf   |
+-------+--------+                    +-------+--------+
        |                                     |
   cat  |                                 cat |
+-------v--------+                    +-------v--------+
|   dev_data     |                    |   migf_data    |
+----------------+                    +----------------+

When accessing debugfs, user can obtain the most recent status data
of the device through the "dev_data" file. It can read recent
complete status data of the device. If the current device is being
migrated, it will wait for it to complete.
The data for the last completed migration function will be stored
in debug_migf. Users can read it via "migf_data".

Signed-off-by: Longfang Liu <liulongfang@huawei.com>
Reviewed-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
 .../vfio/pci/hisilicon/hisi_acc_vfio_pci.c    | 191 ++++++++++++++++++
 .../vfio/pci/hisilicon/hisi_acc_vfio_pci.h    |  15 ++
 2 files changed, 206 insertions(+)

diff --git a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
index a8c53952d82e..7728c9745b9d 100644
--- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
+++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
@@ -627,15 +627,30 @@ static void hisi_acc_vf_disable_fd(struct hisi_acc_vf_migration_file *migf)
 	mutex_unlock(&migf->lock);
 }
 
+static void hisi_acc_debug_migf_copy(struct hisi_acc_vf_core_device *hisi_acc_vdev,
+	struct hisi_acc_vf_migration_file *src_migf)
+{
+	struct hisi_acc_vf_migration_file *dst_migf = hisi_acc_vdev->debug_migf;
+
+	if (!dst_migf)
+		return;
+
+	dst_migf->total_length = src_migf->total_length;
+	memcpy(&dst_migf->vf_data, &src_migf->vf_data,
+		sizeof(struct acc_vf_data));
+}
+
 static void hisi_acc_vf_disable_fds(struct hisi_acc_vf_core_device *hisi_acc_vdev)
 {
 	if (hisi_acc_vdev->resuming_migf) {
+		hisi_acc_debug_migf_copy(hisi_acc_vdev, hisi_acc_vdev->resuming_migf);
 		hisi_acc_vf_disable_fd(hisi_acc_vdev->resuming_migf);
 		fput(hisi_acc_vdev->resuming_migf->filp);
 		hisi_acc_vdev->resuming_migf = NULL;
 	}
 
 	if (hisi_acc_vdev->saving_migf) {
+		hisi_acc_debug_migf_copy(hisi_acc_vdev, hisi_acc_vdev->saving_migf);
 		hisi_acc_vf_disable_fd(hisi_acc_vdev->saving_migf);
 		fput(hisi_acc_vdev->saving_migf->filp);
 		hisi_acc_vdev->saving_migf = NULL;
@@ -1294,6 +1309,129 @@ static long hisi_acc_vfio_pci_ioctl(struct vfio_device *core_vdev, unsigned int
 	return vfio_pci_core_ioctl(core_vdev, cmd, arg);
 }
 
+static int hisi_acc_vf_debug_check(struct seq_file *seq, struct vfio_device *vdev)
+{
+	struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(vdev);
+	struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
+	int ret;
+
+	lockdep_assert_held(&hisi_acc_vdev->open_mutex);
+	/*
+	 * When the device is not opened, the io_base is not mapped.
+	 * The driver cannot perform device read and write operations.
+	 */
+	if (!hisi_acc_vdev->dev_opened) {
+		seq_printf(seq, "device not opened!\n");
+		return -EINVAL;
+	}
+
+	ret = qm_wait_dev_not_ready(vf_qm);
+	if (ret) {
+		seq_printf(seq, "VF device not ready!\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int hisi_acc_vf_debug_cmd(struct seq_file *seq, void *data)
+{
+	struct device *vf_dev = seq->private;
+	struct vfio_pci_core_device *core_device = dev_get_drvdata(vf_dev);
+	struct vfio_device *vdev = &core_device->vdev;
+	struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(vdev);
+	struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
+	u64 value;
+	int ret;
+
+	mutex_lock(&hisi_acc_vdev->open_mutex);
+	ret = hisi_acc_vf_debug_check(seq, vdev);
+	if (ret) {
+		mutex_unlock(&hisi_acc_vdev->open_mutex);
+		return ret;
+	}
+
+	value = readl(vf_qm->io_base + QM_MB_CMD_SEND_BASE);
+	if (value == QM_MB_CMD_NOT_READY) {
+		mutex_unlock(&hisi_acc_vdev->open_mutex);
+		seq_printf(seq, "mailbox cmd channel not ready!\n");
+		return -EINVAL;
+	}
+	mutex_unlock(&hisi_acc_vdev->open_mutex);
+	seq_printf(seq, "mailbox cmd channel ready!\n");
+
+	return 0;
+}
+
+static int hisi_acc_vf_dev_read(struct seq_file *seq, void *data)
+{
+	struct device *vf_dev = seq->private;
+	struct vfio_pci_core_device *core_device = dev_get_drvdata(vf_dev);
+	struct vfio_device *vdev = &core_device->vdev;
+	struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(vdev);
+	size_t vf_data_sz = offsetofend(struct acc_vf_data, padding);
+	struct acc_vf_data *vf_data;
+	int ret;
+
+	mutex_lock(&hisi_acc_vdev->open_mutex);
+	ret = hisi_acc_vf_debug_check(seq, vdev);
+	if (ret) {
+		mutex_unlock(&hisi_acc_vdev->open_mutex);
+		return ret;
+	}
+
+	mutex_lock(&hisi_acc_vdev->state_mutex);
+	vf_data = kzalloc(sizeof(struct acc_vf_data), GFP_KERNEL);
+	if (!vf_data) {
+		ret = -ENOMEM;
+		goto mutex_release;
+	}
+
+	vf_data->vf_qm_state = hisi_acc_vdev->vf_qm_state;
+	ret = vf_qm_read_data(&hisi_acc_vdev->vf_qm, vf_data);
+	if (ret)
+		goto migf_err;
+
+	seq_hex_dump(seq, "Dev Data:", DUMP_PREFIX_OFFSET, 16, 1,
+		     (const void *)vf_data, vf_data_sz, false);
+
+	seq_printf(seq,
+		   "guest driver load: %u\n"
+		   "data size: %lu\n",
+		   hisi_acc_vdev->vf_qm_state,
+		   sizeof(struct acc_vf_data));
+
+migf_err:
+	kfree(vf_data);
+mutex_release:
+	mutex_unlock(&hisi_acc_vdev->state_mutex);
+	mutex_unlock(&hisi_acc_vdev->open_mutex);
+
+	return ret;
+}
+
+static int hisi_acc_vf_migf_read(struct seq_file *seq, void *data)
+{
+	struct device *vf_dev = seq->private;
+	struct vfio_pci_core_device *core_device = dev_get_drvdata(vf_dev);
+	struct vfio_device *vdev = &core_device->vdev;
+	struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(vdev);
+	size_t vf_data_sz = offsetofend(struct acc_vf_data, padding);
+	struct hisi_acc_vf_migration_file *debug_migf = hisi_acc_vdev->debug_migf;
+
+	/* Check whether the live migration operation has been performed */
+	if (debug_migf->total_length < QM_MATCH_SIZE) {
+		seq_printf(seq, "device not migrated!\n");
+		return -EAGAIN;
+	}
+
+	seq_hex_dump(seq, "Mig Data:", DUMP_PREFIX_OFFSET, 16, 1,
+		     (const void *)&debug_migf->vf_data, vf_data_sz, false);
+	seq_printf(seq, "migrate data length: %lu\n", debug_migf->total_length);
+
+	return 0;
+}
+
 static int hisi_acc_vfio_pci_open_device(struct vfio_device *core_vdev)
 {
 	struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(core_vdev);
@@ -1305,12 +1443,16 @@ static int hisi_acc_vfio_pci_open_device(struct vfio_device *core_vdev)
 		return ret;
 
 	if (core_vdev->mig_ops) {
+		mutex_lock(&hisi_acc_vdev->open_mutex);
 		ret = hisi_acc_vf_qm_init(hisi_acc_vdev);
 		if (ret) {
+			mutex_unlock(&hisi_acc_vdev->open_mutex);
 			vfio_pci_core_disable(vdev);
 			return ret;
 		}
 		hisi_acc_vdev->mig_state = VFIO_DEVICE_STATE_RUNNING;
+		hisi_acc_vdev->dev_opened = true;
+		mutex_unlock(&hisi_acc_vdev->open_mutex);
 	}
 
 	vfio_pci_core_finish_enable(vdev);
@@ -1322,7 +1464,10 @@ static void hisi_acc_vfio_pci_close_device(struct vfio_device *core_vdev)
 	struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_get_vf_dev(core_vdev);
 	struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
 
+	mutex_lock(&hisi_acc_vdev->open_mutex);
+	hisi_acc_vdev->dev_opened = false;
 	iounmap(vf_qm->io_base);
+	mutex_unlock(&hisi_acc_vdev->open_mutex);
 	vfio_pci_core_close_device(core_vdev);
 }
 
@@ -1342,6 +1487,7 @@ static int hisi_acc_vfio_pci_migrn_init_dev(struct vfio_device *core_vdev)
 	hisi_acc_vdev->pf_qm = pf_qm;
 	hisi_acc_vdev->vf_dev = pdev;
 	mutex_init(&hisi_acc_vdev->state_mutex);
+	mutex_init(&hisi_acc_vdev->open_mutex);
 
 	core_vdev->migration_flags = VFIO_MIGRATION_STOP_COPY | VFIO_MIGRATION_PRE_COPY;
 	core_vdev->mig_ops = &hisi_acc_vfio_pci_migrn_state_ops;
@@ -1387,6 +1533,48 @@ static const struct vfio_device_ops hisi_acc_vfio_pci_ops = {
 	.detach_ioas = vfio_iommufd_physical_detach_ioas,
 };
 
+static void hisi_acc_vfio_debug_init(struct hisi_acc_vf_core_device *hisi_acc_vdev)
+{
+	struct vfio_device *vdev = &hisi_acc_vdev->core_device.vdev;
+	struct dentry *vfio_dev_migration = NULL;
+	struct dentry *vfio_hisi_acc = NULL;
+	struct device *dev = vdev->dev;
+	void *migf = NULL;
+
+	if (!debugfs_initialized() ||
+	    !IS_ENABLED(CONFIG_VFIO_DEBUGFS))
+		return;
+
+	if (vdev->ops != &hisi_acc_vfio_pci_migrn_ops)
+		return;
+
+	vfio_dev_migration = debugfs_lookup("migration", vdev->debug_root);
+	if (!vfio_dev_migration) {
+		dev_err(dev, "failed to lookup migration debugfs file!\n");
+		return;
+	}
+
+	migf = kzalloc(sizeof(struct hisi_acc_vf_migration_file), GFP_KERNEL);
+	if (!migf)
+		return;
+	hisi_acc_vdev->debug_migf = migf;
+
+	vfio_hisi_acc = debugfs_create_dir("hisi_acc", vfio_dev_migration);
+	debugfs_create_devm_seqfile(dev, "dev_data", vfio_hisi_acc,
+				    hisi_acc_vf_dev_read);
+	debugfs_create_devm_seqfile(dev, "migf_data", vfio_hisi_acc,
+				    hisi_acc_vf_migf_read);
+	debugfs_create_devm_seqfile(dev, "cmd_state", vfio_hisi_acc,
+				    hisi_acc_vf_debug_cmd);
+}
+
+static void hisi_acc_vf_debugfs_exit(struct hisi_acc_vf_core_device *hisi_acc_vdev)
+{
+	/* If migrn_ops is not used, kfree(NULL) is valid */
+	kfree(hisi_acc_vdev->debug_migf);
+	hisi_acc_vdev->debug_migf = NULL;
+}
+
 static int hisi_acc_vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct hisi_acc_vf_core_device *hisi_acc_vdev;
@@ -1413,6 +1601,8 @@ static int hisi_acc_vfio_pci_probe(struct pci_dev *pdev, const struct pci_device
 	ret = vfio_pci_core_register_device(&hisi_acc_vdev->core_device);
 	if (ret)
 		goto out_put_vdev;
+
+	hisi_acc_vfio_debug_init(hisi_acc_vdev);
 	return 0;
 
 out_put_vdev:
@@ -1425,6 +1615,7 @@ static void hisi_acc_vfio_pci_remove(struct pci_dev *pdev)
 	struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_drvdata(pdev);
 
 	vfio_pci_core_unregister_device(&hisi_acc_vdev->core_device);
+	hisi_acc_vf_debugfs_exit(hisi_acc_vdev);
 	vfio_put_device(&hisi_acc_vdev->core_device.vdev);
 }
 
diff --git a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h
index 5bab46602fad..47092cf4cf5c 100644
--- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h
+++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.h
@@ -32,6 +32,7 @@
 #define QM_SQC_VFT_BASE_MASK_V2		GENMASK(15, 0)
 #define QM_SQC_VFT_NUM_SHIFT_V2		45
 #define QM_SQC_VFT_NUM_MASK_V2		GENMASK(9, 0)
+#define QM_MB_CMD_NOT_READY	0xffffffff
 
 /* RW regs */
 #define QM_REGS_MAX_LEN		7
@@ -99,6 +100,12 @@ struct hisi_acc_vf_migration_file {
 struct hisi_acc_vf_core_device {
 	struct vfio_pci_core_device core_device;
 	u8 match_done;
+	/*
+	 * io_base is only valid when dev_opened is true,
+	 * which is protected by open_mutex.
+	 */
+	bool dev_opened;
+	struct mutex open_mutex;
 
 	/* For migration state */
 	struct mutex state_mutex;
@@ -107,9 +114,17 @@ struct hisi_acc_vf_core_device {
 	struct pci_dev *vf_dev;
 	struct hisi_qm *pf_qm;
 	struct hisi_qm vf_qm;
+	/*
+	 * Record whether a driver is added to the acc device in Guest OS.
+	 * The value of QM_VF_STATE is set by the acc device driver.
+	 * The migration driver queries through the QM_VF_STATE register.
+	 */
 	u32 vf_qm_state;
 	int vf_id;
 	struct hisi_acc_vf_migration_file *resuming_migf;
 	struct hisi_acc_vf_migration_file *saving_migf;
+
+	/* An extra buffer for reporting migration data via debugfs */
+	struct hisi_acc_vf_migration_file *debug_migf;
 };
 #endif /* HISI_ACC_VFIO_PCI_H */
-- 
2.24.0
RE: [PATCH v12 3/4] hisi_acc_vfio_pci: register debugfs for hisilicon migration driver
Posted by Shameerali Kolothum Thodi 1 year, 3 months ago

> -----Original Message-----
> From: liulongfang <liulongfang@huawei.com>
> Sent: Tuesday, November 5, 2024 3:53 AM
> To: alex.williamson@redhat.com; jgg@nvidia.com; Shameerali Kolothum
> Thodi <shameerali.kolothum.thodi@huawei.com>; Jonathan Cameron
> <jonathan.cameron@huawei.com>
> Cc: kvm@vger.kernel.org; linux-kernel@vger.kernel.org;
> linuxarm@openeuler.org; liulongfang <liulongfang@huawei.com>
> Subject: [PATCH v12 3/4] hisi_acc_vfio_pci: register debugfs for hisilicon
> migration driver

Hi,

Few minor comments below. Please don't re-spin just for these yet.
Please wait for others to review as well.

Thanks,
Shameer

> diff --git a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
> b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
> index a8c53952d82e..7728c9745b9d 100644
> --- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
> +++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
> @@ -627,15 +627,30 @@ static void hisi_acc_vf_disable_fd(struct
> hisi_acc_vf_migration_file *migf)
>  	mutex_unlock(&migf->lock);
>  }
> 
> +static void hisi_acc_debug_migf_copy(struct hisi_acc_vf_core_device
> *hisi_acc_vdev,
> +	struct hisi_acc_vf_migration_file *src_migf)

Alignment should match open parenthesis here.

> +{
> +	struct hisi_acc_vf_migration_file *dst_migf = hisi_acc_vdev-
> >debug_migf;
> +
> +	if (!dst_migf)
> +		return;
> +
> +	dst_migf->total_length = src_migf->total_length;
> +	memcpy(&dst_migf->vf_data, &src_migf->vf_data,
> +		sizeof(struct acc_vf_data));

Here too, alignment not correct. It is better to run,
./scripts/checkpatch --strict on these patches if you haven't done already.

> +}
> +
>  static void hisi_acc_vf_disable_fds(struct hisi_acc_vf_core_device
> *hisi_acc_vdev)
>  {
>  	if (hisi_acc_vdev->resuming_migf) {
> +		hisi_acc_debug_migf_copy(hisi_acc_vdev, hisi_acc_vdev-
> >resuming_migf);
>  		hisi_acc_vf_disable_fd(hisi_acc_vdev->resuming_migf);
>  		fput(hisi_acc_vdev->resuming_migf->filp);
>  		hisi_acc_vdev->resuming_migf = NULL;
>  	}
> 
>  	if (hisi_acc_vdev->saving_migf) {
> +		hisi_acc_debug_migf_copy(hisi_acc_vdev, hisi_acc_vdev-
> >saving_migf);
>  		hisi_acc_vf_disable_fd(hisi_acc_vdev->saving_migf);
>  		fput(hisi_acc_vdev->saving_migf->filp);
>  		hisi_acc_vdev->saving_migf = NULL;
> @@ -1294,6 +1309,129 @@ static long hisi_acc_vfio_pci_ioctl(struct
> vfio_device *core_vdev, unsigned int
>  	return vfio_pci_core_ioctl(core_vdev, cmd, arg);
>  }
> 
> +static int hisi_acc_vf_debug_check(struct seq_file *seq, struct vfio_device
> *vdev)
> +{
> +	struct hisi_acc_vf_core_device *hisi_acc_vdev =
> hisi_acc_get_vf_dev(vdev);
> +	struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
> +	int ret;
> +
> +	lockdep_assert_held(&hisi_acc_vdev->open_mutex);
> +	/*
> +	 * When the device is not opened, the io_base is not mapped.
> +	 * The driver cannot perform device read and write operations.
> +	 */
> +	if (!hisi_acc_vdev->dev_opened) {
> +		seq_printf(seq, "device not opened!\n");
> +		return -EINVAL;
> +	}
> +
> +	ret = qm_wait_dev_not_ready(vf_qm);
> +	if (ret) {
> +		seq_printf(seq, "VF device not ready!\n");
> +		return -EBUSY;
> +	}
> +
> +	return 0;
> +}
> +
> +static int hisi_acc_vf_debug_cmd(struct seq_file *seq, void *data)
> +{
> +	struct device *vf_dev = seq->private;
> +	struct vfio_pci_core_device *core_device =
> dev_get_drvdata(vf_dev);
> +	struct vfio_device *vdev = &core_device->vdev;
> +	struct hisi_acc_vf_core_device *hisi_acc_vdev =
> hisi_acc_get_vf_dev(vdev);
> +	struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
> +	u64 value;
> +	int ret;
> +
> +	mutex_lock(&hisi_acc_vdev->open_mutex);
> +	ret = hisi_acc_vf_debug_check(seq, vdev);
> +	if (ret) {
> +		mutex_unlock(&hisi_acc_vdev->open_mutex);
> +		return ret;
> +	}
> +
> +	value = readl(vf_qm->io_base + QM_MB_CMD_SEND_BASE);
> +	if (value == QM_MB_CMD_NOT_READY) {
> +		mutex_unlock(&hisi_acc_vdev->open_mutex);
> +		seq_printf(seq, "mailbox cmd channel not ready!\n");
> +		return -EINVAL;
> +	}
> +	mutex_unlock(&hisi_acc_vdev->open_mutex);
> +	seq_printf(seq, "mailbox cmd channel ready!\n");
> +
> +	return 0;
> +}
> +
> +static int hisi_acc_vf_dev_read(struct seq_file *seq, void *data)
> +{
> +	struct device *vf_dev = seq->private;
> +	struct vfio_pci_core_device *core_device =
> dev_get_drvdata(vf_dev);
> +	struct vfio_device *vdev = &core_device->vdev;
> +	struct hisi_acc_vf_core_device *hisi_acc_vdev =
> hisi_acc_get_vf_dev(vdev);
> +	size_t vf_data_sz = offsetofend(struct acc_vf_data, padding);
> +	struct acc_vf_data *vf_data;
> +	int ret;
> +
> +	mutex_lock(&hisi_acc_vdev->open_mutex);
> +	ret = hisi_acc_vf_debug_check(seq, vdev);
> +	if (ret) {
> +		mutex_unlock(&hisi_acc_vdev->open_mutex);
> +		return ret;
> +	}
> +
> +	mutex_lock(&hisi_acc_vdev->state_mutex);
> +	vf_data = kzalloc(sizeof(struct acc_vf_data), GFP_KERNEL);
> +	if (!vf_data) {
> +		ret = -ENOMEM;
> +		goto mutex_release;
> +	}
> +
> +	vf_data->vf_qm_state = hisi_acc_vdev->vf_qm_state;
> +	ret = vf_qm_read_data(&hisi_acc_vdev->vf_qm, vf_data);
> +	if (ret)
> +		goto migf_err;
> +
> +	seq_hex_dump(seq, "Dev Data:", DUMP_PREFIX_OFFSET, 16, 1,
> +		     (const void *)vf_data, vf_data_sz, false);
> +
> +	seq_printf(seq,
> +		   "guest driver load: %u\n"
> +		   "data size: %lu\n",
> +		   hisi_acc_vdev->vf_qm_state,
> +		   sizeof(struct acc_vf_data));

There was a suggestion to add a comment here to describe vf_qm_state better.
May be something like,

vf_qm_state here indicates whether the Guest has loaded the driver for the ACC VF
device or not.

> +
> +migf_err:
> +	kfree(vf_data);
> +mutex_release:
> +	mutex_unlock(&hisi_acc_vdev->state_mutex);
> +	mutex_unlock(&hisi_acc_vdev->open_mutex);
> +
> +	return ret;
> +}
> +
> +static int hisi_acc_vf_migf_read(struct seq_file *seq, void *data)
> +{
> +	struct device *vf_dev = seq->private;
> +	struct vfio_pci_core_device *core_device =
> dev_get_drvdata(vf_dev);
> +	struct vfio_device *vdev = &core_device->vdev;
> +	struct hisi_acc_vf_core_device *hisi_acc_vdev =
> hisi_acc_get_vf_dev(vdev);
> +	size_t vf_data_sz = offsetofend(struct acc_vf_data, padding);
> +	struct hisi_acc_vf_migration_file *debug_migf = hisi_acc_vdev-
> >debug_migf;
> +
> +	/* Check whether the live migration operation has been performed
> */
> +	if (debug_migf->total_length < QM_MATCH_SIZE) {
> +		seq_printf(seq, "device not migrated!\n");
> +		return -EAGAIN;
> +	}
> +
> +	seq_hex_dump(seq, "Mig Data:", DUMP_PREFIX_OFFSET, 16, 1,
> +		     (const void *)&debug_migf->vf_data, vf_data_sz, false);
> +	seq_printf(seq, "migrate data length: %lu\n", debug_migf-
> >total_length);
> +
> +	return 0;
> +}
> +
>  static int hisi_acc_vfio_pci_open_device(struct vfio_device *core_vdev)
>  {
>  	struct hisi_acc_vf_core_device *hisi_acc_vdev =
> hisi_acc_get_vf_dev(core_vdev);
> @@ -1305,12 +1443,16 @@ static int hisi_acc_vfio_pci_open_device(struct
> vfio_device *core_vdev)
>  		return ret;
> 
>  	if (core_vdev->mig_ops) {
> +		mutex_lock(&hisi_acc_vdev->open_mutex);
>  		ret = hisi_acc_vf_qm_init(hisi_acc_vdev);
>  		if (ret) {
> +			mutex_unlock(&hisi_acc_vdev->open_mutex);
>  			vfio_pci_core_disable(vdev);
>  			return ret;
>  		}
>  		hisi_acc_vdev->mig_state = VFIO_DEVICE_STATE_RUNNING;
> +		hisi_acc_vdev->dev_opened = true;
> +		mutex_unlock(&hisi_acc_vdev->open_mutex);
>  	}
> 
>  	vfio_pci_core_finish_enable(vdev);
> @@ -1322,7 +1464,10 @@ static void hisi_acc_vfio_pci_close_device(struct
> vfio_device *core_vdev)
>  	struct hisi_acc_vf_core_device *hisi_acc_vdev =
> hisi_acc_get_vf_dev(core_vdev);
>  	struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
> 
> +	mutex_lock(&hisi_acc_vdev->open_mutex);
> +	hisi_acc_vdev->dev_opened = false;
>  	iounmap(vf_qm->io_base);
> +	mutex_unlock(&hisi_acc_vdev->open_mutex);
>  	vfio_pci_core_close_device(core_vdev);
>  }
> 
> @@ -1342,6 +1487,7 @@ static int hisi_acc_vfio_pci_migrn_init_dev(struct
> vfio_device *core_vdev)
>  	hisi_acc_vdev->pf_qm = pf_qm;
>  	hisi_acc_vdev->vf_dev = pdev;
>  	mutex_init(&hisi_acc_vdev->state_mutex);
> +	mutex_init(&hisi_acc_vdev->open_mutex);
> 
>  	core_vdev->migration_flags = VFIO_MIGRATION_STOP_COPY |
> VFIO_MIGRATION_PRE_COPY;
>  	core_vdev->mig_ops = &hisi_acc_vfio_pci_migrn_state_ops;
> @@ -1387,6 +1533,48 @@ static const struct vfio_device_ops
> hisi_acc_vfio_pci_ops = {
>  	.detach_ioas = vfio_iommufd_physical_detach_ioas,
>  };
> 
> +static void hisi_acc_vfio_debug_init(struct hisi_acc_vf_core_device
> *hisi_acc_vdev)
> +{
> +	struct vfio_device *vdev = &hisi_acc_vdev->core_device.vdev;
> +	struct dentry *vfio_dev_migration = NULL;
> +	struct dentry *vfio_hisi_acc = NULL;
> +	struct device *dev = vdev->dev;
> +	void *migf = NULL;
> +
> +	if (!debugfs_initialized() ||
> +	    !IS_ENABLED(CONFIG_VFIO_DEBUGFS))
> +		return;
> +
> +	if (vdev->ops != &hisi_acc_vfio_pci_migrn_ops)
> +		return;
> +
> +	vfio_dev_migration = debugfs_lookup("migration", vdev-
> >debug_root);
> +	if (!vfio_dev_migration) {
> +		dev_err(dev, "failed to lookup migration debugfs file!\n");
> +		return;
> +	}
> +
> +	migf = kzalloc(sizeof(struct hisi_acc_vf_migration_file),
> GFP_KERNEL);
> +	if (!migf)
> +		return;
> +	hisi_acc_vdev->debug_migf = migf;
> +
> +	vfio_hisi_acc = debugfs_create_dir("hisi_acc", vfio_dev_migration);
> +	debugfs_create_devm_seqfile(dev, "dev_data", vfio_hisi_acc,
> +				    hisi_acc_vf_dev_read);
> +	debugfs_create_devm_seqfile(dev, "migf_data", vfio_hisi_acc,
> +				    hisi_acc_vf_migf_read);
> +	debugfs_create_devm_seqfile(dev, "cmd_state", vfio_hisi_acc,
> +				    hisi_acc_vf_debug_cmd);
> +}
> +
> +static void hisi_acc_vf_debugfs_exit(struct hisi_acc_vf_core_device
> *hisi_acc_vdev)
> +{
> +	/* If migrn_ops is not used, kfree(NULL) is valid */

The above comment is not required. Please remove.

> +	kfree(hisi_acc_vdev->debug_migf);
> +	hisi_acc_vdev->debug_migf = NULL;
> +}
> +
Re: [PATCH v12 3/4] hisi_acc_vfio_pci: register debugfs for hisilicon migration driver
Posted by Alex Williamson 1 year, 3 months ago
On Tue, 5 Nov 2024 08:55:51 +0000
Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com> wrote:

> > -----Original Message-----
> > From: liulongfang <liulongfang@huawei.com>
> > Sent: Tuesday, November 5, 2024 3:53 AM
> > To: alex.williamson@redhat.com; jgg@nvidia.com; Shameerali Kolothum
> > Thodi <shameerali.kolothum.thodi@huawei.com>; Jonathan Cameron
> > <jonathan.cameron@huawei.com>
> > Cc: kvm@vger.kernel.org; linux-kernel@vger.kernel.org;
> > linuxarm@openeuler.org; liulongfang <liulongfang@huawei.com>
> > Subject: [PATCH v12 3/4] hisi_acc_vfio_pci: register debugfs for hisilicon
> > migration driver  
> 
> Hi,
> 
> Few minor comments below. Please don't re-spin just for these yet.
> Please wait for others to review as well.
> 
> Thanks,
> Shameer
> 
> > diff --git a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
> > b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
> > index a8c53952d82e..7728c9745b9d 100644
> > --- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
> > +++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
> > @@ -627,15 +627,30 @@ static void hisi_acc_vf_disable_fd(struct
> > hisi_acc_vf_migration_file *migf)
> >  	mutex_unlock(&migf->lock);
> >  }
> > 
> > +static void hisi_acc_debug_migf_copy(struct hisi_acc_vf_core_device
> > *hisi_acc_vdev,
> > +	struct hisi_acc_vf_migration_file *src_migf)  
> 
> Alignment should match open parenthesis here.

I might also shorten the first line to 80 chars by putting "static" or
"static void" on a line by itself, but we're getting into personal
preference at that point and this driver already has lines exceeding 80
columns.

> > +{
> > +	struct hisi_acc_vf_migration_file *dst_migf = hisi_acc_vdev-  
> > >debug_migf;  
> > +
> > +	if (!dst_migf)
> > +		return;
> > +
> > +	dst_migf->total_length = src_migf->total_length;
> > +	memcpy(&dst_migf->vf_data, &src_migf->vf_data,
> > +		sizeof(struct acc_vf_data));  
> 
> Here too, alignment not correct. It is better to run,
> ./scripts/checkpatch --strict on these patches if you haven't done already.

Yup.  Only those two were missed as far as I see, but checkpatch does
warn several places where we should use seq_puts() rather than
seq_printf() for cases of printing a constant format without additional
arguments.  For example "device not opened!\n" is the first one below
but there are others.

> > +}
> > +
> >  static void hisi_acc_vf_disable_fds(struct hisi_acc_vf_core_device
> > *hisi_acc_vdev)
> >  {
> >  	if (hisi_acc_vdev->resuming_migf) {
> > +		hisi_acc_debug_migf_copy(hisi_acc_vdev, hisi_acc_vdev-  
> > >resuming_migf);  
> >  		hisi_acc_vf_disable_fd(hisi_acc_vdev->resuming_migf);
> >  		fput(hisi_acc_vdev->resuming_migf->filp);
> >  		hisi_acc_vdev->resuming_migf = NULL;
> >  	}
> > 
> >  	if (hisi_acc_vdev->saving_migf) {
> > +		hisi_acc_debug_migf_copy(hisi_acc_vdev, hisi_acc_vdev-  
> > >saving_migf);  
> >  		hisi_acc_vf_disable_fd(hisi_acc_vdev->saving_migf);
> >  		fput(hisi_acc_vdev->saving_migf->filp);
> >  		hisi_acc_vdev->saving_migf = NULL;
> > @@ -1294,6 +1309,129 @@ static long hisi_acc_vfio_pci_ioctl(struct
> > vfio_device *core_vdev, unsigned int
> >  	return vfio_pci_core_ioctl(core_vdev, cmd, arg);
> >  }
> > 
> > +static int hisi_acc_vf_debug_check(struct seq_file *seq, struct vfio_device
> > *vdev)
> > +{
> > +	struct hisi_acc_vf_core_device *hisi_acc_vdev =
> > hisi_acc_get_vf_dev(vdev);
> > +	struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
> > +	int ret;
> > +
> > +	lockdep_assert_held(&hisi_acc_vdev->open_mutex);
> > +	/*
> > +	 * When the device is not opened, the io_base is not mapped.
> > +	 * The driver cannot perform device read and write operations.
> > +	 */
> > +	if (!hisi_acc_vdev->dev_opened) {
> > +		seq_printf(seq, "device not opened!\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	ret = qm_wait_dev_not_ready(vf_qm);
> > +	if (ret) {
> > +		seq_printf(seq, "VF device not ready!\n");
> > +		return -EBUSY;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int hisi_acc_vf_debug_cmd(struct seq_file *seq, void *data)
> > +{
> > +	struct device *vf_dev = seq->private;
> > +	struct vfio_pci_core_device *core_device =
> > dev_get_drvdata(vf_dev);
> > +	struct vfio_device *vdev = &core_device->vdev;
> > +	struct hisi_acc_vf_core_device *hisi_acc_vdev =
> > hisi_acc_get_vf_dev(vdev);
> > +	struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
> > +	u64 value;
> > +	int ret;
> > +
> > +	mutex_lock(&hisi_acc_vdev->open_mutex);
> > +	ret = hisi_acc_vf_debug_check(seq, vdev);
> > +	if (ret) {
> > +		mutex_unlock(&hisi_acc_vdev->open_mutex);
> > +		return ret;
> > +	}
> > +
> > +	value = readl(vf_qm->io_base + QM_MB_CMD_SEND_BASE);
> > +	if (value == QM_MB_CMD_NOT_READY) {
> > +		mutex_unlock(&hisi_acc_vdev->open_mutex);
> > +		seq_printf(seq, "mailbox cmd channel not ready!\n");
> > +		return -EINVAL;
> > +	}
> > +	mutex_unlock(&hisi_acc_vdev->open_mutex);
> > +	seq_printf(seq, "mailbox cmd channel ready!\n");
> > +
> > +	return 0;
> > +}
> > +
> > +static int hisi_acc_vf_dev_read(struct seq_file *seq, void *data)
> > +{
> > +	struct device *vf_dev = seq->private;
> > +	struct vfio_pci_core_device *core_device =
> > dev_get_drvdata(vf_dev);
> > +	struct vfio_device *vdev = &core_device->vdev;
> > +	struct hisi_acc_vf_core_device *hisi_acc_vdev =
> > hisi_acc_get_vf_dev(vdev);
> > +	size_t vf_data_sz = offsetofend(struct acc_vf_data, padding);
> > +	struct acc_vf_data *vf_data;
> > +	int ret;
> > +
> > +	mutex_lock(&hisi_acc_vdev->open_mutex);
> > +	ret = hisi_acc_vf_debug_check(seq, vdev);
> > +	if (ret) {
> > +		mutex_unlock(&hisi_acc_vdev->open_mutex);
> > +		return ret;
> > +	}
> > +
> > +	mutex_lock(&hisi_acc_vdev->state_mutex);
> > +	vf_data = kzalloc(sizeof(struct acc_vf_data), GFP_KERNEL);
> > +	if (!vf_data) {
> > +		ret = -ENOMEM;
> > +		goto mutex_release;
> > +	}
> > +
> > +	vf_data->vf_qm_state = hisi_acc_vdev->vf_qm_state;
> > +	ret = vf_qm_read_data(&hisi_acc_vdev->vf_qm, vf_data);
> > +	if (ret)
> > +		goto migf_err;
> > +
> > +	seq_hex_dump(seq, "Dev Data:", DUMP_PREFIX_OFFSET, 16, 1,
> > +		     (const void *)vf_data, vf_data_sz, false);
> > +
> > +	seq_printf(seq,
> > +		   "guest driver load: %u\n"
> > +		   "data size: %lu\n",
> > +		   hisi_acc_vdev->vf_qm_state,
> > +		   sizeof(struct acc_vf_data));  
> 
> There was a suggestion to add a comment here to describe vf_qm_state better.
> May be something like,
> 
> vf_qm_state here indicates whether the Guest has loaded the driver for the ACC VF
> device or not.

I think the comment ended up at the declaration of vf_qm_state in the
header file:

> @@ -107,9 +114,17 @@ struct hisi_acc_vf_core_device {
>  	struct pci_dev *vf_dev;
>  	struct hisi_qm *pf_qm;
>  	struct hisi_qm vf_qm;
> +	/*
> +	 * Record whether a driver is added to the acc device in Guest OS.
> +	 * The value of QM_VF_STATE is set by the acc device driver.
> +	 * The migration driver queries through the QM_VF_STATE register.
> +	 */
>  	u32 vf_qm_state;
>  	int vf_id;
>  	struct hisi_acc_vf_migration_file *resuming_migf;
>  	struct hisi_acc_vf_migration_file *saving_migf;
> +
> +	/* An extra buffer for reporting migration data via debugfs */
> +	struct hisi_acc_vf_migration_file *debug_migf;
>  };
>  #endif /* HISI_ACC_VFIO_PCI_H */

Is that satisfactory?

> > +
> > +migf_err:
> > +	kfree(vf_data);
> > +mutex_release:
> > +	mutex_unlock(&hisi_acc_vdev->state_mutex);
> > +	mutex_unlock(&hisi_acc_vdev->open_mutex);
> > +
> > +	return ret;
> > +}
> > +
> > +static int hisi_acc_vf_migf_read(struct seq_file *seq, void *data)
> > +{
> > +	struct device *vf_dev = seq->private;
> > +	struct vfio_pci_core_device *core_device =
> > dev_get_drvdata(vf_dev);
> > +	struct vfio_device *vdev = &core_device->vdev;
> > +	struct hisi_acc_vf_core_device *hisi_acc_vdev =
> > hisi_acc_get_vf_dev(vdev);
> > +	size_t vf_data_sz = offsetofend(struct acc_vf_data, padding);
> > +	struct hisi_acc_vf_migration_file *debug_migf = hisi_acc_vdev-  
> > >debug_migf;  
> > +
> > +	/* Check whether the live migration operation has been performed
> > */
> > +	if (debug_migf->total_length < QM_MATCH_SIZE) {
> > +		seq_printf(seq, "device not migrated!\n");
> > +		return -EAGAIN;
> > +	}
> > +
> > +	seq_hex_dump(seq, "Mig Data:", DUMP_PREFIX_OFFSET, 16, 1,
> > +		     (const void *)&debug_migf->vf_data, vf_data_sz, false);
> > +	seq_printf(seq, "migrate data length: %lu\n", debug_migf-  
> > >total_length);  
> > +
> > +	return 0;
> > +}
> > +
> >  static int hisi_acc_vfio_pci_open_device(struct vfio_device *core_vdev)
> >  {
> >  	struct hisi_acc_vf_core_device *hisi_acc_vdev =
> > hisi_acc_get_vf_dev(core_vdev);
> > @@ -1305,12 +1443,16 @@ static int hisi_acc_vfio_pci_open_device(struct
> > vfio_device *core_vdev)
> >  		return ret;
> > 
> >  	if (core_vdev->mig_ops) {
> > +		mutex_lock(&hisi_acc_vdev->open_mutex);
> >  		ret = hisi_acc_vf_qm_init(hisi_acc_vdev);
> >  		if (ret) {
> > +			mutex_unlock(&hisi_acc_vdev->open_mutex);
> >  			vfio_pci_core_disable(vdev);
> >  			return ret;
> >  		}
> >  		hisi_acc_vdev->mig_state = VFIO_DEVICE_STATE_RUNNING;
> > +		hisi_acc_vdev->dev_opened = true;
> > +		mutex_unlock(&hisi_acc_vdev->open_mutex);
> >  	}
> > 
> >  	vfio_pci_core_finish_enable(vdev);
> > @@ -1322,7 +1464,10 @@ static void hisi_acc_vfio_pci_close_device(struct
> > vfio_device *core_vdev)
> >  	struct hisi_acc_vf_core_device *hisi_acc_vdev =
> > hisi_acc_get_vf_dev(core_vdev);
> >  	struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
> > 
> > +	mutex_lock(&hisi_acc_vdev->open_mutex);
> > +	hisi_acc_vdev->dev_opened = false;
> >  	iounmap(vf_qm->io_base);
> > +	mutex_unlock(&hisi_acc_vdev->open_mutex);
> >  	vfio_pci_core_close_device(core_vdev);
> >  }
> > 
> > @@ -1342,6 +1487,7 @@ static int hisi_acc_vfio_pci_migrn_init_dev(struct
> > vfio_device *core_vdev)
> >  	hisi_acc_vdev->pf_qm = pf_qm;
> >  	hisi_acc_vdev->vf_dev = pdev;
> >  	mutex_init(&hisi_acc_vdev->state_mutex);
> > +	mutex_init(&hisi_acc_vdev->open_mutex);
> > 
> >  	core_vdev->migration_flags = VFIO_MIGRATION_STOP_COPY |
> > VFIO_MIGRATION_PRE_COPY;
> >  	core_vdev->mig_ops = &hisi_acc_vfio_pci_migrn_state_ops;
> > @@ -1387,6 +1533,48 @@ static const struct vfio_device_ops
> > hisi_acc_vfio_pci_ops = {
> >  	.detach_ioas = vfio_iommufd_physical_detach_ioas,
> >  };
> > 
> > +static void hisi_acc_vfio_debug_init(struct hisi_acc_vf_core_device
> > *hisi_acc_vdev)
> > +{
> > +	struct vfio_device *vdev = &hisi_acc_vdev->core_device.vdev;
> > +	struct dentry *vfio_dev_migration = NULL;
> > +	struct dentry *vfio_hisi_acc = NULL;
> > +	struct device *dev = vdev->dev;
> > +	void *migf = NULL;
> > +
> > +	if (!debugfs_initialized() ||
> > +	    !IS_ENABLED(CONFIG_VFIO_DEBUGFS))
> > +		return;
> > +
> > +	if (vdev->ops != &hisi_acc_vfio_pci_migrn_ops)
> > +		return;
> > +
> > +	vfio_dev_migration = debugfs_lookup("migration", vdev-  
> > >debug_root);  
> > +	if (!vfio_dev_migration) {
> > +		dev_err(dev, "failed to lookup migration debugfs file!\n");
> > +		return;
> > +	}
> > +
> > +	migf = kzalloc(sizeof(struct hisi_acc_vf_migration_file),
> > GFP_KERNEL);

checkpatch --strict also advises this could be written as:

	migf = kzalloc(sizeof(*migf), GFP_KERNEL);

There's another one above with acc_vf_data.  I'd consider these
optional, but I think it is good practice and is more consistent with
existing allocations in this file.

> > +	if (!migf)
> > +		return;
> > +	hisi_acc_vdev->debug_migf = migf;
> > +
> > +	vfio_hisi_acc = debugfs_create_dir("hisi_acc", vfio_dev_migration);
> > +	debugfs_create_devm_seqfile(dev, "dev_data", vfio_hisi_acc,
> > +				    hisi_acc_vf_dev_read);
> > +	debugfs_create_devm_seqfile(dev, "migf_data", vfio_hisi_acc,
> > +				    hisi_acc_vf_migf_read);
> > +	debugfs_create_devm_seqfile(dev, "cmd_state", vfio_hisi_acc,
> > +				    hisi_acc_vf_debug_cmd);
> > +}
> > +
> > +static void hisi_acc_vf_debugfs_exit(struct hisi_acc_vf_core_device
> > *hisi_acc_vdev)
> > +{
> > +	/* If migrn_ops is not used, kfree(NULL) is valid */  
> 
> The above comment is not required. Please remove.

I don't have a problem with it, but I'll let the two of you decide as
co-owners of the file.  Thanks,

Alex


> > +	kfree(hisi_acc_vdev->debug_migf);
> > +	hisi_acc_vdev->debug_migf = NULL;
> > +}
> > +  
>
Re: [PATCH v12 3/4] hisi_acc_vfio_pci: register debugfs for hisilicon migration driver
Posted by liulongfang 1 year, 3 months ago
On 2024/11/6 2:21, Alex Williamson wrote:
> On Tue, 5 Nov 2024 08:55:51 +0000
> Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com> wrote:
> 
>>> -----Original Message-----
>>> From: liulongfang <liulongfang@huawei.com>
>>> Sent: Tuesday, November 5, 2024 3:53 AM
>>> To: alex.williamson@redhat.com; jgg@nvidia.com; Shameerali Kolothum
>>> Thodi <shameerali.kolothum.thodi@huawei.com>; Jonathan Cameron
>>> <jonathan.cameron@huawei.com>
>>> Cc: kvm@vger.kernel.org; linux-kernel@vger.kernel.org;
>>> linuxarm@openeuler.org; liulongfang <liulongfang@huawei.com>
>>> Subject: [PATCH v12 3/4] hisi_acc_vfio_pci: register debugfs for hisilicon
>>> migration driver  
>>
>> Hi,
>>
>> Few minor comments below. Please don't re-spin just for these yet.
>> Please wait for others to review as well.
>>
>> Thanks,
>> Shameer
>>
>>> diff --git a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
>>> b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
>>> index a8c53952d82e..7728c9745b9d 100644
>>> --- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
>>> +++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
>>> @@ -627,15 +627,30 @@ static void hisi_acc_vf_disable_fd(struct
>>> hisi_acc_vf_migration_file *migf)
>>>  	mutex_unlock(&migf->lock);
>>>  }
>>>
>>> +static void hisi_acc_debug_migf_copy(struct hisi_acc_vf_core_device
>>> *hisi_acc_vdev,
>>> +	struct hisi_acc_vf_migration_file *src_migf)  
>>
>> Alignment should match open parenthesis here.
> 
> I might also shorten the first line to 80 chars by putting "static" or
> "static void" on a line by itself, but we're getting into personal
> preference at that point and this driver already has lines exceeding 80
> columns.
>

Okay, I put static void on a separate line,
and the following two are aligned.

>>> +{
>>> +	struct hisi_acc_vf_migration_file *dst_migf = hisi_acc_vdev-  
>>>> debug_migf;  
>>> +
>>> +	if (!dst_migf)
>>> +		return;
>>> +
>>> +	dst_migf->total_length = src_migf->total_length;
>>> +	memcpy(&dst_migf->vf_data, &src_migf->vf_data,
>>> +		sizeof(struct acc_vf_data));  
>>
>> Here too, alignment not correct. It is better to run,
>> ./scripts/checkpatch --strict on these patches if you haven't done already.
> 
> Yup.  Only those two were missed as far as I see, but checkpatch does
> warn several places where we should use seq_puts() rather than
> seq_printf() for cases of printing a constant format without additional
> arguments.  For example "device not opened!\n" is the first one below
> but there are others.
>

OK!
I will use "./scripts/checkpatch --strict" to handle it,
and replace seq_printf() with seq_puts()

>>> +}
>>> +
>>>  static void hisi_acc_vf_disable_fds(struct hisi_acc_vf_core_device
>>> *hisi_acc_vdev)
>>>  {
>>>  	if (hisi_acc_vdev->resuming_migf) {
>>> +		hisi_acc_debug_migf_copy(hisi_acc_vdev, hisi_acc_vdev-  
>>>> resuming_migf);  
>>>  		hisi_acc_vf_disable_fd(hisi_acc_vdev->resuming_migf);
>>>  		fput(hisi_acc_vdev->resuming_migf->filp);
>>>  		hisi_acc_vdev->resuming_migf = NULL;
>>>  	}
>>>
>>>  	if (hisi_acc_vdev->saving_migf) {
>>> +		hisi_acc_debug_migf_copy(hisi_acc_vdev, hisi_acc_vdev-  
>>>> saving_migf);  
>>>  		hisi_acc_vf_disable_fd(hisi_acc_vdev->saving_migf);
>>>  		fput(hisi_acc_vdev->saving_migf->filp);
>>>  		hisi_acc_vdev->saving_migf = NULL;
>>> @@ -1294,6 +1309,129 @@ static long hisi_acc_vfio_pci_ioctl(struct
>>> vfio_device *core_vdev, unsigned int
>>>  	return vfio_pci_core_ioctl(core_vdev, cmd, arg);
>>>  }
>>>
>>> +static int hisi_acc_vf_debug_check(struct seq_file *seq, struct vfio_device
>>> *vdev)
>>> +{
>>> +	struct hisi_acc_vf_core_device *hisi_acc_vdev =
>>> hisi_acc_get_vf_dev(vdev);
>>> +	struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
>>> +	int ret;
>>> +
>>> +	lockdep_assert_held(&hisi_acc_vdev->open_mutex);
>>> +	/*
>>> +	 * When the device is not opened, the io_base is not mapped.
>>> +	 * The driver cannot perform device read and write operations.
>>> +	 */
>>> +	if (!hisi_acc_vdev->dev_opened) {
>>> +		seq_printf(seq, "device not opened!\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>> +	ret = qm_wait_dev_not_ready(vf_qm);
>>> +	if (ret) {
>>> +		seq_printf(seq, "VF device not ready!\n");
>>> +		return -EBUSY;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int hisi_acc_vf_debug_cmd(struct seq_file *seq, void *data)
>>> +{
>>> +	struct device *vf_dev = seq->private;
>>> +	struct vfio_pci_core_device *core_device =
>>> dev_get_drvdata(vf_dev);
>>> +	struct vfio_device *vdev = &core_device->vdev;
>>> +	struct hisi_acc_vf_core_device *hisi_acc_vdev =
>>> hisi_acc_get_vf_dev(vdev);
>>> +	struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
>>> +	u64 value;
>>> +	int ret;
>>> +
>>> +	mutex_lock(&hisi_acc_vdev->open_mutex);
>>> +	ret = hisi_acc_vf_debug_check(seq, vdev);
>>> +	if (ret) {
>>> +		mutex_unlock(&hisi_acc_vdev->open_mutex);
>>> +		return ret;
>>> +	}
>>> +
>>> +	value = readl(vf_qm->io_base + QM_MB_CMD_SEND_BASE);
>>> +	if (value == QM_MB_CMD_NOT_READY) {
>>> +		mutex_unlock(&hisi_acc_vdev->open_mutex);
>>> +		seq_printf(seq, "mailbox cmd channel not ready!\n");
>>> +		return -EINVAL;
>>> +	}
>>> +	mutex_unlock(&hisi_acc_vdev->open_mutex);
>>> +	seq_printf(seq, "mailbox cmd channel ready!\n");
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int hisi_acc_vf_dev_read(struct seq_file *seq, void *data)
>>> +{
>>> +	struct device *vf_dev = seq->private;
>>> +	struct vfio_pci_core_device *core_device =
>>> dev_get_drvdata(vf_dev);
>>> +	struct vfio_device *vdev = &core_device->vdev;
>>> +	struct hisi_acc_vf_core_device *hisi_acc_vdev =
>>> hisi_acc_get_vf_dev(vdev);
>>> +	size_t vf_data_sz = offsetofend(struct acc_vf_data, padding);
>>> +	struct acc_vf_data *vf_data;
>>> +	int ret;
>>> +
>>> +	mutex_lock(&hisi_acc_vdev->open_mutex);
>>> +	ret = hisi_acc_vf_debug_check(seq, vdev);
>>> +	if (ret) {
>>> +		mutex_unlock(&hisi_acc_vdev->open_mutex);
>>> +		return ret;
>>> +	}
>>> +
>>> +	mutex_lock(&hisi_acc_vdev->state_mutex);
>>> +	vf_data = kzalloc(sizeof(struct acc_vf_data), GFP_KERNEL);
>>> +	if (!vf_data) {
>>> +		ret = -ENOMEM;
>>> +		goto mutex_release;
>>> +	}
>>> +
>>> +	vf_data->vf_qm_state = hisi_acc_vdev->vf_qm_state;
>>> +	ret = vf_qm_read_data(&hisi_acc_vdev->vf_qm, vf_data);
>>> +	if (ret)
>>> +		goto migf_err;
>>> +
>>> +	seq_hex_dump(seq, "Dev Data:", DUMP_PREFIX_OFFSET, 16, 1,
>>> +		     (const void *)vf_data, vf_data_sz, false);
>>> +
>>> +	seq_printf(seq,
>>> +		   "guest driver load: %u\n"
>>> +		   "data size: %lu\n",
>>> +		   hisi_acc_vdev->vf_qm_state,
>>> +		   sizeof(struct acc_vf_data));  
>>
>> There was a suggestion to add a comment here to describe vf_qm_state better.
>> May be something like,
>>
>> vf_qm_state here indicates whether the Guest has loaded the driver for the ACC VF
>> device or not.
> 
> I think the comment ended up at the declaration of vf_qm_state in the
> header file:
>>> @@ -107,9 +114,17 @@ struct hisi_acc_vf_core_device {
>>  	struct pci_dev *vf_dev;
>>  	struct hisi_qm *pf_qm;
>>  	struct hisi_qm vf_qm;
>> +	/*
>> +	 * Record whether a driver is added to the acc device in Guest OS.
>> +	 * The value of QM_VF_STATE is set by the acc device driver.
>> +	 * The migration driver queries through the QM_VF_STATE register.
>> +	 */
>>  	u32 vf_qm_state;
>>  	int vf_id;
>>  	struct hisi_acc_vf_migration_file *resuming_migf;
>>  	struct hisi_acc_vf_migration_file *saving_migf;
>> +
>> +	/* An extra buffer for reporting migration data via debugfs */
>> +	struct hisi_acc_vf_migration_file *debug_migf;
>>  };
>>  #endif /* HISI_ACC_VFIO_PCI_H */
> 
> Is that satisfactory?
>
Okay, I'll update the comment.

>>> +
>>> +migf_err:
>>> +	kfree(vf_data);
>>> +mutex_release:
>>> +	mutex_unlock(&hisi_acc_vdev->state_mutex);
>>> +	mutex_unlock(&hisi_acc_vdev->open_mutex);
>>> +
>>> +	return ret;
>>> +}
>>> +
>>> +static int hisi_acc_vf_migf_read(struct seq_file *seq, void *data)
>>> +{
>>> +	struct device *vf_dev = seq->private;
>>> +	struct vfio_pci_core_device *core_device =
>>> dev_get_drvdata(vf_dev);
>>> +	struct vfio_device *vdev = &core_device->vdev;
>>> +	struct hisi_acc_vf_core_device *hisi_acc_vdev =
>>> hisi_acc_get_vf_dev(vdev);
>>> +	size_t vf_data_sz = offsetofend(struct acc_vf_data, padding);
>>> +	struct hisi_acc_vf_migration_file *debug_migf = hisi_acc_vdev-  
>>>> debug_migf;  
>>> +
>>> +	/* Check whether the live migration operation has been performed
>>> */
>>> +	if (debug_migf->total_length < QM_MATCH_SIZE) {
>>> +		seq_printf(seq, "device not migrated!\n");
>>> +		return -EAGAIN;
>>> +	}
>>> +
>>> +	seq_hex_dump(seq, "Mig Data:", DUMP_PREFIX_OFFSET, 16, 1,
>>> +		     (const void *)&debug_migf->vf_data, vf_data_sz, false);
>>> +	seq_printf(seq, "migrate data length: %lu\n", debug_migf-  
>>>> total_length);  
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>  static int hisi_acc_vfio_pci_open_device(struct vfio_device *core_vdev)
>>>  {
>>>  	struct hisi_acc_vf_core_device *hisi_acc_vdev =
>>> hisi_acc_get_vf_dev(core_vdev);
>>> @@ -1305,12 +1443,16 @@ static int hisi_acc_vfio_pci_open_device(struct
>>> vfio_device *core_vdev)
>>>  		return ret;
>>>
>>>  	if (core_vdev->mig_ops) {
>>> +		mutex_lock(&hisi_acc_vdev->open_mutex);
>>>  		ret = hisi_acc_vf_qm_init(hisi_acc_vdev);
>>>  		if (ret) {
>>> +			mutex_unlock(&hisi_acc_vdev->open_mutex);
>>>  			vfio_pci_core_disable(vdev);
>>>  			return ret;
>>>  		}
>>>  		hisi_acc_vdev->mig_state = VFIO_DEVICE_STATE_RUNNING;
>>> +		hisi_acc_vdev->dev_opened = true;
>>> +		mutex_unlock(&hisi_acc_vdev->open_mutex);
>>>  	}
>>>
>>>  	vfio_pci_core_finish_enable(vdev);
>>> @@ -1322,7 +1464,10 @@ static void hisi_acc_vfio_pci_close_device(struct
>>> vfio_device *core_vdev)
>>>  	struct hisi_acc_vf_core_device *hisi_acc_vdev =
>>> hisi_acc_get_vf_dev(core_vdev);
>>>  	struct hisi_qm *vf_qm = &hisi_acc_vdev->vf_qm;
>>>
>>> +	mutex_lock(&hisi_acc_vdev->open_mutex);
>>> +	hisi_acc_vdev->dev_opened = false;
>>>  	iounmap(vf_qm->io_base);
>>> +	mutex_unlock(&hisi_acc_vdev->open_mutex);
>>>  	vfio_pci_core_close_device(core_vdev);
>>>  }
>>>
>>> @@ -1342,6 +1487,7 @@ static int hisi_acc_vfio_pci_migrn_init_dev(struct
>>> vfio_device *core_vdev)
>>>  	hisi_acc_vdev->pf_qm = pf_qm;
>>>  	hisi_acc_vdev->vf_dev = pdev;
>>>  	mutex_init(&hisi_acc_vdev->state_mutex);
>>> +	mutex_init(&hisi_acc_vdev->open_mutex);
>>>
>>>  	core_vdev->migration_flags = VFIO_MIGRATION_STOP_COPY |
>>> VFIO_MIGRATION_PRE_COPY;
>>>  	core_vdev->mig_ops = &hisi_acc_vfio_pci_migrn_state_ops;
>>> @@ -1387,6 +1533,48 @@ static const struct vfio_device_ops
>>> hisi_acc_vfio_pci_ops = {
>>>  	.detach_ioas = vfio_iommufd_physical_detach_ioas,
>>>  };
>>>
>>> +static void hisi_acc_vfio_debug_init(struct hisi_acc_vf_core_device
>>> *hisi_acc_vdev)
>>> +{
>>> +	struct vfio_device *vdev = &hisi_acc_vdev->core_device.vdev;
>>> +	struct dentry *vfio_dev_migration = NULL;
>>> +	struct dentry *vfio_hisi_acc = NULL;
>>> +	struct device *dev = vdev->dev;
>>> +	void *migf = NULL;
>>> +
>>> +	if (!debugfs_initialized() ||
>>> +	    !IS_ENABLED(CONFIG_VFIO_DEBUGFS))
>>> +		return;
>>> +
>>> +	if (vdev->ops != &hisi_acc_vfio_pci_migrn_ops)
>>> +		return;
>>> +
>>> +	vfio_dev_migration = debugfs_lookup("migration", vdev-  
>>>> debug_root);  
>>> +	if (!vfio_dev_migration) {
>>> +		dev_err(dev, "failed to lookup migration debugfs file!\n");
>>> +		return;
>>> +	}
>>> +
>>> +	migf = kzalloc(sizeof(struct hisi_acc_vf_migration_file),
>>> GFP_KERNEL);
> 
> checkpatch --strict also advises this could be written as:
> 
> 	migf = kzalloc(sizeof(*migf), GFP_KERNEL);
> 
> There's another one above with acc_vf_data.  I'd consider these
> optional, but I think it is good practice and is more consistent with
> existing allocations in this file.
>

OK, I will modify the two "kzalloc" together.

>>> +	if (!migf)
>>> +		return;
>>> +	hisi_acc_vdev->debug_migf = migf;
>>> +
>>> +	vfio_hisi_acc = debugfs_create_dir("hisi_acc", vfio_dev_migration);
>>> +	debugfs_create_devm_seqfile(dev, "dev_data", vfio_hisi_acc,
>>> +				    hisi_acc_vf_dev_read);
>>> +	debugfs_create_devm_seqfile(dev, "migf_data", vfio_hisi_acc,
>>> +				    hisi_acc_vf_migf_read);
>>> +	debugfs_create_devm_seqfile(dev, "cmd_state", vfio_hisi_acc,
>>> +				    hisi_acc_vf_debug_cmd);
>>> +}
>>> +
>>> +static void hisi_acc_vf_debugfs_exit(struct hisi_acc_vf_core_device
>>> *hisi_acc_vdev)
>>> +{
>>> +	/* If migrn_ops is not used, kfree(NULL) is valid */  
>>
>> The above comment is not required. Please remove.
> 
> I don't have a problem with it, but I'll let the two of you decide as
> co-owners of the file.  Thanks,
> 
> Alex
>

OK, I'll delete it.

Thanks.
Longfang.

> 
>>> +	kfree(hisi_acc_vdev->debug_migf);
>>> +	hisi_acc_vdev->debug_migf = NULL;
>>> +}
>>> +  
>>
> 
> 
> .
>