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
This commit is contained in:
Коммит
f8a665b159
|
@ -228,6 +228,19 @@ int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev, pci_power_t stat
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
/* D3 might be unsupported via quirk, skip unless in D3 */
|
/* D3 might be unsupported via quirk, skip unless in D3 */
|
||||||
if (needs_save && pdev->current_state >= PCI_D3hot) {
|
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);
|
vdev->pm_save = pci_store_saved_state(pdev);
|
||||||
} else if (needs_restore) {
|
} else if (needs_restore) {
|
||||||
pci_load_and_free_saved_state(pdev, &vdev->pm_save);
|
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 */
|
/* For needs_reset */
|
||||||
lockdep_assert_held(&vdev->vdev.dev_set->lock);
|
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 */
|
/* Stop the device from further DMA */
|
||||||
pci_clear_master(pdev);
|
pci_clear_master(pdev);
|
||||||
|
|
||||||
|
@ -921,6 +945,19 @@ long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
vfio_pci_zap_and_down_write_memory_lock(vdev);
|
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);
|
ret = pci_try_reset_function(vdev->pdev);
|
||||||
up_write(&vdev->memory_lock);
|
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;
|
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);
|
ret = pci_reset_bus(pdev);
|
||||||
|
|
||||||
err_undo:
|
err_undo:
|
||||||
|
@ -2089,6 +2138,18 @@ static bool vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set)
|
||||||
if (!pdev)
|
if (!pdev)
|
||||||
return false;
|
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);
|
ret = pci_reset_bus(pdev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -288,6 +288,7 @@ out:
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFIO_PCI_VGA
|
||||||
ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
|
ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
|
||||||
size_t count, loff_t *ppos, bool iswrite)
|
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;
|
return done;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void vfio_pci_ioeventfd_do_write(struct vfio_pci_ioeventfd *ioeventfd,
|
static void vfio_pci_ioeventfd_do_write(struct vfio_pci_ioeventfd *ioeventfd,
|
||||||
bool test_mem)
|
bool test_mem)
|
||||||
|
|
|
@ -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,
|
extern ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
|
||||||
size_t count, loff_t *ppos, bool iswrite);
|
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,
|
extern ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
|
||||||
size_t count, loff_t *ppos, bool iswrite);
|
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,
|
extern long vfio_pci_ioeventfd(struct vfio_pci_core_device *vdev, loff_t offset,
|
||||||
uint64_t data, int count, int fd);
|
uint64_t data, int count, int fd);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче