Skip to content

Commit

Permalink
Merge tag 'vfio-v5.1-rc1' of git://github.com/awilliam/linux-vfio
Browse files Browse the repository at this point in the history
Pull VFIO updates from Alex Williamson:

 - Switch mdev to generic UUID API (Andy Shevchenko)

 - Fixup platform reset include paths (Masahiro Yamada)

 - Fix usage of MINORMASK (Chengguang Xu)

 - Remove noise from duplicate spapr table unsets (Alexey Kardashevskiy)

 - Restore device state after PM reset (Alex Williamson)

 - Ensure memory translation enabled for PCI ROM access (Eric Auger)

* tag 'vfio-v5.1-rc1' of git://github.com/awilliam/linux-vfio:
  vfio_pci: Enable memory accesses before calling pci_map_rom
  vfio/pci: Restore device state on PM transition
  vfio/spapr_tce: Skip unsetting already unset table
  samples/vfio-mdev/mtty: expand minor range when registering chrdev region
  samples/vfio-mdev/mdpy: expand minor range when registering chrdev region
  samples/vfio-mdev/mbochs: expand minor range when registering chrdev region
  vfio: expand minor range when registering chrdev region
  vfio: platform: reset: fix up include directives to remove ccflags-y
  vfio-mdev: Switch to use new generic UUID API
  • Loading branch information
torvalds committed Mar 5, 2019
2 parents ee5e001 + 0cfd027 commit a83b042
Show file tree
Hide file tree
Showing 16 changed files with 125 additions and 54 deletions.
16 changes: 8 additions & 8 deletions drivers/vfio/mdev/mdev_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ struct mdev_device *mdev_from_dev(struct device *dev)
}
EXPORT_SYMBOL(mdev_from_dev);

uuid_le mdev_uuid(struct mdev_device *mdev)
const guid_t *mdev_uuid(struct mdev_device *mdev)
{
return mdev->uuid;
return &mdev->uuid;
}
EXPORT_SYMBOL(mdev_uuid);

Expand All @@ -88,8 +88,7 @@ static void mdev_release_parent(struct kref *kref)
put_device(dev);
}

static
inline struct mdev_parent *mdev_get_parent(struct mdev_parent *parent)
static inline struct mdev_parent *mdev_get_parent(struct mdev_parent *parent)
{
if (parent)
kref_get(&parent->ref);
Expand Down Expand Up @@ -276,7 +275,8 @@ static void mdev_device_release(struct device *dev)
kfree(mdev);
}

int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
int mdev_device_create(struct kobject *kobj,
struct device *dev, const guid_t *uuid)
{
int ret;
struct mdev_device *mdev, *tmp;
Expand All @@ -291,7 +291,7 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)

/* Check for duplicate */
list_for_each_entry(tmp, &mdev_list, next) {
if (!uuid_le_cmp(tmp->uuid, uuid)) {
if (guid_equal(&tmp->uuid, uuid)) {
mutex_unlock(&mdev_list_lock);
ret = -EEXIST;
goto mdev_fail;
Expand All @@ -305,7 +305,7 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
goto mdev_fail;
}

memcpy(&mdev->uuid, &uuid, sizeof(uuid_le));
guid_copy(&mdev->uuid, uuid);
list_add(&mdev->next, &mdev_list);
mutex_unlock(&mdev_list_lock);

Expand All @@ -315,7 +315,7 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
mdev->dev.parent = dev;
mdev->dev.bus = &mdev_bus_type;
mdev->dev.release = mdev_device_release;
dev_set_name(&mdev->dev, "%pUl", uuid.b);
dev_set_name(&mdev->dev, "%pUl", uuid);

ret = device_register(&mdev->dev);
if (ret) {
Expand Down
5 changes: 3 additions & 2 deletions drivers/vfio/mdev/mdev_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ struct mdev_parent {
struct mdev_device {
struct device dev;
struct mdev_parent *parent;
uuid_le uuid;
guid_t uuid;
void *driver_data;
struct kref ref;
struct list_head next;
Expand Down Expand Up @@ -58,7 +58,8 @@ void parent_remove_sysfs_files(struct mdev_parent *parent);
int mdev_create_sysfs_files(struct device *dev, struct mdev_type *type);
void mdev_remove_sysfs_files(struct device *dev, struct mdev_type *type);

int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid);
int mdev_device_create(struct kobject *kobj,
struct device *dev, const guid_t *uuid);
int mdev_device_remove(struct device *dev, bool force_remove);

#endif /* MDEV_PRIVATE_H */
6 changes: 3 additions & 3 deletions drivers/vfio/mdev/mdev_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static ssize_t create_store(struct kobject *kobj, struct device *dev,
const char *buf, size_t count)
{
char *str;
uuid_le uuid;
guid_t uuid;
int ret;

if ((count < UUID_STRING_LEN) || (count > UUID_STRING_LEN + 1))
Expand All @@ -65,12 +65,12 @@ static ssize_t create_store(struct kobject *kobj, struct device *dev,
if (!str)
return -ENOMEM;

ret = uuid_le_to_bin(str, &uuid);
ret = guid_parse(str, &uuid);
kfree(str);
if (ret)
return ret;

ret = mdev_device_create(kobj, dev, uuid);
ret = mdev_device_create(kobj, dev, &uuid);
if (ret)
return ret;

Expand Down
90 changes: 77 additions & 13 deletions drivers/vfio/pci/vfio_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,14 +209,65 @@ static bool vfio_pci_nointx(struct pci_dev *pdev)
return false;
}

static void vfio_pci_probe_power_state(struct vfio_pci_device *vdev)
{
struct pci_dev *pdev = vdev->pdev;
u16 pmcsr;

if (!pdev->pm_cap)
return;

pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmcsr);

vdev->needs_pm_restore = !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET);
}

/*
* pci_set_power_state() wrapper handling devices which perform a soft reset on
* D3->D0 transition. Save state prior to D0/1/2->D3, stash it on the vdev,
* restore when returned to D0. Saved separately from pci_saved_state for use
* by PM capability emulation and separately from pci_dev internal saved state
* to avoid it being overwritten and consumed around other resets.
*/
int vfio_pci_set_power_state(struct vfio_pci_device *vdev, pci_power_t state)
{
struct pci_dev *pdev = vdev->pdev;
bool needs_restore = false, needs_save = false;
int ret;

if (vdev->needs_pm_restore) {
if (pdev->current_state < PCI_D3hot && state >= PCI_D3hot) {
pci_save_state(pdev);
needs_save = true;
}

if (pdev->current_state >= PCI_D3hot && state <= PCI_D0)
needs_restore = true;
}

ret = pci_set_power_state(pdev, state);

if (!ret) {
/* D3 might be unsupported via quirk, skip unless in D3 */
if (needs_save && pdev->current_state >= PCI_D3hot) {
vdev->pm_save = pci_store_saved_state(pdev);
} else if (needs_restore) {
pci_load_and_free_saved_state(pdev, &vdev->pm_save);
pci_restore_state(pdev);
}
}

return ret;
}

static int vfio_pci_enable(struct vfio_pci_device *vdev)
{
struct pci_dev *pdev = vdev->pdev;
int ret;
u16 cmd;
u8 msix_pos;

pci_set_power_state(pdev, PCI_D0);
vfio_pci_set_power_state(vdev, PCI_D0);

/* Don't allow our initial saved state to include busmaster */
pci_clear_master(pdev);
Expand Down Expand Up @@ -407,7 +458,7 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
vfio_pci_try_bus_reset(vdev);

if (!disable_idle_d3)
pci_set_power_state(pdev, PCI_D3hot);
vfio_pci_set_power_state(vdev, PCI_D3hot);
}

static void vfio_pci_release(void *device_data)
Expand Down Expand Up @@ -708,6 +759,7 @@ static long vfio_pci_ioctl(void *device_data,
{
void __iomem *io;
size_t size;
u16 orig_cmd;

info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
info.flags = 0;
Expand All @@ -723,15 +775,23 @@ static long vfio_pci_ioctl(void *device_data,
break;
}

/* Is it really there? */
/*
* Is it really there? Enable memory decode for
* implicit access in pci_map_rom().
*/
pci_read_config_word(pdev, PCI_COMMAND, &orig_cmd);
pci_write_config_word(pdev, PCI_COMMAND,
orig_cmd | PCI_COMMAND_MEMORY);

io = pci_map_rom(pdev, &size);
if (!io || !size) {
if (io) {
info.flags = VFIO_REGION_INFO_FLAG_READ;
pci_unmap_rom(pdev, io);
} else {
info.size = 0;
break;
}
pci_unmap_rom(pdev, io);

info.flags = VFIO_REGION_INFO_FLAG_READ;
pci_write_config_word(pdev, PCI_COMMAND, orig_cmd);
break;
}
case VFIO_PCI_VGA_REGION_INDEX:
Expand Down Expand Up @@ -1286,6 +1346,8 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
vfio_pci_set_vga_decode(vdev, false));
}

vfio_pci_probe_power_state(vdev);

if (!disable_idle_d3) {
/*
* pci-core sets the device power state to an unknown value at
Expand All @@ -1296,8 +1358,8 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* be able to get to D3. Therefore first do a D0 transition
* before going to D3.
*/
pci_set_power_state(pdev, PCI_D0);
pci_set_power_state(pdev, PCI_D3hot);
vfio_pci_set_power_state(vdev, PCI_D0);
vfio_pci_set_power_state(vdev, PCI_D3hot);
}

return ret;
Expand All @@ -1316,6 +1378,11 @@ static void vfio_pci_remove(struct pci_dev *pdev)
vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev);
kfree(vdev->region);
mutex_destroy(&vdev->ioeventfds_lock);

if (!disable_idle_d3)
vfio_pci_set_power_state(vdev, PCI_D0);

kfree(vdev->pm_save);
kfree(vdev);

if (vfio_pci_is_vga(pdev)) {
Expand All @@ -1324,9 +1391,6 @@ static void vfio_pci_remove(struct pci_dev *pdev)
VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM |
VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM);
}

if (!disable_idle_d3)
pci_set_power_state(pdev, PCI_D0);
}

static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev,
Expand Down Expand Up @@ -1551,7 +1615,7 @@ static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev)
tmp->needs_reset = false;

if (tmp != vdev && !disable_idle_d3)
pci_set_power_state(tmp->pdev, PCI_D3hot);
vfio_pci_set_power_state(tmp, PCI_D3hot);
}

vfio_device_put(devs.devices[i]);
Expand Down
2 changes: 1 addition & 1 deletion drivers/vfio/pci/vfio_pci_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,7 @@ static int vfio_pm_config_write(struct vfio_pci_device *vdev, int pos,
break;
}

pci_set_power_state(vdev->pdev, state);
vfio_pci_set_power_state(vdev, state);
}

return count;
Expand Down
6 changes: 6 additions & 0 deletions drivers/vfio/pci/vfio_pci_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ struct vfio_pci_device {
bool has_vga;
bool needs_reset;
bool nointx;
bool needs_pm_restore;
struct pci_saved_state *pci_saved_state;
struct pci_saved_state *pm_save;
struct vfio_pci_reflck *reflck;
int refcnt;
int ioeventfds_nr;
Expand Down Expand Up @@ -161,6 +163,10 @@ extern int vfio_pci_register_dev_region(struct vfio_pci_device *vdev,
unsigned int type, unsigned int subtype,
const struct vfio_pci_regops *ops,
size_t size, u32 flags, void *data);

extern int vfio_pci_set_power_state(struct vfio_pci_device *vdev,
pci_power_t state);

#ifdef CONFIG_VFIO_PCI_IGD
extern int vfio_pci_igd_init(struct vfio_pci_device *vdev);
#else
Expand Down
2 changes: 0 additions & 2 deletions drivers/vfio/platform/reset/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
vfio-platform-calxedaxgmac-y := vfio_platform_calxedaxgmac.o
vfio-platform-amdxgbe-y := vfio_platform_amdxgbe.o

ccflags-y += -Idrivers/vfio/platform

obj-$(CONFIG_VFIO_PLATFORM_CALXEDAXGMAC_RESET) += vfio-platform-calxedaxgmac.o
obj-$(CONFIG_VFIO_PLATFORM_AMDXGBE_RESET) += vfio-platform-amdxgbe.o
obj-$(CONFIG_VFIO_PLATFORM_BCMFLEXRM_RESET) += vfio_platform_bcmflexrm.o
2 changes: 1 addition & 1 deletion drivers/vfio/platform/reset/vfio_platform_amdxgbe.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include <uapi/linux/mdio.h>
#include <linux/delay.h>

#include "vfio_platform_private.h"
#include "../vfio_platform_private.h"

#define DMA_MR 0x3000
#define MAC_VR 0x0110
Expand Down
2 changes: 1 addition & 1 deletion drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include <linux/kernel.h>
#include <linux/module.h>

#include "vfio_platform_private.h"
#include "../vfio_platform_private.h"

/* FlexRM configuration */
#define RING_REGS_SIZE 0x10000
Expand Down
2 changes: 1 addition & 1 deletion drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include <linux/init.h>
#include <linux/io.h>

#include "vfio_platform_private.h"
#include "../vfio_platform_private.h"

#define DRIVER_VERSION "0.1"
#define DRIVER_AUTHOR "Eric Auger <[email protected]>"
Expand Down
8 changes: 4 additions & 4 deletions drivers/vfio/vfio.c
Original file line number Diff line number Diff line change
Expand Up @@ -2219,12 +2219,12 @@ static int __init vfio_init(void)

vfio.class->devnode = vfio_devnode;

ret = alloc_chrdev_region(&vfio.group_devt, 0, MINORMASK, "vfio");
ret = alloc_chrdev_region(&vfio.group_devt, 0, MINORMASK + 1, "vfio");
if (ret)
goto err_alloc_chrdev;

cdev_init(&vfio.group_cdev, &vfio_group_fops);
ret = cdev_add(&vfio.group_cdev, vfio.group_devt, MINORMASK);
ret = cdev_add(&vfio.group_cdev, vfio.group_devt, MINORMASK + 1);
if (ret)
goto err_cdev_add;

Expand All @@ -2236,7 +2236,7 @@ static int __init vfio_init(void)
return 0;

err_cdev_add:
unregister_chrdev_region(vfio.group_devt, MINORMASK);
unregister_chrdev_region(vfio.group_devt, MINORMASK + 1);
err_alloc_chrdev:
class_destroy(vfio.class);
vfio.class = NULL;
Expand All @@ -2254,7 +2254,7 @@ static void __exit vfio_cleanup(void)
#endif
idr_destroy(&vfio.group_idr);
cdev_del(&vfio.group_cdev);
unregister_chrdev_region(vfio.group_devt, MINORMASK);
unregister_chrdev_region(vfio.group_devt, MINORMASK + 1);
class_destroy(vfio.class);
vfio.class = NULL;
misc_deregister(&vfio_dev);
Expand Down
3 changes: 2 additions & 1 deletion drivers/vfio/vfio_iommu_spapr_tce.c
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,8 @@ static void tce_iommu_release_ownership_ddw(struct tce_container *container,
}

for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i)
table_group->ops->unset_window(table_group, i);
if (container->tables[i])
table_group->ops->unset_window(table_group, i);

table_group->ops->release_ownership(table_group);
}
Expand Down
2 changes: 1 addition & 1 deletion include/linux/mdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ struct mdev_driver {

extern void *mdev_get_drvdata(struct mdev_device *mdev);
extern void mdev_set_drvdata(struct mdev_device *mdev, void *data);
extern uuid_le mdev_uuid(struct mdev_device *mdev);
extern const guid_t *mdev_uuid(struct mdev_device *mdev);

extern struct bus_type mdev_bus_type;

Expand Down
Loading

0 comments on commit a83b042

Please sign in to comment.