Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ed40875d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'drm-intel-fixes-2017-01-05' of git://anongit.freedesktop.org/git/drm-intel

Pull i915 drm fixes from Jani Nikula:
 "Here's a bunch of drm/i915 fixes for v4.10-rc3. It includes GVT-g
  fixes.

  My new year's resolution is to start using signed tags for pulls. If
  that feels like a déjà vu, it's ((new year's) resolution), not (new
  (year's resolution))"

[ Taking this directly from Jani because Dave Airlie is only partially
  connected right now.  - Linus ]

* tag 'drm-intel-fixes-2017-01-05' of git://anongit.freedesktop.org/git/drm-intel:
  drm/i915: Prevent timeline updates whilst performing reset
  drm/i915: Silence allocation failure during sg_trim()
  drm/i915: Don't clflush before release phys object
  drm/i915: Fix oops in overlay due to frontbuffer tracking
  drm/i915: Fix oopses in the overlay code due to i915_gem_active stuff
  drm/i915: Initialize overlay->last_flip properly
  drm/i915: Move the min_pixclk[] handling to the end of readout
  drm/i915: Force VDD off on the new power seqeuencer before starting to use it
  drm/i915/gvt: fix typo in cfg_space range check
  drm/i915/gvt: fix an issue in emulating cfg space PCI_COMMAND
  drm/i915/gvt/kvmgt: trival: code cleanup
  drm/i915/gvt/kvmgt: prevent double-release of vgpu
  drm/i915/gvt/kvmgt: check returned slot for gfn
  drm/i915/gvt/kvmgt: dereference the pointer within lock
  drm/i915/gvt: reset the GGTT entry when vGPU created
  drm/i915/gvt: fix an error in opregion handling
parents c433eb70 2471eb5f
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ static int emulate_pci_command_write(struct intel_vgpu *vgpu,
	u8 changed = old ^ new;
	int ret;

	memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes);
	if (!(changed & PCI_COMMAND_MEMORY))
		return 0;

@@ -142,7 +143,6 @@ static int emulate_pci_command_write(struct intel_vgpu *vgpu,
			return ret;
	}

	memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes);
	return 0;
}

@@ -240,7 +240,7 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
	if (WARN_ON(bytes > 4))
		return -EINVAL;

	if (WARN_ON(offset + bytes >= INTEL_GVT_MAX_CFG_SPACE_SZ))
	if (WARN_ON(offset + bytes > INTEL_GVT_MAX_CFG_SPACE_SZ))
		return -EINVAL;

	/* First check if it's PCI_COMMAND */
+55 −0
Original line number Diff line number Diff line
@@ -1998,6 +1998,8 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)
	INIT_LIST_HEAD(&gtt->oos_page_list_head);
	INIT_LIST_HEAD(&gtt->post_shadow_list_head);

	intel_vgpu_reset_ggtt(vgpu);

	ggtt_mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_GGTT,
			NULL, 1, 0);
	if (IS_ERR(ggtt_mm)) {
@@ -2206,6 +2208,7 @@ int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu,
int intel_gvt_init_gtt(struct intel_gvt *gvt)
{
	int ret;
	void *page_addr;

	gvt_dbg_core("init gtt\n");

@@ -2218,6 +2221,23 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt)
		return -ENODEV;
	}

	gvt->gtt.scratch_ggtt_page =
		alloc_page(GFP_KERNEL | GFP_ATOMIC | __GFP_ZERO);
	if (!gvt->gtt.scratch_ggtt_page) {
		gvt_err("fail to allocate scratch ggtt page\n");
		return -ENOMEM;
	}

	page_addr = page_address(gvt->gtt.scratch_ggtt_page);

	gvt->gtt.scratch_ggtt_mfn =
		intel_gvt_hypervisor_virt_to_mfn(page_addr);
	if (gvt->gtt.scratch_ggtt_mfn == INTEL_GVT_INVALID_ADDR) {
		gvt_err("fail to translate scratch ggtt page\n");
		__free_page(gvt->gtt.scratch_ggtt_page);
		return -EFAULT;
	}

	if (enable_out_of_sync) {
		ret = setup_spt_oos(gvt);
		if (ret) {
@@ -2239,6 +2259,41 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt)
 */
void intel_gvt_clean_gtt(struct intel_gvt *gvt)
{
	__free_page(gvt->gtt.scratch_ggtt_page);

	if (enable_out_of_sync)
		clean_spt_oos(gvt);
}

/**
 * intel_vgpu_reset_ggtt - reset the GGTT entry
 * @vgpu: a vGPU
 *
 * This function is called at the vGPU create stage
 * to reset all the GGTT entries.
 *
 */
void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu)
{
	struct intel_gvt *gvt = vgpu->gvt;
	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
	u32 index;
	u32 offset;
	u32 num_entries;
	struct intel_gvt_gtt_entry e;

	memset(&e, 0, sizeof(struct intel_gvt_gtt_entry));
	e.type = GTT_TYPE_GGTT_PTE;
	ops->set_pfn(&e, gvt->gtt.scratch_ggtt_mfn);
	e.val64 |= _PAGE_PRESENT;

	index = vgpu_aperture_gmadr_base(vgpu) >> PAGE_SHIFT;
	num_entries = vgpu_aperture_sz(vgpu) >> PAGE_SHIFT;
	for (offset = 0; offset < num_entries; offset++)
		ops->set_entry(NULL, &e, index + offset, false, 0, vgpu);

	index = vgpu_hidden_gmadr_base(vgpu) >> PAGE_SHIFT;
	num_entries = vgpu_hidden_sz(vgpu) >> PAGE_SHIFT;
	for (offset = 0; offset < num_entries; offset++)
		ops->set_entry(NULL, &e, index + offset, false, 0, vgpu);
}
+4 −0
Original line number Diff line number Diff line
@@ -81,6 +81,9 @@ struct intel_gvt_gtt {
	struct list_head oos_page_use_list_head;
	struct list_head oos_page_free_list_head;
	struct list_head mm_lru_list_head;

	struct page *scratch_ggtt_page;
	unsigned long scratch_ggtt_mfn;
};

enum {
@@ -202,6 +205,7 @@ struct intel_vgpu_gtt {

extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu);
extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu);
void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu);

extern int intel_gvt_init_gtt(struct intel_gvt *gvt);
extern void intel_gvt_clean_gtt(struct intel_gvt *gvt);
+1 −0
Original line number Diff line number Diff line
@@ -175,6 +175,7 @@ struct intel_vgpu {
		struct notifier_block group_notifier;
		struct kvm *kvm;
		struct work_struct release_work;
		atomic_t released;
	} vdev;
#endif
};
+36 −10
Original line number Diff line number Diff line
@@ -114,12 +114,15 @@ static struct gvt_dma *__gvt_cache_find(struct intel_vgpu *vgpu, gfn_t gfn)
static kvm_pfn_t gvt_cache_find(struct intel_vgpu *vgpu, gfn_t gfn)
{
	struct gvt_dma *entry;
	kvm_pfn_t pfn;

	mutex_lock(&vgpu->vdev.cache_lock);

	entry = __gvt_cache_find(vgpu, gfn);
	mutex_unlock(&vgpu->vdev.cache_lock);
	pfn = (entry == NULL) ? 0 : entry->pfn;

	return entry == NULL ? 0 : entry->pfn;
	mutex_unlock(&vgpu->vdev.cache_lock);
	return pfn;
}

static void gvt_cache_add(struct intel_vgpu *vgpu, gfn_t gfn, kvm_pfn_t pfn)
@@ -497,7 +500,16 @@ static int intel_vgpu_open(struct mdev_device *mdev)
		goto undo_iommu;
	}

	return kvmgt_guest_init(mdev);
	ret = kvmgt_guest_init(mdev);
	if (ret)
		goto undo_group;

	atomic_set(&vgpu->vdev.released, 0);
	return ret;

undo_group:
	vfio_unregister_notifier(&mdev->dev, VFIO_GROUP_NOTIFY,
					&vgpu->vdev.group_notifier);

undo_iommu:
	vfio_unregister_notifier(&mdev->dev, VFIO_IOMMU_NOTIFY,
@@ -509,17 +521,26 @@ static int intel_vgpu_open(struct mdev_device *mdev)
static void __intel_vgpu_release(struct intel_vgpu *vgpu)
{
	struct kvmgt_guest_info *info;
	int ret;

	if (!handle_valid(vgpu->handle))
		return;

	vfio_unregister_notifier(&vgpu->vdev.mdev->dev, VFIO_IOMMU_NOTIFY,
	if (atomic_cmpxchg(&vgpu->vdev.released, 0, 1))
		return;

	ret = vfio_unregister_notifier(&vgpu->vdev.mdev->dev, VFIO_IOMMU_NOTIFY,
					&vgpu->vdev.iommu_notifier);
	vfio_unregister_notifier(&vgpu->vdev.mdev->dev, VFIO_GROUP_NOTIFY,
	WARN(ret, "vfio_unregister_notifier for iommu failed: %d\n", ret);

	ret = vfio_unregister_notifier(&vgpu->vdev.mdev->dev, VFIO_GROUP_NOTIFY,
					&vgpu->vdev.group_notifier);
	WARN(ret, "vfio_unregister_notifier for group failed: %d\n", ret);

	info = (struct kvmgt_guest_info *)vgpu->handle;
	kvmgt_guest_exit(info);

	vgpu->vdev.kvm = NULL;
	vgpu->handle = 0;
}

@@ -534,6 +555,7 @@ static void intel_vgpu_release_work(struct work_struct *work)
{
	struct intel_vgpu *vgpu = container_of(work, struct intel_vgpu,
					vdev.release_work);

	__intel_vgpu_release(vgpu);
}

@@ -1134,6 +1156,10 @@ static int kvmgt_write_protect_add(unsigned long handle, u64 gfn)

	idx = srcu_read_lock(&kvm->srcu);
	slot = gfn_to_memslot(kvm, gfn);
	if (!slot) {
		srcu_read_unlock(&kvm->srcu, idx);
		return -EINVAL;
	}

	spin_lock(&kvm->mmu_lock);

@@ -1164,6 +1190,10 @@ static int kvmgt_write_protect_remove(unsigned long handle, u64 gfn)

	idx = srcu_read_lock(&kvm->srcu);
	slot = gfn_to_memslot(kvm, gfn);
	if (!slot) {
		srcu_read_unlock(&kvm->srcu, idx);
		return -EINVAL;
	}

	spin_lock(&kvm->mmu_lock);

@@ -1311,18 +1341,14 @@ static int kvmgt_guest_init(struct mdev_device *mdev)

static bool kvmgt_guest_exit(struct kvmgt_guest_info *info)
{
	struct intel_vgpu *vgpu;

	if (!info) {
		gvt_err("kvmgt_guest_info invalid\n");
		return false;
	}

	vgpu = info->vgpu;

	kvm_page_track_unregister_notifier(info->kvm, &info->track_node);
	kvmgt_protect_table_destroy(info);
	gvt_cache_destroy(vgpu);
	gvt_cache_destroy(info->vgpu);
	vfree(info);

	return true;
Loading