From patchwork Mon Dec 3 07:35:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Tina" X-Patchwork-Id: 10708679 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 401DA14BD for ; Mon, 3 Dec 2018 07:40:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 330832ACCC for ; Mon, 3 Dec 2018 07:40:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 26E362ACC4; Mon, 3 Dec 2018 07:40:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 853B82AC79 for ; Mon, 3 Dec 2018 07:40:55 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8546689CDE; Mon, 3 Dec 2018 07:40:54 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by gabe.freedesktop.org (Postfix) with ESMTPS id 08C0889CD8; Mon, 3 Dec 2018 07:40:53 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 Dec 2018 23:40:52 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,309,1539673200"; d="scan'208";a="126550086" Received: from tinazhang-linux-1.bj.intel.com ([10.238.158.97]) by fmsmga001.fm.intel.com with ESMTP; 02 Dec 2018 23:40:51 -0800 From: Tina Zhang To: Date: Mon, 3 Dec 2018 15:35:17 +0800 Message-Id: <1543822522-3413-3-git-send-email-tina.zhang@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1543822522-3413-1-git-send-email-tina.zhang@intel.com> References: <1543822522-3413-1-git-send-email-tina.zhang@intel.com> Subject: [Intel-gfx] [RFC PATCH 2/7] drm/i915/gvt: Use meta fbs to stand for vGPU's planes X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: intel-gfx@lists.freedesktop.org, kalyan.kondapally@intel.com, intel-gvt-dev@lists.freedesktop.org MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Create and initialize vGPU meta framebuffers during vGPU's creation. Each meta framebuffer is an intel_framebuffer. Userspace can get the userspace visible identifier of that meta framebuffer by accessing plane_id_index attribute. For example: In "/sys/bus/pci/devices/0000\:00\:02.0/$vGPU_id/intel_vgpu/" directory, /* plane_id_index: pipe#(bit16:8) and plane#(bit7:0)*/ echo "0x10" > plane_index_id //Set the index to the plane 0 of pipe 1 /* * Dump userspace visible identifier of the meta framebuffer * standing for the primary plane of the vGPU's pipe one */ cat plane_index_id //dump the id for plane 0 of pipe 1 Then userspace can use this id with the exsting KMS IOCTL, e.g. drmModeSetPlane, to assign a physical plane to this virtual plane. Signed-off-by: Tina Zhang Cc: Zhenyu Wang Cc: Zhi Wang --- drivers/gpu/drm/i915/gvt/display.c | 150 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/gvt.h | 16 ++++ drivers/gpu/drm/i915/gvt/kvmgt.c | 46 ++++++++++++ 3 files changed, 212 insertions(+) diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index df1e141..a9176a1 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -442,6 +442,152 @@ void intel_gvt_emulate_vblank(struct intel_gvt *gvt) mutex_unlock(&gvt->lock); } +struct intel_vgpu_fb_meta_data { + u32 vgpu_plane_id; /* vgpu_id(23:16):vgpu_pipe(15:8):vgpu_plane(7:0)*/ + struct intel_vgpu *vgpu; // the vGPU this meta_fb belongs to +}; + +static void meta_fb_destroy(struct drm_framebuffer *fb) +{ + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); + + if (intel_fb->meta_fb.type_id != INTEL_META_FB_VGPU) + return; + + kfree(intel_fb->meta_fb.private); + intel_fb->meta_fb.private = NULL; + + drm_framebuffer_cleanup(fb); + kfree(intel_fb); +} + +static void clean_meta_fb(struct intel_vgpu *vgpu) +{ + enum pipe pipe; + enum plane_id plane_id; + struct intel_framebuffer *intel_fb; + + for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) { + for (plane_id = 0; plane_id < I915_MAX_PLANES; plane_id++) { + intel_fb = vgpu->display.meta_fbs.meta_fb[pipe][plane_id]; + if (!intel_fb) + drm_framebuffer_put(&intel_fb->base); + + intel_fb = NULL; + } + } +} + +static int meta_fb_create_handle(struct drm_framebuffer *fb, + struct drm_file *file, + unsigned int *handle) +{ + return -ENODEV; +} + +static int meta_fb_dirty(struct drm_framebuffer *fb, + struct drm_file *file, + unsigned int flags, + unsigned int color, + struct drm_clip_rect *clips, + unsigned int num_clips) +{ + return 0; +} + +static const struct drm_framebuffer_funcs meta_fb_funcs = { + .destroy = meta_fb_destroy, + .create_handle = meta_fb_create_handle, + .dirty = meta_fb_dirty, +}; + +static void meta_fb_update(struct intel_framebuffer *intel_fb, + enum pipe pipe, enum plane_id plane_id) +{ + struct intel_vgpu_fb_meta_data *meta_data; + struct intel_gvt *gvt; + + if (!intel_fb || intel_fb->meta_fb.type_id != INTEL_META_FB_VGPU) + return; + + meta_data = intel_fb->meta_fb.private; + gvt = meta_data->vgpu->gvt; + + if (gvt->assigned_plane[pipe][plane_id].vgpu_plane_id != + meta_data->vgpu_plane_id) { + gvt->assigned_plane[pipe][plane_id].vgpu_plane_id = + meta_data->vgpu_plane_id; + gvt->assigned_plane[pipe][plane_id].framebuffer_id = + intel_fb->base.base.id; + intel_fb->meta_fb.ggtt_offset = 0; + intel_fb->meta_fb.should_be_offscreen = true; + } else if (!intel_fb->meta_fb.ggtt_offset) { + intel_fb->meta_fb.should_be_offscreen = true; + } else { + intel_fb->meta_fb.should_be_offscreen = false; + } +} + +static int init_meta_fb(struct intel_vgpu *vgpu) +{ + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; + struct intel_vgpu_fb_meta_data *meta_data; + struct drm_mode_fb_cmd2 mode_cmd; + struct intel_framebuffer *intel_fb; + enum pipe pipe; + enum plane_id plane_id; + int ret = 0; + + for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) { + for (plane_id = 0; plane_id < I915_MAX_PLANES; plane_id++) { + intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); + if (!intel_fb) + return -ENOMEM; + + /* + * Create a drm_framebuffer with defaults. + */ + mode_cmd.pixel_format = DRM_FORMAT_XRGB8888; + mode_cmd.width = dev_priv->drm.mode_config.max_width; + mode_cmd.height = dev_priv->drm.mode_config.max_height; + mode_cmd.flags = DRM_MODE_FB_MODIFIERS; + mode_cmd.handles[0] = 0; + mode_cmd.pitches[0] = mode_cmd.width * 4; + mode_cmd.offsets[0] = 0; + mode_cmd.modifier[0] = DRM_FORMAT_MOD_LINEAR; + + drm_helper_mode_fill_fb_struct(&dev_priv->drm, + &intel_fb->base, &mode_cmd); + + ret = drm_framebuffer_init(&dev_priv->drm, + &intel_fb->base, &meta_fb_funcs); + if (ret) { + DRM_ERROR("%s: framebuffer init failed %d\n", + __func__, ret); + kfree(intel_fb); + return ret; + } + + meta_data = kmalloc(sizeof(struct intel_vgpu_fb_meta_data), + GFP_KERNEL); + if (unlikely(!meta_data)) { + return -ENOMEM; + } + + meta_data->vgpu_plane_id = (vgpu->id << 16) | + (pipe << 8) | plane_id; + meta_data->vgpu = vgpu; + + intel_fb->meta_fb.private = meta_data; + intel_fb->meta_fb.update = meta_fb_update; + intel_fb->meta_fb.type_id = INTEL_META_FB_VGPU; + + vgpu->display.meta_fbs.meta_fb[pipe][plane_id] = intel_fb; + } + } + return 0; +} + /** * intel_vgpu_clean_display - clean vGPU virtual display emulation * @vgpu: a vGPU @@ -457,6 +603,8 @@ void intel_vgpu_clean_display(struct intel_vgpu *vgpu) clean_virtual_dp_monitor(vgpu, PORT_D); else clean_virtual_dp_monitor(vgpu, PORT_B); + + clean_meta_fb(vgpu); } /** @@ -476,6 +624,8 @@ int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution) intel_vgpu_init_i2c_edid(vgpu); + init_meta_fb(vgpu); + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D, resolution); diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 31f6cdb..0ab10b0 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -131,10 +131,16 @@ struct intel_vgpu_opregion { #define vgpu_opregion(vgpu) (&(vgpu->opregion)) +struct intel_vgpu_meta_fbs { + struct intel_framebuffer *meta_fb[I915_MAX_PIPES][I915_MAX_PLANES]; + u32 plane_id_index; +}; + struct intel_vgpu_display { struct intel_vgpu_i2c_edid i2c_edid; struct intel_vgpu_port ports[I915_MAX_PORTS]; struct intel_vgpu_sbi sbi; + struct intel_vgpu_meta_fbs meta_fbs; }; struct vgpu_sched_ctl { @@ -301,6 +307,13 @@ struct intel_vgpu_type { enum intel_vgpu_edid resolution; }; +struct assigned_plane { + u32 vgpu_plane_id; + + /* userspace visible identifier */ + int framebuffer_id; +}; + struct intel_gvt { /* GVT scope lock, protect GVT itself, and all resource currently * not yet protected by special locks(vgpu and scheduler lock). @@ -340,6 +353,9 @@ struct intel_gvt { } engine_mmio_list; struct dentry *debugfs_root; + + /* vGPU plane assignment */ + struct assigned_plane assigned_plane[I915_MAX_PIPES][I915_MAX_PLANES]; }; static inline struct intel_gvt *to_gvt(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index c107214..7f4704d 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -1420,12 +1420,58 @@ hw_id_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "\n"); } +static ssize_t +plane_id_index_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct mdev_device *mdev = mdev_from_dev(dev); + + if (mdev) { + struct intel_vgpu *vgpu = (struct intel_vgpu *) + mdev_get_drvdata(mdev); + enum pipe pipe = vgpu->display.meta_fbs.plane_id_index & + 0x000000F0; + enum plane_id plane_id = vgpu->display.meta_fbs.plane_id_index & + 0x0000000F; + + if ((pipe < I915_MAX_PIPES || plane_id < I915_MAX_PLANES) && + vgpu->display.meta_fbs.meta_fb[pipe][plane_id]) { + return sprintf(buf, "%u\n", + vgpu->display.meta_fbs.meta_fb[pipe][plane_id]->base.base.id); + } + } + return sprintf(buf, "\n"); +} + +static ssize_t +plane_id_index_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t n) +{ + struct mdev_device *mdev = mdev_from_dev(dev); + ssize_t ret; + u32 val; + + ret = kstrtou32(buf, 0, &val); + if (ret) + return ret; + + if (mdev) { + struct intel_vgpu *vgpu = (struct intel_vgpu *) + mdev_get_drvdata(mdev); + vgpu->display.meta_fbs.plane_id_index = val; + } + + return n; +} + static DEVICE_ATTR_RO(vgpu_id); static DEVICE_ATTR_RO(hw_id); +static DEVICE_ATTR_RW(plane_id_index); static struct attribute *intel_vgpu_attrs[] = { &dev_attr_vgpu_id.attr, &dev_attr_hw_id.attr, + &dev_attr_plane_id_index.attr, NULL };