From a88a7b3eb076ade6205176915fd2ee73a60f4a32 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Sat, 30 Mar 2019 09:41:35 -0500 Subject: [PATCH 01/11] vfio: Use dev_printk() when possible Use dev_printk() when possible to make messages consistent with other device-related messages. Signed-off-by: Bjorn Helgaas Acked-by: Eric Auger Reviewed-by: Eric Auger Signed-off-by: Alex Williamson --- drivers/vfio/pci/vfio_pci.c | 23 +++++++-------- drivers/vfio/pci/vfio_pci_config.c | 29 +++++++++---------- .../platform/reset/vfio_platform_amdxgbe.c | 5 ++-- drivers/vfio/platform/vfio_platform_common.c | 12 ++++---- drivers/vfio/vfio.c | 29 +++++++++---------- include/linux/pci.h | 3 ++ 6 files changed, 49 insertions(+), 52 deletions(-) diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 3fa20e95a6bb..cab71da46f4a 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -12,6 +12,7 @@ */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#define dev_fmt pr_fmt #include #include @@ -287,12 +288,11 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) pci_save_state(pdev); vdev->pci_saved_state = pci_store_saved_state(pdev); if (!vdev->pci_saved_state) - pr_debug("%s: Couldn't store %s saved state\n", - __func__, dev_name(&pdev->dev)); + pci_dbg(pdev, "%s: Couldn't store saved state\n", __func__); if (likely(!nointxmask)) { if (vfio_pci_nointx(pdev)) { - dev_info(&pdev->dev, "Masking broken INTx support\n"); + pci_info(pdev, "Masking broken INTx support\n"); vdev->nointx = true; pci_intx(pdev, 0); } else @@ -336,8 +336,7 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) IS_ENABLED(CONFIG_VFIO_PCI_IGD)) { ret = vfio_pci_igd_init(vdev); if (ret) { - dev_warn(&vdev->pdev->dev, - "Failed to setup Intel IGD regions\n"); + pci_warn(pdev, "Failed to setup Intel IGD regions\n"); goto disable_exit; } } @@ -346,8 +345,7 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) IS_ENABLED(CONFIG_VFIO_PCI_NVLINK2)) { ret = vfio_pci_nvdia_v100_nvlink2_init(vdev); if (ret && ret != -ENODEV) { - dev_warn(&vdev->pdev->dev, - "Failed to setup NVIDIA NV2 RAM region\n"); + pci_warn(pdev, "Failed to setup NVIDIA NV2 RAM region\n"); goto disable_exit; } } @@ -356,8 +354,7 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) IS_ENABLED(CONFIG_VFIO_PCI_NVLINK2)) { ret = vfio_pci_ibm_npu2_init(vdev); if (ret && ret != -ENODEV) { - dev_warn(&vdev->pdev->dev, - "Failed to setup NVIDIA NV2 ATSD region\n"); + pci_warn(pdev, "Failed to setup NVIDIA NV2 ATSD region\n"); goto disable_exit; } } @@ -429,8 +426,7 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev) * is just busy work. */ if (pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state)) { - pr_info("%s: Couldn't reload %s saved state\n", - __func__, dev_name(&pdev->dev)); + pci_info(pdev, "%s: Couldn't reload saved state\n", __func__); if (!vdev->reset_works) goto out; @@ -1255,17 +1251,18 @@ static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma) static void vfio_pci_request(void *device_data, unsigned int count) { struct vfio_pci_device *vdev = device_data; + struct pci_dev *pdev = vdev->pdev; mutex_lock(&vdev->igate); if (vdev->req_trigger) { if (!(count % 10)) - dev_notice_ratelimited(&vdev->pdev->dev, + pci_notice_ratelimited(pdev, "Relaying device request to user (#%u)\n", count); eventfd_signal(vdev->req_trigger, 1); } else if (count == 0) { - dev_warn(&vdev->pdev->dev, + pci_warn(pdev, "No device request channel registered, blocked until released by user\n"); } diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c index e82b51114687..52963a904790 100644 --- a/drivers/vfio/pci/vfio_pci_config.c +++ b/drivers/vfio/pci/vfio_pci_config.c @@ -412,8 +412,7 @@ static void vfio_bar_restore(struct vfio_pci_device *vdev) if (pdev->is_virtfn) return; - pr_info("%s: %s reset recovery - restoring bars\n", - __func__, dev_name(&pdev->dev)); + pci_info(pdev, "%s: reset recovery - restoring BARs\n", __func__); for (i = PCI_BASE_ADDRESS_0; i <= PCI_BASE_ADDRESS_5; i += 4, rbar++) pci_user_write_config_dword(pdev, i, *rbar); @@ -1298,8 +1297,8 @@ static int vfio_cap_len(struct vfio_pci_device *vdev, u8 cap, u8 pos) else return PCI_SATA_SIZEOF_SHORT; default: - pr_warn("%s: %s unknown length for pci cap 0x%x@0x%x\n", - dev_name(&pdev->dev), __func__, cap, pos); + pci_warn(pdev, "%s: unknown length for PCI cap %#x@%#x\n", + __func__, cap, pos); } return 0; @@ -1372,8 +1371,8 @@ static int vfio_ext_cap_len(struct vfio_pci_device *vdev, u16 ecap, u16 epos) } return PCI_TPH_BASE_SIZEOF; default: - pr_warn("%s: %s unknown length for pci ecap 0x%x@0x%x\n", - dev_name(&pdev->dev), __func__, ecap, epos); + pci_warn(pdev, "%s: unknown length for PCI ecap %#x@%#x\n", + __func__, ecap, epos); } return 0; @@ -1474,8 +1473,8 @@ static int vfio_cap_init(struct vfio_pci_device *vdev) } if (!len) { - pr_info("%s: %s hiding cap 0x%x\n", - __func__, dev_name(&pdev->dev), cap); + pci_info(pdev, "%s: hiding cap %#x@%#x\n", __func__, + cap, pos); *prev = next; pos = next; continue; @@ -1486,9 +1485,8 @@ static int vfio_cap_init(struct vfio_pci_device *vdev) if (likely(map[pos + i] == PCI_CAP_ID_INVALID)) continue; - pr_warn("%s: %s pci config conflict @0x%x, was cap 0x%x now cap 0x%x\n", - __func__, dev_name(&pdev->dev), - pos + i, map[pos + i], cap); + pci_warn(pdev, "%s: PCI config conflict @%#x, was cap %#x now cap %#x\n", + __func__, pos + i, map[pos + i], cap); } BUILD_BUG_ON(PCI_CAP_ID_MAX >= PCI_CAP_ID_INVALID_VIRT); @@ -1549,8 +1547,8 @@ static int vfio_ecap_init(struct vfio_pci_device *vdev) } if (!len) { - pr_info("%s: %s hiding ecap 0x%x@0x%x\n", - __func__, dev_name(&pdev->dev), ecap, epos); + pci_info(pdev, "%s: hiding ecap %#x@%#x\n", + __func__, ecap, epos); /* If not the first in the chain, we can skip over it */ if (prev) { @@ -1572,9 +1570,8 @@ static int vfio_ecap_init(struct vfio_pci_device *vdev) if (likely(map[epos + i] == PCI_CAP_ID_INVALID)) continue; - pr_warn("%s: %s pci config conflict @0x%x, was ecap 0x%x now ecap 0x%x\n", - __func__, dev_name(&pdev->dev), - epos + i, map[epos + i], ecap); + pci_warn(pdev, "%s: PCI config conflict @%#x, was ecap %#x now ecap %#x\n", + __func__, epos + i, map[epos + i], ecap); } /* diff --git a/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c b/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c index 3ddb2704221d..fe95964bc3be 100644 --- a/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c +++ b/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c @@ -89,7 +89,8 @@ static int vfio_platform_amdxgbe_reset(struct vfio_platform_device *vdev) } while ((pcs_value & MDIO_CTRL1_RESET) && --count); if (pcs_value & MDIO_CTRL1_RESET) - pr_warn("%s XGBE PHY reset timeout\n", __func__); + dev_warn(vdev->device, "%s: XGBE PHY reset timeout\n", + __func__); /* disable auto-negotiation */ value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_CTRL1); @@ -114,7 +115,7 @@ static int vfio_platform_amdxgbe_reset(struct vfio_platform_device *vdev) usleep_range(500, 600); if (!count) - pr_warn("%s MAC SW reset failed\n", __func__); + dev_warn(vdev->device, "%s: MAC SW reset failed\n", __func__); return 0; } diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c index c0cd824be2b7..2a45b36bcf58 100644 --- a/drivers/vfio/platform/vfio_platform_common.c +++ b/drivers/vfio/platform/vfio_platform_common.c @@ -12,6 +12,8 @@ * GNU General Public License for more details. */ +#define dev_fmt(fmt) "VFIO: " fmt + #include #include #include @@ -63,7 +65,7 @@ static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev, adev = ACPI_COMPANION(dev); if (!adev) { - pr_err("VFIO: ACPI companion device not found for %s\n", + dev_err(dev, "ACPI companion device not found for %s\n", vdev->name); return -ENODEV; } @@ -638,7 +640,7 @@ static int vfio_platform_of_probe(struct vfio_platform_device *vdev, ret = device_property_read_string(dev, "compatible", &vdev->compat); if (ret) - pr_err("VFIO: Cannot retrieve compat for %s\n", vdev->name); + dev_err(dev, "Cannot retrieve compat for %s\n", vdev->name); return ret; } @@ -680,14 +682,14 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev, ret = vfio_platform_get_reset(vdev); if (ret && vdev->reset_required) { - pr_err("VFIO: No reset function found for device %s\n", - vdev->name); + dev_err(dev, "No reset function found for device %s\n", + vdev->name); return ret; } group = vfio_iommu_group_get(dev); if (!group) { - pr_err("VFIO: No IOMMU group for device %s\n", vdev->name); + dev_err(dev, "No IOMMU group for device %s\n", vdev->name); ret = -EINVAL; goto put_reset; } diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index a3030cdf3c18..7fb68968097a 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -704,8 +704,8 @@ static int vfio_group_nb_add_dev(struct vfio_group *group, struct device *dev) return 0; /* TODO Prevent device auto probing */ - WARN(1, "Device %s added to live group %d!\n", dev_name(dev), - iommu_group_id(group->iommu_group)); + dev_WARN(dev, "Device added to live group %d!\n", + iommu_group_id(group->iommu_group)); return 0; } @@ -748,25 +748,22 @@ static int vfio_iommu_group_notifier(struct notifier_block *nb, */ break; case IOMMU_GROUP_NOTIFY_BIND_DRIVER: - pr_debug("%s: Device %s, group %d binding to driver\n", - __func__, dev_name(dev), - iommu_group_id(group->iommu_group)); + dev_dbg(dev, "%s: group %d binding to driver\n", __func__, + iommu_group_id(group->iommu_group)); break; case IOMMU_GROUP_NOTIFY_BOUND_DRIVER: - pr_debug("%s: Device %s, group %d bound to driver %s\n", - __func__, dev_name(dev), - iommu_group_id(group->iommu_group), dev->driver->name); + dev_dbg(dev, "%s: group %d bound to driver %s\n", __func__, + iommu_group_id(group->iommu_group), dev->driver->name); BUG_ON(vfio_group_nb_verify(group, dev)); break; case IOMMU_GROUP_NOTIFY_UNBIND_DRIVER: - pr_debug("%s: Device %s, group %d unbinding from driver %s\n", - __func__, dev_name(dev), - iommu_group_id(group->iommu_group), dev->driver->name); + dev_dbg(dev, "%s: group %d unbinding from driver %s\n", + __func__, iommu_group_id(group->iommu_group), + dev->driver->name); break; case IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER: - pr_debug("%s: Device %s, group %d unbound from driver\n", - __func__, dev_name(dev), - iommu_group_id(group->iommu_group)); + dev_dbg(dev, "%s: group %d unbound from driver\n", __func__, + iommu_group_id(group->iommu_group)); /* * XXX An unbound device in a live group is ok, but we'd * really like to avoid the above BUG_ON by preventing other @@ -830,8 +827,8 @@ int vfio_add_group_dev(struct device *dev, device = vfio_group_get_device(group, dev); if (device) { - WARN(1, "Device %s already exists on group %d\n", - dev_name(dev), iommu_group_id(iommu_group)); + dev_WARN(dev, "Device already exists on group %d\n", + iommu_group_id(iommu_group)); vfio_device_put(device); vfio_group_put(group); return -EBUSY; diff --git a/include/linux/pci.h b/include/linux/pci.h index 77448215ef5b..27854731afc4 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2363,4 +2363,7 @@ void pci_uevent_ers(struct pci_dev *pdev, enum pci_ers_result err_type); #define pci_info(pdev, fmt, arg...) dev_info(&(pdev)->dev, fmt, ##arg) #define pci_dbg(pdev, fmt, arg...) dev_dbg(&(pdev)->dev, fmt, ##arg) +#define pci_notice_ratelimited(pdev, fmt, arg...) \ + dev_notice_ratelimited(&(pdev)->dev, fmt, ##arg) + #endif /* LINUX_PCI_H */ From 41be3e2618174fdf3361e49e64f2bf530f40c6b0 Mon Sep 17 00:00:00 2001 From: Farhan Ali Date: Wed, 3 Apr 2019 14:22:27 -0400 Subject: [PATCH 02/11] vfio: Fix WARNING "do not call blocking ops when !TASK_RUNNING" vfio_dev_present() which is the condition to wait_event_interruptible_timeout(), will call vfio_group_get_device and try to acquire the mutex group->device_lock. wait_event_interruptible_timeout() will set the state of the current task to TASK_INTERRUPTIBLE, before doing the condition check. This means that we will try to acquire the mutex while already in a sleeping state. The scheduler warns us by giving the following warning: [ 4050.264464] ------------[ cut here ]------------ [ 4050.264508] do not call blocking ops when !TASK_RUNNING; state=1 set at [<00000000b33c00e2>] prepare_to_wait_event+0x14a/0x188 [ 4050.264529] WARNING: CPU: 12 PID: 35924 at kernel/sched/core.c:6112 __might_sleep+0x76/0x90 .... 4050.264756] Call Trace: [ 4050.264765] ([<000000000017bbaa>] __might_sleep+0x72/0x90) [ 4050.264774] [<0000000000b97edc>] __mutex_lock+0x44/0x8c0 [ 4050.264782] [<0000000000b9878a>] mutex_lock_nested+0x32/0x40 [ 4050.264793] [<000003ff800d7abe>] vfio_group_get_device+0x36/0xa8 [vfio] [ 4050.264803] [<000003ff800d87c0>] vfio_del_group_dev+0x238/0x378 [vfio] [ 4050.264813] [<000003ff8015f67c>] mdev_remove+0x3c/0x68 [mdev] [ 4050.264825] [<00000000008e01b0>] device_release_driver_internal+0x168/0x268 [ 4050.264834] [<00000000008de692>] bus_remove_device+0x162/0x190 [ 4050.264843] [<00000000008daf42>] device_del+0x1e2/0x368 [ 4050.264851] [<00000000008db12c>] device_unregister+0x64/0x88 [ 4050.264862] [<000003ff8015ed84>] mdev_device_remove+0xec/0x130 [mdev] [ 4050.264872] [<000003ff8015f074>] remove_store+0x6c/0xa8 [mdev] [ 4050.264881] [<000000000046f494>] kernfs_fop_write+0x14c/0x1f8 [ 4050.264890] [<00000000003c1530>] __vfs_write+0x38/0x1a8 [ 4050.264899] [<00000000003c187c>] vfs_write+0xb4/0x198 [ 4050.264908] [<00000000003c1af2>] ksys_write+0x5a/0xb0 [ 4050.264916] [<0000000000b9e270>] system_call+0xdc/0x2d8 [ 4050.264925] 4 locks held by sh/35924: [ 4050.264933] #0: 000000001ef90325 (sb_writers#4){.+.+}, at: vfs_write+0x9e/0x198 [ 4050.264948] #1: 000000005c1ab0b3 (&of->mutex){+.+.}, at: kernfs_fop_write+0x1cc/0x1f8 [ 4050.264963] #2: 0000000034831ab8 (kn->count#297){++++}, at: kernfs_remove_self+0x12e/0x150 [ 4050.264979] #3: 00000000e152484f (&dev->mutex){....}, at: device_release_driver_internal+0x5c/0x268 [ 4050.264993] Last Breaking-Event-Address: [ 4050.265002] [<000000000017bbaa>] __might_sleep+0x72/0x90 [ 4050.265010] irq event stamp: 7039 [ 4050.265020] hardirqs last enabled at (7047): [<00000000001cee7a>] console_unlock+0x6d2/0x740 [ 4050.265029] hardirqs last disabled at (7054): [<00000000001ce87e>] console_unlock+0xd6/0x740 [ 4050.265040] softirqs last enabled at (6416): [<0000000000b8fe26>] __udelay+0xb6/0x100 [ 4050.265049] softirqs last disabled at (6415): [<0000000000b8fe06>] __udelay+0x96/0x100 [ 4050.265057] ---[ end trace d04a07d39d99a9f9 ]--- Let's fix this as described in the article https://lwn.net/Articles/628628/. Signed-off-by: Farhan Ali [remove now redundant vfio_dev_present()] Signed-off-by: Alex Williamson --- drivers/vfio/vfio.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 7fb68968097a..82fcf07fa9ea 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -34,6 +34,7 @@ #include #include #include +#include #define DRIVER_VERSION "0.3" #define DRIVER_AUTHOR "Alex Williamson " @@ -901,30 +902,17 @@ void *vfio_device_data(struct vfio_device *device) } EXPORT_SYMBOL_GPL(vfio_device_data); -/* Given a referenced group, check if it contains the device */ -static bool vfio_dev_present(struct vfio_group *group, struct device *dev) -{ - struct vfio_device *device; - - device = vfio_group_get_device(group, dev); - if (!device) - return false; - - vfio_device_put(device); - return true; -} - /* * Decrement the device reference count and wait for the device to be * removed. Open file descriptors for the device... */ void *vfio_del_group_dev(struct device *dev) { + DEFINE_WAIT_FUNC(wait, woken_wake_function); struct vfio_device *device = dev_get_drvdata(dev); struct vfio_group *group = device->group; void *device_data = device->device_data; struct vfio_unbound_dev *unbound; unsigned int i = 0; - long ret; bool interrupted = false; /* @@ -961,6 +949,8 @@ void *vfio_del_group_dev(struct device *dev) * interval with counter to allow the driver to take escalating * measures to release the device if it has the ability to do so. */ + add_wait_queue(&vfio.release_q, &wait); + do { device = vfio_group_get_device(group, dev); if (!device) @@ -972,12 +962,10 @@ void *vfio_del_group_dev(struct device *dev) vfio_device_put(device); if (interrupted) { - ret = wait_event_timeout(vfio.release_q, - !vfio_dev_present(group, dev), HZ * 10); + wait_woken(&wait, TASK_UNINTERRUPTIBLE, HZ * 10); } else { - ret = wait_event_interruptible_timeout(vfio.release_q, - !vfio_dev_present(group, dev), HZ * 10); - if (ret == -ERESTARTSYS) { + wait_woken(&wait, TASK_INTERRUPTIBLE, HZ * 10); + if (signal_pending(current)) { interrupted = true; dev_warn(dev, "Device is currently in use, task" @@ -986,8 +974,10 @@ void *vfio_del_group_dev(struct device *dev) current->comm, task_pid_nr(current)); } } - } while (ret <= 0); + } while (1); + + remove_wait_queue(&vfio.release_q, &wait); /* * In order to support multiple devices per group, devices can be * plucked from the group while other devices in the group are still From 2c85f2bd519457073444ec28bbb4743a4e4237a7 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Fri, 19 Apr 2019 17:37:17 +0200 Subject: [PATCH 03/11] vfio-pci/nvlink2: Fix potential VMA leak If vfio_pci_register_dev_region() fails then we should rollback previous changes, ie. unmap the ATSD registers. Fixes: 7f92891778df ("vfio_pci: Add NVIDIA GV100GL [Tesla V100 SXM2] subdriver") Signed-off-by: Greg Kurz Reviewed-by: Alexey Kardashevskiy Signed-off-by: Alex Williamson --- drivers/vfio/pci/vfio_pci_nvlink2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/vfio/pci/vfio_pci_nvlink2.c b/drivers/vfio/pci/vfio_pci_nvlink2.c index 32f695ffe128..50fe3c4f7feb 100644 --- a/drivers/vfio/pci/vfio_pci_nvlink2.c +++ b/drivers/vfio/pci/vfio_pci_nvlink2.c @@ -472,6 +472,8 @@ int vfio_pci_ibm_npu2_init(struct vfio_pci_device *vdev) return 0; free_exit: + if (data->base) + memunmap(data->base); kfree(data); return ret; From 60e7f2c3fe9919cee9534b422865eed49f4efb15 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Tue, 30 Apr 2019 17:49:28 -0500 Subject: [PATCH 04/11] vfio/mdev: Avoid release parent reference during error path During mdev parent registration in mdev_register_device(), if parent device is duplicate, it releases the reference of existing parent device. This is incorrect. Existing parent device should not be touched. Fixes: 7b96953bc640 ("vfio: Mediated device Core driver") Reviewed-by: Cornelia Huck Reviewed-by: Kirti Wankhede Reviewed-by: Maxim Levitsky Signed-off-by: Parav Pandit Signed-off-by: Alex Williamson --- drivers/vfio/mdev/mdev_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c index b96fedc77ee5..1299d2e72ce2 100644 --- a/drivers/vfio/mdev/mdev_core.c +++ b/drivers/vfio/mdev/mdev_core.c @@ -181,6 +181,7 @@ int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops) /* Check for duplicate */ parent = __find_parent_device(dev); if (parent) { + parent = NULL; ret = -EEXIST; goto add_dev_err; } From f707d837b6c24792a724ec51117c0fdb92bd352f Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Tue, 30 Apr 2019 17:49:29 -0500 Subject: [PATCH 05/11] vfio/mdev: Removed unused kref Remove unused kref from the mdev_device structure. Fixes: 7b96953bc640 ("vfio: Mediated device Core driver") Reviewed-by: Cornelia Huck Reviewed-by: Kirti Wankhede Reviewed-by: Maxim Levitsky Signed-off-by: Parav Pandit Signed-off-by: Alex Williamson --- drivers/vfio/mdev/mdev_core.c | 1 - drivers/vfio/mdev/mdev_private.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c index 1299d2e72ce2..00ca61392de9 100644 --- a/drivers/vfio/mdev/mdev_core.c +++ b/drivers/vfio/mdev/mdev_core.c @@ -311,7 +311,6 @@ int mdev_device_create(struct kobject *kobj, mutex_unlock(&mdev_list_lock); mdev->parent = parent; - kref_init(&mdev->ref); mdev->dev.parent = dev; mdev->dev.bus = &mdev_bus_type; diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h index 379758c52b1b..ddcf9c72bd8a 100644 --- a/drivers/vfio/mdev/mdev_private.h +++ b/drivers/vfio/mdev/mdev_private.h @@ -30,7 +30,6 @@ struct mdev_device { struct mdev_parent *parent; guid_t uuid; void *driver_data; - struct kref ref; struct list_head next; struct kobject *type_kobj; bool active; From 50732af3b65691666c32fe89808545134c1ee2a0 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Tue, 30 Apr 2019 17:49:30 -0500 Subject: [PATCH 06/11] vfio/mdev: Drop redundant extern for exported symbols There is no need use 'extern' for exported functions. Acked-by: Cornelia Huck Reviewed-by: Maxim Levitsky Signed-off-by: Parav Pandit Signed-off-by: Alex Williamson --- include/linux/mdev.h | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/include/linux/mdev.h b/include/linux/mdev.h index d7aee90e5da5..4924d8038814 100644 --- a/include/linux/mdev.h +++ b/include/linux/mdev.h @@ -118,21 +118,20 @@ struct mdev_driver { #define to_mdev_driver(drv) container_of(drv, struct mdev_driver, driver) -extern void *mdev_get_drvdata(struct mdev_device *mdev); -extern void mdev_set_drvdata(struct mdev_device *mdev, void *data); -extern const guid_t *mdev_uuid(struct mdev_device *mdev); +void *mdev_get_drvdata(struct mdev_device *mdev); +void mdev_set_drvdata(struct mdev_device *mdev, void *data); +const guid_t *mdev_uuid(struct mdev_device *mdev); extern struct bus_type mdev_bus_type; -extern int mdev_register_device(struct device *dev, - const struct mdev_parent_ops *ops); -extern void mdev_unregister_device(struct device *dev); +int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops); +void mdev_unregister_device(struct device *dev); -extern int mdev_register_driver(struct mdev_driver *drv, struct module *owner); -extern void mdev_unregister_driver(struct mdev_driver *drv); +int mdev_register_driver(struct mdev_driver *drv, struct module *owner); +void mdev_unregister_driver(struct mdev_driver *drv); -extern struct device *mdev_parent_dev(struct mdev_device *mdev); -extern struct device *mdev_dev(struct mdev_device *mdev); -extern struct mdev_device *mdev_from_dev(struct device *dev); +struct device *mdev_parent_dev(struct mdev_device *mdev); +struct device *mdev_dev(struct mdev_device *mdev); +struct mdev_device *mdev_from_dev(struct device *dev); #endif /* MDEV_H */ From d3000463504b561db3c6d3aedc2c3106bdb29648 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Tue, 30 Apr 2019 17:49:31 -0500 Subject: [PATCH 07/11] vfio/mdev: Avoid masking error code to EBUSY Instead of masking return error to -EBUSY, return actual error returned by the driver. Reviewed-by: Cornelia Huck Reviewed-by: Maxim Levitsky Signed-off-by: Parav Pandit Signed-off-by: Alex Williamson --- drivers/vfio/mdev/mdev_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c index 00ca61392de9..836d31985f14 100644 --- a/drivers/vfio/mdev/mdev_core.c +++ b/drivers/vfio/mdev/mdev_core.c @@ -141,7 +141,7 @@ static int mdev_device_remove_ops(struct mdev_device *mdev, bool force_remove) */ ret = parent->ops->remove(mdev); if (ret && !force_remove) - return -EBUSY; + return ret; sysfs_remove_groups(&mdev->dev.kobj, parent->ops->mdev_attr_groups); return 0; From a6d6f4f160f76d840e59affe664b8d3159e23056 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Tue, 30 Apr 2019 17:49:32 -0500 Subject: [PATCH 08/11] vfio/mdev: Follow correct remove sequence mdev_remove_sysfs_files() should follow exact mirror sequence of a create, similar to what is followed in error unwinding path of mdev_create_sysfs_files(). Fixes: 6a62c1dfb5c7 ("vfio/mdev: Re-order sysfs attribute creation") Reviewed-by: Cornelia Huck Reviewed-by: Maxim Levitsky Signed-off-by: Parav Pandit Signed-off-by: Alex Williamson --- drivers/vfio/mdev/mdev_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c index 5193a0e0ce5a..cbf94b8165ea 100644 --- a/drivers/vfio/mdev/mdev_sysfs.c +++ b/drivers/vfio/mdev/mdev_sysfs.c @@ -280,7 +280,7 @@ type_link_failed: void mdev_remove_sysfs_files(struct device *dev, struct mdev_type *type) { + sysfs_remove_files(&dev->kobj, mdev_device_attrs); sysfs_remove_link(&dev->kobj, "mdev_type"); sysfs_remove_link(type->devices_kobj, dev_name(dev)); - sysfs_remove_files(&dev->kobj, mdev_device_attrs); } From 6093e348a5e2475c5bb2e571346460f939998670 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Tue, 30 Apr 2019 17:49:33 -0500 Subject: [PATCH 09/11] vfio/mdev: Fix aborting mdev child device removal if one fails device_for_each_child() stops executing callback function for remaining child devices, if callback hits an error. Each child mdev device is independent of each other. While unregistering parent device, mdev core must remove all child mdev devices. Therefore, mdev_device_remove_cb() always returns success so that device_for_each_child doesn't abort if one child removal hits error. While at it, improve remove and unregister functions for below simplicity. There isn't need to pass forced flag pointer during mdev parent removal which invokes mdev_device_remove(). So simplify the flow. mdev_device_remove() is called from two paths. 1. mdev_unregister_driver() mdev_device_remove_cb() mdev_device_remove() 2. remove_store() mdev_device_remove() Fixes: 7b96953bc640 ("vfio: Mediated device Core driver") Reviewed-by: Maxim Levitsky Signed-off-by: Parav Pandit Signed-off-by: Alex Williamson --- drivers/vfio/mdev/mdev_core.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c index 836d31985f14..1a317e409355 100644 --- a/drivers/vfio/mdev/mdev_core.c +++ b/drivers/vfio/mdev/mdev_core.c @@ -149,10 +149,10 @@ static int mdev_device_remove_ops(struct mdev_device *mdev, bool force_remove) static int mdev_device_remove_cb(struct device *dev, void *data) { - if (!dev_is_mdev(dev)) - return 0; + if (dev_is_mdev(dev)) + mdev_device_remove(dev, true); - return mdev_device_remove(dev, data ? *(bool *)data : true); + return 0; } /* @@ -240,7 +240,6 @@ EXPORT_SYMBOL(mdev_register_device); void mdev_unregister_device(struct device *dev) { struct mdev_parent *parent; - bool force_remove = true; mutex_lock(&parent_list_lock); parent = __find_parent_device(dev); @@ -254,8 +253,7 @@ void mdev_unregister_device(struct device *dev) list_del(&parent->next); class_compat_remove_link(mdev_bus_compat_class, dev, NULL); - device_for_each_child(dev, (void *)&force_remove, - mdev_device_remove_cb); + device_for_each_child(dev, NULL, mdev_device_remove_cb); parent_remove_sysfs_files(parent); From 405ecbf72f2eb4fc796c4c99ca4881e2cb2ab158 Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Tue, 30 Apr 2019 17:49:34 -0500 Subject: [PATCH 10/11] vfio/mdev: Avoid inline get and put parent helpers As section 15 of Documentation/process/coding-style.rst clearly describes that compiler will be able to optimize code. Hence drop inline for get and put helpers for parent. Signed-off-by: Parav Pandit Signed-off-by: Alex Williamson --- drivers/vfio/mdev/mdev_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c index 1a317e409355..1040a4a2dcbc 100644 --- a/drivers/vfio/mdev/mdev_core.c +++ b/drivers/vfio/mdev/mdev_core.c @@ -88,7 +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 struct mdev_parent *mdev_get_parent(struct mdev_parent *parent) { if (parent) kref_get(&parent->ref); @@ -96,7 +96,7 @@ static inline struct mdev_parent *mdev_get_parent(struct mdev_parent *parent) return parent; } -static inline void mdev_put_parent(struct mdev_parent *parent) +static void mdev_put_parent(struct mdev_parent *parent) { if (parent) kref_put(&parent->ref, mdev_release_parent); From 15c80c1659f27364734a3938b04d1c67479aa11c Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 8 May 2019 18:06:32 +0200 Subject: [PATCH 11/11] vfio: Add Cornelia Huck as reviewer I'm trying to look at vfio patches, and it's easier if I'm cc:ed. Signed-off-by: Cornelia Huck Signed-off-by: Alex Williamson --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 09f43f1bdd15..f62b29167b1f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16382,6 +16382,7 @@ F: fs/fat/ VFIO DRIVER M: Alex Williamson +R: Cornelia Huck L: kvm@vger.kernel.org T: git git://github.com/awilliam/linux-vfio.git S: Maintained