Commit f8a665b1 authored by Alex Williamson's avatar Alex Williamson
Browse files

Merge branches 'v5.18/vfio/next/mlx5-migration-v10',...

Merge branches 'v5.18/vfio/next/mlx5-migration-v10', 'v5.18/vfio/next/pm-fixes' and 'v5.18/vfio/next/uml-build-fix' into v5.18/vfio/next/next
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
@@ -228,6 +228,19 @@ int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev, pci_power_t stat
	if (!ret) {
		/* D3 might be unsupported via quirk, skip unless in D3 */
		if (needs_save && pdev->current_state >= PCI_D3hot) {
			/*
			 * The current PCI state will be saved locally in
			 * 'pm_save' during the D3hot transition. When the
			 * device state is changed to D0 again with the current
			 * function, then pci_store_saved_state() will restore
			 * the state and will free the memory pointed by
			 * 'pm_save'. There are few cases where the PCI power
			 * state can be changed to D0 without the involvement
			 * of the driver. For these cases, free the earlier
			 * allocated memory first before overwriting 'pm_save'
			 * to prevent the memory leak.
			 */
			kfree(vdev->pm_save);
			vdev->pm_save = pci_store_saved_state(pdev);
		} else if (needs_restore) {
			pci_load_and_free_saved_state(pdev, &vdev->pm_save);
@@ -322,6 +335,17 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
	/* For needs_reset */
	lockdep_assert_held(&vdev->vdev.dev_set->lock);

	/*
	 * This function can be invoked while the power state is non-D0.
	 * This function calls __pci_reset_function_locked() which internally
	 * can use pci_pm_reset() for the function reset. pci_pm_reset() will
	 * fail if the power state is non-D0. Also, for the devices which
	 * have NoSoftRst-, the reset function can cause the PCI config space
	 * reset without restoring the original state (saved locally in
	 * 'vdev->pm_save').
	 */
	vfio_pci_set_power_state(vdev, PCI_D0);

	/* Stop the device from further DMA */
	pci_clear_master(pdev);

@@ -921,6 +945,19 @@ long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
			return -EINVAL;

		vfio_pci_zap_and_down_write_memory_lock(vdev);

		/*
		 * This function can be invoked while the power state is non-D0.
		 * If pci_try_reset_function() has been called while the power
		 * state is non-D0, then pci_try_reset_function() will
		 * internally set the power state to D0 without vfio driver
		 * involvement. For the devices which have NoSoftRst-, the
		 * reset function can cause the PCI config space reset without
		 * restoring the original state (saved locally in
		 * 'vdev->pm_save').
		 */
		vfio_pci_set_power_state(vdev, PCI_D0);

		ret = pci_try_reset_function(vdev->pdev);
		up_write(&vdev->memory_lock);

@@ -2036,6 +2073,18 @@ static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set,
	}
	cur_mem = NULL;

	/*
	 * The pci_reset_bus() will reset all the devices in the bus.
	 * The power state can be non-D0 for some of the devices in the bus.
	 * For these devices, the pci_reset_bus() will internally set
	 * the power state to D0 without vfio driver involvement.
	 * For the devices which have NoSoftRst-, the reset function can
	 * cause the PCI config space reset without restoring the original
	 * state (saved locally in 'vdev->pm_save').
	 */
	list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list)
		vfio_pci_set_power_state(cur, PCI_D0);

	ret = pci_reset_bus(pdev);

err_undo:
@@ -2089,6 +2138,18 @@ static bool vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set)
	if (!pdev)
		return false;

	/*
	 * The pci_reset_bus() will reset all the devices in the bus.
	 * The power state can be non-D0 for some of the devices in the bus.
	 * For these devices, the pci_reset_bus() will internally set
	 * the power state to D0 without vfio driver involvement.
	 * For the devices which have NoSoftRst-, the reset function can
	 * cause the PCI config space reset without restoring the original
	 * state (saved locally in 'vdev->pm_save').
	 */
	list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list)
		vfio_pci_set_power_state(cur, PCI_D0);

	ret = pci_reset_bus(pdev);
	if (ret)
		return false;
+2 −0
Original line number Diff line number Diff line
@@ -288,6 +288,7 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
	return done;
}

#ifdef CONFIG_VFIO_PCI_VGA
ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
			       size_t count, loff_t *ppos, bool iswrite)
{
@@ -355,6 +356,7 @@ ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,

	return done;
}
#endif

static void vfio_pci_ioeventfd_do_write(struct vfio_pci_ioeventfd *ioeventfd,
					bool test_mem)
+9 −0
Original line number Diff line number Diff line
@@ -159,8 +159,17 @@ extern ssize_t vfio_pci_config_rw(struct vfio_pci_core_device *vdev,
extern ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
			       size_t count, loff_t *ppos, bool iswrite);

#ifdef CONFIG_VFIO_PCI_VGA
extern ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
			       size_t count, loff_t *ppos, bool iswrite);
#else
static inline ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev,
				      char __user *buf, size_t count,
				      loff_t *ppos, bool iswrite)
{
	return -EINVAL;
}
#endif

extern long vfio_pci_ioeventfd(struct vfio_pci_core_device *vdev, loff_t offset,
			       uint64_t data, int count, int fd);