|
|
9ae3a8 |
From bd32da91efdbcccaeb7eb2ad06f3c87946fce903 Mon Sep 17 00:00:00 2001
|
|
|
9ae3a8 |
From: Alex Williamson <alex.williamson@redhat.com>
|
|
|
9ae3a8 |
Date: Tue, 5 Nov 2013 15:37:29 +0100
|
|
|
9ae3a8 |
Subject: [PATCH 13/25] vfio-pci: Test device reset capabilities
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RH-Author: Alex Williamson <alex.williamson@redhat.com>
|
|
|
9ae3a8 |
Message-id: <20131105153729.16057.85790.stgit@bling.home>
|
|
|
9ae3a8 |
Patchwork-id: 55422
|
|
|
9ae3a8 |
O-Subject: [RHEL7 qemu-kvm PATCH 1/5] vfio-pci: Test device reset capabilities
|
|
|
9ae3a8 |
Bugzilla: 1026550
|
|
|
9ae3a8 |
RH-Acked-by: Bandan Das <bsd@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Bugzilla: 1026550
|
|
|
9ae3a8 |
Upstream commit: befe5176ef7a0004ba23517c97c804e292273635
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Not all resets are created equal. PM reset is not very reliable,
|
|
|
9ae3a8 |
especially for GPUs, so we might want to opt for a bus reset if a
|
|
|
9ae3a8 |
standard reset will only do a D3hot->D0 transition. We can also
|
|
|
9ae3a8 |
use this to tell if the standard reset will do a bus reset (if
|
|
|
9ae3a8 |
neither has_pm_reset or has_flr is probed, but the device still
|
|
|
9ae3a8 |
supports reset).
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
hw/misc/vfio.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
9ae3a8 |
1 file changed, 46 insertions(+)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
hw/misc/vfio.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
9ae3a8 |
1 files changed, 46 insertions(+), 0 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
|
|
|
9ae3a8 |
index 286dad1..8e69182 100644
|
|
|
9ae3a8 |
--- a/hw/misc/vfio.c
|
|
|
9ae3a8 |
+++ b/hw/misc/vfio.c
|
|
|
9ae3a8 |
@@ -185,6 +185,8 @@ typedef struct VFIODevice {
|
|
|
9ae3a8 |
bool reset_works;
|
|
|
9ae3a8 |
bool has_vga;
|
|
|
9ae3a8 |
bool pci_aer;
|
|
|
9ae3a8 |
+ bool has_flr;
|
|
|
9ae3a8 |
+ bool has_pm_reset;
|
|
|
9ae3a8 |
} VFIODevice;
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
typedef struct VFIOGroup {
|
|
|
9ae3a8 |
@@ -2508,6 +2510,42 @@ static int vfio_setup_pcie_cap(VFIODevice *vdev, int pos, uint8_t size)
|
|
|
9ae3a8 |
return pos;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
+static void vfio_check_pcie_flr(VFIODevice *vdev, uint8_t pos)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ uint32_t cap = pci_get_long(vdev->pdev.config + pos + PCI_EXP_DEVCAP);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ if (cap & PCI_EXP_DEVCAP_FLR) {
|
|
|
9ae3a8 |
+ DPRINTF("%04x:%02x:%02x.%x Supports FLR via PCIe cap\n",
|
|
|
9ae3a8 |
+ vdev->host.domain, vdev->host.bus, vdev->host.slot,
|
|
|
9ae3a8 |
+ vdev->host.function);
|
|
|
9ae3a8 |
+ vdev->has_flr = true;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+static void vfio_check_pm_reset(VFIODevice *vdev, uint8_t pos)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ uint16_t csr = pci_get_word(vdev->pdev.config + pos + PCI_PM_CTRL);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ if (!(csr & PCI_PM_CTRL_NO_SOFT_RESET)) {
|
|
|
9ae3a8 |
+ DPRINTF("%04x:%02x:%02x.%x Supports PM reset\n",
|
|
|
9ae3a8 |
+ vdev->host.domain, vdev->host.bus, vdev->host.slot,
|
|
|
9ae3a8 |
+ vdev->host.function);
|
|
|
9ae3a8 |
+ vdev->has_pm_reset = true;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+static void vfio_check_af_flr(VFIODevice *vdev, uint8_t pos)
|
|
|
9ae3a8 |
+{
|
|
|
9ae3a8 |
+ uint8_t cap = pci_get_byte(vdev->pdev.config + pos + PCI_AF_CAP);
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ if ((cap & PCI_AF_CAP_TP) && (cap & PCI_AF_CAP_FLR)) {
|
|
|
9ae3a8 |
+ DPRINTF("%04x:%02x:%02x.%x Supports FLR via AF cap\n",
|
|
|
9ae3a8 |
+ vdev->host.domain, vdev->host.bus, vdev->host.slot,
|
|
|
9ae3a8 |
+ vdev->host.function);
|
|
|
9ae3a8 |
+ vdev->has_flr = true;
|
|
|
9ae3a8 |
+ }
|
|
|
9ae3a8 |
+}
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
static int vfio_add_std_cap(VFIODevice *vdev, uint8_t pos)
|
|
|
9ae3a8 |
{
|
|
|
9ae3a8 |
PCIDevice *pdev = &vdev->pdev;
|
|
|
9ae3a8 |
@@ -2552,13 +2590,21 @@ static int vfio_add_std_cap(VFIODevice *vdev, uint8_t pos)
|
|
|
9ae3a8 |
ret = vfio_setup_msi(vdev, pos);
|
|
|
9ae3a8 |
break;
|
|
|
9ae3a8 |
case PCI_CAP_ID_EXP:
|
|
|
9ae3a8 |
+ vfio_check_pcie_flr(vdev, pos);
|
|
|
9ae3a8 |
ret = vfio_setup_pcie_cap(vdev, pos, size);
|
|
|
9ae3a8 |
break;
|
|
|
9ae3a8 |
case PCI_CAP_ID_MSIX:
|
|
|
9ae3a8 |
ret = vfio_setup_msix(vdev, pos);
|
|
|
9ae3a8 |
break;
|
|
|
9ae3a8 |
case PCI_CAP_ID_PM:
|
|
|
9ae3a8 |
+ vfio_check_pm_reset(vdev, pos);
|
|
|
9ae3a8 |
vdev->pm_cap = pos;
|
|
|
9ae3a8 |
+ ret = pci_add_capability(pdev, cap_id, pos, size);
|
|
|
9ae3a8 |
+ break;
|
|
|
9ae3a8 |
+ case PCI_CAP_ID_AF:
|
|
|
9ae3a8 |
+ vfio_check_af_flr(vdev, pos);
|
|
|
9ae3a8 |
+ ret = pci_add_capability(pdev, cap_id, pos, size);
|
|
|
9ae3a8 |
+ break;
|
|
|
9ae3a8 |
default:
|
|
|
9ae3a8 |
ret = pci_add_capability(pdev, cap_id, pos, size);
|
|
|
9ae3a8 |
break;
|
|
|
9ae3a8 |
--
|
|
|
9ae3a8 |
1.7.1
|
|
|
9ae3a8 |
|