Commit e0ca3826 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'vfio-v4.15-rc1' of git://github.com/awilliam/linux-vfio

Pull VFIO updates from Alex Williamson:

 - Virtualize PCI MPS and MRRS registers

 - Avoid soft lockups on SPAPR when clearing TCE

 - Broadcom FlexRM platform device support

 - Samples driver cleanup & type1 integer overflow fix

* tag 'vfio-v4.15-rc1' of git://github.com/awilliam/linux-vfio:
  vfio: platform: reset: Add Broadcom FlexRM reset module
  vfio/type1: silence integer overflow warning
  vfio-mdev/samples: make mdev_fops const and static
  vfio/spapr: Add cond_resched() for huge updates
  vfio/pci: Virtualize Maximum Read Request Size
  vfio/pci: Virtualize Maximum Payload Size
parents 2cd83ba5 f3199673
...@@ -808,6 +808,7 @@ static int vfio_exp_config_write(struct vfio_pci_device *vdev, int pos, ...@@ -808,6 +808,7 @@ static int vfio_exp_config_write(struct vfio_pci_device *vdev, int pos,
{ {
__le16 *ctrl = (__le16 *)(vdev->vconfig + pos - __le16 *ctrl = (__le16 *)(vdev->vconfig + pos -
offset + PCI_EXP_DEVCTL); offset + PCI_EXP_DEVCTL);
int readrq = le16_to_cpu(*ctrl) & PCI_EXP_DEVCTL_READRQ;
count = vfio_default_config_write(vdev, pos, count, perm, offset, val); count = vfio_default_config_write(vdev, pos, count, perm, offset, val);
if (count < 0) if (count < 0)
...@@ -833,6 +834,27 @@ static int vfio_exp_config_write(struct vfio_pci_device *vdev, int pos, ...@@ -833,6 +834,27 @@ static int vfio_exp_config_write(struct vfio_pci_device *vdev, int pos,
pci_try_reset_function(vdev->pdev); pci_try_reset_function(vdev->pdev);
} }
/*
* MPS is virtualized to the user, writes do not change the physical
* register since determining a proper MPS value requires a system wide
* device view. The MRRS is largely independent of MPS, but since the
* user does not have that system-wide view, they might set a safe, but
* inefficiently low value. Here we allow writes through to hardware,
* but we set the floor to the physical device MPS setting, so that
* we can at least use full TLPs, as defined by the MPS value.
*
* NB, if any devices actually depend on an artificially low MRRS
* setting, this will need to be revisited, perhaps with a quirk
* though pcie_set_readrq().
*/
if (readrq != (le16_to_cpu(*ctrl) & PCI_EXP_DEVCTL_READRQ)) {
readrq = 128 <<
((le16_to_cpu(*ctrl) & PCI_EXP_DEVCTL_READRQ) >> 12);
readrq = max(readrq, pcie_get_mps(vdev->pdev));
pcie_set_readrq(vdev->pdev, readrq);
}
return count; return count;
} }
...@@ -849,11 +871,14 @@ static int __init init_pci_cap_exp_perm(struct perm_bits *perm) ...@@ -849,11 +871,14 @@ static int __init init_pci_cap_exp_perm(struct perm_bits *perm)
/* /*
* Allow writes to device control fields, except devctl_phantom, * Allow writes to device control fields, except devctl_phantom,
* which could confuse IOMMU, and the ARI bit in devctl2, which * which could confuse IOMMU, MPS, which can break communication
* is set at probe time. FLR gets virtualized via our writefn. * with other physical devices, and the ARI bit in devctl2, which
* is set at probe time. FLR and MRRS get virtualized via our
* writefn.
*/ */
p_setw(perm, PCI_EXP_DEVCTL, p_setw(perm, PCI_EXP_DEVCTL,
PCI_EXP_DEVCTL_BCR_FLR, ~PCI_EXP_DEVCTL_PHANTOM); PCI_EXP_DEVCTL_BCR_FLR | PCI_EXP_DEVCTL_PAYLOAD |
PCI_EXP_DEVCTL_READRQ, ~PCI_EXP_DEVCTL_PHANTOM);
p_setw(perm, PCI_EXP_DEVCTL2, NO_VIRT, ~PCI_EXP_DEVCTL2_ARI); p_setw(perm, PCI_EXP_DEVCTL2, NO_VIRT, ~PCI_EXP_DEVCTL2_ARI);
return 0; return 0;
} }
......
...@@ -13,3 +13,12 @@ config VFIO_PLATFORM_AMDXGBE_RESET ...@@ -13,3 +13,12 @@ config VFIO_PLATFORM_AMDXGBE_RESET
Enables the VFIO platform driver to handle reset for AMD XGBE Enables the VFIO platform driver to handle reset for AMD XGBE
If you don't know what to do here, say N. If you don't know what to do here, say N.
config VFIO_PLATFORM_BCMFLEXRM_RESET
tristate "VFIO support for Broadcom FlexRM reset"
depends on VFIO_PLATFORM && (ARCH_BCM_IPROC || COMPILE_TEST)
default ARCH_BCM_IPROC
help
Enables the VFIO platform driver to handle reset for Broadcom FlexRM
If you don't know what to do here, say N.
...@@ -6,3 +6,4 @@ ccflags-y += -Idrivers/vfio/platform ...@@ -6,3 +6,4 @@ ccflags-y += -Idrivers/vfio/platform
obj-$(CONFIG_VFIO_PLATFORM_CALXEDAXGMAC_RESET) += vfio-platform-calxedaxgmac.o obj-$(CONFIG_VFIO_PLATFORM_CALXEDAXGMAC_RESET) += vfio-platform-calxedaxgmac.o
obj-$(CONFIG_VFIO_PLATFORM_AMDXGBE_RESET) += vfio-platform-amdxgbe.o obj-$(CONFIG_VFIO_PLATFORM_AMDXGBE_RESET) += vfio-platform-amdxgbe.o
obj-$(CONFIG_VFIO_PLATFORM_BCMFLEXRM_RESET) += vfio_platform_bcmflexrm.o
/*
* Copyright (C) 2017 Broadcom
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/*
* This driver provides reset support for Broadcom FlexRM ring manager
* to VFIO platform.
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include "vfio_platform_private.h"
/* FlexRM configuration */
#define RING_REGS_SIZE 0x10000
#define RING_VER_MAGIC 0x76303031
/* Per-Ring register offsets */
#define RING_VER 0x000
#define RING_CONTROL 0x034
#define RING_FLUSH_DONE 0x038
/* Register RING_CONTROL fields */
#define CONTROL_FLUSH_SHIFT 5
/* Register RING_FLUSH_DONE fields */
#define FLUSH_DONE_MASK 0x1
static int vfio_platform_bcmflexrm_shutdown(void __iomem *ring)
{
unsigned int timeout;
/* Disable/inactivate ring */
writel_relaxed(0x0, ring + RING_CONTROL);
/* Set ring flush state */
timeout = 1000; /* timeout of 1s */
writel_relaxed(BIT(CONTROL_FLUSH_SHIFT), ring + RING_CONTROL);
do {
if (readl_relaxed(ring + RING_FLUSH_DONE) &
FLUSH_DONE_MASK)
break;
mdelay(1);
} while (--timeout);
if (!timeout)
return -ETIMEDOUT;
/* Clear ring flush state */
timeout = 1000; /* timeout of 1s */
writel_relaxed(0x0, ring + RING_CONTROL);
do {
if (!(readl_relaxed(ring + RING_FLUSH_DONE) &
FLUSH_DONE_MASK))
break;
mdelay(1);
} while (--timeout);
if (!timeout)
return -ETIMEDOUT;
return 0;
}
static int vfio_platform_bcmflexrm_reset(struct vfio_platform_device *vdev)
{
void __iomem *ring;
int rc = 0, ret = 0, ring_num = 0;
struct vfio_platform_region *reg = &vdev->regions[0];
/* Map FlexRM ring registers if not mapped */
if (!reg->ioaddr) {
reg->ioaddr = ioremap_nocache(reg->addr, reg->size);
if (!reg->ioaddr)
return -ENOMEM;
}
/* Discover and shutdown each FlexRM ring */
for (ring = reg->ioaddr;
ring < (reg->ioaddr + reg->size); ring += RING_REGS_SIZE) {
if (readl_relaxed(ring + RING_VER) == RING_VER_MAGIC) {
rc = vfio_platform_bcmflexrm_shutdown(ring);
if (rc) {
dev_warn(vdev->device,
"FlexRM ring%d shutdown error %d\n",
ring_num, rc);
ret |= rc;
}
ring_num++;
}
}
return ret;
}
module_vfio_reset_handler("brcm,iproc-flexrm-mbox",
vfio_platform_bcmflexrm_reset);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Anup Patel <anup.patel@broadcom.com>");
MODULE_DESCRIPTION("Reset support for Broadcom FlexRM VFIO platform device");
...@@ -507,6 +507,8 @@ static int tce_iommu_clear(struct tce_container *container, ...@@ -507,6 +507,8 @@ static int tce_iommu_clear(struct tce_container *container,
enum dma_data_direction direction; enum dma_data_direction direction;
for ( ; pages; --pages, ++entry) { for ( ; pages; --pages, ++entry) {
cond_resched();
direction = DMA_NONE; direction = DMA_NONE;
oldhpa = 0; oldhpa = 0;
ret = iommu_tce_xchg(tbl, entry, &oldhpa, &direction); ret = iommu_tce_xchg(tbl, entry, &oldhpa, &direction);
......
...@@ -767,6 +767,9 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu, ...@@ -767,6 +767,9 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
return -EINVAL; return -EINVAL;
if (!unmap->size || unmap->size & mask) if (!unmap->size || unmap->size & mask)
return -EINVAL; return -EINVAL;
if (unmap->iova + unmap->size < unmap->iova ||
unmap->size > SIZE_MAX)
return -EINVAL;
WARN_ON(mask & PAGE_MASK); WARN_ON(mask & PAGE_MASK);
again: again:
......
...@@ -1413,7 +1413,7 @@ struct attribute_group *mdev_type_groups[] = { ...@@ -1413,7 +1413,7 @@ struct attribute_group *mdev_type_groups[] = {
NULL, NULL,
}; };
struct mdev_parent_ops mdev_fops = { static const struct mdev_parent_ops mdev_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.dev_attr_groups = mtty_dev_groups, .dev_attr_groups = mtty_dev_groups,
.mdev_attr_groups = mdev_dev_groups, .mdev_attr_groups = mdev_dev_groups,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment