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: Christoph Hellwig <hch@lst.de>
Signed-off-by: Zhi Wang <zhi.a.wang@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20220411141403.86980-18-hch@lst.de
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Zhi Wang <zhi.a.wang@intel.com>
This commit is contained in:
Christoph Hellwig 2022-04-11 16:13:46 +02:00 committed by Zhi Wang
parent 4c705ad0d7
commit b3bece3495
4 changed files with 39 additions and 63 deletions

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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