From patchwork Mon Dec 3 07:35:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Tina" X-Patchwork-Id: 10708685 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 6EE0316B1 for ; Mon, 3 Dec 2018 07:41:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 61D822ACCF for ; Mon, 3 Dec 2018 07:41:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 55DFC2ACD0; Mon, 3 Dec 2018 07:41:01 +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 B68252AC96 for ; Mon, 3 Dec 2018 07:41:00 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 22B8289D42; Mon, 3 Dec 2018 07:41:00 +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 C794E89CFA; Mon, 3 Dec 2018 07:40:57 +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:57 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,309,1539673200"; d="scan'208";a="126550096" Received: from tinazhang-linux-1.bj.intel.com ([10.238.158.97]) by fmsmga001.fm.intel.com with ESMTP; 02 Dec 2018 23:40:56 -0800 From: Tina Zhang To: Date: Mon, 3 Dec 2018 15:35:20 +0800 Message-Id: <1543822522-3413-6-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 5/7] drm/i915/gvt: Introduce vGPU plane page flip framework 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 The vGPU plane page flip framework supports to update the assigned planes with the meta framebuffer information during guest vGPU page flip. With the updated meta framebuffer information, the proposed framework will use the asynchronous atomic commit path to do the plane update on behalf of vGPUs as much as possible. Signed-off-by: Tina Zhang Cc: Zhenyu Wang Cc: Zhi Wang --- drivers/gpu/drm/i915/gvt/display.c | 265 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/display.h | 18 +++ 2 files changed, 283 insertions(+) diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index a9176a1..e06d8d6 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -32,6 +32,9 @@ * */ +#include +#include +#include #include "i915_drv.h" #include "gvt.h" @@ -442,6 +445,268 @@ void intel_gvt_emulate_vblank(struct intel_gvt *gvt) mutex_unlock(&gvt->lock); } +static bool check_vgpu_plane_table(struct intel_gvt *gvt, u32 vgpu_plane_id, + enum pipe *pipe, enum plane_id *plane_id, + u32 *framebuffer_id) +{ + int i, j; + + for (i = 0; i < I915_MAX_PIPES; i++) { + for (j = 0; j < I915_MAX_PLANES; j++) + if (gvt->assigned_plane[i][j].vgpu_plane_id == + vgpu_plane_id) { + *pipe = i; + *plane_id = j; + *framebuffer_id = + gvt->assigned_plane[i][j].framebuffer_id; + break; + } + + if (j < I915_MAX_PLANES) + return true; + } + + return false; +} + +static u64 plane_ctl_modifier(u64 fb_tiling) +{ + switch (fb_tiling) { + case PLANE_CTL_TILED_LINEAR: + return DRM_FORMAT_MOD_LINEAR; + case PLANE_CTL_TILED_X: + return I915_FORMAT_MOD_X_TILED; + case PLANE_CTL_TILED_Y: + return I915_FORMAT_MOD_Y_TILED; + case PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE: + return I915_FORMAT_MOD_Y_TILED_CCS; + case PLANE_CTL_TILED_YF: + return I915_FORMAT_MOD_Yf_TILED; + case PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE: + return I915_FORMAT_MOD_Yf_TILED_CCS; + default: + MISSING_CASE(fb_tiling); + } + + return 0; +} + +static int vgpu_fb_update(struct intel_gvt *gvt, + struct drm_framebuffer *fb, + struct intel_vgpu_plane_info *vgpu_plane_info, + struct drm_mode_fb_cmd2 *mode_cmd) +{ + int ret; + + if (vgpu_plane_info->plane == PLANE_PRIMARY) { + struct intel_vgpu_primary_plane_format plane; + + ret = intel_vgpu_decode_primary_plane(vgpu_plane_info->vgpu, &plane); + if (ret) + return ret; + + mode_cmd->pixel_format = plane.drm_format; + mode_cmd->width = plane.width; + mode_cmd->height = plane.height; + mode_cmd->handles[0] = 0; + mode_cmd->offsets[0] = 0; + mode_cmd->pitches[0] = plane.stride; + mode_cmd->flags = DRM_MODE_FB_MODIFIERS; + mode_cmd->modifier[0] = plane_ctl_modifier(plane.tiled); + } else if (vgpu_plane_info->plane == PLANE_CURSOR) { + struct intel_vgpu_cursor_plane_format plane; + + ret = intel_vgpu_decode_cursor_plane(vgpu_plane_info->vgpu, &plane); + if (ret) + return ret; + + mode_cmd->pixel_format = plane.drm_format; + mode_cmd->width = plane.width; + mode_cmd->height = plane.height; + mode_cmd->handles[0] = 0; + mode_cmd->offsets[0] = 0; + mode_cmd->pitches[0] = plane.width * (plane.bpp / 8); + mode_cmd->flags = DRM_MODE_FB_MODIFIERS; + mode_cmd->modifier[0] = 0; + } else { + struct intel_vgpu_sprite_plane_format plane; + + ret = intel_vgpu_decode_sprite_plane(vgpu_plane_info->vgpu, &plane); + if (ret) + return ret; + + mode_cmd->pixel_format = plane.hw_format; + mode_cmd->width = plane.width; + mode_cmd->height = plane.height; + mode_cmd->handles[0] = 0; + mode_cmd->offsets[0] = 0; + mode_cmd->pitches[0] = plane.stride; + mode_cmd->flags = DRM_MODE_FB_MODIFIERS; + mode_cmd->modifier[0] = plane_ctl_modifier(plane.tiled); + } + + return ret; +} + +static int update_vgpu_assigned_plane(struct intel_gvt *gvt, + struct drm_plane *plane, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_modeset_acquire_ctx *ctx, + struct intel_vgpu_plane_info *vgpu_plane_info) +{ + struct drm_device *drm = &gvt->dev_priv->drm; + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); + struct drm_atomic_state *state; + struct drm_plane_state *plane_state; + struct drm_mode_fb_cmd2 mode_cmd; + int ret = 0; + + state = drm_atomic_state_alloc(plane->dev); + if (!state) + return -ENOMEM; + + state->acquire_ctx = ctx; + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + ret = PTR_ERR(plane_state); + goto fail; + } + + ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); + if (ret != 0) + goto fail; + drm_atomic_set_fb_for_plane(plane_state, fb); + + ret = vgpu_fb_update(gvt, fb, vgpu_plane_info, &mode_cmd); + if (ret) + goto fail; + + if (memcmp(mode_cmd.pitches, fb->pitches, 16) || + memcmp(mode_cmd.offsets, fb->offsets, 16) || + drm_get_format_info(drm, &mode_cmd) != fb->format || + mode_cmd.modifier[0] != fb->modifier || + drm_atomic_helper_async_check(drm, state)) + state->async_update = false; + else + state->async_update = true; + + drm_helper_mode_fill_fb_struct(plane->dev, fb, &mode_cmd); + plane_state->src_x = vgpu_plane_info->plane_offset & 0x0000ffff; + plane_state->src_y = (vgpu_plane_info->plane_offset >> 16) & 0x0000ffff; + plane_state->src_w = mode_cmd.width << 16; + plane_state->src_h = mode_cmd.height << 16; + + intel_fb->meta_fb.ggtt_offset = vgpu_plane_info->offset; + + /* Don't allow full modeset */ + state->allow_modeset = false; + + ret = drm_atomic_commit(state); +fail: + drm_atomic_state_put(state); + return ret; +} + +static int vgpu_plane_update_internal(struct intel_gvt *gvt, + struct drm_plane *plane, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_modeset_acquire_ctx *ctx, + struct intel_vgpu_plane_info *vgpu_plane_info) +{ + int ret = 0; + + /* Check whether this plane is usable on this CRTC */ + if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) { + DRM_DEBUG_KMS("Invalid crtc for plane\n"); + ret = -EINVAL; + goto out; + } + + ret = update_vgpu_assigned_plane(gvt, plane, crtc, fb, ctx, vgpu_plane_info); + +out: + return ret; +} + +void intel_vgpu_plane_update(struct intel_gvt *gvt, + struct intel_vgpu_plane_info *vgpu_plane_info) +{ + struct drm_device *drm = &gvt->dev_priv->drm; + struct drm_modeset_acquire_ctx ctx; + struct drm_mode_object *obj_fb = NULL; + struct drm_plane *plane; + struct intel_plane *intel_plane = NULL; + struct intel_crtc *intel_crtc; + struct intel_framebuffer *intel_fb; + u32 framebuffer_id = 0; + enum pipe pipe; + enum plane_id plane_id; + int ret; + + drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); +retry: + ret = drm_modeset_lock_all_ctx(drm, &ctx); + if (ret) + goto fail; + + ret = check_vgpu_plane_table(gvt, vgpu_plane_info->id, &pipe, + &plane_id, &framebuffer_id); + if (!ret) { + ret = -EINVAL; + goto fail; + } + + DRM_DEBUG_KMS("%s: pipe is %d, plane_id is %d, fb_id is %d\n", + __func__, pipe, plane_id, framebuffer_id); + + if (framebuffer_id) { + intel_crtc = intel_get_crtc_for_pipe(gvt->dev_priv, pipe); + + drm_for_each_plane(plane, drm) { + intel_plane = to_intel_plane(plane); + if (intel_plane->pipe == pipe && + intel_plane->id == plane_id) + break; + + intel_plane = NULL; + } + if (!intel_plane) + goto fail; + + //vGPU might want to disable the assigned plane + if (vgpu_plane_info->offset == 0) { + intel_plane->disable_plane(intel_plane, intel_crtc); + goto out; + } + + obj_fb = idr_find(&drm->mode_config.crtc_idr, framebuffer_id); + intel_fb = to_intel_framebuffer(obj_to_fb(obj_fb)); + + } else { + DRM_DEBUG_KMS("no assgined plane for the vGPU plane 0x%x\n", + vgpu_plane_info->id); + goto fail; + } + + ret = vgpu_plane_update_internal(gvt, &intel_plane->base, + &intel_crtc->base, &intel_fb->base, + &ctx, vgpu_plane_info); + +fail: + if (ret == -EDEADLK) { + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry; + } +out: + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} + + + 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 diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h index ea7c1c5..5d929bb 100644 --- a/drivers/gpu/drm/i915/gvt/display.h +++ b/drivers/gpu/drm/i915/gvt/display.h @@ -160,6 +160,20 @@ enum intel_vgpu_edid { GVT_EDID_NUM, }; +struct intel_vgpu_plane_info { + u32 id;; /* vgpu plane id */ + enum plane_id plane; + struct intel_vgpu *vgpu; + + /* vGPU plane registers values. */ + u32 offset; + u32 stride; + u32 control; + u32 plane_offset; + + u32 size; +}; + static inline char *vgpu_edid_str(enum intel_vgpu_edid id) { switch (id) { @@ -181,4 +195,8 @@ void intel_vgpu_clean_display(struct intel_vgpu *vgpu); int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe); + +void intel_vgpu_plane_update(struct intel_gvt *gvt, + struct intel_vgpu_plane_info *plane_info); + #endif