Commit b3bece34 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Zhi Wang
Browse files

drm/i915/gvt: devirtualize ->inject_msi



Just open code the MSI injection in a single place instead of going
through the method table.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarZhi Wang <zhi.a.wang@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20220411141403.86980-18-hch@lst.de


Reviewed-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Reviewed-by: default avatarZhi Wang <zhi.a.wang@intel.com>
parent 4c705ad0
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@ struct intel_vgpu;
struct intel_gvt_mpt {
	int (*host_init)(struct device *dev, void *gvt);
	void (*host_exit)(struct device *dev, void *gvt);
	int (*inject_msi)(struct intel_vgpu *vgpu, u32 addr, u16 data);
	int (*enable_page_track)(struct intel_vgpu *vgpu, u64 gfn);
	int (*disable_page_track)(struct intel_vgpu *vgpu, u64 gfn);
	unsigned long (*gfn_to_mfn)(struct intel_vgpu *vgpu, unsigned long gfn);
+39 −1
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@
 *
 */

#include <linux/eventfd.h>

#include "i915_drv.h"
#include "i915_reg.h"
#include "gvt.h"
@@ -397,9 +399,45 @@ static void init_irq_map(struct intel_gvt_irq *irq)
}

/* =======================vEvent injection===================== */

#define MSI_CAP_CONTROL(offset) (offset + 2)
#define MSI_CAP_ADDRESS(offset) (offset + 4)
#define MSI_CAP_DATA(offset) (offset + 8)
#define MSI_CAP_EN 0x1

static int inject_virtual_interrupt(struct intel_vgpu *vgpu)
{
	return intel_gvt_hypervisor_inject_msi(vgpu);
	unsigned long offset = vgpu->gvt->device_info.msi_cap_offset;
	u16 control, data;
	u32 addr;

	control = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_CONTROL(offset));
	addr = *(u32 *)(vgpu_cfg_space(vgpu) + MSI_CAP_ADDRESS(offset));
	data = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_DATA(offset));

	/* Do not generate MSI if MSIEN is disabled */
	if (!(control & MSI_CAP_EN))
		return 0;

	if (WARN(control & GENMASK(15, 1), "only support one MSI format\n"))
		return -EINVAL;

	trace_inject_msi(vgpu->id, addr, data);

	/*
	 * When guest is powered off, msi_trigger is set to NULL, but vgpu's
	 * config and mmio register isn't restored to default during guest
	 * poweroff. If this vgpu is still used in next vm, this vgpu's pipe
	 * may be enabled, then once this vgpu is active, it will get inject
	 * vblank interrupt request. But msi_trigger is null until msi is
	 * enabled by guest. so if msi_trigger is null, success is still
	 * returned and don't inject interrupt into guest.
	 */
	if (!vgpu->attached)
		return -ESRCH;
	if (vgpu->msi_trigger && eventfd_signal(vgpu->msi_trigger, 1) != 1)
		return -EFAULT;
	return 0;
}

static void propagate_event(struct intel_gvt_irq *irq,
+0 −24
Original line number Diff line number Diff line
@@ -1874,29 +1874,6 @@ void intel_vgpu_detach_regions(struct intel_vgpu *vgpu)
	vgpu->region = NULL;
}

static int kvmgt_inject_msi(struct intel_vgpu *vgpu, u32 addr, u16 data)
{
	if (!vgpu->attached)
		return -ESRCH;

	/*
	 * When guest is poweroff, msi_trigger is set to NULL, but vgpu's
	 * config and mmio register isn't restored to default during guest
	 * poweroff. If this vgpu is still used in next vm, this vgpu's pipe
	 * may be enabled, then once this vgpu is active, it will get inject
	 * vblank interrupt request. But msi_trigger is null until msi is
	 * enabled by guest. so if msi_trigger is null, success is still
	 * returned and don't inject interrupt into guest.
	 */
	if (vgpu->msi_trigger == NULL)
		return 0;

	if (eventfd_signal(vgpu->msi_trigger, 1) == 1)
		return 0;

	return -EFAULT;
}

static unsigned long kvmgt_gfn_to_pfn(struct intel_vgpu *vgpu,
		unsigned long gfn)
{
@@ -2022,7 +1999,6 @@ static bool kvmgt_is_valid_gfn(struct intel_vgpu *vgpu, unsigned long gfn)
static const struct intel_gvt_mpt kvmgt_mpt = {
	.host_init = kvmgt_host_init,
	.host_exit = kvmgt_host_exit,
	.inject_msi = kvmgt_inject_msi,
	.enable_page_track = kvmgt_page_track_add,
	.disable_page_track = kvmgt_page_track_remove,
	.gfn_to_mfn = kvmgt_gfn_to_pfn,
+0 −37
Original line number Diff line number Diff line
@@ -71,43 +71,6 @@ static inline void intel_gvt_hypervisor_host_exit(struct device *dev, void *gvt)
	intel_gvt_host.mpt->host_exit(dev, gvt);
}

#define MSI_CAP_CONTROL(offset) (offset + 2)
#define MSI_CAP_ADDRESS(offset) (offset + 4)
#define MSI_CAP_DATA(offset) (offset + 8)
#define MSI_CAP_EN 0x1

/**
 * intel_gvt_hypervisor_inject_msi - inject a MSI interrupt into vGPU
 *
 * Returns:
 * Zero on success, negative error code if failed.
 */
static inline int intel_gvt_hypervisor_inject_msi(struct intel_vgpu *vgpu)
{
	unsigned long offset = vgpu->gvt->device_info.msi_cap_offset;
	u16 control, data;
	u32 addr;
	int ret;

	control = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_CONTROL(offset));
	addr = *(u32 *)(vgpu_cfg_space(vgpu) + MSI_CAP_ADDRESS(offset));
	data = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_DATA(offset));

	/* Do not generate MSI if MSIEN is disable */
	if (!(control & MSI_CAP_EN))
		return 0;

	if (WARN(control & GENMASK(15, 1), "only support one MSI format\n"))
		return -EINVAL;

	trace_inject_msi(vgpu->id, addr, data);

	ret = intel_gvt_host.mpt->inject_msi(vgpu, addr, data);
	if (ret)
		return ret;
	return 0;
}

/**
 * intel_gvt_hypervisor_enable_page_track - track a guest page
 * @vgpu: a vGPU