From 50525c332b55f899fb231d786931d0b45a3f3d41 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Tue, 15 May 2018 16:59:27 +0300 Subject: drm: content-type property for HDMI connector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added content_type property to drm_connector_state in order to properly handle external HDMI TV content-type setting. v2: * Moved helper function which attaches content type property to the drm core, as was suggested. Removed redundant connector state initialization. v3: * Removed caps in drm_content_type_enum_list. After some discussion it turned out that HDMI Spec 1.4 was wrongly assuming that IT Content(itc) bit doesn't affect Content type states, however itc bit needs to be manupulated as well. In order to not expose additional property for itc, for sake of simplicity it was decided to bind those together in same "content type" property. v4: * Added it_content checking in intel_digital_connector_atomic_check. Fixed documentation for new content type enum. v5: * Moved patch revision's description to commit messages. v6: * Minor naming fix for the content type enumeration string. v7: * Fix parameter name for documentation and parameter alignment in order not to get warning. Added Content Type description to new HDMI connector properties section. v8: * Thrown away unneeded numbers from HDMI content-type property description. Switch to strings desription instead of plain definitions. v9: * Moved away hdmi specific content-type enum from drm_connector_state. Content type property should probably not be bound to any specific connector interface in drm_connector_state. Same probably should be done to hdmi_picture_aspect_ration enum which is also contained in drm_connector_state. Added special helper function to get derive hdmi specific relevant infoframe fields. v10: * Added usage description to HDMI properties kernel doc. v11: * Created centralized function for filling HDMI AVI infoframe, based on correspondent DRM property value. Acked-by: Hans Verkuil Acked-by: Daniel Vetter Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20180515135928.31092-2-stanislav.lisovskiy@intel.com [vsyrjala: clean up checkpatch multiple blank lines warnings] Signed-off-by: Ville Syrjälä --- include/uapi/drm/drm_mode.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/uapi') diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 4b3a1bb58e68..971c016b368c 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -96,6 +96,13 @@ extern "C" { #define DRM_MODE_PICTURE_ASPECT_64_27 3 #define DRM_MODE_PICTURE_ASPECT_256_135 4 +/* Content type options */ +#define DRM_MODE_CONTENT_TYPE_NO_DATA 0 +#define DRM_MODE_CONTENT_TYPE_GRAPHICS 1 +#define DRM_MODE_CONTENT_TYPE_PHOTO 2 +#define DRM_MODE_CONTENT_TYPE_CINEMA 3 +#define DRM_MODE_CONTENT_TYPE_GAME 4 + /* Aspect ratio flag bitmask (4 bits 22:19) */ #define DRM_MODE_FLAG_PIC_AR_MASK (0x0F<<19) #define DRM_MODE_FLAG_PIC_AR_NONE \ -- cgit v1.2.3 From e065a8dd30af703b4794dc740c0825ee12b92efd Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Fri, 16 Mar 2018 15:04:35 -0700 Subject: drm/vc4: Add support for SAND modifier. This is the format generated by VC4's H.264 engine, and preferred by the ISP as well. By displaying SAND buffers directly, we can avoid needing to use the ISP to rewrite the SAND H.264 output to linear before display. This is a joint effort by Dave Stevenson (who wrote the initial patch and DRM demo) and Eric Anholt (drm_fourcc.h generalization, safety checks, RGBA support). v2: Make the parameter macro give all of the middle 48 bits (suggested by Daniels). Fix fourcc_mod_broadcom_mod()'s bits/shift being swapped. Mark NV12/21 as supported, not YUV420. Signed-off-by: Dave Stevenson Signed-off-by: Eric Anholt Cc: Daniel Vetter Acked-by: Daniel Stone (v1) Cc: Boris Brezillon Cc: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20180316220435.31416-3-eric@anholt.net --- drivers/gpu/drm/vc4/vc4_plane.c | 84 +++++++++++++++++++++++++++++++++++++---- drivers/gpu/drm/vc4/vc4_regs.h | 6 +++ include/uapi/drm/drm_fourcc.h | 59 +++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 7 deletions(-) (limited to 'include/uapi') diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 6efd55bae8db..2575bd81a010 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -467,12 +467,14 @@ static int vc4_plane_mode_set(struct drm_plane *plane, struct drm_framebuffer *fb = state->fb; u32 ctl0_offset = vc4_state->dlist_count; const struct hvs_format *format = vc4_get_hvs_format(fb->format->format); + u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier); int num_planes = drm_format_num_planes(format->drm); bool mix_plane_alpha; bool covers_screen; u32 scl0, scl1, pitch0; u32 lbm_size, tiling; unsigned long irqflags; + u32 hvs_format = format->hvs; int ret, i; ret = vc4_plane_setup_clipping_and_scaling(state); @@ -512,7 +514,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane, scl1 = vc4_get_scl_field(state, 0); } - switch (fb->modifier) { + switch (base_format_mod) { case DRM_FORMAT_MOD_LINEAR: tiling = SCALER_CTL0_TILING_LINEAR; pitch0 = VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH); @@ -535,6 +537,49 @@ static int vc4_plane_mode_set(struct drm_plane *plane, break; } + case DRM_FORMAT_MOD_BROADCOM_SAND64: + case DRM_FORMAT_MOD_BROADCOM_SAND128: + case DRM_FORMAT_MOD_BROADCOM_SAND256: { + uint32_t param = fourcc_mod_broadcom_param(fb->modifier); + + /* Column-based NV12 or RGBA. + */ + if (fb->format->num_planes > 1) { + if (hvs_format != HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE) { + DRM_DEBUG_KMS("SAND format only valid for NV12/21"); + return -EINVAL; + } + hvs_format = HVS_PIXEL_FORMAT_H264; + } else { + if (base_format_mod == DRM_FORMAT_MOD_BROADCOM_SAND256) { + DRM_DEBUG_KMS("SAND256 format only valid for H.264"); + return -EINVAL; + } + } + + switch (base_format_mod) { + case DRM_FORMAT_MOD_BROADCOM_SAND64: + tiling = SCALER_CTL0_TILING_64B; + break; + case DRM_FORMAT_MOD_BROADCOM_SAND128: + tiling = SCALER_CTL0_TILING_128B; + break; + case DRM_FORMAT_MOD_BROADCOM_SAND256: + tiling = SCALER_CTL0_TILING_256B_OR_T; + break; + default: + break; + } + + if (param > SCALER_TILE_HEIGHT_MASK) { + DRM_DEBUG_KMS("SAND height too large (%d)\n", param); + return -EINVAL; + } + + pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT); + break; + } + default: DRM_DEBUG_KMS("Unsupported FB tiling flag 0x%16llx", (long long)fb->modifier); @@ -546,7 +591,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane, SCALER_CTL0_VALID | VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) | (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) | - (format->hvs << SCALER_CTL0_PIXEL_FORMAT_SHIFT) | + (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) | VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) | (vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) | VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) | @@ -608,8 +653,13 @@ static int vc4_plane_mode_set(struct drm_plane *plane, /* Pitch word 1/2 */ for (i = 1; i < num_planes; i++) { - vc4_dlist_write(vc4_state, - VC4_SET_FIELD(fb->pitches[i], SCALER_SRC_PITCH)); + if (hvs_format != HVS_PIXEL_FORMAT_H264) { + vc4_dlist_write(vc4_state, + VC4_SET_FIELD(fb->pitches[i], + SCALER_SRC_PITCH)); + } else { + vc4_dlist_write(vc4_state, pitch0); + } } /* Colorspace conversion words */ @@ -867,13 +917,30 @@ static bool vc4_format_mod_supported(struct drm_plane *plane, case DRM_FORMAT_BGR565: case DRM_FORMAT_ARGB1555: case DRM_FORMAT_XRGB1555: - return true; + switch (fourcc_mod_broadcom_mod(modifier)) { + case DRM_FORMAT_MOD_LINEAR: + case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: + case DRM_FORMAT_MOD_BROADCOM_SAND64: + case DRM_FORMAT_MOD_BROADCOM_SAND128: + return true; + default: + return false; + } + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + switch (fourcc_mod_broadcom_mod(modifier)) { + case DRM_FORMAT_MOD_LINEAR: + case DRM_FORMAT_MOD_BROADCOM_SAND64: + case DRM_FORMAT_MOD_BROADCOM_SAND128: + case DRM_FORMAT_MOD_BROADCOM_SAND256: + return true; + default: + return false; + } case DRM_FORMAT_YUV422: case DRM_FORMAT_YVU422: case DRM_FORMAT_YUV420: case DRM_FORMAT_YVU420: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: case DRM_FORMAT_NV16: case DRM_FORMAT_NV61: default: @@ -903,6 +970,9 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, unsigned i; static const uint64_t modifiers[] = { DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED, + DRM_FORMAT_MOD_BROADCOM_SAND128, + DRM_FORMAT_MOD_BROADCOM_SAND64, + DRM_FORMAT_MOD_BROADCOM_SAND256, DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_INVALID }; diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index d1fb6fec46eb..d6864fa4bd14 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -1031,6 +1031,12 @@ enum hvs_pixel_format { #define SCALER_SRC_PITCH_MASK VC4_MASK(15, 0) #define SCALER_SRC_PITCH_SHIFT 0 +/* PITCH0/1/2 fields for tiled (SAND). */ +#define SCALER_TILE_SKIP_0_MASK VC4_MASK(18, 16) +#define SCALER_TILE_SKIP_0_SHIFT 16 +#define SCALER_TILE_HEIGHT_MASK VC4_MASK(15, 0) +#define SCALER_TILE_HEIGHT_SHIFT 0 + /* PITCH0 fields for T-tiled. */ #define SCALER_PITCH0_TILE_WIDTH_L_MASK VC4_MASK(22, 16) #define SCALER_PITCH0_TILE_WIDTH_L_SHIFT 16 diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index e04613d30a13..64bf67abff7e 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -384,6 +384,23 @@ extern "C" { #define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB \ fourcc_mod_code(NVIDIA, 0x15) +/* + * Some Broadcom modifiers take parameters, for example the number of + * vertical lines in the image. Reserve the lower 32 bits for modifier + * type, and the next 24 bits for parameters. Top 8 bits are the + * vendor code. + */ +#define __fourcc_mod_broadcom_param_shift 8 +#define __fourcc_mod_broadcom_param_bits 48 +#define fourcc_mod_broadcom_code(val, params) \ + fourcc_mod_code(BROADCOM, ((((__u64)params) << __fourcc_mod_broadcom_param_shift) | val)) +#define fourcc_mod_broadcom_param(m) \ + ((int)(((m) >> __fourcc_mod_broadcom_param_shift) & \ + ((1ULL << __fourcc_mod_broadcom_param_bits) - 1))) +#define fourcc_mod_broadcom_mod(m) \ + ((m) & ~(((1ULL << __fourcc_mod_broadcom_param_bits) - 1) << \ + __fourcc_mod_broadcom_param_shift)) + /* * Broadcom VC4 "T" format * @@ -405,6 +422,48 @@ extern "C" { */ #define DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED fourcc_mod_code(BROADCOM, 1) +/* + * Broadcom SAND format + * + * This is the native format that the H.264 codec block uses. For VC4 + * HVS, it is only valid for H.264 (NV12/21) and RGBA modes. + * + * The image can be considered to be split into columns, and the + * columns are placed consecutively into memory. The width of those + * columns can be either 32, 64, 128, or 256 pixels, but in practice + * only 128 pixel columns are used. + * + * The pitch between the start of each column is set to optimally + * switch between SDRAM banks. This is passed as the number of lines + * of column width in the modifier (we can't use the stride value due + * to various core checks that look at it , so you should set the + * stride to width*cpp). + * + * Note that the column height for this format modifier is the same + * for all of the planes, assuming that each column contains both Y + * and UV. Some SAND-using hardware stores UV in a separate tiled + * image from Y to reduce the column height, which is not supported + * with these modifiers. + */ + +#define DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(2, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(3, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(4, v) +#define DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(v) \ + fourcc_mod_broadcom_code(5, v) + +#define DRM_FORMAT_MOD_BROADCOM_SAND32 \ + DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND64 \ + DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND128 \ + DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(0) +#define DRM_FORMAT_MOD_BROADCOM_SAND256 \ + DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(0) + #if defined(__cplusplus) } #endif -- cgit v1.2.3 From b646c1dc835b6b73884a88643c2534f1a4a1928f Mon Sep 17 00:00:00 2001 From: Samuel Li Date: Thu, 24 May 2018 14:32:49 -0400 Subject: drm/amdgpu: add kernel doc for memory domains. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document the GEM domains exposed to userspace. Suggested-by: Alex Deucher Signed-off-by: Samuel Li Reviewed-by: Christian König Signed-off-by: Alex Deucher --- include/uapi/drm/amdgpu_drm.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'include/uapi') diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 78b4dd89fcb4..0dc9e606114e 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -72,6 +72,29 @@ extern "C" { #define DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_FENCE_TO_HANDLE, union drm_amdgpu_fence_to_handle) #define DRM_IOCTL_AMDGPU_SCHED DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_SCHED, union drm_amdgpu_sched) +/** + * DOC: memory domains + * + * %AMDGPU_GEM_DOMAIN_CPU System memory that is not GPU accessible. + * Memory in this pool could be swapped out to disk if there is pressure. + * + * %AMDGPU_GEM_DOMAIN_GTT GPU accessible system memory, mapped into the + * GPU's virtual address space via gart. Gart memory linearizes non-contiguous + * pages of system memory, allows GPU access system memory in a linezrized + * fashion. + * + * %AMDGPU_GEM_DOMAIN_VRAM Local video memory. For APUs, it is memory + * carved out by the BIOS. + * + * %AMDGPU_GEM_DOMAIN_GDS Global on-chip data storage used to share data + * across shader threads. + * + * %AMDGPU_GEM_DOMAIN_GWS Global wave sync, used to synchronize the + * execution of all the waves on a device. + * + * %AMDGPU_GEM_DOMAIN_OA Ordered append, used by 3D or Compute engines + * for appending data. + */ #define AMDGPU_GEM_DOMAIN_CPU 0x1 #define AMDGPU_GEM_DOMAIN_GTT 0x2 #define AMDGPU_GEM_DOMAIN_VRAM 0x4 -- cgit v1.2.3 From 81d350144bd4590ae546d83344421106e8faf69a Mon Sep 17 00:00:00 2001 From: Boyuan Zhang Date: Tue, 1 May 2018 14:47:31 -0400 Subject: uapi/drm: add AMDGPU_HW_IP_VCN_JPEG for jpeg CS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add AMDGPU_HW_IP_VCN_JPEG define for jpeg CS Signed-off-by: Boyuan Zhang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- include/uapi/drm/amdgpu_drm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/uapi') diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 0dc9e606114e..784b0fe470ee 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -506,7 +506,8 @@ struct drm_amdgpu_gem_va { #define AMDGPU_HW_IP_UVD_ENC 5 #define AMDGPU_HW_IP_VCN_DEC 6 #define AMDGPU_HW_IP_VCN_ENC 7 -#define AMDGPU_HW_IP_NUM 8 +#define AMDGPU_HW_IP_VCN_JPEG 8 +#define AMDGPU_HW_IP_NUM 9 #define AMDGPU_HW_IP_INSTANCE_MAX_COUNT 1 -- cgit v1.2.3 From 935774cd71fe604cc8ed24adcb507d7784255672 Mon Sep 17 00:00:00 2001 From: Brian Starkey Date: Wed, 29 Mar 2017 17:42:32 +0100 Subject: drm: Add writeback connector type Writeback connectors represent writeback engines which can write the CRTC output to a memory framebuffer. Add a writeback connector type and related support functions. Drivers should initialize a writeback connector with drm_writeback_connector_init() which takes care of setting up all the writeback-specific details on top of the normal functionality of drm_connector_init(). Writeback connectors have a WRITEBACK_FB_ID property, used to set the output framebuffer, and a WRITEBACK_PIXEL_FORMATS blob used to expose the supported writeback formats to userspace. When a framebuffer is attached to a writeback connector with the WRITEBACK_FB_ID property, it is used only once (for the commit in which it was included), and userspace can never read back the value of WRITEBACK_FB_ID. WRITEBACK_FB_ID can only be set if the connector is attached to a CRTC. Changes since v1: - Added drm_writeback.c + documentation - Added helper to initialize writeback connector in one go - Added core checks - Squashed into a single commit - Dropped the client cap - Writeback framebuffers are no longer persistent Changes since v2: Daniel Vetter: - Subclass drm_connector to drm_writeback_connector - Relax check to allow CRTC to be set without an FB - Add some writeback_ prefixes - Drop PIXEL_FORMATS_SIZE property, as it was unnecessary Gustavo Padovan: - Add drm_writeback_job to handle writeback signalling centrally Changes since v3: - Rebased - Rename PIXEL_FORMATS -> WRITEBACK_PIXEL_FORMATS Chances since v4: - Embed a drm_encoder inside the drm_writeback_connector to reduce the amount of boilerplate code required from the drivers that are using it. Changes since v5: - Added Rob Clark's atomic_commit() vfunc to connector helper funcs, so that writeback jobs are committed from atomic helpers - Updated create_writeback_properties() signature to return an error code rather than a boolean false for failure. - Free writeback job with the connector state rather than when doing the cleanup_work() Changes since v7: - fix extraneous use of out_fence that is only introduced in a subsequent patch. Changes since v8: - whitespace changes pull from subsequent patch Changes since v9: - Revert the v6 changes that free the writeback job in the connector state cleanup and return to doing it in the cleanup_work() function Signed-off-by: Brian Starkey [rebased and fixed conflicts] Signed-off-by: Mihail Atanassov [rebased and added atomic_commit() vfunc for writeback jobs] Signed-off-by: Rob Clark Signed-off-by: Liviu Dudau Reviewed-by: Eric Anholt Link: https://patchwork.freedesktop.org/patch/229037/ --- Documentation/gpu/drm-kms.rst | 9 ++ drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/drm_atomic.c | 124 ++++++++++++++++ drivers/gpu/drm/drm_atomic_helper.c | 25 ++++ drivers/gpu/drm/drm_connector.c | 4 +- drivers/gpu/drm/drm_writeback.c | 245 +++++++++++++++++++++++++++++++ include/drm/drm_atomic.h | 3 + include/drm/drm_connector.h | 13 ++ include/drm/drm_mode_config.h | 15 ++ include/drm/drm_modeset_helper_vtables.h | 11 ++ include/drm/drm_writeback.h | 91 ++++++++++++ include/uapi/drm/drm_mode.h | 1 + 12 files changed, 541 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/drm_writeback.c create mode 100644 include/drm/drm_writeback.h (limited to 'include/uapi') diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index e233c2626bd0..4f6f113a7f5d 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -373,6 +373,15 @@ Connector Functions Reference .. kernel-doc:: drivers/gpu/drm/drm_connector.c :export: +Writeback Connectors +-------------------- + +.. kernel-doc:: drivers/gpu/drm/drm_writeback.c + :doc: overview + +.. kernel-doc:: drivers/gpu/drm/drm_writeback.c + :export: + Encoder Abstraction =================== diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index ef9f3dab287f..69c13517ea3a 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -18,7 +18,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ drm_encoder.o drm_mode_object.o drm_property.o \ drm_plane.o drm_color_mgmt.o drm_print.o \ drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \ - drm_syncobj.o drm_lease.o + drm_syncobj.o drm_lease.o drm_writeback.o drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o drm-$(CONFIG_DRM_VM) += drm_vm.o diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 9ec5c865a043..3e53d6e5c340 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "drm_crtc_internal.h" @@ -690,6 +691,45 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p, crtc->funcs->atomic_print_state(p, state); } +/** + * drm_atomic_connector_check - check connector state + * @connector: connector to check + * @state: connector state to check + * + * Provides core sanity checks for connector state. + * + * RETURNS: + * Zero on success, error code on failure + */ +static int drm_atomic_connector_check(struct drm_connector *connector, + struct drm_connector_state *state) +{ + struct drm_crtc_state *crtc_state; + struct drm_writeback_job *writeback_job = state->writeback_job; + + if ((connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK) || !writeback_job) + return 0; + + if (writeback_job->fb && !state->crtc) { + DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] framebuffer without CRTC\n", + connector->base.id, connector->name); + return -EINVAL; + } + + if (state->crtc) + crtc_state = drm_atomic_get_existing_crtc_state(state->state, + state->crtc); + + if (writeback_job->fb && !crtc_state->active) { + DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] has framebuffer, but [CRTC:%d] is off\n", + connector->base.id, connector->name, + state->crtc->base.id); + return -EINVAL; + } + + return 0; +} + /** * drm_atomic_get_plane_state - get plane state * @state: global atomic state object @@ -1321,6 +1361,12 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, return -EINVAL; } state->content_protection = val; + } else if (property == config->writeback_fb_id_property) { + struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val); + int ret = drm_atomic_set_writeback_fb_for_connector(state, fb); + if (fb) + drm_framebuffer_put(fb); + return ret; } else if (connector->funcs->atomic_set_property) { return connector->funcs->atomic_set_property(connector, state, property, val); @@ -1407,6 +1453,9 @@ drm_atomic_connector_get_property(struct drm_connector *connector, *val = state->scaling_mode; } else if (property == connector->content_protection_property) { *val = state->content_protection; + } else if (property == config->writeback_fb_id_property) { + /* Writeback framebuffer is one-shot, write and forget */ + *val = 0; } else if (connector->funcs->atomic_get_property) { return connector->funcs->atomic_get_property(connector, state, property, val); @@ -1631,6 +1680,70 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, } EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector); +/* + * drm_atomic_get_writeback_job - return or allocate a writeback job + * @conn_state: Connector state to get the job for + * + * Writeback jobs have a different lifetime to the atomic state they are + * associated with. This convenience function takes care of allocating a job + * if there isn't yet one associated with the connector state, otherwise + * it just returns the existing job. + * + * Returns: The writeback job for the given connector state + */ +static struct drm_writeback_job * +drm_atomic_get_writeback_job(struct drm_connector_state *conn_state) +{ + WARN_ON(conn_state->connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK); + + if (!conn_state->writeback_job) + conn_state->writeback_job = + kzalloc(sizeof(*conn_state->writeback_job), GFP_KERNEL); + + return conn_state->writeback_job; +} + +/** + * drm_atomic_set_writeback_fb_for_connector - set writeback framebuffer + * @conn_state: atomic state object for the connector + * @fb: fb to use for the connector + * + * This is used to set the framebuffer for a writeback connector, which outputs + * to a buffer instead of an actual physical connector. + * Changing the assigned framebuffer requires us to grab a reference to the new + * fb and drop the reference to the old fb, if there is one. This function + * takes care of all these details besides updating the pointer in the + * state object itself. + * + * Note: The only way conn_state can already have an fb set is if the commit + * sets the property more than once. + * + * See also: drm_writeback_connector_init() + * + * Returns: 0 on success + */ +int drm_atomic_set_writeback_fb_for_connector( + struct drm_connector_state *conn_state, + struct drm_framebuffer *fb) +{ + struct drm_writeback_job *job = + drm_atomic_get_writeback_job(conn_state); + if (!job) + return -ENOMEM; + + drm_framebuffer_assign(&job->fb, fb); + + if (fb) + DRM_DEBUG_ATOMIC("Set [FB:%d] for connector state %p\n", + fb->base.id, conn_state); + else + DRM_DEBUG_ATOMIC("Set [NOFB] for connector state %p\n", + conn_state); + + return 0; +} +EXPORT_SYMBOL(drm_atomic_set_writeback_fb_for_connector); + /** * drm_atomic_add_affected_connectors - add connectors for crtc * @state: atomic state @@ -1752,6 +1865,8 @@ int drm_atomic_check_only(struct drm_atomic_state *state) struct drm_plane_state *plane_state; struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; + struct drm_connector *conn; + struct drm_connector_state *conn_state; int i, ret = 0; DRM_DEBUG_ATOMIC("checking %p\n", state); @@ -1774,6 +1889,15 @@ int drm_atomic_check_only(struct drm_atomic_state *state) } } + for_each_new_connector_in_state(state, conn, conn_state, i) { + ret = drm_atomic_connector_check(conn, conn_state); + if (ret) { + DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] atomic core check failed\n", + conn->base.id, conn->name); + return ret; + } + } + if (config->funcs->atomic_check) ret = config->funcs->atomic_check(state->dev, state); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 232fa11a5e31..17baf5057132 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "drm_crtc_helper_internal.h" @@ -1172,6 +1173,25 @@ void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev, } EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_disables); +static void drm_atomic_helper_commit_writebacks(struct drm_device *dev, + struct drm_atomic_state *old_state) +{ + struct drm_connector *connector; + struct drm_connector_state *new_conn_state; + int i; + + for_each_new_connector_in_state(old_state, connector, new_conn_state, i) { + const struct drm_connector_helper_funcs *funcs; + + funcs = connector->helper_private; + + if (new_conn_state->writeback_job && new_conn_state->writeback_job->fb) { + WARN_ON(connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK); + funcs->atomic_commit(connector, new_conn_state->writeback_job); + } + } +} + /** * drm_atomic_helper_commit_modeset_enables - modeset commit to enable outputs * @dev: DRM device @@ -1251,6 +1271,8 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, drm_bridge_enable(encoder->bridge); } + + drm_atomic_helper_commit_writebacks(dev, old_state); } EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables); @@ -3647,6 +3669,9 @@ __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, if (state->crtc) drm_connector_get(connector); state->commit = NULL; + + /* Don't copy over a writeback job, they are used only once */ + state->writeback_job = NULL; } EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state); diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 549b89501e01..2f9ebddd178e 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -87,6 +87,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, { DRM_MODE_CONNECTOR_DSI, "DSI" }, { DRM_MODE_CONNECTOR_DPI, "DPI" }, + { DRM_MODE_CONNECTOR_WRITEBACK, "Writeback" }, }; void drm_connector_ida_init(void) @@ -253,7 +254,8 @@ int drm_connector_init(struct drm_device *dev, config->num_connector++; spin_unlock_irq(&config->connector_list_lock); - if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL) + if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL && + connector_type != DRM_MODE_CONNECTOR_WRITEBACK) drm_object_attach_property(&connector->base, config->edid_property, 0); diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c new file mode 100644 index 000000000000..e5b8a4b79724 --- /dev/null +++ b/drivers/gpu/drm/drm_writeback.c @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) COPYRIGHT 2016 ARM Limited. All rights reserved. + * Author: Brian Starkey + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + */ + +#include +#include +#include +#include +#include + +/** + * DOC: overview + * + * Writeback connectors are used to expose hardware which can write the output + * from a CRTC to a memory buffer. They are used and act similarly to other + * types of connectors, with some important differences: + * - Writeback connectors don't provide a way to output visually to the user. + * - Writeback connectors should always report as "disconnected" (so that + * clients which don't understand them will ignore them). + * - Writeback connectors don't have EDID. + * + * A framebuffer may only be attached to a writeback connector when the + * connector is attached to a CRTC. The WRITEBACK_FB_ID property which sets the + * framebuffer applies only to a single commit (see below). A framebuffer may + * not be attached while the CRTC is off. + * + * Writeback connectors have some additional properties, which userspace + * can use to query and control them: + * + * "WRITEBACK_FB_ID": + * Write-only object property storing a DRM_MODE_OBJECT_FB: it stores the + * framebuffer to be written by the writeback connector. This property is + * similar to the FB_ID property on planes, but will always read as zero + * and is not preserved across commits. + * Userspace must set this property to an output buffer every time it + * wishes the buffer to get filled. + * + * "WRITEBACK_PIXEL_FORMATS": + * Immutable blob property to store the supported pixel formats table. The + * data is an array of u32 DRM_FORMAT_* fourcc values. + * Userspace can use this blob to find out what pixel formats are supported + * by the connector's writeback engine. + */ + +static int create_writeback_properties(struct drm_device *dev) +{ + struct drm_property *prop; + + if (!dev->mode_config.writeback_fb_id_property) { + prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, + "WRITEBACK_FB_ID", + DRM_MODE_OBJECT_FB); + if (!prop) + return -ENOMEM; + dev->mode_config.writeback_fb_id_property = prop; + } + + if (!dev->mode_config.writeback_pixel_formats_property) { + prop = drm_property_create(dev, DRM_MODE_PROP_BLOB | + DRM_MODE_PROP_ATOMIC | + DRM_MODE_PROP_IMMUTABLE, + "WRITEBACK_PIXEL_FORMATS", 0); + if (!prop) + return -ENOMEM; + dev->mode_config.writeback_pixel_formats_property = prop; + } + + return 0; +} + +static const struct drm_encoder_funcs drm_writeback_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + +/** + * drm_writeback_connector_init - Initialize a writeback connector and its properties + * @dev: DRM device + * @wb_connector: Writeback connector to initialize + * @con_funcs: Connector funcs vtable + * @enc_helper_funcs: Encoder helper funcs vtable to be used by the internal encoder + * @formats: Array of supported pixel formats for the writeback engine + * @n_formats: Length of the formats array + * + * This function creates the writeback-connector-specific properties if they + * have not been already created, initializes the connector as + * type DRM_MODE_CONNECTOR_WRITEBACK, and correctly initializes the property + * values. It will also create an internal encoder associated with the + * drm_writeback_connector and set it to use the @enc_helper_funcs vtable for + * the encoder helper. + * + * Drivers should always use this function instead of drm_connector_init() to + * set up writeback connectors. + * + * Returns: 0 on success, or a negative error code + */ +int drm_writeback_connector_init(struct drm_device *dev, + struct drm_writeback_connector *wb_connector, + const struct drm_connector_funcs *con_funcs, + const struct drm_encoder_helper_funcs *enc_helper_funcs, + const u32 *formats, int n_formats) +{ + struct drm_property_blob *blob; + struct drm_connector *connector = &wb_connector->base; + struct drm_mode_config *config = &dev->mode_config; + int ret = create_writeback_properties(dev); + + if (ret != 0) + return ret; + + blob = drm_property_create_blob(dev, n_formats * sizeof(*formats), + formats); + if (IS_ERR(blob)) + return PTR_ERR(blob); + + drm_encoder_helper_add(&wb_connector->encoder, enc_helper_funcs); + ret = drm_encoder_init(dev, &wb_connector->encoder, + &drm_writeback_encoder_funcs, + DRM_MODE_ENCODER_VIRTUAL, NULL); + if (ret) + goto fail; + + connector->interlace_allowed = 0; + + ret = drm_connector_init(dev, connector, con_funcs, + DRM_MODE_CONNECTOR_WRITEBACK); + if (ret) + goto connector_fail; + + ret = drm_mode_connector_attach_encoder(connector, + &wb_connector->encoder); + if (ret) + goto attach_fail; + + INIT_LIST_HEAD(&wb_connector->job_queue); + spin_lock_init(&wb_connector->job_lock); + + drm_object_attach_property(&connector->base, + config->writeback_fb_id_property, 0); + + drm_object_attach_property(&connector->base, + config->writeback_pixel_formats_property, + blob->base.id); + wb_connector->pixel_formats_blob_ptr = blob; + + return 0; + +attach_fail: + drm_connector_cleanup(connector); +connector_fail: + drm_encoder_cleanup(&wb_connector->encoder); +fail: + drm_property_blob_put(blob); + return ret; +} +EXPORT_SYMBOL(drm_writeback_connector_init); + +/** + * drm_writeback_queue_job - Queue a writeback job for later signalling + * @wb_connector: The writeback connector to queue a job on + * @job: The job to queue + * + * This function adds a job to the job_queue for a writeback connector. It + * should be considered to take ownership of the writeback job, and so any other + * references to the job must be cleared after calling this function. + * + * Drivers must ensure that for a given writeback connector, jobs are queued in + * exactly the same order as they will be completed by the hardware (and + * signaled via drm_writeback_signal_completion). + * + * For every call to drm_writeback_queue_job() there must be exactly one call to + * drm_writeback_signal_completion() + * + * See also: drm_writeback_signal_completion() + */ +void drm_writeback_queue_job(struct drm_writeback_connector *wb_connector, + struct drm_writeback_job *job) +{ + unsigned long flags; + + spin_lock_irqsave(&wb_connector->job_lock, flags); + list_add_tail(&job->list_entry, &wb_connector->job_queue); + spin_unlock_irqrestore(&wb_connector->job_lock, flags); +} +EXPORT_SYMBOL(drm_writeback_queue_job); + +/* + * @cleanup_work: deferred cleanup of a writeback job + * + * The job cannot be cleaned up directly in drm_writeback_signal_completion, + * because it may be called in interrupt context. Dropping the framebuffer + * reference can sleep, and so the cleanup is deferred to a workqueue. + */ +static void cleanup_work(struct work_struct *work) +{ + struct drm_writeback_job *job = container_of(work, + struct drm_writeback_job, + cleanup_work); + drm_framebuffer_put(job->fb); + kfree(job); +} + + +/** + * drm_writeback_signal_completion - Signal the completion of a writeback job + * @wb_connector: The writeback connector whose job is complete + * + * Drivers should call this to signal the completion of a previously queued + * writeback job. It should be called as soon as possible after the hardware + * has finished writing, and may be called from interrupt context. + * It is the driver's responsibility to ensure that for a given connector, the + * hardware completes writeback jobs in the same order as they are queued. + * + * Unless the driver is holding its own reference to the framebuffer, it must + * not be accessed after calling this function. + * + * See also: drm_writeback_queue_job() + */ +void +drm_writeback_signal_completion(struct drm_writeback_connector *wb_connector) +{ + unsigned long flags; + struct drm_writeback_job *job; + + spin_lock_irqsave(&wb_connector->job_lock, flags); + job = list_first_entry_or_null(&wb_connector->job_queue, + struct drm_writeback_job, + list_entry); + if (job) + list_del(&job->list_entry); + spin_unlock_irqrestore(&wb_connector->job_lock, flags); + + if (WARN_ON(!job)) + return; + + INIT_WORK(&job->cleanup_work, cleanup_work); + queue_work(system_long_wq, &job->cleanup_work); +} +EXPORT_SYMBOL(drm_writeback_signal_completion); diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index ca461b6cf71f..8254521b4583 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -594,6 +594,9 @@ void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state, int __must_check drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, struct drm_crtc *crtc); +int drm_atomic_set_writeback_fb_for_connector( + struct drm_connector_state *conn_state, + struct drm_framebuffer *fb); int __must_check drm_atomic_add_affected_connectors(struct drm_atomic_state *state, struct drm_crtc *crtc); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index c5797c24edd3..716c3a0e0e1d 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -437,6 +437,19 @@ struct drm_connector_state { * protection. This is most commonly used for HDCP. */ unsigned int content_protection; + + /** + * @writeback_job: Writeback job for writeback connectors + * + * Holds the framebuffer for a writeback connector. As the writeback + * completion may be asynchronous to the normal commit cycle, the + * writeback job lifetime is managed separately from the normal atomic + * state by this object. + * + * See also: drm_writeback_queue_job() and + * drm_writeback_signal_completion() + */ + struct drm_writeback_job *writeback_job; }; /** diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index fb45839179dd..5f24329e6927 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -784,6 +784,21 @@ struct drm_mode_config { */ struct drm_property *panel_orientation_property; + /** + * @writeback_fb_id_property: Property for writeback connectors, storing + * the ID of the output framebuffer. + * See also: drm_writeback_connector_init() + */ + struct drm_property *writeback_fb_id_property; + + /** + * @writeback_pixel_formats_property: Property for writeback connectors, + * storing an array of the supported pixel formats for the writeback + * engine (read-only). + * See also: drm_writeback_connector_init() + */ + struct drm_property *writeback_pixel_formats_property; + /* dumb ioctl parameters */ uint32_t preferred_depth, prefer_shadow; diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index 35e2a3a79fc5..3b289773297c 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -974,6 +974,17 @@ struct drm_connector_helper_funcs { */ int (*atomic_check)(struct drm_connector *connector, struct drm_connector_state *state); + + /** + * @atomic_commit: + * + * This hook is to be used by drivers implementing writeback connectors + * that need a point when to commit the writeback job to the hardware. + * + * This callback is used by the atomic modeset helpers. + */ + void (*atomic_commit)(struct drm_connector *connector, + struct drm_writeback_job *writeback_job); }; /** diff --git a/include/drm/drm_writeback.h b/include/drm/drm_writeback.h new file mode 100644 index 000000000000..17cd1feecd7e --- /dev/null +++ b/include/drm/drm_writeback.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * (C) COPYRIGHT 2016 ARM Limited. All rights reserved. + * Author: Brian Starkey + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + */ + +#ifndef __DRM_WRITEBACK_H__ +#define __DRM_WRITEBACK_H__ +#include +#include +#include + +struct drm_writeback_connector { + struct drm_connector base; + + /** + * @encoder: Internal encoder used by the connector to fulfill + * the DRM framework requirements. The users of the + * @drm_writeback_connector control the behaviour of the @encoder + * by passing the @enc_funcs parameter to drm_writeback_connector_init() + * function. + */ + struct drm_encoder encoder; + + /** + * @pixel_formats_blob_ptr: + * + * DRM blob property data for the pixel formats list on writeback + * connectors + * See also drm_writeback_connector_init() + */ + struct drm_property_blob *pixel_formats_blob_ptr; + + /** @job_lock: Protects job_queue */ + spinlock_t job_lock; + + /** + * @job_queue: + * + * Holds a list of a connector's writeback jobs; the last item is the + * most recent. The first item may be either waiting for the hardware + * to begin writing, or currently being written. + * + * See also: drm_writeback_queue_job() and + * drm_writeback_signal_completion() + */ + struct list_head job_queue; +}; + +struct drm_writeback_job { + /** + * @cleanup_work: + * + * Used to allow drm_writeback_signal_completion to defer dropping the + * framebuffer reference to a workqueue + */ + struct work_struct cleanup_work; + + /** + * @list_entry: + * + * List item for the writeback connector's @job_queue + */ + struct list_head list_entry; + + /** + * @fb: + * + * Framebuffer to be written to by the writeback connector. Do not set + * directly, use drm_atomic_set_writeback_fb_for_connector() + */ + struct drm_framebuffer *fb; +}; + +int drm_writeback_connector_init(struct drm_device *dev, + struct drm_writeback_connector *wb_connector, + const struct drm_connector_funcs *con_funcs, + const struct drm_encoder_helper_funcs *enc_helper_funcs, + const u32 *formats, int n_formats); + +void drm_writeback_queue_job(struct drm_writeback_connector *wb_connector, + struct drm_writeback_job *job); + +void drm_writeback_cleanup_job(struct drm_writeback_job *job); +void drm_writeback_signal_completion(struct drm_writeback_connector *wb_connector); +#endif diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 971c016b368c..8d67243952f4 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -351,6 +351,7 @@ enum drm_mode_subconnector { #define DRM_MODE_CONNECTOR_VIRTUAL 15 #define DRM_MODE_CONNECTOR_DSI 16 #define DRM_MODE_CONNECTOR_DPI 17 +#define DRM_MODE_CONNECTOR_WRITEBACK 18 struct drm_mode_get_connector { -- cgit v1.2.3 From d67b6a2065076d763c7df626b8c54f16038ad862 Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Wed, 28 Feb 2018 14:11:23 +0000 Subject: drm: writeback: Add client capability for exposing writeback connectors Due to the fact that writeback connectors behave in a special way in DRM (they always report being disconnected) we might confuse some userspace. Add a client capability for writeback connectors that will filter them out for clients that don't understand the capability. Changelog: - only accept the capability if the client has already set the DRM_CLIENT_CAP_ATOMIC one. Cc: Sean Paul Cc: Brian Starkey Signed-off-by: Liviu Dudau Reviewed-by: Eric Anholt Reviewed-by: Brian Starkey Link: https://patchwork.freedesktop.org/patch/229038/ --- drivers/gpu/drm/drm_ioctl.c | 7 +++++++ drivers/gpu/drm/drm_mode_config.c | 5 +++++ include/drm/drm_file.h | 7 +++++++ include/uapi/drm/drm.h | 9 +++++++++ 4 files changed, 28 insertions(+) (limited to 'include/uapi') diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 0d4cfb232576..fe49fb0356b5 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -334,6 +334,13 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) return -EINVAL; file_priv->aspect_ratio_allowed = req->value; break; + case DRM_CLIENT_CAP_WRITEBACK_CONNECTORS: + if (!file_priv->atomic) + return -EINVAL; + if (req->value > 1) + return -EINVAL; + file_priv->writeback_connectors = req->value; + break; default: return -EINVAL; } diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index e5c653357024..21e353bd3948 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -145,6 +145,11 @@ int drm_mode_getresources(struct drm_device *dev, void *data, count = 0; connector_id = u64_to_user_ptr(card_res->connector_id_ptr); drm_for_each_connector_iter(connector, &conn_iter) { + /* only expose writeback connectors if userspace understands them */ + if (!file_priv->writeback_connectors && + (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)) + continue; + if (drm_lease_held(file_priv, connector->base.id)) { if (count < card_res->count_connectors && put_user(connector->base.id, connector_id + count)) { diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 027ac16da3d1..26485acc51d7 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -192,6 +192,13 @@ struct drm_file { */ unsigned aspect_ratio_allowed:1; + /** + * @writeback_connectors: + * + * True if client understands writeback connectors + */ + unsigned writeback_connectors:1; + /** * @is_master: * diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 9c660e1688ab..300f336633f2 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -687,6 +687,15 @@ struct drm_get_cap { */ #define DRM_CLIENT_CAP_ASPECT_RATIO 4 +/** + * DRM_CLIENT_CAP_WRITEBACK_CONNECTORS + * + * If set to 1, the DRM core will expose special connectors to be used for + * writing back to memory the scene setup in the commit. Depends on client + * also supporting DRM_CLIENT_CAP_ATOMIC + */ +#define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5 + /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ struct drm_set_client_cap { __u64 capability; -- cgit v1.2.3 From 14d9deeb273c2bf4ec256589adabd8df65395d36 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 20 Jun 2018 17:17:03 -0700 Subject: drm/v3d: Define the fourcc modifier for the Broadcom UIF format. This will be used by Mesa, and potentially other drivers in the future, to describe tiled buffers. Signed-off-by: Eric Anholt Link: https://patchwork.freedesktop.org/patch/msgid/20180621001703.13522-1-eric@anholt.net Acked-by: Daniel Vetter --- include/uapi/drm/drm_fourcc.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'include/uapi') diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 64bf67abff7e..d5e52350a3aa 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -464,6 +464,27 @@ extern "C" { #define DRM_FORMAT_MOD_BROADCOM_SAND256 \ DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(0) +/* Broadcom UIF format + * + * This is the common format for the current Broadcom multimedia + * blocks, including V3D 3.x and newer, newer video codecs, and + * displays. + * + * The image consists of utiles (64b blocks), UIF blocks (2x2 utiles), + * and macroblocks (4x4 UIF blocks). Those 4x4 UIF block groups are + * stored in columns, with padding between the columns to ensure that + * moving from one column to the next doesn't hit the same SDRAM page + * bank. + * + * To calculate the padding, it is assumed that each hardware block + * and the software driving it knows the platform's SDRAM page size, + * number of banks, and XOR address, and that it's identical between + * all blocks using the format. This tiling modifier will use XOR as + * necessary to reduce the padding. If a hardware block can't do XOR, + * the assumption is that a no-XOR tiling modifier will be created. + */ +#define DRM_FORMAT_MOD_BROADCOM_UIF fourcc_mod_code(BROADCOM, 6) + #if defined(__cplusplus) } #endif -- cgit v1.2.3 From f1d34bfd70b1b4543a139ea28bad4c001c5f413d Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 19 Jun 2018 15:02:16 +0200 Subject: drm/vmwgfx: Replace vmw_dma_buffer with vmw_buffer_object Initially vmware buffer objects were only used as DMA buffers, so the name DMA buffer was a natural one. However, currently they are used also as dumb buffers and MOBs backing guest backed objects so renaming them to buffer objects is logical. Particularly since there is a dmabuf subsystem in the kernel where a dma buffer means something completely different. This also renames user-space api structures and IOCTL names correspondingly, but the old names remain defined for now and the ABI hasn't changed. There are a couple of minor style changes to make checkpatch happy. Signed-off-by: Thomas Hellstrom Reviewed-by: Sinclair Yeh Reviewed-by: Deepak Rawat --- drivers/gpu/drm/vmwgfx/Makefile | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 376 ++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 887 ----------------------------- drivers/gpu/drm/vmwgfx/vmwgfx_context.c | 10 +- drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c | 10 +- drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c | 376 ------------ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 18 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 129 ++--- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 86 ++- drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 16 +- drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 203 ++++--- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 58 +- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 10 +- drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c | 24 +- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 280 ++++----- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 100 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_shader.c | 22 +- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 64 +-- drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 37 +- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 887 +++++++++++++++++++++++++++++ include/uapi/drm/vmwgfx_drm.h | 61 +- 22 files changed, 1822 insertions(+), 1840 deletions(-) create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_bo.c delete mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c delete mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c (limited to 'include/uapi') diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile index 794cc9d5c9b0..09b2aa08363e 100644 --- a/drivers/gpu/drm/vmwgfx/Makefile +++ b/drivers/gpu/drm/vmwgfx/Makefile @@ -1,9 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ - vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \ + vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_ttm_buffer.o \ vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \ vmwgfx_overlay.o vmwgfx_marker.o vmwgfx_gmrid_manager.o \ - vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o vmwgfx_context.o \ + vmwgfx_fence.o vmwgfx_bo.o vmwgfx_scrn.o vmwgfx_context.o \ vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o \ vmwgfx_cmdbuf_res.o vmwgfx_cmdbuf.o vmwgfx_stdu.o \ vmwgfx_cotable.o vmwgfx_so.o vmwgfx_binding.o vmwgfx_msg.o \ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c new file mode 100644 index 000000000000..f26f658cccdb --- /dev/null +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -0,0 +1,376 @@ +/************************************************************************** + * + * Copyright © 2011-2015 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include + +#include +#include "vmwgfx_drv.h" + + +/** + * vmw_bo_pin_in_placement - Validate a buffer to placement. + * + * @dev_priv: Driver private. + * @buf: DMA buffer to move. + * @placement: The placement to pin it. + * @interruptible: Use interruptible wait. + * + * Returns + * -ERESTARTSYS if interrupted by a signal. + */ +int vmw_bo_pin_in_placement(struct vmw_private *dev_priv, + struct vmw_buffer_object *buf, + struct ttm_placement *placement, + bool interruptible) +{ + struct ttm_operation_ctx ctx = {interruptible, false }; + struct ttm_buffer_object *bo = &buf->base; + int ret; + uint32_t new_flags; + + ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible); + if (unlikely(ret != 0)) + return ret; + + vmw_execbuf_release_pinned_bo(dev_priv); + + ret = ttm_bo_reserve(bo, interruptible, false, NULL); + if (unlikely(ret != 0)) + goto err; + + if (buf->pin_count > 0) + ret = ttm_bo_mem_compat(placement, &bo->mem, + &new_flags) == true ? 0 : -EINVAL; + else + ret = ttm_bo_validate(bo, placement, &ctx); + + if (!ret) + vmw_bo_pin_reserved(buf, true); + + ttm_bo_unreserve(bo); + +err: + ttm_write_unlock(&dev_priv->reservation_sem); + return ret; +} + +/** + * vmw_bo_pin_in_vram_or_gmr - Move a buffer to vram or gmr. + * + * This function takes the reservation_sem in write mode. + * Flushes and unpins the query bo to avoid failures. + * + * @dev_priv: Driver private. + * @buf: DMA buffer to move. + * @pin: Pin buffer if true. + * @interruptible: Use interruptible wait. + * + * Returns + * -ERESTARTSYS if interrupted by a signal. + */ +int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, + struct vmw_buffer_object *buf, + bool interruptible) +{ + struct ttm_operation_ctx ctx = {interruptible, false }; + struct ttm_buffer_object *bo = &buf->base; + int ret; + uint32_t new_flags; + + ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible); + if (unlikely(ret != 0)) + return ret; + + vmw_execbuf_release_pinned_bo(dev_priv); + + ret = ttm_bo_reserve(bo, interruptible, false, NULL); + if (unlikely(ret != 0)) + goto err; + + if (buf->pin_count > 0) { + ret = ttm_bo_mem_compat(&vmw_vram_gmr_placement, &bo->mem, + &new_flags) == true ? 0 : -EINVAL; + goto out_unreserve; + } + + ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx); + if (likely(ret == 0) || ret == -ERESTARTSYS) + goto out_unreserve; + + ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx); + +out_unreserve: + if (!ret) + vmw_bo_pin_reserved(buf, true); + + ttm_bo_unreserve(bo); +err: + ttm_write_unlock(&dev_priv->reservation_sem); + return ret; +} + +/** + * vmw_bo_pin_in_vram - Move a buffer to vram. + * + * This function takes the reservation_sem in write mode. + * Flushes and unpins the query bo to avoid failures. + * + * @dev_priv: Driver private. + * @buf: DMA buffer to move. + * @interruptible: Use interruptible wait. + * + * Returns + * -ERESTARTSYS if interrupted by a signal. + */ +int vmw_bo_pin_in_vram(struct vmw_private *dev_priv, + struct vmw_buffer_object *buf, + bool interruptible) +{ + return vmw_bo_pin_in_placement(dev_priv, buf, &vmw_vram_placement, + interruptible); +} + +/** + * vmw_bo_pin_in_start_of_vram - Move a buffer to start of vram. + * + * This function takes the reservation_sem in write mode. + * Flushes and unpins the query bo to avoid failures. + * + * @dev_priv: Driver private. + * @buf: DMA buffer to pin. + * @interruptible: Use interruptible wait. + * + * Returns + * -ERESTARTSYS if interrupted by a signal. + */ +int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, + struct vmw_buffer_object *buf, + bool interruptible) +{ + struct ttm_operation_ctx ctx = {interruptible, false }; + struct ttm_buffer_object *bo = &buf->base; + struct ttm_placement placement; + struct ttm_place place; + int ret = 0; + uint32_t new_flags; + + place = vmw_vram_placement.placement[0]; + place.lpfn = bo->num_pages; + placement.num_placement = 1; + placement.placement = &place; + placement.num_busy_placement = 1; + placement.busy_placement = &place; + + ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible); + if (unlikely(ret != 0)) + return ret; + + vmw_execbuf_release_pinned_bo(dev_priv); + ret = ttm_bo_reserve(bo, interruptible, false, NULL); + if (unlikely(ret != 0)) + goto err_unlock; + + /* + * Is this buffer already in vram but not at the start of it? + * In that case, evict it first because TTM isn't good at handling + * that situation. + */ + if (bo->mem.mem_type == TTM_PL_VRAM && + bo->mem.start < bo->num_pages && + bo->mem.start > 0 && + buf->pin_count == 0) { + ctx.interruptible = false; + (void) ttm_bo_validate(bo, &vmw_sys_placement, &ctx); + } + + if (buf->pin_count > 0) + ret = ttm_bo_mem_compat(&placement, &bo->mem, + &new_flags) == true ? 0 : -EINVAL; + else + ret = ttm_bo_validate(bo, &placement, &ctx); + + /* For some reason we didn't end up at the start of vram */ + WARN_ON(ret == 0 && bo->offset != 0); + if (!ret) + vmw_bo_pin_reserved(buf, true); + + ttm_bo_unreserve(bo); +err_unlock: + ttm_write_unlock(&dev_priv->reservation_sem); + + return ret; +} + +/** + * vmw_bo_unpin - Unpin the buffer given buffer, does not move the buffer. + * + * This function takes the reservation_sem in write mode. + * + * @dev_priv: Driver private. + * @buf: DMA buffer to unpin. + * @interruptible: Use interruptible wait. + * + * Returns + * -ERESTARTSYS if interrupted by a signal. + */ +int vmw_bo_unpin(struct vmw_private *dev_priv, + struct vmw_buffer_object *buf, + bool interruptible) +{ + struct ttm_buffer_object *bo = &buf->base; + int ret; + + ret = ttm_read_lock(&dev_priv->reservation_sem, interruptible); + if (unlikely(ret != 0)) + return ret; + + ret = ttm_bo_reserve(bo, interruptible, false, NULL); + if (unlikely(ret != 0)) + goto err; + + vmw_bo_pin_reserved(buf, false); + + ttm_bo_unreserve(bo); + +err: + ttm_read_unlock(&dev_priv->reservation_sem); + return ret; +} + +/** + * vmw_bo_get_guest_ptr - Get the guest ptr representing the current placement + * of a buffer. + * + * @bo: Pointer to a struct ttm_buffer_object. Must be pinned or reserved. + * @ptr: SVGAGuestPtr returning the result. + */ +void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *bo, + SVGAGuestPtr *ptr) +{ + if (bo->mem.mem_type == TTM_PL_VRAM) { + ptr->gmrId = SVGA_GMR_FRAMEBUFFER; + ptr->offset = bo->offset; + } else { + ptr->gmrId = bo->mem.start; + ptr->offset = 0; + } +} + + +/** + * vmw_bo_pin_reserved - Pin or unpin a buffer object without moving it. + * + * @vbo: The buffer object. Must be reserved. + * @pin: Whether to pin or unpin. + * + */ +void vmw_bo_pin_reserved(struct vmw_buffer_object *vbo, bool pin) +{ + struct ttm_operation_ctx ctx = { false, true }; + struct ttm_place pl; + struct ttm_placement placement; + struct ttm_buffer_object *bo = &vbo->base; + uint32_t old_mem_type = bo->mem.mem_type; + int ret; + + lockdep_assert_held(&bo->resv->lock.base); + + if (pin) { + if (vbo->pin_count++ > 0) + return; + } else { + WARN_ON(vbo->pin_count <= 0); + if (--vbo->pin_count > 0) + return; + } + + pl.fpfn = 0; + pl.lpfn = 0; + pl.flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | VMW_PL_FLAG_MOB + | TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED; + if (pin) + pl.flags |= TTM_PL_FLAG_NO_EVICT; + + memset(&placement, 0, sizeof(placement)); + placement.num_placement = 1; + placement.placement = &pl; + + ret = ttm_bo_validate(bo, &placement, &ctx); + + BUG_ON(ret != 0 || bo->mem.mem_type != old_mem_type); +} + + +/* + * vmw_buffer_object_unmap - Tear down a cached buffer object map. + * + * @vbo: The buffer object whose map we are tearing down. + * + * This function tears down a cached map set up using + * vmw_buffer_object_map_and_cache(). + */ +void vmw_buffer_object_unmap(struct vmw_buffer_object *vbo) +{ + if (vbo->map.bo == NULL) + return; + + ttm_bo_kunmap(&vbo->map); +} + + +/* + * vmw_buffer_object_map_and_cache - Map a buffer object and cache the map + * + * @vbo: The buffer object to map + * Return: A kernel virtual address or NULL if mapping failed. + * + * This function maps a buffer object into the kernel address space, or + * returns the virtual kernel address of an already existing map. The virtual + * address remains valid as long as the buffer object is pinned or reserved. + * The cached map is torn down on either + * 1) Buffer object move + * 2) Buffer object swapout + * 3) Buffer object destruction + * + */ +void *vmw_buffer_object_map_and_cache(struct vmw_buffer_object *vbo) +{ + struct ttm_buffer_object *bo = &vbo->base; + bool not_used; + void *virtual; + int ret; + + virtual = ttm_kmap_obj_virtual(&vbo->map, ¬_used); + if (virtual) + return virtual; + + ret = ttm_bo_kmap(bo, 0, bo->num_pages, &vbo->map); + if (ret) + DRM_ERROR("Buffer object map failed: %d.\n", ret); + + return ttm_kmap_obj_virtual(&vbo->map, ¬_used); +} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c deleted file mode 100644 index 21111fd091f9..000000000000 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ /dev/null @@ -1,887 +0,0 @@ -/************************************************************************** - * - * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "vmwgfx_drv.h" -#include -#include -#include - -static const struct ttm_place vram_placement_flags = { - .fpfn = 0, - .lpfn = 0, - .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED -}; - -static const struct ttm_place vram_ne_placement_flags = { - .fpfn = 0, - .lpfn = 0, - .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT -}; - -static const struct ttm_place sys_placement_flags = { - .fpfn = 0, - .lpfn = 0, - .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED -}; - -static const struct ttm_place sys_ne_placement_flags = { - .fpfn = 0, - .lpfn = 0, - .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT -}; - -static const struct ttm_place gmr_placement_flags = { - .fpfn = 0, - .lpfn = 0, - .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED -}; - -static const struct ttm_place gmr_ne_placement_flags = { - .fpfn = 0, - .lpfn = 0, - .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT -}; - -static const struct ttm_place mob_placement_flags = { - .fpfn = 0, - .lpfn = 0, - .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED -}; - -static const struct ttm_place mob_ne_placement_flags = { - .fpfn = 0, - .lpfn = 0, - .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT -}; - -struct ttm_placement vmw_vram_placement = { - .num_placement = 1, - .placement = &vram_placement_flags, - .num_busy_placement = 1, - .busy_placement = &vram_placement_flags -}; - -static const struct ttm_place vram_gmr_placement_flags[] = { - { - .fpfn = 0, - .lpfn = 0, - .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED - }, { - .fpfn = 0, - .lpfn = 0, - .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED - } -}; - -static const struct ttm_place gmr_vram_placement_flags[] = { - { - .fpfn = 0, - .lpfn = 0, - .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED - }, { - .fpfn = 0, - .lpfn = 0, - .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED - } -}; - -struct ttm_placement vmw_vram_gmr_placement = { - .num_placement = 2, - .placement = vram_gmr_placement_flags, - .num_busy_placement = 1, - .busy_placement = &gmr_placement_flags -}; - -static const struct ttm_place vram_gmr_ne_placement_flags[] = { - { - .fpfn = 0, - .lpfn = 0, - .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED | - TTM_PL_FLAG_NO_EVICT - }, { - .fpfn = 0, - .lpfn = 0, - .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED | - TTM_PL_FLAG_NO_EVICT - } -}; - -struct ttm_placement vmw_vram_gmr_ne_placement = { - .num_placement = 2, - .placement = vram_gmr_ne_placement_flags, - .num_busy_placement = 1, - .busy_placement = &gmr_ne_placement_flags -}; - -struct ttm_placement vmw_vram_sys_placement = { - .num_placement = 1, - .placement = &vram_placement_flags, - .num_busy_placement = 1, - .busy_placement = &sys_placement_flags -}; - -struct ttm_placement vmw_vram_ne_placement = { - .num_placement = 1, - .placement = &vram_ne_placement_flags, - .num_busy_placement = 1, - .busy_placement = &vram_ne_placement_flags -}; - -struct ttm_placement vmw_sys_placement = { - .num_placement = 1, - .placement = &sys_placement_flags, - .num_busy_placement = 1, - .busy_placement = &sys_placement_flags -}; - -struct ttm_placement vmw_sys_ne_placement = { - .num_placement = 1, - .placement = &sys_ne_placement_flags, - .num_busy_placement = 1, - .busy_placement = &sys_ne_placement_flags -}; - -static const struct ttm_place evictable_placement_flags[] = { - { - .fpfn = 0, - .lpfn = 0, - .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED - }, { - .fpfn = 0, - .lpfn = 0, - .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED - }, { - .fpfn = 0, - .lpfn = 0, - .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED - }, { - .fpfn = 0, - .lpfn = 0, - .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED - } -}; - -static const struct ttm_place nonfixed_placement_flags[] = { - { - .fpfn = 0, - .lpfn = 0, - .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED - }, { - .fpfn = 0, - .lpfn = 0, - .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED - }, { - .fpfn = 0, - .lpfn = 0, - .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED - } -}; - -struct ttm_placement vmw_evictable_placement = { - .num_placement = 4, - .placement = evictable_placement_flags, - .num_busy_placement = 1, - .busy_placement = &sys_placement_flags -}; - -struct ttm_placement vmw_srf_placement = { - .num_placement = 1, - .num_busy_placement = 2, - .placement = &gmr_placement_flags, - .busy_placement = gmr_vram_placement_flags -}; - -struct ttm_placement vmw_mob_placement = { - .num_placement = 1, - .num_busy_placement = 1, - .placement = &mob_placement_flags, - .busy_placement = &mob_placement_flags -}; - -struct ttm_placement vmw_mob_ne_placement = { - .num_placement = 1, - .num_busy_placement = 1, - .placement = &mob_ne_placement_flags, - .busy_placement = &mob_ne_placement_flags -}; - -struct ttm_placement vmw_nonfixed_placement = { - .num_placement = 3, - .placement = nonfixed_placement_flags, - .num_busy_placement = 1, - .busy_placement = &sys_placement_flags -}; - -struct vmw_ttm_tt { - struct ttm_dma_tt dma_ttm; - struct vmw_private *dev_priv; - int gmr_id; - struct vmw_mob *mob; - int mem_type; - struct sg_table sgt; - struct vmw_sg_table vsgt; - uint64_t sg_alloc_size; - bool mapped; -}; - -const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt); - -/** - * Helper functions to advance a struct vmw_piter iterator. - * - * @viter: Pointer to the iterator. - * - * These functions return false if past the end of the list, - * true otherwise. Functions are selected depending on the current - * DMA mapping mode. - */ -static bool __vmw_piter_non_sg_next(struct vmw_piter *viter) -{ - return ++(viter->i) < viter->num_pages; -} - -static bool __vmw_piter_sg_next(struct vmw_piter *viter) -{ - return __sg_page_iter_next(&viter->iter); -} - - -/** - * Helper functions to return a pointer to the current page. - * - * @viter: Pointer to the iterator - * - * These functions return a pointer to the page currently - * pointed to by @viter. Functions are selected depending on the - * current mapping mode. - */ -static struct page *__vmw_piter_non_sg_page(struct vmw_piter *viter) -{ - return viter->pages[viter->i]; -} - -static struct page *__vmw_piter_sg_page(struct vmw_piter *viter) -{ - return sg_page_iter_page(&viter->iter); -} - - -/** - * Helper functions to return the DMA address of the current page. - * - * @viter: Pointer to the iterator - * - * These functions return the DMA address of the page currently - * pointed to by @viter. Functions are selected depending on the - * current mapping mode. - */ -static dma_addr_t __vmw_piter_phys_addr(struct vmw_piter *viter) -{ - return page_to_phys(viter->pages[viter->i]); -} - -static dma_addr_t __vmw_piter_dma_addr(struct vmw_piter *viter) -{ - return viter->addrs[viter->i]; -} - -static dma_addr_t __vmw_piter_sg_addr(struct vmw_piter *viter) -{ - return sg_page_iter_dma_address(&viter->iter); -} - - -/** - * vmw_piter_start - Initialize a struct vmw_piter. - * - * @viter: Pointer to the iterator to initialize - * @vsgt: Pointer to a struct vmw_sg_table to initialize from - * - * Note that we're following the convention of __sg_page_iter_start, so that - * the iterator doesn't point to a valid page after initialization; it has - * to be advanced one step first. - */ -void vmw_piter_start(struct vmw_piter *viter, const struct vmw_sg_table *vsgt, - unsigned long p_offset) -{ - viter->i = p_offset - 1; - viter->num_pages = vsgt->num_pages; - switch (vsgt->mode) { - case vmw_dma_phys: - viter->next = &__vmw_piter_non_sg_next; - viter->dma_address = &__vmw_piter_phys_addr; - viter->page = &__vmw_piter_non_sg_page; - viter->pages = vsgt->pages; - break; - case vmw_dma_alloc_coherent: - viter->next = &__vmw_piter_non_sg_next; - viter->dma_address = &__vmw_piter_dma_addr; - viter->page = &__vmw_piter_non_sg_page; - viter->addrs = vsgt->addrs; - viter->pages = vsgt->pages; - break; - case vmw_dma_map_populate: - case vmw_dma_map_bind: - viter->next = &__vmw_piter_sg_next; - viter->dma_address = &__vmw_piter_sg_addr; - viter->page = &__vmw_piter_sg_page; - __sg_page_iter_start(&viter->iter, vsgt->sgt->sgl, - vsgt->sgt->orig_nents, p_offset); - break; - default: - BUG(); - } -} - -/** - * vmw_ttm_unmap_from_dma - unmap device addresses previsouly mapped for - * TTM pages - * - * @vmw_tt: Pointer to a struct vmw_ttm_backend - * - * Used to free dma mappings previously mapped by vmw_ttm_map_for_dma. - */ -static void vmw_ttm_unmap_from_dma(struct vmw_ttm_tt *vmw_tt) -{ - struct device *dev = vmw_tt->dev_priv->dev->dev; - - dma_unmap_sg(dev, vmw_tt->sgt.sgl, vmw_tt->sgt.nents, - DMA_BIDIRECTIONAL); - vmw_tt->sgt.nents = vmw_tt->sgt.orig_nents; -} - -/** - * vmw_ttm_map_for_dma - map TTM pages to get device addresses - * - * @vmw_tt: Pointer to a struct vmw_ttm_backend - * - * This function is used to get device addresses from the kernel DMA layer. - * However, it's violating the DMA API in that when this operation has been - * performed, it's illegal for the CPU to write to the pages without first - * unmapping the DMA mappings, or calling dma_sync_sg_for_cpu(). It is - * therefore only legal to call this function if we know that the function - * dma_sync_sg_for_cpu() is a NOP, and dma_sync_sg_for_device() is at most - * a CPU write buffer flush. - */ -static int vmw_ttm_map_for_dma(struct vmw_ttm_tt *vmw_tt) -{ - struct device *dev = vmw_tt->dev_priv->dev->dev; - int ret; - - ret = dma_map_sg(dev, vmw_tt->sgt.sgl, vmw_tt->sgt.orig_nents, - DMA_BIDIRECTIONAL); - if (unlikely(ret == 0)) - return -ENOMEM; - - vmw_tt->sgt.nents = ret; - - return 0; -} - -/** - * vmw_ttm_map_dma - Make sure TTM pages are visible to the device - * - * @vmw_tt: Pointer to a struct vmw_ttm_tt - * - * Select the correct function for and make sure the TTM pages are - * visible to the device. Allocate storage for the device mappings. - * If a mapping has already been performed, indicated by the storage - * pointer being non NULL, the function returns success. - */ -static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt) -{ - struct vmw_private *dev_priv = vmw_tt->dev_priv; - struct ttm_mem_global *glob = vmw_mem_glob(dev_priv); - struct vmw_sg_table *vsgt = &vmw_tt->vsgt; - struct ttm_operation_ctx ctx = { - .interruptible = true, - .no_wait_gpu = false - }; - struct vmw_piter iter; - dma_addr_t old; - int ret = 0; - static size_t sgl_size; - static size_t sgt_size; - - if (vmw_tt->mapped) - return 0; - - vsgt->mode = dev_priv->map_mode; - vsgt->pages = vmw_tt->dma_ttm.ttm.pages; - vsgt->num_pages = vmw_tt->dma_ttm.ttm.num_pages; - vsgt->addrs = vmw_tt->dma_ttm.dma_address; - vsgt->sgt = &vmw_tt->sgt; - - switch (dev_priv->map_mode) { - case vmw_dma_map_bind: - case vmw_dma_map_populate: - if (unlikely(!sgl_size)) { - sgl_size = ttm_round_pot(sizeof(struct scatterlist)); - sgt_size = ttm_round_pot(sizeof(struct sg_table)); - } - vmw_tt->sg_alloc_size = sgt_size + sgl_size * vsgt->num_pages; - ret = ttm_mem_global_alloc(glob, vmw_tt->sg_alloc_size, &ctx); - if (unlikely(ret != 0)) - return ret; - - ret = sg_alloc_table_from_pages(&vmw_tt->sgt, vsgt->pages, - vsgt->num_pages, 0, - (unsigned long) - vsgt->num_pages << PAGE_SHIFT, - GFP_KERNEL); - if (unlikely(ret != 0)) - goto out_sg_alloc_fail; - - if (vsgt->num_pages > vmw_tt->sgt.nents) { - uint64_t over_alloc = - sgl_size * (vsgt->num_pages - - vmw_tt->sgt.nents); - - ttm_mem_global_free(glob, over_alloc); - vmw_tt->sg_alloc_size -= over_alloc; - } - - ret = vmw_ttm_map_for_dma(vmw_tt); - if (unlikely(ret != 0)) - goto out_map_fail; - - break; - default: - break; - } - - old = ~((dma_addr_t) 0); - vmw_tt->vsgt.num_regions = 0; - for (vmw_piter_start(&iter, vsgt, 0); vmw_piter_next(&iter);) { - dma_addr_t cur = vmw_piter_dma_addr(&iter); - - if (cur != old + PAGE_SIZE) - vmw_tt->vsgt.num_regions++; - old = cur; - } - - vmw_tt->mapped = true; - return 0; - -out_map_fail: - sg_free_table(vmw_tt->vsgt.sgt); - vmw_tt->vsgt.sgt = NULL; -out_sg_alloc_fail: - ttm_mem_global_free(glob, vmw_tt->sg_alloc_size); - return ret; -} - -/** - * vmw_ttm_unmap_dma - Tear down any TTM page device mappings - * - * @vmw_tt: Pointer to a struct vmw_ttm_tt - * - * Tear down any previously set up device DMA mappings and free - * any storage space allocated for them. If there are no mappings set up, - * this function is a NOP. - */ -static void vmw_ttm_unmap_dma(struct vmw_ttm_tt *vmw_tt) -{ - struct vmw_private *dev_priv = vmw_tt->dev_priv; - - if (!vmw_tt->vsgt.sgt) - return; - - switch (dev_priv->map_mode) { - case vmw_dma_map_bind: - case vmw_dma_map_populate: - vmw_ttm_unmap_from_dma(vmw_tt); - sg_free_table(vmw_tt->vsgt.sgt); - vmw_tt->vsgt.sgt = NULL; - ttm_mem_global_free(vmw_mem_glob(dev_priv), - vmw_tt->sg_alloc_size); - break; - default: - break; - } - vmw_tt->mapped = false; -} - - -/** - * vmw_bo_map_dma - Make sure buffer object pages are visible to the device - * - * @bo: Pointer to a struct ttm_buffer_object - * - * Wrapper around vmw_ttm_map_dma, that takes a TTM buffer object pointer - * instead of a pointer to a struct vmw_ttm_backend as argument. - * Note that the buffer object must be either pinned or reserved before - * calling this function. - */ -int vmw_bo_map_dma(struct ttm_buffer_object *bo) -{ - struct vmw_ttm_tt *vmw_tt = - container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm); - - return vmw_ttm_map_dma(vmw_tt); -} - - -/** - * vmw_bo_unmap_dma - Make sure buffer object pages are visible to the device - * - * @bo: Pointer to a struct ttm_buffer_object - * - * Wrapper around vmw_ttm_unmap_dma, that takes a TTM buffer object pointer - * instead of a pointer to a struct vmw_ttm_backend as argument. - */ -void vmw_bo_unmap_dma(struct ttm_buffer_object *bo) -{ - struct vmw_ttm_tt *vmw_tt = - container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm); - - vmw_ttm_unmap_dma(vmw_tt); -} - - -/** - * vmw_bo_sg_table - Return a struct vmw_sg_table object for a - * TTM buffer object - * - * @bo: Pointer to a struct ttm_buffer_object - * - * Returns a pointer to a struct vmw_sg_table object. The object should - * not be freed after use. - * Note that for the device addresses to be valid, the buffer object must - * either be reserved or pinned. - */ -const struct vmw_sg_table *vmw_bo_sg_table(struct ttm_buffer_object *bo) -{ - struct vmw_ttm_tt *vmw_tt = - container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm); - - return &vmw_tt->vsgt; -} - - -static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) -{ - struct vmw_ttm_tt *vmw_be = - container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); - int ret; - - ret = vmw_ttm_map_dma(vmw_be); - if (unlikely(ret != 0)) - return ret; - - vmw_be->gmr_id = bo_mem->start; - vmw_be->mem_type = bo_mem->mem_type; - - switch (bo_mem->mem_type) { - case VMW_PL_GMR: - return vmw_gmr_bind(vmw_be->dev_priv, &vmw_be->vsgt, - ttm->num_pages, vmw_be->gmr_id); - case VMW_PL_MOB: - if (unlikely(vmw_be->mob == NULL)) { - vmw_be->mob = - vmw_mob_create(ttm->num_pages); - if (unlikely(vmw_be->mob == NULL)) - return -ENOMEM; - } - - return vmw_mob_bind(vmw_be->dev_priv, vmw_be->mob, - &vmw_be->vsgt, ttm->num_pages, - vmw_be->gmr_id); - default: - BUG(); - } - return 0; -} - -static int vmw_ttm_unbind(struct ttm_tt *ttm) -{ - struct vmw_ttm_tt *vmw_be = - container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); - - switch (vmw_be->mem_type) { - case VMW_PL_GMR: - vmw_gmr_unbind(vmw_be->dev_priv, vmw_be->gmr_id); - break; - case VMW_PL_MOB: - vmw_mob_unbind(vmw_be->dev_priv, vmw_be->mob); - break; - default: - BUG(); - } - - if (vmw_be->dev_priv->map_mode == vmw_dma_map_bind) - vmw_ttm_unmap_dma(vmw_be); - - return 0; -} - - -static void vmw_ttm_destroy(struct ttm_tt *ttm) -{ - struct vmw_ttm_tt *vmw_be = - container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); - - vmw_ttm_unmap_dma(vmw_be); - if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent) - ttm_dma_tt_fini(&vmw_be->dma_ttm); - else - ttm_tt_fini(ttm); - - if (vmw_be->mob) - vmw_mob_destroy(vmw_be->mob); - - kfree(vmw_be); -} - - -static int vmw_ttm_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) -{ - struct vmw_ttm_tt *vmw_tt = - container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); - struct vmw_private *dev_priv = vmw_tt->dev_priv; - struct ttm_mem_global *glob = vmw_mem_glob(dev_priv); - int ret; - - if (ttm->state != tt_unpopulated) - return 0; - - if (dev_priv->map_mode == vmw_dma_alloc_coherent) { - size_t size = - ttm_round_pot(ttm->num_pages * sizeof(dma_addr_t)); - ret = ttm_mem_global_alloc(glob, size, ctx); - if (unlikely(ret != 0)) - return ret; - - ret = ttm_dma_populate(&vmw_tt->dma_ttm, dev_priv->dev->dev, - ctx); - if (unlikely(ret != 0)) - ttm_mem_global_free(glob, size); - } else - ret = ttm_pool_populate(ttm, ctx); - - return ret; -} - -static void vmw_ttm_unpopulate(struct ttm_tt *ttm) -{ - struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt, - dma_ttm.ttm); - struct vmw_private *dev_priv = vmw_tt->dev_priv; - struct ttm_mem_global *glob = vmw_mem_glob(dev_priv); - - - if (vmw_tt->mob) { - vmw_mob_destroy(vmw_tt->mob); - vmw_tt->mob = NULL; - } - - vmw_ttm_unmap_dma(vmw_tt); - if (dev_priv->map_mode == vmw_dma_alloc_coherent) { - size_t size = - ttm_round_pot(ttm->num_pages * sizeof(dma_addr_t)); - - ttm_dma_unpopulate(&vmw_tt->dma_ttm, dev_priv->dev->dev); - ttm_mem_global_free(glob, size); - } else - ttm_pool_unpopulate(ttm); -} - -static struct ttm_backend_func vmw_ttm_func = { - .bind = vmw_ttm_bind, - .unbind = vmw_ttm_unbind, - .destroy = vmw_ttm_destroy, -}; - -static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo, - uint32_t page_flags) -{ - struct vmw_ttm_tt *vmw_be; - int ret; - - vmw_be = kzalloc(sizeof(*vmw_be), GFP_KERNEL); - if (!vmw_be) - return NULL; - - vmw_be->dma_ttm.ttm.func = &vmw_ttm_func; - vmw_be->dev_priv = container_of(bo->bdev, struct vmw_private, bdev); - vmw_be->mob = NULL; - - if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent) - ret = ttm_dma_tt_init(&vmw_be->dma_ttm, bo, page_flags); - else - ret = ttm_tt_init(&vmw_be->dma_ttm.ttm, bo, page_flags); - if (unlikely(ret != 0)) - goto out_no_init; - - return &vmw_be->dma_ttm.ttm; -out_no_init: - kfree(vmw_be); - return NULL; -} - -static int vmw_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags) -{ - return 0; -} - -static int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, - struct ttm_mem_type_manager *man) -{ - switch (type) { - case TTM_PL_SYSTEM: - /* System memory */ - - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_FLAG_CACHED; - man->default_caching = TTM_PL_FLAG_CACHED; - break; - case TTM_PL_VRAM: - /* "On-card" video ram */ - man->func = &ttm_bo_manager_func; - man->gpu_offset = 0; - man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_FLAG_CACHED; - man->default_caching = TTM_PL_FLAG_CACHED; - break; - case VMW_PL_GMR: - case VMW_PL_MOB: - /* - * "Guest Memory Regions" is an aperture like feature with - * one slot per bo. There is an upper limit of the number of - * slots as well as the bo size. - */ - man->func = &vmw_gmrid_manager_func; - man->gpu_offset = 0; - man->flags = TTM_MEMTYPE_FLAG_CMA | TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_FLAG_CACHED; - man->default_caching = TTM_PL_FLAG_CACHED; - break; - default: - DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); - return -EINVAL; - } - return 0; -} - -static void vmw_evict_flags(struct ttm_buffer_object *bo, - struct ttm_placement *placement) -{ - *placement = vmw_sys_placement; -} - -static int vmw_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{ - struct ttm_object_file *tfile = - vmw_fpriv((struct drm_file *)filp->private_data)->tfile; - - return vmw_user_dmabuf_verify_access(bo, tfile); -} - -static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) -{ - struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; - struct vmw_private *dev_priv = container_of(bdev, struct vmw_private, bdev); - - mem->bus.addr = NULL; - mem->bus.is_iomem = false; - mem->bus.offset = 0; - mem->bus.size = mem->num_pages << PAGE_SHIFT; - mem->bus.base = 0; - if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) - return -EINVAL; - switch (mem->mem_type) { - case TTM_PL_SYSTEM: - case VMW_PL_GMR: - case VMW_PL_MOB: - return 0; - case TTM_PL_VRAM: - mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = dev_priv->vram_start; - mem->bus.is_iomem = true; - break; - default: - return -EINVAL; - } - return 0; -} - -static void vmw_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) -{ -} - -static int vmw_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) -{ - return 0; -} - -/** - * vmw_move_notify - TTM move_notify_callback - * - * @bo: The TTM buffer object about to move. - * @mem: The struct ttm_mem_reg indicating to what memory - * region the move is taking place. - * - * Calls move_notify for all subsystems needing it. - * (currently only resources). - */ -static void vmw_move_notify(struct ttm_buffer_object *bo, - bool evict, - struct ttm_mem_reg *mem) -{ - vmw_resource_move_notify(bo, mem); - vmw_query_move_notify(bo, mem); -} - - -/** - * vmw_swap_notify - TTM move_notify_callback - * - * @bo: The TTM buffer object about to be swapped out. - */ -static void vmw_swap_notify(struct ttm_buffer_object *bo) -{ - vmw_resource_swap_notify(bo); - (void) ttm_bo_wait(bo, false, false); -} - - -struct ttm_bo_driver vmw_bo_driver = { - .ttm_tt_create = &vmw_ttm_tt_create, - .ttm_tt_populate = &vmw_ttm_populate, - .ttm_tt_unpopulate = &vmw_ttm_unpopulate, - .invalidate_caches = vmw_invalidate_caches, - .init_mem_type = vmw_init_mem_type, - .eviction_valuable = ttm_bo_eviction_valuable, - .evict_flags = vmw_evict_flags, - .move = NULL, - .verify_access = vmw_verify_access, - .move_notify = vmw_move_notify, - .swap_notify = vmw_swap_notify, - .fault_reserve_notify = &vmw_ttm_fault_reserve_notify, - .io_mem_reserve = &vmw_ttm_io_mem_reserve, - .io_mem_free = &vmw_ttm_io_mem_free, -}; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c index 3767ac335aca..ff8acc74786c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c @@ -38,7 +38,7 @@ struct vmw_user_context { struct vmw_cmdbuf_res_manager *man; struct vmw_resource *cotables[SVGA_COTABLE_DX10_MAX]; spinlock_t cotable_lock; - struct vmw_dma_buffer *dx_query_mob; + struct vmw_buffer_object *dx_query_mob; }; static void vmw_user_context_free(struct vmw_resource *res); @@ -900,7 +900,7 @@ vmw_context_binding_state(struct vmw_resource *ctx) * specified in the parameter. 0 otherwise. */ int vmw_context_bind_dx_query(struct vmw_resource *ctx_res, - struct vmw_dma_buffer *mob) + struct vmw_buffer_object *mob) { struct vmw_user_context *uctx = container_of(ctx_res, struct vmw_user_context, res); @@ -908,7 +908,7 @@ int vmw_context_bind_dx_query(struct vmw_resource *ctx_res, if (mob == NULL) { if (uctx->dx_query_mob) { uctx->dx_query_mob->dx_query_ctx = NULL; - vmw_dmabuf_unreference(&uctx->dx_query_mob); + vmw_bo_unreference(&uctx->dx_query_mob); uctx->dx_query_mob = NULL; } @@ -922,7 +922,7 @@ int vmw_context_bind_dx_query(struct vmw_resource *ctx_res, mob->dx_query_ctx = ctx_res; if (!uctx->dx_query_mob) - uctx->dx_query_mob = vmw_dmabuf_reference(mob); + uctx->dx_query_mob = vmw_bo_reference(mob); return 0; } @@ -932,7 +932,7 @@ int vmw_context_bind_dx_query(struct vmw_resource *ctx_res, * * @ctx_res: The context resource */ -struct vmw_dma_buffer * +struct vmw_buffer_object * vmw_context_get_dx_query_mob(struct vmw_resource *ctx_res) { struct vmw_user_context *uctx = diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c index cbf54ea7b4c0..1052cd3cb700 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c @@ -390,7 +390,7 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) struct ttm_operation_ctx ctx = { false, false }; struct vmw_private *dev_priv = res->dev_priv; struct vmw_cotable *vcotbl = vmw_cotable(res); - struct vmw_dma_buffer *buf, *old_buf = res->backup; + struct vmw_buffer_object *buf, *old_buf = res->backup; struct ttm_buffer_object *bo, *old_bo = &res->backup->base; size_t old_size = res->backup_size; size_t old_size_read_back = vcotbl->size_read_back; @@ -415,8 +415,8 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) if (!buf) return -ENOMEM; - ret = vmw_dmabuf_init(dev_priv, buf, new_size, &vmw_mob_ne_placement, - true, vmw_dmabuf_bo_free); + ret = vmw_bo_init(dev_priv, buf, new_size, &vmw_mob_ne_placement, + true, vmw_bo_bo_free); if (ret) { DRM_ERROR("Failed initializing new cotable MOB.\n"); return ret; @@ -482,7 +482,7 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) /* Let go of the old mob. */ list_del(&res->mob_head); list_add_tail(&res->mob_head, &buf->res_list); - vmw_dmabuf_unreference(&old_buf); + vmw_bo_unreference(&old_buf); res->id = vcotbl->type; return 0; @@ -491,7 +491,7 @@ out_map_new: ttm_bo_kunmap(&old_map); out_wait: ttm_bo_unreserve(bo); - vmw_dmabuf_unreference(&buf); + vmw_bo_unreference(&buf); return ret; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c deleted file mode 100644 index d59d9dd16ebc..000000000000 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c +++ /dev/null @@ -1,376 +0,0 @@ -/************************************************************************** - * - * Copyright © 2011-2015 VMware, Inc., Palo Alto, CA., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include - -#include -#include "vmwgfx_drv.h" - - -/** - * vmw_dmabuf_pin_in_placement - Validate a buffer to placement. - * - * @dev_priv: Driver private. - * @buf: DMA buffer to move. - * @placement: The placement to pin it. - * @interruptible: Use interruptible wait. - * - * Returns - * -ERESTARTSYS if interrupted by a signal. - */ -int vmw_dmabuf_pin_in_placement(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - struct ttm_placement *placement, - bool interruptible) -{ - struct ttm_operation_ctx ctx = {interruptible, false }; - struct ttm_buffer_object *bo = &buf->base; - int ret; - uint32_t new_flags; - - ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible); - if (unlikely(ret != 0)) - return ret; - - vmw_execbuf_release_pinned_bo(dev_priv); - - ret = ttm_bo_reserve(bo, interruptible, false, NULL); - if (unlikely(ret != 0)) - goto err; - - if (buf->pin_count > 0) - ret = ttm_bo_mem_compat(placement, &bo->mem, - &new_flags) == true ? 0 : -EINVAL; - else - ret = ttm_bo_validate(bo, placement, &ctx); - - if (!ret) - vmw_bo_pin_reserved(buf, true); - - ttm_bo_unreserve(bo); - -err: - ttm_write_unlock(&dev_priv->reservation_sem); - return ret; -} - -/** - * vmw_dmabuf_pin_in_vram_or_gmr - Move a buffer to vram or gmr. - * - * This function takes the reservation_sem in write mode. - * Flushes and unpins the query bo to avoid failures. - * - * @dev_priv: Driver private. - * @buf: DMA buffer to move. - * @pin: Pin buffer if true. - * @interruptible: Use interruptible wait. - * - * Returns - * -ERESTARTSYS if interrupted by a signal. - */ -int vmw_dmabuf_pin_in_vram_or_gmr(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - bool interruptible) -{ - struct ttm_operation_ctx ctx = {interruptible, false }; - struct ttm_buffer_object *bo = &buf->base; - int ret; - uint32_t new_flags; - - ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible); - if (unlikely(ret != 0)) - return ret; - - vmw_execbuf_release_pinned_bo(dev_priv); - - ret = ttm_bo_reserve(bo, interruptible, false, NULL); - if (unlikely(ret != 0)) - goto err; - - if (buf->pin_count > 0) { - ret = ttm_bo_mem_compat(&vmw_vram_gmr_placement, &bo->mem, - &new_flags) == true ? 0 : -EINVAL; - goto out_unreserve; - } - - ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx); - if (likely(ret == 0) || ret == -ERESTARTSYS) - goto out_unreserve; - - ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx); - -out_unreserve: - if (!ret) - vmw_bo_pin_reserved(buf, true); - - ttm_bo_unreserve(bo); -err: - ttm_write_unlock(&dev_priv->reservation_sem); - return ret; -} - -/** - * vmw_dmabuf_pin_in_vram - Move a buffer to vram. - * - * This function takes the reservation_sem in write mode. - * Flushes and unpins the query bo to avoid failures. - * - * @dev_priv: Driver private. - * @buf: DMA buffer to move. - * @interruptible: Use interruptible wait. - * - * Returns - * -ERESTARTSYS if interrupted by a signal. - */ -int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - bool interruptible) -{ - return vmw_dmabuf_pin_in_placement(dev_priv, buf, &vmw_vram_placement, - interruptible); -} - -/** - * vmw_dmabuf_pin_in_start_of_vram - Move a buffer to start of vram. - * - * This function takes the reservation_sem in write mode. - * Flushes and unpins the query bo to avoid failures. - * - * @dev_priv: Driver private. - * @buf: DMA buffer to pin. - * @interruptible: Use interruptible wait. - * - * Returns - * -ERESTARTSYS if interrupted by a signal. - */ -int vmw_dmabuf_pin_in_start_of_vram(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - bool interruptible) -{ - struct ttm_operation_ctx ctx = {interruptible, false }; - struct ttm_buffer_object *bo = &buf->base; - struct ttm_placement placement; - struct ttm_place place; - int ret = 0; - uint32_t new_flags; - - place = vmw_vram_placement.placement[0]; - place.lpfn = bo->num_pages; - placement.num_placement = 1; - placement.placement = &place; - placement.num_busy_placement = 1; - placement.busy_placement = &place; - - ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible); - if (unlikely(ret != 0)) - return ret; - - vmw_execbuf_release_pinned_bo(dev_priv); - ret = ttm_bo_reserve(bo, interruptible, false, NULL); - if (unlikely(ret != 0)) - goto err_unlock; - - /* - * Is this buffer already in vram but not at the start of it? - * In that case, evict it first because TTM isn't good at handling - * that situation. - */ - if (bo->mem.mem_type == TTM_PL_VRAM && - bo->mem.start < bo->num_pages && - bo->mem.start > 0 && - buf->pin_count == 0) { - ctx.interruptible = false; - (void) ttm_bo_validate(bo, &vmw_sys_placement, &ctx); - } - - if (buf->pin_count > 0) - ret = ttm_bo_mem_compat(&placement, &bo->mem, - &new_flags) == true ? 0 : -EINVAL; - else - ret = ttm_bo_validate(bo, &placement, &ctx); - - /* For some reason we didn't end up at the start of vram */ - WARN_ON(ret == 0 && bo->offset != 0); - if (!ret) - vmw_bo_pin_reserved(buf, true); - - ttm_bo_unreserve(bo); -err_unlock: - ttm_write_unlock(&dev_priv->reservation_sem); - - return ret; -} - -/** - * vmw_dmabuf_unpin - Unpin the buffer given buffer, does not move the buffer. - * - * This function takes the reservation_sem in write mode. - * - * @dev_priv: Driver private. - * @buf: DMA buffer to unpin. - * @interruptible: Use interruptible wait. - * - * Returns - * -ERESTARTSYS if interrupted by a signal. - */ -int vmw_dmabuf_unpin(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - bool interruptible) -{ - struct ttm_buffer_object *bo = &buf->base; - int ret; - - ret = ttm_read_lock(&dev_priv->reservation_sem, interruptible); - if (unlikely(ret != 0)) - return ret; - - ret = ttm_bo_reserve(bo, interruptible, false, NULL); - if (unlikely(ret != 0)) - goto err; - - vmw_bo_pin_reserved(buf, false); - - ttm_bo_unreserve(bo); - -err: - ttm_read_unlock(&dev_priv->reservation_sem); - return ret; -} - -/** - * vmw_bo_get_guest_ptr - Get the guest ptr representing the current placement - * of a buffer. - * - * @bo: Pointer to a struct ttm_buffer_object. Must be pinned or reserved. - * @ptr: SVGAGuestPtr returning the result. - */ -void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *bo, - SVGAGuestPtr *ptr) -{ - if (bo->mem.mem_type == TTM_PL_VRAM) { - ptr->gmrId = SVGA_GMR_FRAMEBUFFER; - ptr->offset = bo->offset; - } else { - ptr->gmrId = bo->mem.start; - ptr->offset = 0; - } -} - - -/** - * vmw_bo_pin_reserved - Pin or unpin a buffer object without moving it. - * - * @vbo: The buffer object. Must be reserved. - * @pin: Whether to pin or unpin. - * - */ -void vmw_bo_pin_reserved(struct vmw_dma_buffer *vbo, bool pin) -{ - struct ttm_operation_ctx ctx = { false, true }; - struct ttm_place pl; - struct ttm_placement placement; - struct ttm_buffer_object *bo = &vbo->base; - uint32_t old_mem_type = bo->mem.mem_type; - int ret; - - lockdep_assert_held(&bo->resv->lock.base); - - if (pin) { - if (vbo->pin_count++ > 0) - return; - } else { - WARN_ON(vbo->pin_count <= 0); - if (--vbo->pin_count > 0) - return; - } - - pl.fpfn = 0; - pl.lpfn = 0; - pl.flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | VMW_PL_FLAG_MOB - | TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED; - if (pin) - pl.flags |= TTM_PL_FLAG_NO_EVICT; - - memset(&placement, 0, sizeof(placement)); - placement.num_placement = 1; - placement.placement = &pl; - - ret = ttm_bo_validate(bo, &placement, &ctx); - - BUG_ON(ret != 0 || bo->mem.mem_type != old_mem_type); -} - - -/* - * vmw_dma_buffer_unmap - Tear down a cached buffer object map. - * - * @vbo: The buffer object whose map we are tearing down. - * - * This function tears down a cached map set up using - * vmw_dma_buffer_map_and_cache(). - */ -void vmw_dma_buffer_unmap(struct vmw_dma_buffer *vbo) -{ - if (vbo->map.bo == NULL) - return; - - ttm_bo_kunmap(&vbo->map); -} - - -/* - * vmw_dma_buffer_map_and_cache - Map a buffer object and cache the map - * - * @vbo: The buffer object to map - * Return: A kernel virtual address or NULL if mapping failed. - * - * This function maps a buffer object into the kernel address space, or - * returns the virtual kernel address of an already existing map. The virtual - * address remains valid as long as the buffer object is pinned or reserved. - * The cached map is torn down on either - * 1) Buffer object move - * 2) Buffer object swapout - * 3) Buffer object destruction - * - */ -void *vmw_dma_buffer_map_and_cache(struct vmw_dma_buffer *vbo) -{ - struct ttm_buffer_object *bo = &vbo->base; - bool not_used; - void *virtual; - int ret; - - virtual = ttm_kmap_obj_virtual(&vbo->map, ¬_used); - if (virtual) - return virtual; - - ret = ttm_bo_kmap(bo, 0, bo->num_pages, &vbo->map); - if (ret) - DRM_ERROR("Buffer object map failed: %d.\n", ret); - - return ttm_kmap_obj_virtual(&vbo->map, ¬_used); -} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 09cc721160c4..4f18304226bc 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -153,9 +153,9 @@ static const struct drm_ioctl_desc vmw_ioctls[] = { VMW_IOCTL_DEF(VMW_GET_PARAM, vmw_getparam_ioctl, DRM_AUTH | DRM_RENDER_ALLOW), - VMW_IOCTL_DEF(VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl, + VMW_IOCTL_DEF(VMW_ALLOC_DMABUF, vmw_bo_alloc_ioctl, DRM_AUTH | DRM_RENDER_ALLOW), - VMW_IOCTL_DEF(VMW_UNREF_DMABUF, vmw_dmabuf_unref_ioctl, + VMW_IOCTL_DEF(VMW_UNREF_DMABUF, vmw_bo_unref_ioctl, DRM_RENDER_ALLOW), VMW_IOCTL_DEF(VMW_CURSOR_BYPASS, vmw_kms_cursor_bypass_ioctl, @@ -219,7 +219,7 @@ static const struct drm_ioctl_desc vmw_ioctls[] = { vmw_gb_surface_reference_ioctl, DRM_AUTH | DRM_RENDER_ALLOW), VMW_IOCTL_DEF(VMW_SYNCCPU, - vmw_user_dmabuf_synccpu_ioctl, + vmw_user_bo_synccpu_ioctl, DRM_RENDER_ALLOW), VMW_IOCTL_DEF(VMW_CREATE_EXTENDED_CONTEXT, vmw_extended_context_define_ioctl, @@ -321,7 +321,7 @@ static void vmw_print_capabilities(uint32_t capabilities) static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) { int ret; - struct vmw_dma_buffer *vbo; + struct vmw_buffer_object *vbo; struct ttm_bo_kmap_obj map; volatile SVGA3dQueryResult *result; bool dummy; @@ -335,9 +335,9 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) if (!vbo) return -ENOMEM; - ret = vmw_dmabuf_init(dev_priv, vbo, PAGE_SIZE, - &vmw_sys_ne_placement, false, - &vmw_dmabuf_bo_free); + ret = vmw_bo_init(dev_priv, vbo, PAGE_SIZE, + &vmw_sys_ne_placement, false, + &vmw_bo_bo_free); if (unlikely(ret != 0)) return ret; @@ -358,7 +358,7 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) if (unlikely(ret != 0)) { DRM_ERROR("Dummy query buffer map failed.\n"); - vmw_dmabuf_unreference(&vbo); + vmw_bo_unreference(&vbo); } else dev_priv->dummy_query_bo = vbo; @@ -460,7 +460,7 @@ static void vmw_release_device_early(struct vmw_private *dev_priv) BUG_ON(dev_priv->pinned_bo != NULL); - vmw_dmabuf_unreference(&dev_priv->dummy_query_bo); + vmw_bo_unreference(&dev_priv->dummy_query_bo); if (dev_priv->cman) vmw_cmdbuf_remove_pool(dev_priv->cman); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 5fcbe1620d50..25c2f668ad6c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -86,7 +86,7 @@ struct vmw_fpriv { bool gb_aware; }; -struct vmw_dma_buffer { +struct vmw_buffer_object { struct ttm_buffer_object base; struct list_head res_list; s32 pin_count; @@ -120,7 +120,7 @@ struct vmw_resource { unsigned long backup_size; bool res_dirty; /* Protected by backup buffer reserved */ bool backup_dirty; /* Protected by backup buffer reserved */ - struct vmw_dma_buffer *backup; + struct vmw_buffer_object *backup; unsigned long backup_offset; unsigned long pin_count; /* Protected by resource reserved */ const struct vmw_res_func *func; @@ -304,7 +304,7 @@ struct vmw_sw_context{ uint32_t cmd_bounce_size; struct list_head resource_list; struct list_head ctx_resource_list; /* For contexts and cotables */ - struct vmw_dma_buffer *cur_query_bo; + struct vmw_buffer_object *cur_query_bo; struct list_head res_relocations; uint32_t *buf_start; struct vmw_res_cache_entry res_cache[vmw_res_max]; @@ -315,7 +315,7 @@ struct vmw_sw_context{ bool staged_bindings_inuse; struct list_head staged_cmd_res; struct vmw_resource_val_node *dx_ctx_node; - struct vmw_dma_buffer *dx_query_mob; + struct vmw_buffer_object *dx_query_mob; struct vmw_resource *dx_query_ctx; struct vmw_cmdbuf_res_manager *man; }; @@ -513,8 +513,8 @@ struct vmw_private { * are protected by the cmdbuf mutex. */ - struct vmw_dma_buffer *dummy_query_bo; - struct vmw_dma_buffer *pinned_bo; + struct vmw_buffer_object *dummy_query_bo; + struct vmw_buffer_object *pinned_bo; uint32_t query_cid; uint32_t query_cid_valid; bool dummy_query_bo_pinned; @@ -623,43 +623,43 @@ extern int vmw_user_lookup_handle(struct vmw_private *dev_priv, struct ttm_object_file *tfile, uint32_t handle, struct vmw_surface **out_surf, - struct vmw_dma_buffer **out_buf); + struct vmw_buffer_object **out_buf); extern int vmw_user_resource_lookup_handle( struct vmw_private *dev_priv, struct ttm_object_file *tfile, uint32_t handle, const struct vmw_user_resource_conv *converter, struct vmw_resource **p_res); -extern void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo); -extern int vmw_dmabuf_init(struct vmw_private *dev_priv, - struct vmw_dma_buffer *vmw_bo, - size_t size, struct ttm_placement *placement, - bool interuptable, - void (*bo_free) (struct ttm_buffer_object *bo)); -extern int vmw_user_dmabuf_verify_access(struct ttm_buffer_object *bo, - struct ttm_object_file *tfile); -extern int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv, - struct ttm_object_file *tfile, - uint32_t size, - bool shareable, - uint32_t *handle, - struct vmw_dma_buffer **p_dma_buf, - struct ttm_base_object **p_base); -extern int vmw_user_dmabuf_reference(struct ttm_object_file *tfile, - struct vmw_dma_buffer *dma_buf, - uint32_t *handle); -extern int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo, - uint32_t cur_validate_node); -extern void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo); -extern int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, - uint32_t id, struct vmw_dma_buffer **out, - struct ttm_base_object **base); +extern void vmw_bo_bo_free(struct ttm_buffer_object *bo); +extern int vmw_bo_init(struct vmw_private *dev_priv, + struct vmw_buffer_object *vmw_bo, + size_t size, struct ttm_placement *placement, + bool interuptable, + void (*bo_free)(struct ttm_buffer_object *bo)); +extern int vmw_user_bo_verify_access(struct ttm_buffer_object *bo, + struct ttm_object_file *tfile); +extern int vmw_user_bo_alloc(struct vmw_private *dev_priv, + struct ttm_object_file *tfile, + uint32_t size, + bool shareable, + uint32_t *handle, + struct vmw_buffer_object **p_dma_buf, + struct ttm_base_object **p_base); +extern int vmw_user_bo_reference(struct ttm_object_file *tfile, + struct vmw_buffer_object *dma_buf, + uint32_t *handle); +extern int vmw_bo_alloc_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int vmw_bo_unref_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern uint32_t vmw_bo_validate_node(struct ttm_buffer_object *bo, + uint32_t cur_validate_node); +extern void vmw_bo_validate_clear(struct ttm_buffer_object *bo); +extern int vmw_user_bo_lookup(struct ttm_object_file *tfile, + uint32_t id, struct vmw_buffer_object **out, + struct ttm_base_object **base); extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data, @@ -670,43 +670,43 @@ extern int vmw_user_stream_lookup(struct vmw_private *dev_priv, struct vmw_resource **out); extern void vmw_resource_unreserve(struct vmw_resource *res, bool switch_backup, - struct vmw_dma_buffer *new_backup, + struct vmw_buffer_object *new_backup, unsigned long new_backup_offset); extern void vmw_resource_move_notify(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem); extern void vmw_query_move_notify(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem); extern void vmw_resource_swap_notify(struct ttm_buffer_object *bo); -extern int vmw_query_readback_all(struct vmw_dma_buffer *dx_query_mob); +extern int vmw_query_readback_all(struct vmw_buffer_object *dx_query_mob); extern void vmw_fence_single_bo(struct ttm_buffer_object *bo, struct vmw_fence_obj *fence); extern void vmw_resource_evict_all(struct vmw_private *dev_priv); /** - * DMA buffer helper routines - vmwgfx_dmabuf.c + * Buffer object helper functions - vmwgfx_bo.c */ -extern int vmw_dmabuf_pin_in_placement(struct vmw_private *vmw_priv, - struct vmw_dma_buffer *bo, - struct ttm_placement *placement, +extern int vmw_bo_pin_in_placement(struct vmw_private *vmw_priv, + struct vmw_buffer_object *bo, + struct ttm_placement *placement, + bool interruptible); +extern int vmw_bo_pin_in_vram(struct vmw_private *dev_priv, + struct vmw_buffer_object *buf, + bool interruptible); +extern int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv, + struct vmw_buffer_object *buf, + bool interruptible); +extern int vmw_bo_pin_in_start_of_vram(struct vmw_private *vmw_priv, + struct vmw_buffer_object *bo, bool interruptible); -extern int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - bool interruptible); -extern int vmw_dmabuf_pin_in_vram_or_gmr(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - bool interruptible); -extern int vmw_dmabuf_pin_in_start_of_vram(struct vmw_private *vmw_priv, - struct vmw_dma_buffer *bo, - bool interruptible); -extern int vmw_dmabuf_unpin(struct vmw_private *vmw_priv, - struct vmw_dma_buffer *bo, - bool interruptible); +extern int vmw_bo_unpin(struct vmw_private *vmw_priv, + struct vmw_buffer_object *bo, + bool interruptible); extern void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *buf, SVGAGuestPtr *ptr); -extern void vmw_bo_pin_reserved(struct vmw_dma_buffer *bo, bool pin); -extern void *vmw_dma_buffer_map_and_cache(struct vmw_dma_buffer *vbo); -extern void vmw_dma_buffer_unmap(struct vmw_dma_buffer *vbo); +extern void vmw_bo_pin_reserved(struct vmw_buffer_object *bo, bool pin); +extern void *vmw_buffer_object_map_and_cache(struct vmw_buffer_object *vbo); +extern void vmw_buffer_object_unmap(struct vmw_buffer_object *vbo); /** * Misc Ioctl functionality - vmwgfx_ioctl.c @@ -758,7 +758,7 @@ extern void vmw_ttm_global_release(struct vmw_private *dev_priv); extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma); /** - * TTM buffer object driver - vmwgfx_buffer.c + * TTM buffer object driver - vmwgfx_ttm_buffer.c */ extern const size_t vmw_tt_size; @@ -1041,8 +1041,8 @@ vmw_context_binding_state(struct vmw_resource *ctx); extern void vmw_dx_context_scrub_cotables(struct vmw_resource *ctx, bool readback); extern int vmw_context_bind_dx_query(struct vmw_resource *ctx_res, - struct vmw_dma_buffer *mob); -extern struct vmw_dma_buffer * + struct vmw_buffer_object *mob); +extern struct vmw_buffer_object * vmw_context_get_dx_query_mob(struct vmw_resource *ctx_res); @@ -1243,9 +1243,9 @@ static inline struct vmw_surface *vmw_surface_reference(struct vmw_surface *srf) return srf; } -static inline void vmw_dmabuf_unreference(struct vmw_dma_buffer **buf) +static inline void vmw_bo_unreference(struct vmw_buffer_object **buf) { - struct vmw_dma_buffer *tmp_buf = *buf; + struct vmw_buffer_object *tmp_buf = *buf; *buf = NULL; if (tmp_buf != NULL) { @@ -1255,7 +1255,8 @@ static inline void vmw_dmabuf_unreference(struct vmw_dma_buffer **buf) } } -static inline struct vmw_dma_buffer *vmw_dmabuf_reference(struct vmw_dma_buffer *buf) +static inline struct vmw_buffer_object * +vmw_bo_reference(struct vmw_buffer_object *buf) { if (ttm_bo_reference(&buf->base)) return buf; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index c9d5cc237124..a8b194655c40 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -92,7 +92,7 @@ struct vmw_resource_val_node { struct list_head head; struct drm_hash_item hash; struct vmw_resource *res; - struct vmw_dma_buffer *new_backup; + struct vmw_buffer_object *new_backup; struct vmw_ctx_binding_state *staged_bindings; unsigned long new_backup_offset; u32 first_usage : 1; @@ -126,9 +126,9 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGAMobId *id, - struct vmw_dma_buffer **vmw_bo_p); + struct vmw_buffer_object **vmw_bo_p); static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context, - struct vmw_dma_buffer *vbo, + struct vmw_buffer_object *vbo, bool validate_as_mob, uint32_t *p_val_node); /** @@ -185,7 +185,7 @@ static void vmw_resources_unreserve(struct vmw_sw_context *sw_context, } vmw_resource_unreserve(res, switch_backup, val->new_backup, val->new_backup_offset); - vmw_dmabuf_unreference(&val->new_backup); + vmw_bo_unreference(&val->new_backup); } } @@ -423,7 +423,7 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, } if (dev_priv->has_dx && vmw_res_type(ctx) == vmw_res_dx_context) { - struct vmw_dma_buffer *dx_query_mob; + struct vmw_buffer_object *dx_query_mob; dx_query_mob = vmw_context_get_dx_query_mob(ctx); if (dx_query_mob) @@ -544,7 +544,7 @@ static int vmw_cmd_ok(struct vmw_private *dev_priv, * submission is reached. */ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context, - struct vmw_dma_buffer *vbo, + struct vmw_buffer_object *vbo, bool validate_as_mob, uint32_t *p_val_node) { @@ -616,7 +616,7 @@ static int vmw_resources_reserve(struct vmw_sw_context *sw_context) return ret; if (res->backup) { - struct vmw_dma_buffer *vbo = res->backup; + struct vmw_buffer_object *vbo = res->backup; ret = vmw_bo_to_validate_list (sw_context, vbo, @@ -628,7 +628,7 @@ static int vmw_resources_reserve(struct vmw_sw_context *sw_context) } if (sw_context->dx_query_mob) { - struct vmw_dma_buffer *expected_dx_query_mob; + struct vmw_buffer_object *expected_dx_query_mob; expected_dx_query_mob = vmw_context_get_dx_query_mob(sw_context->dx_query_ctx); @@ -657,7 +657,7 @@ static int vmw_resources_validate(struct vmw_sw_context *sw_context) list_for_each_entry(val, &sw_context->resource_list, head) { struct vmw_resource *res = val->res; - struct vmw_dma_buffer *backup = res->backup; + struct vmw_buffer_object *backup = res->backup; ret = vmw_resource_validate(res); if (unlikely(ret != 0)) { @@ -668,7 +668,7 @@ static int vmw_resources_validate(struct vmw_sw_context *sw_context) /* Check if the resource switched backup buffer */ if (backup && res->backup && (backup != res->backup)) { - struct vmw_dma_buffer *vbo = res->backup; + struct vmw_buffer_object *vbo = res->backup; ret = vmw_bo_to_validate_list (sw_context, vbo, @@ -821,7 +821,7 @@ out_no_reloc: static int vmw_rebind_all_dx_query(struct vmw_resource *ctx_res) { struct vmw_private *dev_priv = ctx_res->dev_priv; - struct vmw_dma_buffer *dx_query_mob; + struct vmw_buffer_object *dx_query_mob; struct { SVGA3dCmdHeader header; SVGA3dCmdDXBindAllQuery body; @@ -1152,7 +1152,7 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv, * command batch. */ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, - struct vmw_dma_buffer *new_query_bo, + struct vmw_buffer_object *new_query_bo, struct vmw_sw_context *sw_context) { struct vmw_res_cache_entry *ctx_entry = @@ -1234,7 +1234,7 @@ static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv, if (dev_priv->pinned_bo != sw_context->cur_query_bo) { if (dev_priv->pinned_bo) { vmw_bo_pin_reserved(dev_priv->pinned_bo, false); - vmw_dmabuf_unreference(&dev_priv->pinned_bo); + vmw_bo_unreference(&dev_priv->pinned_bo); } if (!sw_context->needs_post_query_barrier) { @@ -1256,7 +1256,7 @@ static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv, dev_priv->query_cid = sw_context->last_query_ctx->id; dev_priv->query_cid_valid = true; dev_priv->pinned_bo = - vmw_dmabuf_reference(sw_context->cur_query_bo); + vmw_bo_reference(sw_context->cur_query_bo); } } } @@ -1282,15 +1282,14 @@ static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv, static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGAMobId *id, - struct vmw_dma_buffer **vmw_bo_p) + struct vmw_buffer_object **vmw_bo_p) { - struct vmw_dma_buffer *vmw_bo = NULL; + struct vmw_buffer_object *vmw_bo = NULL; uint32_t handle = *id; struct vmw_relocation *reloc; int ret; - ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo, - NULL); + ret = vmw_user_bo_lookup(sw_context->fp->tfile, handle, &vmw_bo, NULL); if (unlikely(ret != 0)) { DRM_ERROR("Could not find or use MOB buffer.\n"); ret = -EINVAL; @@ -1316,7 +1315,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, return 0; out_no_reloc: - vmw_dmabuf_unreference(&vmw_bo); + vmw_bo_unreference(&vmw_bo); *vmw_bo_p = NULL; return ret; } @@ -1343,15 +1342,14 @@ out_no_reloc: static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGAGuestPtr *ptr, - struct vmw_dma_buffer **vmw_bo_p) + struct vmw_buffer_object **vmw_bo_p) { - struct vmw_dma_buffer *vmw_bo = NULL; + struct vmw_buffer_object *vmw_bo = NULL; uint32_t handle = ptr->gmrId; struct vmw_relocation *reloc; int ret; - ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo, - NULL); + ret = vmw_user_bo_lookup(sw_context->fp->tfile, handle, &vmw_bo, NULL); if (unlikely(ret != 0)) { DRM_ERROR("Could not find or use GMR region.\n"); ret = -EINVAL; @@ -1376,7 +1374,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, return 0; out_no_reloc: - vmw_dmabuf_unreference(&vmw_bo); + vmw_bo_unreference(&vmw_bo); *vmw_bo_p = NULL; return ret; } @@ -1447,7 +1445,7 @@ static int vmw_cmd_dx_bind_query(struct vmw_private *dev_priv, SVGA3dCmdDXBindQuery q; } *cmd; - struct vmw_dma_buffer *vmw_bo; + struct vmw_buffer_object *vmw_bo; int ret; @@ -1466,7 +1464,7 @@ static int vmw_cmd_dx_bind_query(struct vmw_private *dev_priv, sw_context->dx_query_mob = vmw_bo; sw_context->dx_query_ctx = sw_context->dx_ctx_node->res; - vmw_dmabuf_unreference(&vmw_bo); + vmw_bo_unreference(&vmw_bo); return ret; } @@ -1549,7 +1547,7 @@ static int vmw_cmd_end_gb_query(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_dma_buffer *vmw_bo; + struct vmw_buffer_object *vmw_bo; struct vmw_query_cmd { SVGA3dCmdHeader header; SVGA3dCmdEndGBQuery q; @@ -1569,7 +1567,7 @@ static int vmw_cmd_end_gb_query(struct vmw_private *dev_priv, ret = vmw_query_bo_switch_prepare(dev_priv, vmw_bo, sw_context); - vmw_dmabuf_unreference(&vmw_bo); + vmw_bo_unreference(&vmw_bo); return ret; } @@ -1584,7 +1582,7 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_dma_buffer *vmw_bo; + struct vmw_buffer_object *vmw_bo; struct vmw_query_cmd { SVGA3dCmdHeader header; SVGA3dCmdEndQuery q; @@ -1623,7 +1621,7 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv, ret = vmw_query_bo_switch_prepare(dev_priv, vmw_bo, sw_context); - vmw_dmabuf_unreference(&vmw_bo); + vmw_bo_unreference(&vmw_bo); return ret; } @@ -1638,7 +1636,7 @@ static int vmw_cmd_wait_gb_query(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_dma_buffer *vmw_bo; + struct vmw_buffer_object *vmw_bo; struct vmw_query_cmd { SVGA3dCmdHeader header; SVGA3dCmdWaitForGBQuery q; @@ -1656,7 +1654,7 @@ static int vmw_cmd_wait_gb_query(struct vmw_private *dev_priv, if (unlikely(ret != 0)) return ret; - vmw_dmabuf_unreference(&vmw_bo); + vmw_bo_unreference(&vmw_bo); return 0; } @@ -1671,7 +1669,7 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_dma_buffer *vmw_bo; + struct vmw_buffer_object *vmw_bo; struct vmw_query_cmd { SVGA3dCmdHeader header; SVGA3dCmdWaitForQuery q; @@ -1708,7 +1706,7 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv, if (unlikely(ret != 0)) return ret; - vmw_dmabuf_unreference(&vmw_bo); + vmw_bo_unreference(&vmw_bo); return 0; } @@ -1716,7 +1714,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_dma_buffer *vmw_bo = NULL; + struct vmw_buffer_object *vmw_bo = NULL; struct vmw_surface *srf = NULL; struct vmw_dma_cmd { SVGA3dCmdHeader header; @@ -1768,7 +1766,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, header); out_no_surface: - vmw_dmabuf_unreference(&vmw_bo); + vmw_bo_unreference(&vmw_bo); return ret; } @@ -1887,7 +1885,7 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, void *buf) { - struct vmw_dma_buffer *vmw_bo; + struct vmw_buffer_object *vmw_bo; int ret; struct { @@ -1901,7 +1899,7 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv, if (unlikely(ret != 0)) return ret; - vmw_dmabuf_unreference(&vmw_bo); + vmw_bo_unreference(&vmw_bo); return ret; } @@ -1928,7 +1926,7 @@ static int vmw_cmd_res_switch_backup(struct vmw_private *dev_priv, uint32_t *buf_id, unsigned long backup_offset) { - struct vmw_dma_buffer *dma_buf; + struct vmw_buffer_object *dma_buf; int ret; ret = vmw_translate_mob_ptr(dev_priv, sw_context, buf_id, &dma_buf); @@ -1939,7 +1937,7 @@ static int vmw_cmd_res_switch_backup(struct vmw_private *dev_priv, if (val_node->first_usage) val_node->no_buffer_needed = true; - vmw_dmabuf_unreference(&val_node->new_backup); + vmw_bo_unreference(&val_node->new_backup); val_node->new_backup = dma_buf; val_node->new_backup_offset = backup_offset; @@ -3701,8 +3699,8 @@ int vmw_validate_single_buffer(struct vmw_private *dev_priv, bool interruptible, bool validate_as_mob) { - struct vmw_dma_buffer *vbo = container_of(bo, struct vmw_dma_buffer, - base); + struct vmw_buffer_object *vbo = + container_of(bo, struct vmw_buffer_object, base); struct ttm_operation_ctx ctx = { interruptible, true }; int ret; @@ -4423,7 +4421,7 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, ttm_bo_unref(&query_val.bo); ttm_bo_unref(&pinned_val.bo); - vmw_dmabuf_unreference(&dev_priv->pinned_bo); + vmw_bo_unreference(&dev_priv->pinned_bo); out_unlock: return; @@ -4432,7 +4430,7 @@ out_no_emit: out_no_reserve: ttm_bo_unref(&query_val.bo); ttm_bo_unref(&pinned_val.bo); - vmw_dmabuf_unreference(&dev_priv->pinned_bo); + vmw_bo_unreference(&dev_priv->pinned_bo); } /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 9b7e0aca5f84..dcde4985c574 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -42,7 +42,7 @@ struct vmw_fb_par { void *vmalloc; struct mutex bo_mutex; - struct vmw_dma_buffer *vmw_bo; + struct vmw_buffer_object *vmw_bo; unsigned bo_size; struct drm_framebuffer *set_fb; struct drm_display_mode *set_mode; @@ -184,7 +184,7 @@ static void vmw_fb_dirty_flush(struct work_struct *work) struct drm_clip_rect clip; struct drm_framebuffer *cur_fb; u8 *src_ptr, *dst_ptr; - struct vmw_dma_buffer *vbo = par->vmw_bo; + struct vmw_buffer_object *vbo = par->vmw_bo; void *virtual; if (!READ_ONCE(par->dirty.active)) @@ -197,7 +197,7 @@ static void vmw_fb_dirty_flush(struct work_struct *work) (void) ttm_read_lock(&vmw_priv->reservation_sem, false); (void) ttm_bo_reserve(&vbo->base, false, false, NULL); - virtual = vmw_dma_buffer_map_and_cache(vbo); + virtual = vmw_buffer_object_map_and_cache(vbo); if (!virtual) goto out_unreserve; @@ -391,9 +391,9 @@ static void vmw_fb_imageblit(struct fb_info *info, const struct fb_image *image) */ static int vmw_fb_create_bo(struct vmw_private *vmw_priv, - size_t size, struct vmw_dma_buffer **out) + size_t size, struct vmw_buffer_object **out) { - struct vmw_dma_buffer *vmw_bo; + struct vmw_buffer_object *vmw_bo; int ret; (void) ttm_write_lock(&vmw_priv->reservation_sem, false); @@ -404,10 +404,10 @@ static int vmw_fb_create_bo(struct vmw_private *vmw_priv, goto err_unlock; } - ret = vmw_dmabuf_init(vmw_priv, vmw_bo, size, + ret = vmw_bo_init(vmw_priv, vmw_bo, size, &vmw_sys_placement, false, - &vmw_dmabuf_bo_free); + &vmw_bo_bo_free); if (unlikely(ret != 0)) goto err_unlock; /* init frees the buffer on failure */ @@ -491,7 +491,7 @@ static int vmw_fb_kms_detach(struct vmw_fb_par *par, } if (par->vmw_bo && detach_bo && unref_bo) - vmw_dmabuf_unreference(&par->vmw_bo); + vmw_bo_unreference(&par->vmw_bo); return 0; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index c5e8eae0dbe2..5e0c8f775c92 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -377,8 +377,8 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data, } vfb = vmw_framebuffer_to_vfb(fb); - if (!vfb->dmabuf) { - DRM_ERROR("Framebuffer not dmabuf backed.\n"); + if (!vfb->bo) { + DRM_ERROR("Framebuffer not buffer backed.\n"); ret = -EINVAL; goto out_no_ttm_lock; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index ef96ba7432ad..7a32be0cef14 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -85,10 +85,10 @@ static int vmw_cursor_update_image(struct vmw_private *dev_priv, return 0; } -static int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv, - struct vmw_dma_buffer *dmabuf, - u32 width, u32 height, - u32 hotspotX, u32 hotspotY) +static int vmw_cursor_update_bo(struct vmw_private *dev_priv, + struct vmw_buffer_object *bo, + u32 width, u32 height, + u32 hotspotX, u32 hotspotY) { struct ttm_bo_kmap_obj map; unsigned long kmap_offset; @@ -100,13 +100,13 @@ static int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv, kmap_offset = 0; kmap_num = (width*height*4 + PAGE_SIZE - 1) >> PAGE_SHIFT; - ret = ttm_bo_reserve(&dmabuf->base, true, false, NULL); + ret = ttm_bo_reserve(&bo->base, true, false, NULL); if (unlikely(ret != 0)) { DRM_ERROR("reserve failed\n"); return -EINVAL; } - ret = ttm_bo_kmap(&dmabuf->base, kmap_offset, kmap_num, &map); + ret = ttm_bo_kmap(&bo->base, kmap_offset, kmap_num, &map); if (unlikely(ret != 0)) goto err_unreserve; @@ -116,7 +116,7 @@ static int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv, ttm_bo_kunmap(&map); err_unreserve: - ttm_bo_unreserve(&dmabuf->base); + ttm_bo_unreserve(&bo->base); return ret; } @@ -352,13 +352,13 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane, if (vps->surf) vmw_surface_unreference(&vps->surf); - if (vps->dmabuf) - vmw_dmabuf_unreference(&vps->dmabuf); + if (vps->bo) + vmw_bo_unreference(&vps->bo); if (fb) { - if (vmw_framebuffer_to_vfb(fb)->dmabuf) { - vps->dmabuf = vmw_framebuffer_to_vfbd(fb)->buffer; - vmw_dmabuf_reference(vps->dmabuf); + if (vmw_framebuffer_to_vfb(fb)->bo) { + vps->bo = vmw_framebuffer_to_vfbd(fb)->buffer; + vmw_bo_reference(vps->bo); } else { vps->surf = vmw_framebuffer_to_vfbs(fb)->surface; vmw_surface_reference(vps->surf); @@ -390,7 +390,7 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, } du->cursor_surface = vps->surf; - du->cursor_dmabuf = vps->dmabuf; + du->cursor_bo = vps->bo; if (vps->surf) { du->cursor_age = du->cursor_surface->snooper.age; @@ -399,11 +399,11 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, vps->surf->snooper.image, 64, 64, hotspot_x, hotspot_y); - } else if (vps->dmabuf) { - ret = vmw_cursor_update_dmabuf(dev_priv, vps->dmabuf, - plane->state->crtc_w, - plane->state->crtc_h, - hotspot_x, hotspot_y); + } else if (vps->bo) { + ret = vmw_cursor_update_bo(dev_priv, vps->bo, + plane->state->crtc_w, + plane->state->crtc_h, + hotspot_x, hotspot_y); } else { vmw_cursor_update_position(dev_priv, false, 0, 0); return; @@ -519,7 +519,7 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, ret = -EINVAL; } - if (!vmw_framebuffer_to_vfb(fb)->dmabuf) + if (!vmw_framebuffer_to_vfb(fb)->bo) surface = vmw_framebuffer_to_vfbs(fb)->surface; if (surface && !surface->snooper.image) { @@ -687,8 +687,8 @@ vmw_du_plane_duplicate_state(struct drm_plane *plane) if (vps->surf) (void) vmw_surface_reference(vps->surf); - if (vps->dmabuf) - (void) vmw_dmabuf_reference(vps->dmabuf); + if (vps->bo) + (void) vmw_bo_reference(vps->bo); state = &vps->base; @@ -745,8 +745,8 @@ vmw_du_plane_destroy_state(struct drm_plane *plane, if (vps->surf) vmw_surface_unreference(&vps->surf); - if (vps->dmabuf) - vmw_dmabuf_unreference(&vps->dmabuf); + if (vps->bo) + vmw_bo_unreference(&vps->bo); drm_atomic_helper_plane_destroy_state(plane, state); } @@ -902,12 +902,12 @@ static int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, /** * vmw_kms_readback - Perform a readback from the screen system to - * a dma-buffer backed framebuffer. + * a buffer-object backed framebuffer. * * @dev_priv: Pointer to the device private structure. * @file_priv: Pointer to a struct drm_file identifying the caller. * Must be set to NULL if @user_fence_rep is NULL. - * @vfb: Pointer to the dma-buffer backed framebuffer. + * @vfb: Pointer to the buffer-object backed framebuffer. * @user_fence_rep: User-space provided structure for fence information. * Must be set to non-NULL if @file_priv is non-NULL. * @vclips: Array of clip rects. @@ -951,7 +951,7 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, struct vmw_framebuffer **out, const struct drm_mode_fb_cmd2 *mode_cmd, - bool is_dmabuf_proxy) + bool is_bo_proxy) { struct drm_device *dev = dev_priv->dev; @@ -1019,7 +1019,7 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, drm_helper_mode_fill_fb_struct(dev, &vfbs->base.base, mode_cmd); vfbs->surface = vmw_surface_reference(surface); vfbs->base.user_handle = mode_cmd->handles[0]; - vfbs->is_dmabuf_proxy = is_dmabuf_proxy; + vfbs->is_bo_proxy = is_bo_proxy; *out = &vfbs->base; @@ -1038,30 +1038,30 @@ out_err1: } /* - * Dmabuf framebuffer code + * Buffer-object framebuffer code */ -static void vmw_framebuffer_dmabuf_destroy(struct drm_framebuffer *framebuffer) +static void vmw_framebuffer_bo_destroy(struct drm_framebuffer *framebuffer) { - struct vmw_framebuffer_dmabuf *vfbd = + struct vmw_framebuffer_bo *vfbd = vmw_framebuffer_to_vfbd(framebuffer); drm_framebuffer_cleanup(framebuffer); - vmw_dmabuf_unreference(&vfbd->buffer); + vmw_bo_unreference(&vfbd->buffer); if (vfbd->base.user_obj) ttm_base_object_unref(&vfbd->base.user_obj); kfree(vfbd); } -static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, - struct drm_file *file_priv, - unsigned flags, unsigned color, - struct drm_clip_rect *clips, - unsigned num_clips) +static int vmw_framebuffer_bo_dirty(struct drm_framebuffer *framebuffer, + struct drm_file *file_priv, + unsigned int flags, unsigned int color, + struct drm_clip_rect *clips, + unsigned int num_clips) { struct vmw_private *dev_priv = vmw_priv(framebuffer->dev); - struct vmw_framebuffer_dmabuf *vfbd = + struct vmw_framebuffer_bo *vfbd = vmw_framebuffer_to_vfbd(framebuffer); struct drm_clip_rect norect; int ret, increment = 1; @@ -1092,13 +1092,13 @@ static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, true, true, NULL); break; case vmw_du_screen_object: - ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, &vfbd->base, - clips, NULL, num_clips, - increment, true, NULL, NULL); + ret = vmw_kms_sou_do_bo_dirty(dev_priv, &vfbd->base, + clips, NULL, num_clips, + increment, true, NULL, NULL); break; case vmw_du_legacy: - ret = vmw_kms_ldu_do_dmabuf_dirty(dev_priv, &vfbd->base, 0, 0, - clips, num_clips, increment); + ret = vmw_kms_ldu_do_bo_dirty(dev_priv, &vfbd->base, 0, 0, + clips, num_clips, increment); break; default: ret = -EINVAL; @@ -1114,23 +1114,23 @@ static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, return ret; } -static const struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = { - .destroy = vmw_framebuffer_dmabuf_destroy, - .dirty = vmw_framebuffer_dmabuf_dirty, +static const struct drm_framebuffer_funcs vmw_framebuffer_bo_funcs = { + .destroy = vmw_framebuffer_bo_destroy, + .dirty = vmw_framebuffer_bo_dirty, }; /** - * Pin the dmabuffer in a location suitable for access by the + * Pin the bofer in a location suitable for access by the * display system. */ static int vmw_framebuffer_pin(struct vmw_framebuffer *vfb) { struct vmw_private *dev_priv = vmw_priv(vfb->base.dev); - struct vmw_dma_buffer *buf; + struct vmw_buffer_object *buf; struct ttm_placement *placement; int ret; - buf = vfb->dmabuf ? vmw_framebuffer_to_vfbd(&vfb->base)->buffer : + buf = vfb->bo ? vmw_framebuffer_to_vfbd(&vfb->base)->buffer : vmw_framebuffer_to_vfbs(&vfb->base)->surface->res.backup; if (!buf) @@ -1139,12 +1139,12 @@ static int vmw_framebuffer_pin(struct vmw_framebuffer *vfb) switch (dev_priv->active_display_unit) { case vmw_du_legacy: vmw_overlay_pause_all(dev_priv); - ret = vmw_dmabuf_pin_in_start_of_vram(dev_priv, buf, false); + ret = vmw_bo_pin_in_start_of_vram(dev_priv, buf, false); vmw_overlay_resume_all(dev_priv); break; case vmw_du_screen_object: case vmw_du_screen_target: - if (vfb->dmabuf) { + if (vfb->bo) { if (dev_priv->capabilities & SVGA_CAP_3D) { /* * Use surface DMA to get content to @@ -1160,8 +1160,7 @@ static int vmw_framebuffer_pin(struct vmw_framebuffer *vfb) placement = &vmw_mob_placement; } - return vmw_dmabuf_pin_in_placement(dev_priv, buf, placement, - false); + return vmw_bo_pin_in_placement(dev_priv, buf, placement, false); default: return -EINVAL; } @@ -1172,36 +1171,36 @@ static int vmw_framebuffer_pin(struct vmw_framebuffer *vfb) static int vmw_framebuffer_unpin(struct vmw_framebuffer *vfb) { struct vmw_private *dev_priv = vmw_priv(vfb->base.dev); - struct vmw_dma_buffer *buf; + struct vmw_buffer_object *buf; - buf = vfb->dmabuf ? vmw_framebuffer_to_vfbd(&vfb->base)->buffer : + buf = vfb->bo ? vmw_framebuffer_to_vfbd(&vfb->base)->buffer : vmw_framebuffer_to_vfbs(&vfb->base)->surface->res.backup; if (WARN_ON(!buf)) return 0; - return vmw_dmabuf_unpin(dev_priv, buf, false); + return vmw_bo_unpin(dev_priv, buf, false); } /** - * vmw_create_dmabuf_proxy - create a proxy surface for the DMA buf + * vmw_create_bo_proxy - create a proxy surface for the buffer object * * @dev: DRM device * @mode_cmd: parameters for the new surface - * @dmabuf_mob: MOB backing the DMA buf + * @bo_mob: MOB backing the buffer object * @srf_out: newly created surface * - * When the content FB is a DMA buf, we create a surface as a proxy to the + * When the content FB is a buffer object, we create a surface as a proxy to the * same buffer. This way we can do a surface copy rather than a surface DMA. * This is a more efficient approach * * RETURNS: * 0 on success, error code otherwise */ -static int vmw_create_dmabuf_proxy(struct drm_device *dev, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct vmw_dma_buffer *dmabuf_mob, - struct vmw_surface **srf_out) +static int vmw_create_bo_proxy(struct drm_device *dev, + const struct drm_mode_fb_cmd2 *mode_cmd, + struct vmw_buffer_object *bo_mob, + struct vmw_surface **srf_out) { uint32_t format; struct drm_vmw_size content_base_size = {0}; @@ -1258,8 +1257,8 @@ static int vmw_create_dmabuf_proxy(struct drm_device *dev, /* Reserve and switch the backing mob. */ mutex_lock(&res->dev_priv->cmdbuf_mutex); (void) vmw_resource_reserve(res, false, true); - vmw_dmabuf_unreference(&res->backup); - res->backup = vmw_dmabuf_reference(dmabuf_mob); + vmw_bo_unreference(&res->backup); + res->backup = vmw_bo_reference(bo_mob); res->backup_offset = 0; vmw_resource_unreserve(res, false, NULL, 0); mutex_unlock(&res->dev_priv->cmdbuf_mutex); @@ -1269,21 +1268,21 @@ static int vmw_create_dmabuf_proxy(struct drm_device *dev, -static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv, - struct vmw_dma_buffer *dmabuf, - struct vmw_framebuffer **out, - const struct drm_mode_fb_cmd2 - *mode_cmd) +static int vmw_kms_new_framebuffer_bo(struct vmw_private *dev_priv, + struct vmw_buffer_object *bo, + struct vmw_framebuffer **out, + const struct drm_mode_fb_cmd2 + *mode_cmd) { struct drm_device *dev = dev_priv->dev; - struct vmw_framebuffer_dmabuf *vfbd; + struct vmw_framebuffer_bo *vfbd; unsigned int requested_size; struct drm_format_name_buf format_name; int ret; requested_size = mode_cmd->height * mode_cmd->pitches[0]; - if (unlikely(requested_size > dmabuf->base.num_pages * PAGE_SIZE)) { + if (unlikely(requested_size > bo->base.num_pages * PAGE_SIZE)) { DRM_ERROR("Screen buffer object size is too small " "for requested mode.\n"); return -EINVAL; @@ -1312,20 +1311,20 @@ static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv, } drm_helper_mode_fill_fb_struct(dev, &vfbd->base.base, mode_cmd); - vfbd->base.dmabuf = true; - vfbd->buffer = vmw_dmabuf_reference(dmabuf); + vfbd->base.bo = true; + vfbd->buffer = vmw_bo_reference(bo); vfbd->base.user_handle = mode_cmd->handles[0]; *out = &vfbd->base; ret = drm_framebuffer_init(dev, &vfbd->base.base, - &vmw_framebuffer_dmabuf_funcs); + &vmw_framebuffer_bo_funcs); if (ret) goto out_err2; return 0; out_err2: - vmw_dmabuf_unreference(&dmabuf); + vmw_bo_unreference(&bo); kfree(vfbd); out_err1: return ret; @@ -1354,57 +1353,57 @@ vmw_kms_srf_ok(struct vmw_private *dev_priv, uint32_t width, uint32_t height) * vmw_kms_new_framebuffer - Create a new framebuffer. * * @dev_priv: Pointer to device private struct. - * @dmabuf: Pointer to dma buffer to wrap the kms framebuffer around. - * Either @dmabuf or @surface must be NULL. + * @bo: Pointer to buffer object to wrap the kms framebuffer around. + * Either @bo or @surface must be NULL. * @surface: Pointer to a surface to wrap the kms framebuffer around. - * Either @dmabuf or @surface must be NULL. - * @only_2d: No presents will occur to this dma buffer based framebuffer. This - * Helps the code to do some important optimizations. + * Either @bo or @surface must be NULL. + * @only_2d: No presents will occur to this buffer object based framebuffer. + * This helps the code to do some important optimizations. * @mode_cmd: Frame-buffer metadata. */ struct vmw_framebuffer * vmw_kms_new_framebuffer(struct vmw_private *dev_priv, - struct vmw_dma_buffer *dmabuf, + struct vmw_buffer_object *bo, struct vmw_surface *surface, bool only_2d, const struct drm_mode_fb_cmd2 *mode_cmd) { struct vmw_framebuffer *vfb = NULL; - bool is_dmabuf_proxy = false; + bool is_bo_proxy = false; int ret; /* * We cannot use the SurfaceDMA command in an non-accelerated VM, - * therefore, wrap the DMA buf in a surface so we can use the + * therefore, wrap the buffer object in a surface so we can use the * SurfaceCopy command. */ if (vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height) && - dmabuf && only_2d && + bo && only_2d && mode_cmd->width > 64 && /* Don't create a proxy for cursor */ dev_priv->active_display_unit == vmw_du_screen_target) { - ret = vmw_create_dmabuf_proxy(dev_priv->dev, mode_cmd, - dmabuf, &surface); + ret = vmw_create_bo_proxy(dev_priv->dev, mode_cmd, + bo, &surface); if (ret) return ERR_PTR(ret); - is_dmabuf_proxy = true; + is_bo_proxy = true; } /* Create the new framebuffer depending one what we have */ if (surface) { ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb, mode_cmd, - is_dmabuf_proxy); + is_bo_proxy); /* - * vmw_create_dmabuf_proxy() adds a reference that is no longer + * vmw_create_bo_proxy() adds a reference that is no longer * needed */ - if (is_dmabuf_proxy) + if (is_bo_proxy) vmw_surface_unreference(&surface); - } else if (dmabuf) { - ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, dmabuf, &vfb, - mode_cmd); + } else if (bo) { + ret = vmw_kms_new_framebuffer_bo(dev_priv, bo, &vfb, + mode_cmd); } else { BUG(); } @@ -1430,7 +1429,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; struct vmw_framebuffer *vfb = NULL; struct vmw_surface *surface = NULL; - struct vmw_dma_buffer *bo = NULL; + struct vmw_buffer_object *bo = NULL; struct ttm_base_object *user_obj; int ret; @@ -1466,7 +1465,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, * End conditioned code. */ - /* returns either a dmabuf or surface */ + /* returns either a bo or surface */ ret = vmw_user_lookup_handle(dev_priv, tfile, mode_cmd->handles[0], &surface, &bo); @@ -1494,7 +1493,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, err_out: /* vmw_user_lookup_handle takes one ref so does new_fb */ if (bo) - vmw_dmabuf_unreference(&bo); + vmw_bo_unreference(&bo); if (surface) vmw_surface_unreference(&surface); @@ -2427,7 +2426,7 @@ int vmw_kms_helper_dirty(struct vmw_private *dev_priv, * interrupted by a signal. */ int vmw_kms_helper_buffer_prepare(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, + struct vmw_buffer_object *buf, bool interruptible, bool validate_as_mob, bool for_cpu_blit) @@ -2459,7 +2458,7 @@ int vmw_kms_helper_buffer_prepare(struct vmw_private *dev_priv, * Helper to be used if an error forces the caller to undo the actions of * vmw_kms_helper_buffer_prepare. */ -void vmw_kms_helper_buffer_revert(struct vmw_dma_buffer *buf) +void vmw_kms_helper_buffer_revert(struct vmw_buffer_object *buf) { if (buf) ttm_bo_unreserve(&buf->base); @@ -2482,7 +2481,7 @@ void vmw_kms_helper_buffer_revert(struct vmw_dma_buffer *buf) */ void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv, struct drm_file *file_priv, - struct vmw_dma_buffer *buf, + struct vmw_buffer_object *buf, struct vmw_fence_obj **out_fence, struct drm_vmw_fence_rep __user * user_fence_rep) @@ -2522,7 +2521,7 @@ void vmw_kms_helper_resource_revert(struct vmw_validation_ctx *ctx) struct vmw_resource *res = ctx->res; vmw_kms_helper_buffer_revert(ctx->buf); - vmw_dmabuf_unreference(&ctx->buf); + vmw_bo_unreference(&ctx->buf); vmw_resource_unreserve(res, false, NULL, 0); mutex_unlock(&res->dev_priv->cmdbuf_mutex); } @@ -2567,7 +2566,7 @@ int vmw_kms_helper_resource_prepare(struct vmw_resource *res, if (ret) goto out_unreserve; - ctx->buf = vmw_dmabuf_reference(res->backup); + ctx->buf = vmw_bo_reference(res->backup); } ret = vmw_resource_validate(res); if (ret) @@ -2600,7 +2599,7 @@ void vmw_kms_helper_resource_finish(struct vmw_validation_ctx *ctx, vmw_kms_helper_buffer_finish(res->dev_priv, NULL, ctx->buf, out_fence, NULL); - vmw_dmabuf_unreference(&ctx->buf); + vmw_bo_unreference(&ctx->buf); vmw_resource_unreserve(res, false, NULL, 0); mutex_unlock(&res->dev_priv->cmdbuf_mutex); } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 6b7c012719f1..ff1caed38f94 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -90,7 +90,7 @@ struct vmw_kms_dirty { #define vmw_framebuffer_to_vfbs(x) \ container_of(x, struct vmw_framebuffer_surface, base.base) #define vmw_framebuffer_to_vfbd(x) \ - container_of(x, struct vmw_framebuffer_dmabuf, base.base) + container_of(x, struct vmw_framebuffer_bo, base.base) /** * Base class for framebuffers @@ -102,7 +102,7 @@ struct vmw_framebuffer { struct drm_framebuffer base; int (*pin)(struct vmw_framebuffer *fb); int (*unpin)(struct vmw_framebuffer *fb); - bool dmabuf; + bool bo; struct ttm_base_object *user_obj; uint32_t user_handle; }; @@ -117,15 +117,15 @@ struct vmw_clip_rect { struct vmw_framebuffer_surface { struct vmw_framebuffer base; struct vmw_surface *surface; - struct vmw_dma_buffer *buffer; + struct vmw_buffer_object *buffer; struct list_head head; - bool is_dmabuf_proxy; /* true if this is proxy surface for DMA buf */ + bool is_bo_proxy; /* true if this is proxy surface for DMA buf */ }; -struct vmw_framebuffer_dmabuf { +struct vmw_framebuffer_bo { struct vmw_framebuffer base; - struct vmw_dma_buffer *buffer; + struct vmw_buffer_object *buffer; }; @@ -161,18 +161,18 @@ struct vmw_crtc_state { * * @base DRM plane object * @surf Display surface for STDU - * @dmabuf display dmabuf for SOU + * @bo display bo for SOU * @content_fb_type Used by STDU. - * @dmabuf_size Size of the dmabuf, used by Screen Object Display Unit + * @bo_size Size of the bo, used by Screen Object Display Unit * @pinned pin count for STDU display surface */ struct vmw_plane_state { struct drm_plane_state base; struct vmw_surface *surf; - struct vmw_dma_buffer *dmabuf; + struct vmw_buffer_object *bo; int content_fb_type; - unsigned long dmabuf_size; + unsigned long bo_size; int pinned; @@ -209,7 +209,7 @@ struct vmw_display_unit { struct drm_plane cursor; struct vmw_surface *cursor_surface; - struct vmw_dma_buffer *cursor_dmabuf; + struct vmw_buffer_object *cursor_bo; size_t cursor_age; int cursor_x; @@ -243,7 +243,7 @@ struct vmw_display_unit { struct vmw_validation_ctx { struct vmw_resource *res; - struct vmw_dma_buffer *buf; + struct vmw_buffer_object *buf; }; #define vmw_crtc_to_du(x) \ @@ -291,14 +291,14 @@ int vmw_kms_helper_dirty(struct vmw_private *dev_priv, struct vmw_kms_dirty *dirty); int vmw_kms_helper_buffer_prepare(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, + struct vmw_buffer_object *buf, bool interruptible, bool validate_as_mob, bool for_cpu_blit); -void vmw_kms_helper_buffer_revert(struct vmw_dma_buffer *buf); +void vmw_kms_helper_buffer_revert(struct vmw_buffer_object *buf); void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv, struct drm_file *file_priv, - struct vmw_dma_buffer *buf, + struct vmw_buffer_object *buf, struct vmw_fence_obj **out_fence, struct drm_vmw_fence_rep __user * user_fence_rep); @@ -316,7 +316,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv, uint32_t num_clips); struct vmw_framebuffer * vmw_kms_new_framebuffer(struct vmw_private *dev_priv, - struct vmw_dma_buffer *dmabuf, + struct vmw_buffer_object *bo, struct vmw_surface *surface, bool only_2d, const struct drm_mode_fb_cmd2 *mode_cmd); @@ -384,11 +384,11 @@ void vmw_du_connector_destroy_state(struct drm_connector *connector, */ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv); int vmw_kms_ldu_close_display(struct vmw_private *dev_priv); -int vmw_kms_ldu_do_dmabuf_dirty(struct vmw_private *dev_priv, - struct vmw_framebuffer *framebuffer, - unsigned flags, unsigned color, - struct drm_clip_rect *clips, - unsigned num_clips, int increment); +int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv, + struct vmw_framebuffer *framebuffer, + unsigned int flags, unsigned int color, + struct drm_clip_rect *clips, + unsigned int num_clips, int increment); int vmw_kms_update_proxy(struct vmw_resource *res, const struct drm_clip_rect *clips, unsigned num_clips, @@ -408,14 +408,14 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv, unsigned num_clips, int inc, struct vmw_fence_obj **out_fence, struct drm_crtc *crtc); -int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv, - struct vmw_framebuffer *framebuffer, - struct drm_clip_rect *clips, - struct drm_vmw_rect *vclips, - unsigned num_clips, int increment, - bool interruptible, - struct vmw_fence_obj **out_fence, - struct drm_crtc *crtc); +int vmw_kms_sou_do_bo_dirty(struct vmw_private *dev_priv, + struct vmw_framebuffer *framebuffer, + struct drm_clip_rect *clips, + struct drm_vmw_rect *vclips, + unsigned int num_clips, int increment, + bool interruptible, + struct vmw_fence_obj **out_fence, + struct drm_crtc *crtc); int vmw_kms_sou_readback(struct vmw_private *dev_priv, struct drm_file *file_priv, struct vmw_framebuffer *vfb, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 4a5907e3f560..a2dd9a829219 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -547,11 +547,11 @@ int vmw_kms_ldu_close_display(struct vmw_private *dev_priv) } -int vmw_kms_ldu_do_dmabuf_dirty(struct vmw_private *dev_priv, - struct vmw_framebuffer *framebuffer, - unsigned flags, unsigned color, - struct drm_clip_rect *clips, - unsigned num_clips, int increment) +int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv, + struct vmw_framebuffer *framebuffer, + unsigned int flags, unsigned int color, + struct drm_clip_rect *clips, + unsigned int num_clips, int increment) { size_t fifo_size; int i; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c index 222c9c2123a1..09420ef19ecb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c @@ -38,7 +38,7 @@ #define VMW_OVERLAY_CAP_MASK (SVGA_FIFO_CAP_VIDEO | SVGA_FIFO_CAP_ESCAPE) struct vmw_stream { - struct vmw_dma_buffer *buf; + struct vmw_buffer_object *buf; bool claimed; bool paused; struct drm_vmw_control_stream_arg saved; @@ -94,7 +94,7 @@ static inline void fill_flush(struct vmw_escape_video_flush *cmd, * -ERESTARTSYS if interrupted by a signal. */ static int vmw_overlay_send_put(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, + struct vmw_buffer_object *buf, struct drm_vmw_control_stream_arg *arg, bool interruptible) { @@ -225,16 +225,16 @@ static int vmw_overlay_send_stop(struct vmw_private *dev_priv, * used with GMRs instead of being locked to vram. */ static int vmw_overlay_move_buffer(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, + struct vmw_buffer_object *buf, bool pin, bool inter) { if (!pin) - return vmw_dmabuf_unpin(dev_priv, buf, inter); + return vmw_bo_unpin(dev_priv, buf, inter); if (dev_priv->active_display_unit == vmw_du_legacy) - return vmw_dmabuf_pin_in_vram(dev_priv, buf, inter); + return vmw_bo_pin_in_vram(dev_priv, buf, inter); - return vmw_dmabuf_pin_in_vram_or_gmr(dev_priv, buf, inter); + return vmw_bo_pin_in_vram_or_gmr(dev_priv, buf, inter); } /** @@ -278,7 +278,7 @@ static int vmw_overlay_stop(struct vmw_private *dev_priv, } if (!pause) { - vmw_dmabuf_unreference(&stream->buf); + vmw_bo_unreference(&stream->buf); stream->paused = false; } else { stream->paused = true; @@ -297,7 +297,7 @@ static int vmw_overlay_stop(struct vmw_private *dev_priv, * -ERESTARTSYS if interrupted. */ static int vmw_overlay_update_stream(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, + struct vmw_buffer_object *buf, struct drm_vmw_control_stream_arg *arg, bool interruptible) { @@ -347,7 +347,7 @@ static int vmw_overlay_update_stream(struct vmw_private *dev_priv, } if (stream->buf != buf) - stream->buf = vmw_dmabuf_reference(buf); + stream->buf = vmw_bo_reference(buf); stream->saved = *arg; /* stream is no longer stopped/paused */ stream->paused = false; @@ -466,7 +466,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data, struct vmw_overlay *overlay = dev_priv->overlay_priv; struct drm_vmw_control_stream_arg *arg = (struct drm_vmw_control_stream_arg *)data; - struct vmw_dma_buffer *buf; + struct vmw_buffer_object *buf; struct vmw_resource *res; int ret; @@ -484,13 +484,13 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data, goto out_unlock; } - ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &buf, NULL); + ret = vmw_user_bo_lookup(tfile, arg->handle, &buf, NULL); if (ret) goto out_unlock; ret = vmw_overlay_update_stream(dev_priv, buf, arg, true); - vmw_dmabuf_unreference(&buf); + vmw_bo_unreference(&buf); out_unlock: mutex_unlock(&overlay->mutex); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 6b3a942b18df..5aaf9ac65cba 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -35,9 +35,9 @@ #define VMW_RES_EVICT_ERR_COUNT 10 -struct vmw_user_dma_buffer { +struct vmw_user_buffer_object { struct ttm_prime_object prime; - struct vmw_dma_buffer dma; + struct vmw_buffer_object vbo; }; struct vmw_bo_user_rep { @@ -45,17 +45,18 @@ struct vmw_bo_user_rep { uint64_t map_handle; }; -static inline struct vmw_dma_buffer * -vmw_dma_buffer(struct ttm_buffer_object *bo) +static inline struct vmw_buffer_object * +vmw_buffer_object(struct ttm_buffer_object *bo) { - return container_of(bo, struct vmw_dma_buffer, base); + return container_of(bo, struct vmw_buffer_object, base); } -static inline struct vmw_user_dma_buffer * -vmw_user_dma_buffer(struct ttm_buffer_object *bo) +static inline struct vmw_user_buffer_object * +vmw_user_buffer_object(struct ttm_buffer_object *bo) { - struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); - return container_of(vmw_bo, struct vmw_user_dma_buffer, dma); + struct vmw_buffer_object *vmw_bo = vmw_buffer_object(bo); + + return container_of(vmw_bo, struct vmw_user_buffer_object, vbo); } struct vmw_resource *vmw_resource_reference(struct vmw_resource *res) @@ -116,7 +117,7 @@ static void vmw_resource_release(struct kref *kref) res->backup_dirty = false; list_del_init(&res->mob_head); ttm_bo_unreserve(bo); - vmw_dmabuf_unreference(&res->backup); + vmw_bo_unreference(&res->backup); } if (likely(res->hw_destroy != NULL)) { @@ -287,7 +288,7 @@ out_bad_resource: } /** - * Helper function that looks either a surface or dmabuf. + * Helper function that looks either a surface or bo. * * The pointer this pointed at by out_surf and out_buf needs to be null. */ @@ -295,7 +296,7 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv, struct ttm_object_file *tfile, uint32_t handle, struct vmw_surface **out_surf, - struct vmw_dma_buffer **out_buf) + struct vmw_buffer_object **out_buf) { struct vmw_resource *res; int ret; @@ -311,7 +312,7 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv, } *out_surf = NULL; - ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf, NULL); + ret = vmw_user_bo_lookup(tfile, handle, out_buf, NULL); return ret; } @@ -320,14 +321,14 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv, */ /** - * vmw_dmabuf_acc_size - Calculate the pinned memory usage of buffers + * vmw_bo_acc_size - Calculate the pinned memory usage of buffers * * @dev_priv: Pointer to a struct vmw_private identifying the device. * @size: The requested buffer size. * @user: Whether this is an ordinary dma buffer or a user dma buffer. */ -static size_t vmw_dmabuf_acc_size(struct vmw_private *dev_priv, size_t size, - bool user) +static size_t vmw_bo_acc_size(struct vmw_private *dev_priv, size_t size, + bool user) { static size_t struct_size, user_struct_size; size_t num_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; @@ -337,9 +338,9 @@ static size_t vmw_dmabuf_acc_size(struct vmw_private *dev_priv, size_t size, size_t backend_size = ttm_round_pot(vmw_tt_size); struct_size = backend_size + - ttm_round_pot(sizeof(struct vmw_dma_buffer)); + ttm_round_pot(sizeof(struct vmw_buffer_object)); user_struct_size = backend_size + - ttm_round_pot(sizeof(struct vmw_user_dma_buffer)); + ttm_round_pot(sizeof(struct vmw_user_buffer_object)); } if (dev_priv->map_mode == vmw_dma_alloc_coherent) @@ -350,36 +351,36 @@ static size_t vmw_dmabuf_acc_size(struct vmw_private *dev_priv, size_t size, page_array_size; } -void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo) +void vmw_bo_bo_free(struct ttm_buffer_object *bo) { - struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); + struct vmw_buffer_object *vmw_bo = vmw_buffer_object(bo); - vmw_dma_buffer_unmap(vmw_bo); + vmw_buffer_object_unmap(vmw_bo); kfree(vmw_bo); } -static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo) +static void vmw_user_bo_destroy(struct ttm_buffer_object *bo) { - struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo); + struct vmw_user_buffer_object *vmw_user_bo = vmw_user_buffer_object(bo); - vmw_dma_buffer_unmap(&vmw_user_bo->dma); + vmw_buffer_object_unmap(&vmw_user_bo->vbo); ttm_prime_object_kfree(vmw_user_bo, prime); } -int vmw_dmabuf_init(struct vmw_private *dev_priv, - struct vmw_dma_buffer *vmw_bo, - size_t size, struct ttm_placement *placement, - bool interruptible, - void (*bo_free) (struct ttm_buffer_object *bo)) +int vmw_bo_init(struct vmw_private *dev_priv, + struct vmw_buffer_object *vmw_bo, + size_t size, struct ttm_placement *placement, + bool interruptible, + void (*bo_free)(struct ttm_buffer_object *bo)) { struct ttm_bo_device *bdev = &dev_priv->bdev; size_t acc_size; int ret; - bool user = (bo_free == &vmw_user_dmabuf_destroy); + bool user = (bo_free == &vmw_user_bo_destroy); - BUG_ON(!bo_free && (!user && (bo_free != vmw_dmabuf_bo_free))); + WARN_ON_ONCE(!bo_free && (!user && (bo_free != vmw_bo_bo_free))); - acc_size = vmw_dmabuf_acc_size(dev_priv, size, user); + acc_size = vmw_bo_acc_size(dev_priv, size, user); memset(vmw_bo, 0, sizeof(*vmw_bo)); INIT_LIST_HEAD(&vmw_bo->res_list); @@ -391,9 +392,9 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv, return ret; } -static void vmw_user_dmabuf_release(struct ttm_base_object **p_base) +static void vmw_user_bo_release(struct ttm_base_object **p_base) { - struct vmw_user_dma_buffer *vmw_user_bo; + struct vmw_user_buffer_object *vmw_user_bo; struct ttm_base_object *base = *p_base; struct ttm_buffer_object *bo; @@ -402,21 +403,22 @@ static void vmw_user_dmabuf_release(struct ttm_base_object **p_base) if (unlikely(base == NULL)) return; - vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, + vmw_user_bo = container_of(base, struct vmw_user_buffer_object, prime.base); - bo = &vmw_user_bo->dma.base; + bo = &vmw_user_bo->vbo.base; ttm_bo_unref(&bo); } -static void vmw_user_dmabuf_ref_obj_release(struct ttm_base_object *base, - enum ttm_ref_type ref_type) +static void vmw_user_bo_ref_obj_release(struct ttm_base_object *base, + enum ttm_ref_type ref_type) { - struct vmw_user_dma_buffer *user_bo; - user_bo = container_of(base, struct vmw_user_dma_buffer, prime.base); + struct vmw_user_buffer_object *user_bo; + + user_bo = container_of(base, struct vmw_user_buffer_object, prime.base); switch (ref_type) { case TTM_REF_SYNCCPU_WRITE: - ttm_bo_synccpu_write_release(&user_bo->dma.base); + ttm_bo_synccpu_write_release(&user_bo->vbo.base); break; default: BUG(); @@ -424,7 +426,7 @@ static void vmw_user_dmabuf_ref_obj_release(struct ttm_base_object *base, } /** - * vmw_user_dmabuf_alloc - Allocate a user dma buffer + * vmw_user_bo_alloc - Allocate a user dma buffer * * @dev_priv: Pointer to a struct device private. * @tfile: Pointer to a struct ttm_object_file on which to register the user @@ -432,18 +434,18 @@ static void vmw_user_dmabuf_ref_obj_release(struct ttm_base_object *base, * @size: Size of the dma buffer. * @shareable: Boolean whether the buffer is shareable with other open files. * @handle: Pointer to where the handle value should be assigned. - * @p_dma_buf: Pointer to where the refcounted struct vmw_dma_buffer pointer + * @p_vbo: Pointer to where the refcounted struct vmw_buffer_object pointer * should be assigned. */ -int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv, - struct ttm_object_file *tfile, - uint32_t size, - bool shareable, - uint32_t *handle, - struct vmw_dma_buffer **p_dma_buf, - struct ttm_base_object **p_base) +int vmw_user_bo_alloc(struct vmw_private *dev_priv, + struct ttm_object_file *tfile, + uint32_t size, + bool shareable, + uint32_t *handle, + struct vmw_buffer_object **p_vbo, + struct ttm_base_object **p_base) { - struct vmw_user_dma_buffer *user_bo; + struct vmw_user_buffer_object *user_bo; struct ttm_buffer_object *tmp; int ret; @@ -453,28 +455,28 @@ int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv, return -ENOMEM; } - ret = vmw_dmabuf_init(dev_priv, &user_bo->dma, size, - (dev_priv->has_mob) ? - &vmw_sys_placement : - &vmw_vram_sys_placement, true, - &vmw_user_dmabuf_destroy); + ret = vmw_bo_init(dev_priv, &user_bo->vbo, size, + (dev_priv->has_mob) ? + &vmw_sys_placement : + &vmw_vram_sys_placement, true, + &vmw_user_bo_destroy); if (unlikely(ret != 0)) return ret; - tmp = ttm_bo_reference(&user_bo->dma.base); + tmp = ttm_bo_reference(&user_bo->vbo.base); ret = ttm_prime_object_init(tfile, size, &user_bo->prime, shareable, ttm_buffer_type, - &vmw_user_dmabuf_release, - &vmw_user_dmabuf_ref_obj_release); + &vmw_user_bo_release, + &vmw_user_bo_ref_obj_release); if (unlikely(ret != 0)) { ttm_bo_unref(&tmp); goto out_no_base_object; } - *p_dma_buf = &user_bo->dma; + *p_vbo = &user_bo->vbo; if (p_base) { *p_base = &user_bo->prime.base; kref_get(&(*p_base)->refcount); @@ -486,21 +488,21 @@ out_no_base_object: } /** - * vmw_user_dmabuf_verify_access - verify access permissions on this + * vmw_user_bo_verify_access - verify access permissions on this * buffer object. * * @bo: Pointer to the buffer object being accessed * @tfile: Identifying the caller. */ -int vmw_user_dmabuf_verify_access(struct ttm_buffer_object *bo, +int vmw_user_bo_verify_access(struct ttm_buffer_object *bo, struct ttm_object_file *tfile) { - struct vmw_user_dma_buffer *vmw_user_bo; + struct vmw_user_buffer_object *vmw_user_bo; - if (unlikely(bo->destroy != vmw_user_dmabuf_destroy)) + if (unlikely(bo->destroy != vmw_user_bo_destroy)) return -EPERM; - vmw_user_bo = vmw_user_dma_buffer(bo); + vmw_user_bo = vmw_user_buffer_object(bo); /* Check that the caller has opened the object. */ if (likely(ttm_ref_object_exists(tfile, &vmw_user_bo->prime.base))) @@ -511,7 +513,7 @@ int vmw_user_dmabuf_verify_access(struct ttm_buffer_object *bo, } /** - * vmw_user_dmabuf_synccpu_grab - Grab a struct vmw_user_dma_buffer for cpu + * vmw_user_bo_synccpu_grab - Grab a struct vmw_user_buffer_object for cpu * access, idling previous GPU operations on the buffer and optionally * blocking it for further command submissions. * @@ -521,11 +523,11 @@ int vmw_user_dmabuf_verify_access(struct ttm_buffer_object *bo, * * A blocking grab will be automatically released when @tfile is closed. */ -static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo, +static int vmw_user_bo_synccpu_grab(struct vmw_user_buffer_object *user_bo, struct ttm_object_file *tfile, uint32_t flags) { - struct ttm_buffer_object *bo = &user_bo->dma.base; + struct ttm_buffer_object *bo = &user_bo->vbo.base; bool existed; int ret; @@ -550,20 +552,20 @@ static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo, ret = ttm_ref_object_add(tfile, &user_bo->prime.base, TTM_REF_SYNCCPU_WRITE, &existed, false); if (ret != 0 || existed) - ttm_bo_synccpu_write_release(&user_bo->dma.base); + ttm_bo_synccpu_write_release(&user_bo->vbo.base); return ret; } /** - * vmw_user_dmabuf_synccpu_release - Release a previous grab for CPU access, + * vmw_user_bo_synccpu_release - Release a previous grab for CPU access, * and unblock command submission on the buffer if blocked. * * @handle: Handle identifying the buffer object. * @tfile: Identifying the caller. * @flags: Flags indicating the type of release. */ -static int vmw_user_dmabuf_synccpu_release(uint32_t handle, +static int vmw_user_bo_synccpu_release(uint32_t handle, struct ttm_object_file *tfile, uint32_t flags) { @@ -575,7 +577,7 @@ static int vmw_user_dmabuf_synccpu_release(uint32_t handle, } /** - * vmw_user_dmabuf_synccpu_release - ioctl function implementing the synccpu + * vmw_user_bo_synccpu_release - ioctl function implementing the synccpu * functionality. * * @dev: Identifies the drm device. @@ -585,13 +587,13 @@ static int vmw_user_dmabuf_synccpu_release(uint32_t handle, * This function checks the ioctl arguments for validity and calls the * relevant synccpu functions. */ -int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data, +int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_vmw_synccpu_arg *arg = (struct drm_vmw_synccpu_arg *) data; - struct vmw_dma_buffer *dma_buf; - struct vmw_user_dma_buffer *user_bo; + struct vmw_buffer_object *vbo; + struct vmw_user_buffer_object *user_bo; struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; struct ttm_base_object *buffer_base; int ret; @@ -606,15 +608,15 @@ int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data, switch (arg->op) { case drm_vmw_synccpu_grab: - ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &dma_buf, + ret = vmw_user_bo_lookup(tfile, arg->handle, &vbo, &buffer_base); if (unlikely(ret != 0)) return ret; - user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, - dma); - ret = vmw_user_dmabuf_synccpu_grab(user_bo, tfile, arg->flags); - vmw_dmabuf_unreference(&dma_buf); + user_bo = container_of(vbo, struct vmw_user_buffer_object, + vbo); + ret = vmw_user_bo_synccpu_grab(user_bo, tfile, arg->flags); + vmw_bo_unreference(&vbo); ttm_base_object_unref(&buffer_base); if (unlikely(ret != 0 && ret != -ERESTARTSYS && ret != -EBUSY)) { @@ -624,8 +626,8 @@ int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data, } break; case drm_vmw_synccpu_release: - ret = vmw_user_dmabuf_synccpu_release(arg->handle, tfile, - arg->flags); + ret = vmw_user_bo_synccpu_release(arg->handle, tfile, + arg->flags); if (unlikely(ret != 0)) { DRM_ERROR("Failed synccpu release on handle 0x%08x.\n", (unsigned int) arg->handle); @@ -640,15 +642,15 @@ int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data, return 0; } -int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int vmw_bo_alloc_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct vmw_private *dev_priv = vmw_priv(dev); union drm_vmw_alloc_dmabuf_arg *arg = (union drm_vmw_alloc_dmabuf_arg *)data; struct drm_vmw_alloc_dmabuf_req *req = &arg->req; struct drm_vmw_dmabuf_rep *rep = &arg->rep; - struct vmw_dma_buffer *dma_buf; + struct vmw_buffer_object *vbo; uint32_t handle; int ret; @@ -656,27 +658,27 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data, if (unlikely(ret != 0)) return ret; - ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile, - req->size, false, &handle, &dma_buf, - NULL); + ret = vmw_user_bo_alloc(dev_priv, vmw_fpriv(file_priv)->tfile, + req->size, false, &handle, &vbo, + NULL); if (unlikely(ret != 0)) - goto out_no_dmabuf; + goto out_no_bo; rep->handle = handle; - rep->map_handle = drm_vma_node_offset_addr(&dma_buf->base.vma_node); + rep->map_handle = drm_vma_node_offset_addr(&vbo->base.vma_node); rep->cur_gmr_id = handle; rep->cur_gmr_offset = 0; - vmw_dmabuf_unreference(&dma_buf); + vmw_bo_unreference(&vbo); -out_no_dmabuf: +out_no_bo: ttm_read_unlock(&dev_priv->reservation_sem); return ret; } -int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int vmw_bo_unref_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct drm_vmw_unref_dmabuf_arg *arg = (struct drm_vmw_unref_dmabuf_arg *)data; @@ -686,11 +688,11 @@ int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data, TTM_REF_USAGE); } -int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, - uint32_t handle, struct vmw_dma_buffer **out, +int vmw_user_bo_lookup(struct ttm_object_file *tfile, + uint32_t handle, struct vmw_buffer_object **out, struct ttm_base_object **p_base) { - struct vmw_user_dma_buffer *vmw_user_bo; + struct vmw_user_buffer_object *vmw_user_bo; struct ttm_base_object *base; base = ttm_base_object_lookup(tfile, handle); @@ -707,28 +709,28 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, return -EINVAL; } - vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, + vmw_user_bo = container_of(base, struct vmw_user_buffer_object, prime.base); - (void)ttm_bo_reference(&vmw_user_bo->dma.base); + (void)ttm_bo_reference(&vmw_user_bo->vbo.base); if (p_base) *p_base = base; else ttm_base_object_unref(&base); - *out = &vmw_user_bo->dma; + *out = &vmw_user_bo->vbo; return 0; } -int vmw_user_dmabuf_reference(struct ttm_object_file *tfile, - struct vmw_dma_buffer *dma_buf, +int vmw_user_bo_reference(struct ttm_object_file *tfile, + struct vmw_buffer_object *vbo, uint32_t *handle) { - struct vmw_user_dma_buffer *user_bo; + struct vmw_user_buffer_object *user_bo; - if (dma_buf->base.destroy != vmw_user_dmabuf_destroy) + if (vbo->base.destroy != vmw_user_bo_destroy) return -EINVAL; - user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, dma); + user_bo = container_of(vbo, struct vmw_user_buffer_object, vbo); *handle = user_bo->prime.base.hash.key; return ttm_ref_object_add(tfile, &user_bo->prime.base, @@ -743,7 +745,7 @@ int vmw_user_dmabuf_reference(struct ttm_object_file *tfile, * @args: Pointer to a struct drm_mode_create_dumb structure * * This is a driver callback for the core drm create_dumb functionality. - * Note that this is very similar to the vmw_dmabuf_alloc ioctl, except + * Note that this is very similar to the vmw_bo_alloc ioctl, except * that the arguments have a different format. */ int vmw_dumb_create(struct drm_file *file_priv, @@ -751,7 +753,7 @@ int vmw_dumb_create(struct drm_file *file_priv, struct drm_mode_create_dumb *args) { struct vmw_private *dev_priv = vmw_priv(dev); - struct vmw_dma_buffer *dma_buf; + struct vmw_buffer_object *vbo; int ret; args->pitch = args->width * ((args->bpp + 7) / 8); @@ -761,14 +763,14 @@ int vmw_dumb_create(struct drm_file *file_priv, if (unlikely(ret != 0)) return ret; - ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile, + ret = vmw_user_bo_alloc(dev_priv, vmw_fpriv(file_priv)->tfile, args->size, false, &args->handle, - &dma_buf, NULL); + &vbo, NULL); if (unlikely(ret != 0)) - goto out_no_dmabuf; + goto out_no_bo; - vmw_dmabuf_unreference(&dma_buf); -out_no_dmabuf: + vmw_bo_unreference(&vbo); +out_no_bo: ttm_read_unlock(&dev_priv->reservation_sem); return ret; } @@ -788,15 +790,15 @@ int vmw_dumb_map_offset(struct drm_file *file_priv, uint64_t *offset) { struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - struct vmw_dma_buffer *out_buf; + struct vmw_buffer_object *out_buf; int ret; - ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf, NULL); + ret = vmw_user_bo_lookup(tfile, handle, &out_buf, NULL); if (ret != 0) return -EINVAL; *offset = drm_vma_node_offset_addr(&out_buf->base.vma_node); - vmw_dmabuf_unreference(&out_buf); + vmw_bo_unreference(&out_buf); return 0; } @@ -829,7 +831,7 @@ static int vmw_resource_buf_alloc(struct vmw_resource *res, { unsigned long size = (res->backup_size + PAGE_SIZE - 1) & PAGE_MASK; - struct vmw_dma_buffer *backup; + struct vmw_buffer_object *backup; int ret; if (likely(res->backup)) { @@ -841,16 +843,16 @@ static int vmw_resource_buf_alloc(struct vmw_resource *res, if (unlikely(!backup)) return -ENOMEM; - ret = vmw_dmabuf_init(res->dev_priv, backup, res->backup_size, + ret = vmw_bo_init(res->dev_priv, backup, res->backup_size, res->func->backup_placement, interruptible, - &vmw_dmabuf_bo_free); + &vmw_bo_bo_free); if (unlikely(ret != 0)) - goto out_no_dmabuf; + goto out_no_bo; res->backup = backup; -out_no_dmabuf: +out_no_bo: return ret; } @@ -919,7 +921,7 @@ out_bind_failed: */ void vmw_resource_unreserve(struct vmw_resource *res, bool switch_backup, - struct vmw_dma_buffer *new_backup, + struct vmw_buffer_object *new_backup, unsigned long new_backup_offset) { struct vmw_private *dev_priv = res->dev_priv; @@ -931,11 +933,11 @@ void vmw_resource_unreserve(struct vmw_resource *res, if (res->backup) { lockdep_assert_held(&res->backup->base.resv->lock.base); list_del_init(&res->mob_head); - vmw_dmabuf_unreference(&res->backup); + vmw_bo_unreference(&res->backup); } if (new_backup) { - res->backup = vmw_dmabuf_reference(new_backup); + res->backup = vmw_bo_reference(new_backup); lockdep_assert_held(&new_backup->base.resv->lock.base); list_add_tail(&res->mob_head, &new_backup->res_list); } else { @@ -1007,7 +1009,7 @@ out_no_validate: out_no_reserve: ttm_bo_unref(&val_buf->bo); if (backup_dirty) - vmw_dmabuf_unreference(&res->backup); + vmw_bo_unreference(&res->backup); return ret; } @@ -1171,7 +1173,7 @@ int vmw_resource_validate(struct vmw_resource *res) goto out_no_validate; else if (!res->func->needs_backup && res->backup) { list_del_init(&res->mob_head); - vmw_dmabuf_unreference(&res->backup); + vmw_bo_unreference(&res->backup); } return 0; @@ -1230,22 +1232,22 @@ void vmw_fence_single_bo(struct ttm_buffer_object *bo, void vmw_resource_move_notify(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem) { - struct vmw_dma_buffer *dma_buf; + struct vmw_buffer_object *vbo; if (mem == NULL) return; - if (bo->destroy != vmw_dmabuf_bo_free && - bo->destroy != vmw_user_dmabuf_destroy) + if (bo->destroy != vmw_bo_bo_free && + bo->destroy != vmw_user_bo_destroy) return; - dma_buf = container_of(bo, struct vmw_dma_buffer, base); + vbo = container_of(bo, struct vmw_buffer_object, base); /* * Kill any cached kernel maps before move. An optimization could * be to do this iff source or destination memory type is VRAM. */ - vmw_dma_buffer_unmap(dma_buf); + vmw_buffer_object_unmap(vbo); if (mem->mem_type != VMW_PL_MOB) { struct vmw_resource *res, *n; @@ -1254,7 +1256,7 @@ void vmw_resource_move_notify(struct ttm_buffer_object *bo, val_buf.bo = bo; val_buf.shared = false; - list_for_each_entry_safe(res, n, &dma_buf->res_list, mob_head) { + list_for_each_entry_safe(res, n, &vbo->res_list, mob_head) { if (unlikely(res->func->unbind == NULL)) continue; @@ -1277,12 +1279,12 @@ void vmw_resource_move_notify(struct ttm_buffer_object *bo, */ void vmw_resource_swap_notify(struct ttm_buffer_object *bo) { - if (bo->destroy != vmw_dmabuf_bo_free && - bo->destroy != vmw_user_dmabuf_destroy) + if (bo->destroy != vmw_bo_bo_free && + bo->destroy != vmw_user_bo_destroy) return; /* Kill any cached kernel maps before swapout */ - vmw_dma_buffer_unmap(vmw_dma_buffer(bo)); + vmw_buffer_object_unmap(vmw_buffer_object(bo)); } @@ -1294,7 +1296,7 @@ void vmw_resource_swap_notify(struct ttm_buffer_object *bo) * Read back cached states from the device if they exist. This function * assumings binding_mutex is held. */ -int vmw_query_readback_all(struct vmw_dma_buffer *dx_query_mob) +int vmw_query_readback_all(struct vmw_buffer_object *dx_query_mob) { struct vmw_resource *dx_query_ctx; struct vmw_private *dev_priv; @@ -1344,7 +1346,7 @@ int vmw_query_readback_all(struct vmw_dma_buffer *dx_query_mob) void vmw_query_move_notify(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem) { - struct vmw_dma_buffer *dx_query_mob; + struct vmw_buffer_object *dx_query_mob; struct ttm_bo_device *bdev = bo->bdev; struct vmw_private *dev_priv; @@ -1353,7 +1355,7 @@ void vmw_query_move_notify(struct ttm_buffer_object *bo, mutex_lock(&dev_priv->binding_mutex); - dx_query_mob = container_of(bo, struct vmw_dma_buffer, base); + dx_query_mob = container_of(bo, struct vmw_buffer_object, base); if (mem == NULL || !dx_query_mob || !dx_query_mob->dx_query_ctx) { mutex_unlock(&dev_priv->binding_mutex); return; @@ -1481,7 +1483,7 @@ int vmw_resource_pin(struct vmw_resource *res, bool interruptible) goto out_no_reserve; if (res->pin_count == 0) { - struct vmw_dma_buffer *vbo = NULL; + struct vmw_buffer_object *vbo = NULL; if (res->backup) { vbo = res->backup; @@ -1539,7 +1541,7 @@ void vmw_resource_unpin(struct vmw_resource *res) WARN_ON(res->pin_count == 0); if (--res->pin_count == 0 && res->backup) { - struct vmw_dma_buffer *vbo = res->backup; + struct vmw_buffer_object *vbo = res->backup; (void) ttm_bo_reserve(&vbo->base, false, false, NULL); vmw_bo_pin_reserved(vbo, false); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 9798640cbfcd..74dfd4621b7e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -66,7 +66,7 @@ struct vmw_kms_sou_readback_blit { SVGAFifoCmdBlitScreenToGMRFB body; }; -struct vmw_kms_sou_dmabuf_blit { +struct vmw_kms_sou_bo_blit { uint32 header; SVGAFifoCmdBlitGMRFBToScreen body; }; @@ -83,7 +83,7 @@ struct vmw_screen_object_unit { struct vmw_display_unit base; unsigned long buffer_size; /**< Size of allocated buffer */ - struct vmw_dma_buffer *buffer; /**< Backing store buffer */ + struct vmw_buffer_object *buffer; /**< Backing store buffer */ bool defined; }; @@ -240,8 +240,8 @@ static void vmw_sou_crtc_mode_set_nofb(struct drm_crtc *crtc) } if (vfb) { - sou->buffer = vps->dmabuf; - sou->buffer_size = vps->dmabuf_size; + sou->buffer = vps->bo; + sou->buffer_size = vps->bo_size; ret = vmw_sou_fifo_create(dev_priv, sou, crtc->x, crtc->y, &crtc->mode); @@ -408,10 +408,10 @@ vmw_sou_primary_plane_cleanup_fb(struct drm_plane *plane, struct drm_crtc *crtc = plane->state->crtc ? plane->state->crtc : old_state->crtc; - if (vps->dmabuf) - vmw_dmabuf_unpin(vmw_priv(crtc->dev), vps->dmabuf, false); - vmw_dmabuf_unreference(&vps->dmabuf); - vps->dmabuf_size = 0; + if (vps->bo) + vmw_bo_unpin(vmw_priv(crtc->dev), vps->bo, false); + vmw_bo_unreference(&vps->bo); + vps->bo_size = 0; vmw_du_plane_cleanup_fb(plane, old_state); } @@ -440,8 +440,8 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, if (!new_fb) { - vmw_dmabuf_unreference(&vps->dmabuf); - vps->dmabuf_size = 0; + vmw_bo_unreference(&vps->bo); + vps->bo_size = 0; return 0; } @@ -449,22 +449,22 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, size = new_state->crtc_w * new_state->crtc_h * 4; dev_priv = vmw_priv(crtc->dev); - if (vps->dmabuf) { - if (vps->dmabuf_size == size) { + if (vps->bo) { + if (vps->bo_size == size) { /* * Note that this might temporarily up the pin-count * to 2, until cleanup_fb() is called. */ - return vmw_dmabuf_pin_in_vram(dev_priv, vps->dmabuf, + return vmw_bo_pin_in_vram(dev_priv, vps->bo, true); } - vmw_dmabuf_unreference(&vps->dmabuf); - vps->dmabuf_size = 0; + vmw_bo_unreference(&vps->bo); + vps->bo_size = 0; } - vps->dmabuf = kzalloc(sizeof(*vps->dmabuf), GFP_KERNEL); - if (!vps->dmabuf) + vps->bo = kzalloc(sizeof(*vps->bo), GFP_KERNEL); + if (!vps->bo) return -ENOMEM; vmw_svga_enable(dev_priv); @@ -473,22 +473,22 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, * resume the overlays, this is preferred to failing to alloc. */ vmw_overlay_pause_all(dev_priv); - ret = vmw_dmabuf_init(dev_priv, vps->dmabuf, size, + ret = vmw_bo_init(dev_priv, vps->bo, size, &vmw_vram_ne_placement, - false, &vmw_dmabuf_bo_free); + false, &vmw_bo_bo_free); vmw_overlay_resume_all(dev_priv); if (ret) { - vps->dmabuf = NULL; /* vmw_dmabuf_init frees on error */ + vps->bo = NULL; /* vmw_bo_init frees on error */ return ret; } - vps->dmabuf_size = size; + vps->bo_size = size; /* * TTM already thinks the buffer is pinned, but make sure the * pin_count is upped. */ - return vmw_dmabuf_pin_in_vram(dev_priv, vps->dmabuf, true); + return vmw_bo_pin_in_vram(dev_priv, vps->bo, true); } @@ -512,10 +512,10 @@ vmw_sou_primary_plane_atomic_update(struct drm_plane *plane, vclips.w = crtc->mode.hdisplay; vclips.h = crtc->mode.vdisplay; - if (vfb->dmabuf) - ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, vfb, NULL, - &vclips, 1, 1, true, - &fence, crtc); + if (vfb->bo) + ret = vmw_kms_sou_do_bo_dirty(dev_priv, vfb, NULL, + &vclips, 1, 1, true, + &fence, crtc); else ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb, NULL, &vclips, NULL, 0, 0, @@ -775,11 +775,11 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv) return 0; } -static int do_dmabuf_define_gmrfb(struct vmw_private *dev_priv, +static int do_bo_define_gmrfb(struct vmw_private *dev_priv, struct vmw_framebuffer *framebuffer) { - struct vmw_dma_buffer *buf = - container_of(framebuffer, struct vmw_framebuffer_dmabuf, + struct vmw_buffer_object *buf = + container_of(framebuffer, struct vmw_framebuffer_bo, base)->buffer; int depth = framebuffer->base.format->depth; struct { @@ -970,13 +970,13 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv, } /** - * vmw_sou_dmabuf_fifo_commit - Callback to submit a set of readback clips. + * vmw_sou_bo_fifo_commit - Callback to submit a set of readback clips. * * @dirty: The closure structure. * * Commits a previously built command buffer of readback clips. */ -static void vmw_sou_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty) +static void vmw_sou_bo_fifo_commit(struct vmw_kms_dirty *dirty) { if (!dirty->num_hits) { vmw_fifo_commit(dirty->dev_priv, 0); @@ -984,20 +984,20 @@ static void vmw_sou_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty) } vmw_fifo_commit(dirty->dev_priv, - sizeof(struct vmw_kms_sou_dmabuf_blit) * + sizeof(struct vmw_kms_sou_bo_blit) * dirty->num_hits); } /** - * vmw_sou_dmabuf_clip - Callback to encode a readback cliprect. + * vmw_sou_bo_clip - Callback to encode a readback cliprect. * * @dirty: The closure structure * * Encodes a BLIT_GMRFB_TO_SCREEN cliprect. */ -static void vmw_sou_dmabuf_clip(struct vmw_kms_dirty *dirty) +static void vmw_sou_bo_clip(struct vmw_kms_dirty *dirty) { - struct vmw_kms_sou_dmabuf_blit *blit = dirty->cmd; + struct vmw_kms_sou_bo_blit *blit = dirty->cmd; blit += dirty->num_hits; blit->header = SVGA_CMD_BLIT_GMRFB_TO_SCREEN; @@ -1012,10 +1012,10 @@ static void vmw_sou_dmabuf_clip(struct vmw_kms_dirty *dirty) } /** - * vmw_kms_do_dmabuf_dirty - Dirty part of a dma-buffer backed framebuffer + * vmw_kms_do_bo_dirty - Dirty part of a buffer-object backed framebuffer * * @dev_priv: Pointer to the device private structure. - * @framebuffer: Pointer to the dma-buffer backed framebuffer. + * @framebuffer: Pointer to the buffer-object backed framebuffer. * @clips: Array of clip rects. * @vclips: Alternate array of clip rects. Either @clips or @vclips must * be NULL. @@ -1025,12 +1025,12 @@ static void vmw_sou_dmabuf_clip(struct vmw_kms_dirty *dirty) * @out_fence: If non-NULL, will return a ref-counted pointer to a * struct vmw_fence_obj. The returned fence pointer may be NULL in which * case the device has already synchronized. - * @crtc: If crtc is passed, perform dmabuf dirty on that crtc only. + * @crtc: If crtc is passed, perform bo dirty on that crtc only. * * Returns 0 on success, negative error code on failure. -ERESTARTSYS if * interrupted. */ -int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv, +int vmw_kms_sou_do_bo_dirty(struct vmw_private *dev_priv, struct vmw_framebuffer *framebuffer, struct drm_clip_rect *clips, struct drm_vmw_rect *vclips, @@ -1039,8 +1039,8 @@ int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv, struct vmw_fence_obj **out_fence, struct drm_crtc *crtc) { - struct vmw_dma_buffer *buf = - container_of(framebuffer, struct vmw_framebuffer_dmabuf, + struct vmw_buffer_object *buf = + container_of(framebuffer, struct vmw_framebuffer_bo, base)->buffer; struct vmw_kms_dirty dirty; int ret; @@ -1050,14 +1050,14 @@ int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv, if (ret) return ret; - ret = do_dmabuf_define_gmrfb(dev_priv, framebuffer); + ret = do_bo_define_gmrfb(dev_priv, framebuffer); if (unlikely(ret != 0)) goto out_revert; dirty.crtc = crtc; - dirty.fifo_commit = vmw_sou_dmabuf_fifo_commit; - dirty.clip = vmw_sou_dmabuf_clip; - dirty.fifo_reserve_size = sizeof(struct vmw_kms_sou_dmabuf_blit) * + dirty.fifo_commit = vmw_sou_bo_fifo_commit; + dirty.clip = vmw_sou_bo_clip; + dirty.fifo_reserve_size = sizeof(struct vmw_kms_sou_bo_blit) * num_clips; ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips, 0, 0, num_clips, increment, &dirty); @@ -1116,12 +1116,12 @@ static void vmw_sou_readback_clip(struct vmw_kms_dirty *dirty) /** * vmw_kms_sou_readback - Perform a readback from the screen object system to - * a dma-buffer backed framebuffer. + * a buffer-object backed framebuffer. * * @dev_priv: Pointer to the device private structure. * @file_priv: Pointer to a struct drm_file identifying the caller. * Must be set to NULL if @user_fence_rep is NULL. - * @vfb: Pointer to the dma-buffer backed framebuffer. + * @vfb: Pointer to the buffer-object backed framebuffer. * @user_fence_rep: User-space provided structure for fence information. * Must be set to non-NULL if @file_priv is non-NULL. * @vclips: Array of clip rects. @@ -1139,8 +1139,8 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv, uint32_t num_clips, struct drm_crtc *crtc) { - struct vmw_dma_buffer *buf = - container_of(vfb, struct vmw_framebuffer_dmabuf, base)->buffer; + struct vmw_buffer_object *buf = + container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; struct vmw_kms_dirty dirty; int ret; @@ -1149,7 +1149,7 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv, if (ret) return ret; - ret = do_dmabuf_define_gmrfb(dev_priv, vfb); + ret = do_bo_define_gmrfb(dev_priv, vfb); if (unlikely(ret != 0)) goto out_revert; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c index 73b8e9a16368..f6c939f3ff5e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c @@ -159,7 +159,7 @@ static int vmw_gb_shader_init(struct vmw_private *dev_priv, SVGA3dShaderType type, uint8_t num_input_sig, uint8_t num_output_sig, - struct vmw_dma_buffer *byte_code, + struct vmw_buffer_object *byte_code, void (*res_free) (struct vmw_resource *res)) { struct vmw_shader *shader = vmw_res_to_shader(res); @@ -178,7 +178,7 @@ static int vmw_gb_shader_init(struct vmw_private *dev_priv, res->backup_size = size; if (byte_code) { - res->backup = vmw_dmabuf_reference(byte_code); + res->backup = vmw_bo_reference(byte_code); res->backup_offset = offset; } shader->size = size; @@ -723,7 +723,7 @@ int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data, } static int vmw_user_shader_alloc(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buffer, + struct vmw_buffer_object *buffer, size_t shader_size, size_t offset, SVGA3dShaderType shader_type, @@ -801,7 +801,7 @@ out: static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buffer, + struct vmw_buffer_object *buffer, size_t shader_size, size_t offset, SVGA3dShaderType shader_type) @@ -862,12 +862,12 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv, { struct vmw_private *dev_priv = vmw_priv(dev); struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - struct vmw_dma_buffer *buffer = NULL; + struct vmw_buffer_object *buffer = NULL; SVGA3dShaderType shader_type; int ret; if (buffer_handle != SVGA3D_INVALID_ID) { - ret = vmw_user_dmabuf_lookup(tfile, buffer_handle, + ret = vmw_user_bo_lookup(tfile, buffer_handle, &buffer, NULL); if (unlikely(ret != 0)) { DRM_ERROR("Could not find buffer for shader " @@ -906,7 +906,7 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv, ttm_read_unlock(&dev_priv->reservation_sem); out_bad_arg: - vmw_dmabuf_unreference(&buffer); + vmw_bo_unreference(&buffer); return ret; } @@ -983,7 +983,7 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, struct list_head *list) { struct ttm_operation_ctx ctx = { false, true }; - struct vmw_dma_buffer *buf; + struct vmw_buffer_object *buf; struct ttm_bo_kmap_obj map; bool is_iomem; int ret; @@ -997,8 +997,8 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, if (unlikely(!buf)) return -ENOMEM; - ret = vmw_dmabuf_init(dev_priv, buf, size, &vmw_sys_ne_placement, - true, vmw_dmabuf_bo_free); + ret = vmw_bo_init(dev_priv, buf, size, &vmw_sys_ne_placement, + true, vmw_bo_bo_free); if (unlikely(ret != 0)) goto out; @@ -1031,7 +1031,7 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, res, list); vmw_resource_unreference(&res); no_reserve: - vmw_dmabuf_unreference(&buf); + vmw_bo_unreference(&buf); out: return ret; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 152e96cb1c01..537df9034008 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -44,7 +44,7 @@ enum stdu_content_type { SAME_AS_DISPLAY = 0, SEPARATE_SURFACE, - SEPARATE_DMA + SEPARATE_BO }; /** @@ -58,7 +58,7 @@ enum stdu_content_type { * @bottom: Bottom side of bounding box. * @fb_left: Left side of the framebuffer/content bounding box * @fb_top: Top of the framebuffer/content bounding box - * @buf: DMA buffer when DMA-ing between buffer and screen targets. + * @buf: buffer object when DMA-ing between buffer and screen targets. * @sid: Surface ID when copying between surface and screen targets. */ struct vmw_stdu_dirty { @@ -68,7 +68,7 @@ struct vmw_stdu_dirty { s32 fb_left, fb_top; u32 pitch; union { - struct vmw_dma_buffer *buf; + struct vmw_buffer_object *buf; u32 sid; }; }; @@ -508,14 +508,14 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc, /** - * vmw_stdu_dmabuf_clip - Callback to encode a suface DMA command cliprect + * vmw_stdu_bo_clip - Callback to encode a suface DMA command cliprect * * @dirty: The closure structure. * * Encodes a surface DMA command cliprect and updates the bounding box * for the DMA. */ -static void vmw_stdu_dmabuf_clip(struct vmw_kms_dirty *dirty) +static void vmw_stdu_bo_clip(struct vmw_kms_dirty *dirty) { struct vmw_stdu_dirty *ddirty = container_of(dirty, struct vmw_stdu_dirty, base); @@ -543,14 +543,14 @@ static void vmw_stdu_dmabuf_clip(struct vmw_kms_dirty *dirty) } /** - * vmw_stdu_dmabuf_fifo_commit - Callback to fill in and submit a DMA command. + * vmw_stdu_bo_fifo_commit - Callback to fill in and submit a DMA command. * * @dirty: The closure structure. * * Fills in the missing fields in a DMA command, and optionally encodes * a screen target update command, depending on transfer direction. */ -static void vmw_stdu_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty) +static void vmw_stdu_bo_fifo_commit(struct vmw_kms_dirty *dirty) { struct vmw_stdu_dirty *ddirty = container_of(dirty, struct vmw_stdu_dirty, base); @@ -594,13 +594,13 @@ static void vmw_stdu_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty) /** - * vmw_stdu_dmabuf_cpu_clip - Callback to encode a CPU blit + * vmw_stdu_bo_cpu_clip - Callback to encode a CPU blit * * @dirty: The closure structure. * * This function calculates the bounding box for all the incoming clips. */ -static void vmw_stdu_dmabuf_cpu_clip(struct vmw_kms_dirty *dirty) +static void vmw_stdu_bo_cpu_clip(struct vmw_kms_dirty *dirty) { struct vmw_stdu_dirty *ddirty = container_of(dirty, struct vmw_stdu_dirty, base); @@ -624,14 +624,14 @@ static void vmw_stdu_dmabuf_cpu_clip(struct vmw_kms_dirty *dirty) /** - * vmw_stdu_dmabuf_cpu_commit - Callback to do a CPU blit from DMAbuf + * vmw_stdu_bo_cpu_commit - Callback to do a CPU blit from buffer object * * @dirty: The closure structure. * * For the special case when we cannot create a proxy surface in a * 2D VM, we have to do a CPU blit ourselves. */ -static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty) +static void vmw_stdu_bo_cpu_commit(struct vmw_kms_dirty *dirty) { struct vmw_stdu_dirty *ddirty = container_of(dirty, struct vmw_stdu_dirty, base); @@ -652,7 +652,7 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty) if (width == 0 || height == 0) return; - /* Assume we are blitting from Guest (dmabuf) to Host (display_srf) */ + /* Assume we are blitting from Guest (bo) to Host (display_srf) */ dst_pitch = stdu->display_srf->base_size.width * stdu->cpp; dst_bo = &stdu->display_srf->res.backup->base; dst_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; @@ -712,13 +712,13 @@ out_cleanup: } /** - * vmw_kms_stdu_dma - Perform a DMA transfer between a dma-buffer backed + * vmw_kms_stdu_dma - Perform a DMA transfer between a buffer-object backed * framebuffer and the screen target system. * * @dev_priv: Pointer to the device private structure. * @file_priv: Pointer to a struct drm-file identifying the caller. May be * set to NULL, but then @user_fence_rep must also be set to NULL. - * @vfb: Pointer to the dma-buffer backed framebuffer. + * @vfb: Pointer to the buffer-object backed framebuffer. * @clips: Array of clip rects. Either @clips or @vclips must be NULL. * @vclips: Alternate array of clip rects. Either @clips or @vclips must * be NULL. @@ -747,8 +747,8 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv, bool interruptible, struct drm_crtc *crtc) { - struct vmw_dma_buffer *buf = - container_of(vfb, struct vmw_framebuffer_dmabuf, base)->buffer; + struct vmw_buffer_object *buf = + container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; struct vmw_stdu_dirty ddirty; int ret; bool cpu_blit = !(dev_priv->capabilities & SVGA_CAP_3D); @@ -770,8 +770,8 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv, ddirty.fb_left = ddirty.fb_top = S32_MAX; ddirty.pitch = vfb->base.pitches[0]; ddirty.buf = buf; - ddirty.base.fifo_commit = vmw_stdu_dmabuf_fifo_commit; - ddirty.base.clip = vmw_stdu_dmabuf_clip; + ddirty.base.fifo_commit = vmw_stdu_bo_fifo_commit; + ddirty.base.clip = vmw_stdu_bo_clip; ddirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_dma) + num_clips * sizeof(SVGA3dCopyBox) + sizeof(SVGA3dCmdSurfaceDMASuffix); @@ -780,8 +780,8 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv, if (cpu_blit) { - ddirty.base.fifo_commit = vmw_stdu_dmabuf_cpu_commit; - ddirty.base.clip = vmw_stdu_dmabuf_cpu_clip; + ddirty.base.fifo_commit = vmw_stdu_bo_cpu_commit; + ddirty.base.clip = vmw_stdu_bo_cpu_clip; ddirty.base.fifo_reserve_size = 0; } @@ -927,7 +927,7 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, if (ret) return ret; - if (vfbs->is_dmabuf_proxy) { + if (vfbs->is_bo_proxy) { ret = vmw_kms_update_proxy(srf, clips, num_clips, inc); if (ret) goto out_finish; @@ -1075,7 +1075,7 @@ vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane, * @new_state: info on the new plane state, including the FB * * This function allocates a new display surface if the content is - * backed by a DMA. The display surface is pinned here, and it'll + * backed by a buffer object. The display surface is pinned here, and it'll * be unpinned in .cleanup_fb() * * Returns 0 on success @@ -1105,13 +1105,13 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, } vfb = vmw_framebuffer_to_vfb(new_fb); - new_vfbs = (vfb->dmabuf) ? NULL : vmw_framebuffer_to_vfbs(new_fb); + new_vfbs = (vfb->bo) ? NULL : vmw_framebuffer_to_vfbs(new_fb); if (new_vfbs && new_vfbs->surface->base_size.width == hdisplay && new_vfbs->surface->base_size.height == vdisplay) new_content_type = SAME_AS_DISPLAY; - else if (vfb->dmabuf) - new_content_type = SEPARATE_DMA; + else if (vfb->bo) + new_content_type = SEPARATE_BO; else new_content_type = SEPARATE_SURFACE; @@ -1124,10 +1124,10 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, display_base_size.depth = 1; /* - * If content buffer is a DMA buf, then we have to construct - * surface info + * If content buffer is a buffer object, then we have to + * construct surface info */ - if (new_content_type == SEPARATE_DMA) { + if (new_content_type == SEPARATE_BO) { switch (new_fb->format->cpp[0]*8) { case 32: @@ -1212,12 +1212,12 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, vps->content_fb_type = new_content_type; /* - * This should only happen if the DMA buf is too large to create a + * This should only happen if the buffer object is too large to create a * proxy surface for. - * If we are a 2D VM with a DMA buffer then we have to use CPU blit + * If we are a 2D VM with a buffer object then we have to use CPU blit * so cache these mappings */ - if (vps->content_fb_type == SEPARATE_DMA && + if (vps->content_fb_type == SEPARATE_BO && !(dev_priv->capabilities & SVGA_CAP_3D)) vps->cpp = new_fb->pitches[0] / new_fb->width; @@ -1276,7 +1276,7 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane, if (ret) DRM_ERROR("Failed to bind surface to STDU.\n"); - if (vfb->dmabuf) + if (vfb->bo) ret = vmw_kms_stdu_dma(dev_priv, NULL, vfb, NULL, NULL, &vclips, 1, 1, true, false, crtc); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index b236c48bf265..2b2e8aa7114a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -842,12 +842,12 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, if (dev_priv->has_mob && req->shareable) { uint32_t backup_handle; - ret = vmw_user_dmabuf_alloc(dev_priv, tfile, - res->backup_size, - true, - &backup_handle, - &res->backup, - &user_srf->backup_base); + ret = vmw_user_bo_alloc(dev_priv, tfile, + res->backup_size, + true, + &backup_handle, + &res->backup, + &user_srf->backup_base); if (unlikely(ret != 0)) { vmw_resource_unreference(&res); goto out_unlock; @@ -1317,14 +1317,14 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, if (req->buffer_handle != SVGA3D_INVALID_ID) { - ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle, - &res->backup, - &user_srf->backup_base); + ret = vmw_user_bo_lookup(tfile, req->buffer_handle, + &res->backup, + &user_srf->backup_base); if (ret == 0) { if (res->backup->base.num_pages * PAGE_SIZE < res->backup_size) { DRM_ERROR("Surface backup buffer is too small.\n"); - vmw_dmabuf_unreference(&res->backup); + vmw_bo_unreference(&res->backup); ret = -EINVAL; goto out_unlock; } else { @@ -1332,13 +1332,13 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, } } } else if (req->drm_surface_flags & drm_vmw_surface_flag_create_buffer) - ret = vmw_user_dmabuf_alloc(dev_priv, tfile, - res->backup_size, - req->drm_surface_flags & - drm_vmw_surface_flag_shareable, - &backup_handle, - &res->backup, - &user_srf->backup_base); + ret = vmw_user_bo_alloc(dev_priv, tfile, + res->backup_size, + req->drm_surface_flags & + drm_vmw_surface_flag_shareable, + &backup_handle, + &res->backup, + &user_srf->backup_base); if (unlikely(ret != 0)) { vmw_resource_unreference(&res); @@ -1414,8 +1414,7 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data, } mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */ - ret = vmw_user_dmabuf_reference(tfile, srf->res.backup, - &backup_handle); + ret = vmw_user_bo_reference(tfile, srf->res.backup, &backup_handle); mutex_unlock(&dev_priv->cmdbuf_mutex); if (unlikely(ret != 0)) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c new file mode 100644 index 000000000000..0931f43913b1 --- /dev/null +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -0,0 +1,887 @@ +/************************************************************************** + * + * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vmwgfx_drv.h" +#include +#include +#include + +static const struct ttm_place vram_placement_flags = { + .fpfn = 0, + .lpfn = 0, + .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED +}; + +static const struct ttm_place vram_ne_placement_flags = { + .fpfn = 0, + .lpfn = 0, + .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT +}; + +static const struct ttm_place sys_placement_flags = { + .fpfn = 0, + .lpfn = 0, + .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED +}; + +static const struct ttm_place sys_ne_placement_flags = { + .fpfn = 0, + .lpfn = 0, + .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT +}; + +static const struct ttm_place gmr_placement_flags = { + .fpfn = 0, + .lpfn = 0, + .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED +}; + +static const struct ttm_place gmr_ne_placement_flags = { + .fpfn = 0, + .lpfn = 0, + .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT +}; + +static const struct ttm_place mob_placement_flags = { + .fpfn = 0, + .lpfn = 0, + .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED +}; + +static const struct ttm_place mob_ne_placement_flags = { + .fpfn = 0, + .lpfn = 0, + .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT +}; + +struct ttm_placement vmw_vram_placement = { + .num_placement = 1, + .placement = &vram_placement_flags, + .num_busy_placement = 1, + .busy_placement = &vram_placement_flags +}; + +static const struct ttm_place vram_gmr_placement_flags[] = { + { + .fpfn = 0, + .lpfn = 0, + .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED + }, { + .fpfn = 0, + .lpfn = 0, + .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED + } +}; + +static const struct ttm_place gmr_vram_placement_flags[] = { + { + .fpfn = 0, + .lpfn = 0, + .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED + }, { + .fpfn = 0, + .lpfn = 0, + .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED + } +}; + +struct ttm_placement vmw_vram_gmr_placement = { + .num_placement = 2, + .placement = vram_gmr_placement_flags, + .num_busy_placement = 1, + .busy_placement = &gmr_placement_flags +}; + +static const struct ttm_place vram_gmr_ne_placement_flags[] = { + { + .fpfn = 0, + .lpfn = 0, + .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED | + TTM_PL_FLAG_NO_EVICT + }, { + .fpfn = 0, + .lpfn = 0, + .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED | + TTM_PL_FLAG_NO_EVICT + } +}; + +struct ttm_placement vmw_vram_gmr_ne_placement = { + .num_placement = 2, + .placement = vram_gmr_ne_placement_flags, + .num_busy_placement = 1, + .busy_placement = &gmr_ne_placement_flags +}; + +struct ttm_placement vmw_vram_sys_placement = { + .num_placement = 1, + .placement = &vram_placement_flags, + .num_busy_placement = 1, + .busy_placement = &sys_placement_flags +}; + +struct ttm_placement vmw_vram_ne_placement = { + .num_placement = 1, + .placement = &vram_ne_placement_flags, + .num_busy_placement = 1, + .busy_placement = &vram_ne_placement_flags +}; + +struct ttm_placement vmw_sys_placement = { + .num_placement = 1, + .placement = &sys_placement_flags, + .num_busy_placement = 1, + .busy_placement = &sys_placement_flags +}; + +struct ttm_placement vmw_sys_ne_placement = { + .num_placement = 1, + .placement = &sys_ne_placement_flags, + .num_busy_placement = 1, + .busy_placement = &sys_ne_placement_flags +}; + +static const struct ttm_place evictable_placement_flags[] = { + { + .fpfn = 0, + .lpfn = 0, + .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED + }, { + .fpfn = 0, + .lpfn = 0, + .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED + }, { + .fpfn = 0, + .lpfn = 0, + .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED + }, { + .fpfn = 0, + .lpfn = 0, + .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED + } +}; + +static const struct ttm_place nonfixed_placement_flags[] = { + { + .fpfn = 0, + .lpfn = 0, + .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED + }, { + .fpfn = 0, + .lpfn = 0, + .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED + }, { + .fpfn = 0, + .lpfn = 0, + .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED + } +}; + +struct ttm_placement vmw_evictable_placement = { + .num_placement = 4, + .placement = evictable_placement_flags, + .num_busy_placement = 1, + .busy_placement = &sys_placement_flags +}; + +struct ttm_placement vmw_srf_placement = { + .num_placement = 1, + .num_busy_placement = 2, + .placement = &gmr_placement_flags, + .busy_placement = gmr_vram_placement_flags +}; + +struct ttm_placement vmw_mob_placement = { + .num_placement = 1, + .num_busy_placement = 1, + .placement = &mob_placement_flags, + .busy_placement = &mob_placement_flags +}; + +struct ttm_placement vmw_mob_ne_placement = { + .num_placement = 1, + .num_busy_placement = 1, + .placement = &mob_ne_placement_flags, + .busy_placement = &mob_ne_placement_flags +}; + +struct ttm_placement vmw_nonfixed_placement = { + .num_placement = 3, + .placement = nonfixed_placement_flags, + .num_busy_placement = 1, + .busy_placement = &sys_placement_flags +}; + +struct vmw_ttm_tt { + struct ttm_dma_tt dma_ttm; + struct vmw_private *dev_priv; + int gmr_id; + struct vmw_mob *mob; + int mem_type; + struct sg_table sgt; + struct vmw_sg_table vsgt; + uint64_t sg_alloc_size; + bool mapped; +}; + +const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt); + +/** + * Helper functions to advance a struct vmw_piter iterator. + * + * @viter: Pointer to the iterator. + * + * These functions return false if past the end of the list, + * true otherwise. Functions are selected depending on the current + * DMA mapping mode. + */ +static bool __vmw_piter_non_sg_next(struct vmw_piter *viter) +{ + return ++(viter->i) < viter->num_pages; +} + +static bool __vmw_piter_sg_next(struct vmw_piter *viter) +{ + return __sg_page_iter_next(&viter->iter); +} + + +/** + * Helper functions to return a pointer to the current page. + * + * @viter: Pointer to the iterator + * + * These functions return a pointer to the page currently + * pointed to by @viter. Functions are selected depending on the + * current mapping mode. + */ +static struct page *__vmw_piter_non_sg_page(struct vmw_piter *viter) +{ + return viter->pages[viter->i]; +} + +static struct page *__vmw_piter_sg_page(struct vmw_piter *viter) +{ + return sg_page_iter_page(&viter->iter); +} + + +/** + * Helper functions to return the DMA address of the current page. + * + * @viter: Pointer to the iterator + * + * These functions return the DMA address of the page currently + * pointed to by @viter. Functions are selected depending on the + * current mapping mode. + */ +static dma_addr_t __vmw_piter_phys_addr(struct vmw_piter *viter) +{ + return page_to_phys(viter->pages[viter->i]); +} + +static dma_addr_t __vmw_piter_dma_addr(struct vmw_piter *viter) +{ + return viter->addrs[viter->i]; +} + +static dma_addr_t __vmw_piter_sg_addr(struct vmw_piter *viter) +{ + return sg_page_iter_dma_address(&viter->iter); +} + + +/** + * vmw_piter_start - Initialize a struct vmw_piter. + * + * @viter: Pointer to the iterator to initialize + * @vsgt: Pointer to a struct vmw_sg_table to initialize from + * + * Note that we're following the convention of __sg_page_iter_start, so that + * the iterator doesn't point to a valid page after initialization; it has + * to be advanced one step first. + */ +void vmw_piter_start(struct vmw_piter *viter, const struct vmw_sg_table *vsgt, + unsigned long p_offset) +{ + viter->i = p_offset - 1; + viter->num_pages = vsgt->num_pages; + switch (vsgt->mode) { + case vmw_dma_phys: + viter->next = &__vmw_piter_non_sg_next; + viter->dma_address = &__vmw_piter_phys_addr; + viter->page = &__vmw_piter_non_sg_page; + viter->pages = vsgt->pages; + break; + case vmw_dma_alloc_coherent: + viter->next = &__vmw_piter_non_sg_next; + viter->dma_address = &__vmw_piter_dma_addr; + viter->page = &__vmw_piter_non_sg_page; + viter->addrs = vsgt->addrs; + viter->pages = vsgt->pages; + break; + case vmw_dma_map_populate: + case vmw_dma_map_bind: + viter->next = &__vmw_piter_sg_next; + viter->dma_address = &__vmw_piter_sg_addr; + viter->page = &__vmw_piter_sg_page; + __sg_page_iter_start(&viter->iter, vsgt->sgt->sgl, + vsgt->sgt->orig_nents, p_offset); + break; + default: + BUG(); + } +} + +/** + * vmw_ttm_unmap_from_dma - unmap device addresses previsouly mapped for + * TTM pages + * + * @vmw_tt: Pointer to a struct vmw_ttm_backend + * + * Used to free dma mappings previously mapped by vmw_ttm_map_for_dma. + */ +static void vmw_ttm_unmap_from_dma(struct vmw_ttm_tt *vmw_tt) +{ + struct device *dev = vmw_tt->dev_priv->dev->dev; + + dma_unmap_sg(dev, vmw_tt->sgt.sgl, vmw_tt->sgt.nents, + DMA_BIDIRECTIONAL); + vmw_tt->sgt.nents = vmw_tt->sgt.orig_nents; +} + +/** + * vmw_ttm_map_for_dma - map TTM pages to get device addresses + * + * @vmw_tt: Pointer to a struct vmw_ttm_backend + * + * This function is used to get device addresses from the kernel DMA layer. + * However, it's violating the DMA API in that when this operation has been + * performed, it's illegal for the CPU to write to the pages without first + * unmapping the DMA mappings, or calling dma_sync_sg_for_cpu(). It is + * therefore only legal to call this function if we know that the function + * dma_sync_sg_for_cpu() is a NOP, and dma_sync_sg_for_device() is at most + * a CPU write buffer flush. + */ +static int vmw_ttm_map_for_dma(struct vmw_ttm_tt *vmw_tt) +{ + struct device *dev = vmw_tt->dev_priv->dev->dev; + int ret; + + ret = dma_map_sg(dev, vmw_tt->sgt.sgl, vmw_tt->sgt.orig_nents, + DMA_BIDIRECTIONAL); + if (unlikely(ret == 0)) + return -ENOMEM; + + vmw_tt->sgt.nents = ret; + + return 0; +} + +/** + * vmw_ttm_map_dma - Make sure TTM pages are visible to the device + * + * @vmw_tt: Pointer to a struct vmw_ttm_tt + * + * Select the correct function for and make sure the TTM pages are + * visible to the device. Allocate storage for the device mappings. + * If a mapping has already been performed, indicated by the storage + * pointer being non NULL, the function returns success. + */ +static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt) +{ + struct vmw_private *dev_priv = vmw_tt->dev_priv; + struct ttm_mem_global *glob = vmw_mem_glob(dev_priv); + struct vmw_sg_table *vsgt = &vmw_tt->vsgt; + struct ttm_operation_ctx ctx = { + .interruptible = true, + .no_wait_gpu = false + }; + struct vmw_piter iter; + dma_addr_t old; + int ret = 0; + static size_t sgl_size; + static size_t sgt_size; + + if (vmw_tt->mapped) + return 0; + + vsgt->mode = dev_priv->map_mode; + vsgt->pages = vmw_tt->dma_ttm.ttm.pages; + vsgt->num_pages = vmw_tt->dma_ttm.ttm.num_pages; + vsgt->addrs = vmw_tt->dma_ttm.dma_address; + vsgt->sgt = &vmw_tt->sgt; + + switch (dev_priv->map_mode) { + case vmw_dma_map_bind: + case vmw_dma_map_populate: + if (unlikely(!sgl_size)) { + sgl_size = ttm_round_pot(sizeof(struct scatterlist)); + sgt_size = ttm_round_pot(sizeof(struct sg_table)); + } + vmw_tt->sg_alloc_size = sgt_size + sgl_size * vsgt->num_pages; + ret = ttm_mem_global_alloc(glob, vmw_tt->sg_alloc_size, &ctx); + if (unlikely(ret != 0)) + return ret; + + ret = sg_alloc_table_from_pages(&vmw_tt->sgt, vsgt->pages, + vsgt->num_pages, 0, + (unsigned long) + vsgt->num_pages << PAGE_SHIFT, + GFP_KERNEL); + if (unlikely(ret != 0)) + goto out_sg_alloc_fail; + + if (vsgt->num_pages > vmw_tt->sgt.nents) { + uint64_t over_alloc = + sgl_size * (vsgt->num_pages - + vmw_tt->sgt.nents); + + ttm_mem_global_free(glob, over_alloc); + vmw_tt->sg_alloc_size -= over_alloc; + } + + ret = vmw_ttm_map_for_dma(vmw_tt); + if (unlikely(ret != 0)) + goto out_map_fail; + + break; + default: + break; + } + + old = ~((dma_addr_t) 0); + vmw_tt->vsgt.num_regions = 0; + for (vmw_piter_start(&iter, vsgt, 0); vmw_piter_next(&iter);) { + dma_addr_t cur = vmw_piter_dma_addr(&iter); + + if (cur != old + PAGE_SIZE) + vmw_tt->vsgt.num_regions++; + old = cur; + } + + vmw_tt->mapped = true; + return 0; + +out_map_fail: + sg_free_table(vmw_tt->vsgt.sgt); + vmw_tt->vsgt.sgt = NULL; +out_sg_alloc_fail: + ttm_mem_global_free(glob, vmw_tt->sg_alloc_size); + return ret; +} + +/** + * vmw_ttm_unmap_dma - Tear down any TTM page device mappings + * + * @vmw_tt: Pointer to a struct vmw_ttm_tt + * + * Tear down any previously set up device DMA mappings and free + * any storage space allocated for them. If there are no mappings set up, + * this function is a NOP. + */ +static void vmw_ttm_unmap_dma(struct vmw_ttm_tt *vmw_tt) +{ + struct vmw_private *dev_priv = vmw_tt->dev_priv; + + if (!vmw_tt->vsgt.sgt) + return; + + switch (dev_priv->map_mode) { + case vmw_dma_map_bind: + case vmw_dma_map_populate: + vmw_ttm_unmap_from_dma(vmw_tt); + sg_free_table(vmw_tt->vsgt.sgt); + vmw_tt->vsgt.sgt = NULL; + ttm_mem_global_free(vmw_mem_glob(dev_priv), + vmw_tt->sg_alloc_size); + break; + default: + break; + } + vmw_tt->mapped = false; +} + + +/** + * vmw_bo_map_dma - Make sure buffer object pages are visible to the device + * + * @bo: Pointer to a struct ttm_buffer_object + * + * Wrapper around vmw_ttm_map_dma, that takes a TTM buffer object pointer + * instead of a pointer to a struct vmw_ttm_backend as argument. + * Note that the buffer object must be either pinned or reserved before + * calling this function. + */ +int vmw_bo_map_dma(struct ttm_buffer_object *bo) +{ + struct vmw_ttm_tt *vmw_tt = + container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm); + + return vmw_ttm_map_dma(vmw_tt); +} + + +/** + * vmw_bo_unmap_dma - Make sure buffer object pages are visible to the device + * + * @bo: Pointer to a struct ttm_buffer_object + * + * Wrapper around vmw_ttm_unmap_dma, that takes a TTM buffer object pointer + * instead of a pointer to a struct vmw_ttm_backend as argument. + */ +void vmw_bo_unmap_dma(struct ttm_buffer_object *bo) +{ + struct vmw_ttm_tt *vmw_tt = + container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm); + + vmw_ttm_unmap_dma(vmw_tt); +} + + +/** + * vmw_bo_sg_table - Return a struct vmw_sg_table object for a + * TTM buffer object + * + * @bo: Pointer to a struct ttm_buffer_object + * + * Returns a pointer to a struct vmw_sg_table object. The object should + * not be freed after use. + * Note that for the device addresses to be valid, the buffer object must + * either be reserved or pinned. + */ +const struct vmw_sg_table *vmw_bo_sg_table(struct ttm_buffer_object *bo) +{ + struct vmw_ttm_tt *vmw_tt = + container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm); + + return &vmw_tt->vsgt; +} + + +static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) +{ + struct vmw_ttm_tt *vmw_be = + container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); + int ret; + + ret = vmw_ttm_map_dma(vmw_be); + if (unlikely(ret != 0)) + return ret; + + vmw_be->gmr_id = bo_mem->start; + vmw_be->mem_type = bo_mem->mem_type; + + switch (bo_mem->mem_type) { + case VMW_PL_GMR: + return vmw_gmr_bind(vmw_be->dev_priv, &vmw_be->vsgt, + ttm->num_pages, vmw_be->gmr_id); + case VMW_PL_MOB: + if (unlikely(vmw_be->mob == NULL)) { + vmw_be->mob = + vmw_mob_create(ttm->num_pages); + if (unlikely(vmw_be->mob == NULL)) + return -ENOMEM; + } + + return vmw_mob_bind(vmw_be->dev_priv, vmw_be->mob, + &vmw_be->vsgt, ttm->num_pages, + vmw_be->gmr_id); + default: + BUG(); + } + return 0; +} + +static int vmw_ttm_unbind(struct ttm_tt *ttm) +{ + struct vmw_ttm_tt *vmw_be = + container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); + + switch (vmw_be->mem_type) { + case VMW_PL_GMR: + vmw_gmr_unbind(vmw_be->dev_priv, vmw_be->gmr_id); + break; + case VMW_PL_MOB: + vmw_mob_unbind(vmw_be->dev_priv, vmw_be->mob); + break; + default: + BUG(); + } + + if (vmw_be->dev_priv->map_mode == vmw_dma_map_bind) + vmw_ttm_unmap_dma(vmw_be); + + return 0; +} + + +static void vmw_ttm_destroy(struct ttm_tt *ttm) +{ + struct vmw_ttm_tt *vmw_be = + container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); + + vmw_ttm_unmap_dma(vmw_be); + if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent) + ttm_dma_tt_fini(&vmw_be->dma_ttm); + else + ttm_tt_fini(ttm); + + if (vmw_be->mob) + vmw_mob_destroy(vmw_be->mob); + + kfree(vmw_be); +} + + +static int vmw_ttm_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) +{ + struct vmw_ttm_tt *vmw_tt = + container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); + struct vmw_private *dev_priv = vmw_tt->dev_priv; + struct ttm_mem_global *glob = vmw_mem_glob(dev_priv); + int ret; + + if (ttm->state != tt_unpopulated) + return 0; + + if (dev_priv->map_mode == vmw_dma_alloc_coherent) { + size_t size = + ttm_round_pot(ttm->num_pages * sizeof(dma_addr_t)); + ret = ttm_mem_global_alloc(glob, size, ctx); + if (unlikely(ret != 0)) + return ret; + + ret = ttm_dma_populate(&vmw_tt->dma_ttm, dev_priv->dev->dev, + ctx); + if (unlikely(ret != 0)) + ttm_mem_global_free(glob, size); + } else + ret = ttm_pool_populate(ttm, ctx); + + return ret; +} + +static void vmw_ttm_unpopulate(struct ttm_tt *ttm) +{ + struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt, + dma_ttm.ttm); + struct vmw_private *dev_priv = vmw_tt->dev_priv; + struct ttm_mem_global *glob = vmw_mem_glob(dev_priv); + + + if (vmw_tt->mob) { + vmw_mob_destroy(vmw_tt->mob); + vmw_tt->mob = NULL; + } + + vmw_ttm_unmap_dma(vmw_tt); + if (dev_priv->map_mode == vmw_dma_alloc_coherent) { + size_t size = + ttm_round_pot(ttm->num_pages * sizeof(dma_addr_t)); + + ttm_dma_unpopulate(&vmw_tt->dma_ttm, dev_priv->dev->dev); + ttm_mem_global_free(glob, size); + } else + ttm_pool_unpopulate(ttm); +} + +static struct ttm_backend_func vmw_ttm_func = { + .bind = vmw_ttm_bind, + .unbind = vmw_ttm_unbind, + .destroy = vmw_ttm_destroy, +}; + +static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo, + uint32_t page_flags) +{ + struct vmw_ttm_tt *vmw_be; + int ret; + + vmw_be = kzalloc(sizeof(*vmw_be), GFP_KERNEL); + if (!vmw_be) + return NULL; + + vmw_be->dma_ttm.ttm.func = &vmw_ttm_func; + vmw_be->dev_priv = container_of(bo->bdev, struct vmw_private, bdev); + vmw_be->mob = NULL; + + if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent) + ret = ttm_dma_tt_init(&vmw_be->dma_ttm, bo, page_flags); + else + ret = ttm_tt_init(&vmw_be->dma_ttm.ttm, bo, page_flags); + if (unlikely(ret != 0)) + goto out_no_init; + + return &vmw_be->dma_ttm.ttm; +out_no_init: + kfree(vmw_be); + return NULL; +} + +static int vmw_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags) +{ + return 0; +} + +static int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, + struct ttm_mem_type_manager *man) +{ + switch (type) { + case TTM_PL_SYSTEM: + /* System memory */ + + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; + man->available_caching = TTM_PL_FLAG_CACHED; + man->default_caching = TTM_PL_FLAG_CACHED; + break; + case TTM_PL_VRAM: + /* "On-card" video ram */ + man->func = &ttm_bo_manager_func; + man->gpu_offset = 0; + man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_MAPPABLE; + man->available_caching = TTM_PL_FLAG_CACHED; + man->default_caching = TTM_PL_FLAG_CACHED; + break; + case VMW_PL_GMR: + case VMW_PL_MOB: + /* + * "Guest Memory Regions" is an aperture like feature with + * one slot per bo. There is an upper limit of the number of + * slots as well as the bo size. + */ + man->func = &vmw_gmrid_manager_func; + man->gpu_offset = 0; + man->flags = TTM_MEMTYPE_FLAG_CMA | TTM_MEMTYPE_FLAG_MAPPABLE; + man->available_caching = TTM_PL_FLAG_CACHED; + man->default_caching = TTM_PL_FLAG_CACHED; + break; + default: + DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); + return -EINVAL; + } + return 0; +} + +static void vmw_evict_flags(struct ttm_buffer_object *bo, + struct ttm_placement *placement) +{ + *placement = vmw_sys_placement; +} + +static int vmw_verify_access(struct ttm_buffer_object *bo, struct file *filp) +{ + struct ttm_object_file *tfile = + vmw_fpriv((struct drm_file *)filp->private_data)->tfile; + + return vmw_user_bo_verify_access(bo, tfile); +} + +static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) +{ + struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; + struct vmw_private *dev_priv = container_of(bdev, struct vmw_private, bdev); + + mem->bus.addr = NULL; + mem->bus.is_iomem = false; + mem->bus.offset = 0; + mem->bus.size = mem->num_pages << PAGE_SHIFT; + mem->bus.base = 0; + if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) + return -EINVAL; + switch (mem->mem_type) { + case TTM_PL_SYSTEM: + case VMW_PL_GMR: + case VMW_PL_MOB: + return 0; + case TTM_PL_VRAM: + mem->bus.offset = mem->start << PAGE_SHIFT; + mem->bus.base = dev_priv->vram_start; + mem->bus.is_iomem = true; + break; + default: + return -EINVAL; + } + return 0; +} + +static void vmw_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) +{ +} + +static int vmw_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) +{ + return 0; +} + +/** + * vmw_move_notify - TTM move_notify_callback + * + * @bo: The TTM buffer object about to move. + * @mem: The struct ttm_mem_reg indicating to what memory + * region the move is taking place. + * + * Calls move_notify for all subsystems needing it. + * (currently only resources). + */ +static void vmw_move_notify(struct ttm_buffer_object *bo, + bool evict, + struct ttm_mem_reg *mem) +{ + vmw_resource_move_notify(bo, mem); + vmw_query_move_notify(bo, mem); +} + + +/** + * vmw_swap_notify - TTM move_notify_callback + * + * @bo: The TTM buffer object about to be swapped out. + */ +static void vmw_swap_notify(struct ttm_buffer_object *bo) +{ + vmw_resource_swap_notify(bo); + (void) ttm_bo_wait(bo, false, false); +} + + +struct ttm_bo_driver vmw_bo_driver = { + .ttm_tt_create = &vmw_ttm_tt_create, + .ttm_tt_populate = &vmw_ttm_populate, + .ttm_tt_unpopulate = &vmw_ttm_unpopulate, + .invalidate_caches = vmw_invalidate_caches, + .init_mem_type = vmw_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, + .evict_flags = vmw_evict_flags, + .move = NULL, + .verify_access = vmw_verify_access, + .move_notify = vmw_move_notify, + .swap_notify = vmw_swap_notify, + .fault_reserve_notify = &vmw_ttm_fault_reserve_notify, + .io_mem_reserve = &vmw_ttm_io_mem_reserve, + .io_mem_free = &vmw_ttm_io_mem_free, +}; diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h index 0bc784f5e0db..57115a5fe61a 100644 --- a/include/uapi/drm/vmwgfx_drm.h +++ b/include/uapi/drm/vmwgfx_drm.h @@ -40,6 +40,7 @@ extern "C" { #define DRM_VMW_GET_PARAM 0 #define DRM_VMW_ALLOC_DMABUF 1 +#define DRM_VMW_ALLOC_BO 1 #define DRM_VMW_UNREF_DMABUF 2 #define DRM_VMW_HANDLE_CLOSE 2 #define DRM_VMW_CURSOR_BYPASS 3 @@ -356,9 +357,9 @@ struct drm_vmw_fence_rep { /*************************************************************************/ /** - * DRM_VMW_ALLOC_DMABUF + * DRM_VMW_ALLOC_BO * - * Allocate a DMA buffer that is visible also to the host. + * Allocate a buffer object that is visible also to the host. * NOTE: The buffer is * identified by a handle and an offset, which are private to the guest, but * useable in the command stream. The guest kernel may translate these @@ -366,27 +367,28 @@ struct drm_vmw_fence_rep { * be zero at all times, or it may disappear from the interface before it is * fixed. * - * The DMA buffer may stay user-space mapped in the guest at all times, + * The buffer object may stay user-space mapped in the guest at all times, * and is thus suitable for sub-allocation. * - * DMA buffers are mapped using the mmap() syscall on the drm device. + * Buffer objects are mapped using the mmap() syscall on the drm device. */ /** - * struct drm_vmw_alloc_dmabuf_req + * struct drm_vmw_alloc_bo_req * * @size: Required minimum size of the buffer. * - * Input data to the DRM_VMW_ALLOC_DMABUF Ioctl. + * Input data to the DRM_VMW_ALLOC_BO Ioctl. */ -struct drm_vmw_alloc_dmabuf_req { +struct drm_vmw_alloc_bo_req { __u32 size; __u32 pad64; }; +#define drm_vmw_alloc_dmabuf_req drm_vmw_alloc_bo_req /** - * struct drm_vmw_dmabuf_rep + * struct drm_vmw_bo_rep * * @map_handle: Offset to use in the mmap() call used to map the buffer. * @handle: Handle unique to this buffer. Used for unreferencing. @@ -395,50 +397,32 @@ struct drm_vmw_alloc_dmabuf_req { * @cur_gmr_offset: Offset to use in the command stream when this buffer is * referenced. See note above. * - * Output data from the DRM_VMW_ALLOC_DMABUF Ioctl. + * Output data from the DRM_VMW_ALLOC_BO Ioctl. */ -struct drm_vmw_dmabuf_rep { +struct drm_vmw_bo_rep { __u64 map_handle; __u32 handle; __u32 cur_gmr_id; __u32 cur_gmr_offset; __u32 pad64; }; +#define drm_vmw_dmabuf_rep drm_vmw_bo_rep /** - * union drm_vmw_dmabuf_arg + * union drm_vmw_alloc_bo_arg * * @req: Input data as described above. * @rep: Output data as described above. * - * Argument to the DRM_VMW_ALLOC_DMABUF Ioctl. + * Argument to the DRM_VMW_ALLOC_BO Ioctl. */ -union drm_vmw_alloc_dmabuf_arg { - struct drm_vmw_alloc_dmabuf_req req; - struct drm_vmw_dmabuf_rep rep; -}; - -/*************************************************************************/ -/** - * DRM_VMW_UNREF_DMABUF - Free a DMA buffer. - * - */ - -/** - * struct drm_vmw_unref_dmabuf_arg - * - * @handle: Handle indicating what buffer to free. Obtained from the - * DRM_VMW_ALLOC_DMABUF Ioctl. - * - * Argument to the DRM_VMW_UNREF_DMABUF Ioctl. - */ - -struct drm_vmw_unref_dmabuf_arg { - __u32 handle; - __u32 pad64; +union drm_vmw_alloc_bo_arg { + struct drm_vmw_alloc_bo_req req; + struct drm_vmw_bo_rep rep; }; +#define drm_vmw_alloc_dmabuf_arg drm_vmw_alloc_bo_arg /*************************************************************************/ /** @@ -1103,9 +1087,8 @@ union drm_vmw_extended_context_arg { * DRM_VMW_HANDLE_CLOSE - Close a user-space handle and release its * underlying resource. * - * Note that this ioctl is overlaid on the DRM_VMW_UNREF_DMABUF Ioctl. - * The ioctl arguments therefore need to be identical in layout. - * + * Note that this ioctl is overlaid on the deprecated DRM_VMW_UNREF_DMABUF + * Ioctl. */ /** @@ -1119,7 +1102,7 @@ struct drm_vmw_handle_close_arg { __u32 handle; __u32 pad64; }; - +#define drm_vmw_unref_dmabuf_arg drm_vmw_handle_close_arg #if defined(__cplusplus) } -- cgit v1.2.3 From 3b4c2511c004521efa89875512b5039a04d5e2e0 Mon Sep 17 00:00:00 2001 From: Neha Bhende Date: Mon, 18 Jun 2018 16:44:48 -0700 Subject: drm/vmwgfx: Add CAP2 support in vmwgfx The device exposes a new capability register. Add support for it. Signed-off-by: Neha Bhende Reviewed-by: Thomas Hellstrom Signed-off-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 17 +++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 3 +++ include/uapi/drm/vmwgfx_drm.h | 1 + 4 files changed, 22 insertions(+) (limited to 'include/uapi') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 1128420de2c0..f2fad88e4c54 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -258,6 +258,15 @@ MODULE_PARM_DESC(assume_16bpp, "Assume 16-bpp when filtering modes"); module_param_named(assume_16bpp, vmw_assume_16bpp, int, 0600); +static void vmw_print_capabilities2(uint32_t capabilities2) +{ + DRM_INFO("Capabilities2:\n"); + if (capabilities2 & SVGA_CAP2_GROW_OTABLE) + DRM_INFO(" Grow oTable.\n"); + if (capabilities2 & SVGA_CAP2_INTRA_SURFACE_COPY) + DRM_INFO(" IntraSurface copy.\n"); +} + static void vmw_print_capabilities(uint32_t capabilities) { DRM_INFO("Capabilities:\n"); @@ -684,6 +693,12 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) } dev_priv->capabilities = vmw_read(dev_priv, SVGA_REG_CAPABILITIES); + + if (dev_priv->capabilities & SVGA_CAP_CAP2_REGISTER) { + dev_priv->capabilities2 = vmw_read(dev_priv, SVGA_REG_CAP2); + } + + ret = vmw_dma_select_mode(dev_priv); if (unlikely(ret != 0)) { DRM_INFO("Restricting capabilities due to IOMMU setup.\n"); @@ -752,6 +767,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) } vmw_print_capabilities(dev_priv->capabilities); + if (dev_priv->capabilities & SVGA_CAP_CAP2_REGISTER) + vmw_print_capabilities2(dev_priv->capabilities2); ret = vmw_dma_masks(dev_priv); if (unlikely(ret != 0)) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index a3a0826958a1..920365c0e9ab 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -386,6 +386,7 @@ struct vmw_private { uint32_t initial_height; u32 *mmio_virt; uint32_t capabilities; + uint32_t capabilities2; uint32_t max_gmr_ids; uint32_t max_gmr_pages; uint32_t max_mob_pages; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index 6872c7ee8a08..ac6da0da2824 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -56,6 +56,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, case DRM_VMW_PARAM_HW_CAPS: param->value = dev_priv->capabilities; break; + case DRM_VMW_PARAM_HW_CAPS2: + param->value = dev_priv->capabilities2; + break; case DRM_VMW_PARAM_FIFO_CAPS: param->value = dev_priv->fifo.capabilities; break; diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h index 57115a5fe61a..84e81b38ca18 100644 --- a/include/uapi/drm/vmwgfx_drm.h +++ b/include/uapi/drm/vmwgfx_drm.h @@ -95,6 +95,7 @@ extern "C" { #define DRM_VMW_PARAM_MAX_MOB_SIZE 10 #define DRM_VMW_PARAM_SCREEN_TARGET 11 #define DRM_VMW_PARAM_DX 12 +#define DRM_VMW_PARAM_HW_CAPS2 13 /** * enum drm_vmw_handle_type - handle type for ref ioctls -- cgit v1.2.3 From 14b1c33e84295693c3b1a1d7c6ac82b3f384cd17 Mon Sep 17 00:00:00 2001 From: Deepak Rawat Date: Wed, 20 Jun 2018 14:48:35 -0700 Subject: drm/vmwgfx: Add new ioctl for GB surface create and reference New ioctls DRM_VMW_GB_SURFACE_CREATE_EXT and DRM_VMW_GB_SURFACE_REF_EXT are added which support 64-bit wide svga device surface flags, quality level and multisample pattern. Signed-off-by: Deepak Rawat Reviewed-by: Sinclair Yeh Reviewed-by: Brian Paul Reviewed-by: Thomas Hellstrom Reviewed-by: Charmaine Lee Signed-off-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 12 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 8 + drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 20 +- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 2 + drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 468 +++++++++++++++++++++----------- include/uapi/drm/vmwgfx_drm.h | 102 +++++++ 6 files changed, 437 insertions(+), 175 deletions(-) (limited to 'include/uapi') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 6cf81e19182f..59229111f303 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -137,6 +137,12 @@ #define DRM_IOCTL_VMW_CREATE_EXTENDED_CONTEXT \ DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_CREATE_EXTENDED_CONTEXT, \ struct drm_vmw_context_arg) +#define DRM_IOCTL_VMW_GB_SURFACE_CREATE_EXT \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_GB_SURFACE_CREATE_EXT, \ + union drm_vmw_gb_surface_create_ext_arg) +#define DRM_IOCTL_VMW_GB_SURFACE_REF_EXT \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_GB_SURFACE_REF_EXT, \ + union drm_vmw_gb_surface_reference_ext_arg) /** * The core DRM version of this macro doesn't account for @@ -224,6 +230,12 @@ static const struct drm_ioctl_desc vmw_ioctls[] = { VMW_IOCTL_DEF(VMW_CREATE_EXTENDED_CONTEXT, vmw_extended_context_define_ioctl, DRM_AUTH | DRM_RENDER_ALLOW), + VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE_EXT, + vmw_gb_surface_define_ext_ioctl, + DRM_AUTH | DRM_RENDER_ALLOW), + VMW_IOCTL_DEF(VMW_GB_SURFACE_REF_EXT, + vmw_gb_surface_reference_ext_ioctl, + DRM_AUTH | DRM_RENDER_ALLOW), }; static const struct pci_device_id vmw_pci_id_list[] = { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 7e5c93083036..59af14714797 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1087,7 +1087,15 @@ int vmw_surface_gb_priv_define(struct drm_device *dev, uint32_t multisample_count, uint32_t array_size, struct drm_vmw_size size, + SVGA3dMSPattern multisample_pattern, + SVGA3dMSQualityLevel quality_level, struct vmw_surface **srf_out); +extern int vmw_gb_surface_define_ext_ioctl(struct drm_device *dev, + void *data, + struct drm_file *file_priv); +extern int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, + void *data, + struct drm_file *file_priv); /* * Shader management - vmwgfx_shader.c diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 0fb363458ab5..3201b0a51d10 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1238,15 +1238,17 @@ static int vmw_create_bo_proxy(struct drm_device *dev, content_base_size.depth = 1; ret = vmw_surface_gb_priv_define(dev, - 0, /* kernel visible only */ - 0, /* flags */ - format, - true, /* can be a scanout buffer */ - 1, /* num of mip levels */ - 0, - 0, - content_base_size, - srf_out); + 0, /* kernel visible only */ + 0, /* flags */ + format, + true, /* can be a scanout buffer */ + 1, /* num of mip levels */ + 0, + 0, + content_base_size, + SVGA3D_MS_PATTERN_NONE, + SVGA3D_MS_QUALITY_NONE, + srf_out); if (ret) { DRM_ERROR("Failed to allocate proxy content buffer\n"); return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 6630abf3a95c..f9872c9e60c4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -1188,6 +1188,8 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, content_srf.multisample_count, 0, display_base_size, + content_srf.multisample_pattern, + content_srf.quality_level, &vps->surf); if (ret != 0) { DRM_ERROR("Couldn't allocate STDU surface.\n"); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index a5f93f62c7fa..1d4c010a0e48 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -33,6 +33,10 @@ #include "vmwgfx_binding.h" #include "device_include/svga3d_surfacedefs.h" +#define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32) +#define SVGA3D_FLAGS_UPPER_32(svga3d_flags) (svga3d_flags >> 32) +#define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \ + (svga3d_flags & ((uint64_t)U32_MAX)) /** * struct vmw_user_surface - User-space visible surface resource @@ -81,7 +85,16 @@ static int vmw_gb_surface_unbind(struct vmw_resource *res, bool readback, struct ttm_validate_buffer *val_buf); static int vmw_gb_surface_destroy(struct vmw_resource *res); - +static int +vmw_gb_surface_define_internal(struct drm_device *dev, + struct drm_vmw_gb_surface_create_ext_req *req, + struct drm_vmw_gb_surface_create_rep *rep, + struct drm_file *file_priv); +static int +vmw_gb_surface_reference_internal(struct drm_device *dev, + struct drm_vmw_surface_arg *req, + struct drm_vmw_gb_surface_ref_ext_rep *rep, + struct drm_file *file_priv); static const struct vmw_user_resource_conv user_surface_conv = { .object_type = VMW_RES_SURFACE, @@ -1289,193 +1302,55 @@ static int vmw_gb_surface_destroy(struct vmw_resource *res) /** * vmw_gb_surface_define_ioctl - Ioctl function implementing - * the user surface define functionality. + * the user surface define functionality. * - * @dev: Pointer to a struct drm_device. - * @data: Pointer to data copied from / to user-space. - * @file_priv: Pointer to a drm file private structure. + * @dev: Pointer to a struct drm_device. + * @data: Pointer to data copied from / to user-space. + * @file_priv: Pointer to a drm file private structure. */ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct vmw_private *dev_priv = vmw_priv(dev); - struct vmw_user_surface *user_srf; - struct vmw_surface *srf; - struct vmw_resource *res; - struct vmw_resource *tmp; union drm_vmw_gb_surface_create_arg *arg = (union drm_vmw_gb_surface_create_arg *)data; - struct drm_vmw_gb_surface_create_req *req = &arg->req; struct drm_vmw_gb_surface_create_rep *rep = &arg->rep; - struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - int ret; - uint32_t size; - uint32_t backup_handle = 0; - - if (req->multisample_count != 0) - return -EINVAL; - - if (req->mip_levels > DRM_VMW_MAX_MIP_LEVELS) - return -EINVAL; - - if (unlikely(vmw_user_surface_size == 0)) - vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) + - 128; - - size = vmw_user_surface_size + 128; - - /* Define a surface based on the parameters. */ - ret = vmw_surface_gb_priv_define(dev, - size, - (SVGA3dSurfaceAllFlags)req->svga3d_flags, - req->format, - req->drm_surface_flags & drm_vmw_surface_flag_scanout, - req->mip_levels, - req->multisample_count, - req->array_size, - req->base_size, - &srf); - if (unlikely(ret != 0)) - return ret; - - user_srf = container_of(srf, struct vmw_user_surface, srf); - if (drm_is_primary_client(file_priv)) - user_srf->master = drm_master_get(file_priv->master); - - ret = ttm_read_lock(&dev_priv->reservation_sem, true); - if (unlikely(ret != 0)) - return ret; - - res = &user_srf->srf.res; - - - if (req->buffer_handle != SVGA3D_INVALID_ID) { - ret = vmw_user_bo_lookup(tfile, req->buffer_handle, - &res->backup, - &user_srf->backup_base); - if (ret == 0) { - if (res->backup->base.num_pages * PAGE_SIZE < - res->backup_size) { - DRM_ERROR("Surface backup buffer is too small.\n"); - vmw_bo_unreference(&res->backup); - ret = -EINVAL; - goto out_unlock; - } else { - backup_handle = req->buffer_handle; - } - } - } else if (req->drm_surface_flags & drm_vmw_surface_flag_create_buffer) - ret = vmw_user_bo_alloc(dev_priv, tfile, - res->backup_size, - req->drm_surface_flags & - drm_vmw_surface_flag_shareable, - &backup_handle, - &res->backup, - &user_srf->backup_base); - - if (unlikely(ret != 0)) { - vmw_resource_unreference(&res); - goto out_unlock; - } - - tmp = vmw_resource_reference(res); - ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime, - req->drm_surface_flags & - drm_vmw_surface_flag_shareable, - VMW_RES_SURFACE, - &vmw_user_surface_base_release, NULL); - - if (unlikely(ret != 0)) { - vmw_resource_unreference(&tmp); - vmw_resource_unreference(&res); - goto out_unlock; - } - - rep->handle = user_srf->prime.base.hash.key; - rep->backup_size = res->backup_size; - if (res->backup) { - rep->buffer_map_handle = - drm_vma_node_offset_addr(&res->backup->base.vma_node); - rep->buffer_size = res->backup->base.num_pages * PAGE_SIZE; - rep->buffer_handle = backup_handle; - } else { - rep->buffer_map_handle = 0; - rep->buffer_size = 0; - rep->buffer_handle = SVGA3D_INVALID_ID; - } + struct drm_vmw_gb_surface_create_ext_req req_ext; - vmw_resource_unreference(&res); + req_ext.base = arg->req; + req_ext.version = drm_vmw_gb_surface_v1; + req_ext.svga3d_flags_upper_32_bits = 0; + req_ext.multisample_pattern = SVGA3D_MS_PATTERN_NONE; + req_ext.quality_level = SVGA3D_MS_QUALITY_NONE; + req_ext.must_be_zero = 0; -out_unlock: - ttm_read_unlock(&dev_priv->reservation_sem); - return ret; + return vmw_gb_surface_define_internal(dev, &req_ext, rep, file_priv); } /** * vmw_gb_surface_reference_ioctl - Ioctl function implementing - * the user surface reference functionality. + * the user surface reference functionality. * - * @dev: Pointer to a struct drm_device. - * @data: Pointer to data copied from / to user-space. - * @file_priv: Pointer to a drm file private structure. + * @dev: Pointer to a struct drm_device. + * @data: Pointer to data copied from / to user-space. + * @file_priv: Pointer to a drm file private structure. */ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct vmw_private *dev_priv = vmw_priv(dev); union drm_vmw_gb_surface_reference_arg *arg = (union drm_vmw_gb_surface_reference_arg *)data; struct drm_vmw_surface_arg *req = &arg->req; struct drm_vmw_gb_surface_ref_rep *rep = &arg->rep; - struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - struct vmw_surface *srf; - struct vmw_user_surface *user_srf; - struct ttm_base_object *base; - uint32_t backup_handle; - int ret = -EINVAL; + struct drm_vmw_gb_surface_ref_ext_rep rep_ext; + int ret; + + ret = vmw_gb_surface_reference_internal(dev, req, &rep_ext, file_priv); - ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid, - req->handle_type, &base); if (unlikely(ret != 0)) return ret; - user_srf = container_of(base, struct vmw_user_surface, prime.base); - srf = &user_srf->srf; - if (!srf->res.backup) { - DRM_ERROR("Shared GB surface is missing a backup buffer.\n"); - goto out_bad_resource; - } - - mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */ - ret = vmw_user_bo_reference(tfile, srf->res.backup, &backup_handle); - mutex_unlock(&dev_priv->cmdbuf_mutex); - - if (unlikely(ret != 0)) { - DRM_ERROR("Could not add a reference to a GB surface " - "backup buffer.\n"); - (void) ttm_ref_object_base_unref(tfile, base->hash.key, - TTM_REF_USAGE); - goto out_bad_resource; - } - - rep->creq.svga3d_flags = (uint32_t)srf->flags; - rep->creq.format = srf->format; - rep->creq.mip_levels = srf->mip_levels[0]; - rep->creq.drm_surface_flags = 0; - rep->creq.multisample_count = srf->multisample_count; - rep->creq.autogen_filter = srf->autogen_filter; - rep->creq.array_size = srf->array_size; - rep->creq.buffer_handle = backup_handle; - rep->creq.base_size = srf->base_size; - rep->crep.handle = user_srf->prime.base.hash.key; - rep->crep.backup_size = srf->res.backup_size; - rep->crep.buffer_handle = backup_handle; - rep->crep.buffer_map_handle = - drm_vma_node_offset_addr(&srf->res.backup->base.vma_node); - rep->crep.buffer_size = srf->res.backup->base.num_pages * PAGE_SIZE; - -out_bad_resource: - ttm_base_object_unref(&base); + rep->creq = rep_ext.creq.base; + rep->crep = rep_ext.crep; return ret; } @@ -1493,6 +1368,8 @@ out_bad_resource: * @multisample_count: * @array_size: Surface array size. * @size: width, heigh, depth of the surface requested + * @multisample_pattern: Multisampling pattern when msaa is supported + * @quality_level: Precision settings * @user_srf_out: allocated user_srf. Set to NULL on failure. * * GB surfaces allocated by this function will not have a user mode handle, and @@ -1509,6 +1386,8 @@ int vmw_surface_gb_priv_define(struct drm_device *dev, uint32_t multisample_count, uint32_t array_size, struct drm_vmw_size size, + SVGA3dMSPattern multisample_pattern, + SVGA3dMSQualityLevel quality_level, struct vmw_surface **srf_out) { struct vmw_private *dev_priv = vmw_priv(dev); @@ -1519,7 +1398,7 @@ int vmw_surface_gb_priv_define(struct drm_device *dev, }; struct vmw_surface *srf; int ret; - u32 num_layers; + u32 num_layers = 1; *srf_out = NULL; @@ -1594,15 +1473,13 @@ int vmw_surface_gb_priv_define(struct drm_device *dev, srf->autogen_filter = SVGA3D_TEX_FILTER_NONE; srf->array_size = array_size; srf->multisample_count = multisample_count; - srf->multisample_pattern = SVGA3D_MS_PATTERN_NONE; - srf->quality_level = SVGA3D_MS_QUALITY_NONE; + srf->multisample_pattern = multisample_pattern; + srf->quality_level = quality_level; if (array_size) num_layers = array_size; else if (svga3d_flags & SVGA3D_SURFACE_CUBEMAP) num_layers = SVGA3D_MAX_SURFACE_FACES; - else - num_layers = 1; srf->res.backup_size = svga3dsurface_get_serialized_size(srf->format, @@ -1633,3 +1510,262 @@ out_unlock: ttm_read_unlock(&dev_priv->reservation_sem); return ret; } + +/** + * vmw_gb_surface_define_ext_ioctl - Ioctl function implementing + * the user surface define functionality. + * + * @dev: Pointer to a struct drm_device. + * @data: Pointer to data copied from / to user-space. + * @file_priv: Pointer to a drm file private structure. + */ +int vmw_gb_surface_define_ext_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + union drm_vmw_gb_surface_create_ext_arg *arg = + (union drm_vmw_gb_surface_create_ext_arg *)data; + struct drm_vmw_gb_surface_create_ext_req *req = &arg->req; + struct drm_vmw_gb_surface_create_rep *rep = &arg->rep; + + return vmw_gb_surface_define_internal(dev, req, rep, file_priv); +} + +/** + * vmw_gb_surface_reference_ext_ioctl - Ioctl function implementing + * the user surface reference functionality. + * + * @dev: Pointer to a struct drm_device. + * @data: Pointer to data copied from / to user-space. + * @file_priv: Pointer to a drm file private structure. + */ +int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + union drm_vmw_gb_surface_reference_ext_arg *arg = + (union drm_vmw_gb_surface_reference_ext_arg *)data; + struct drm_vmw_surface_arg *req = &arg->req; + struct drm_vmw_gb_surface_ref_ext_rep *rep = &arg->rep; + + return vmw_gb_surface_reference_internal(dev, req, rep, file_priv); +} + +/** + * vmw_gb_surface_define_internal - Ioctl function implementing + * the user surface define functionality. + * + * @dev: Pointer to a struct drm_device. + * @req: Request argument from user-space. + * @rep: Response argument to user-space. + * @file_priv: Pointer to a drm file private structure. + */ +static int +vmw_gb_surface_define_internal(struct drm_device *dev, + struct drm_vmw_gb_surface_create_ext_req *req, + struct drm_vmw_gb_surface_create_rep *rep, + struct drm_file *file_priv) +{ + struct vmw_private *dev_priv = vmw_priv(dev); + struct vmw_user_surface *user_srf; + struct vmw_surface *srf; + struct vmw_resource *res; + struct vmw_resource *tmp; + struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; + int ret; + uint32_t size; + uint32_t backup_handle = 0; + SVGA3dSurfaceAllFlags svga3d_flags_64 = + SVGA3D_FLAGS_64(req->svga3d_flags_upper_32_bits, + req->base.svga3d_flags); + + if (!dev_priv->has_sm4_1) { + /* + * If SM4_1 is not support then cannot send 64-bit flag to + * device. + */ + if (req->svga3d_flags_upper_32_bits != 0) + return -EINVAL; + + if (req->base.multisample_count != 0) + return -EINVAL; + + if (req->multisample_pattern != SVGA3D_MS_PATTERN_NONE) + return -EINVAL; + + if (req->quality_level != SVGA3D_MS_QUALITY_NONE) + return -EINVAL; + } + + if (req->base.mip_levels > DRM_VMW_MAX_MIP_LEVELS) + return -EINVAL; + + if (unlikely(vmw_user_surface_size == 0)) + vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) + + 128; + + size = vmw_user_surface_size + 128; + + /* Define a surface based on the parameters. */ + ret = vmw_surface_gb_priv_define(dev, + size, + svga3d_flags_64, + req->base.format, + req->base.drm_surface_flags & + drm_vmw_surface_flag_scanout, + req->base.mip_levels, + req->base.multisample_count, + req->base.array_size, + req->base.base_size, + req->multisample_pattern, + req->quality_level, + &srf); + if (unlikely(ret != 0)) + return ret; + + user_srf = container_of(srf, struct vmw_user_surface, srf); + if (drm_is_primary_client(file_priv)) + user_srf->master = drm_master_get(file_priv->master); + + ret = ttm_read_lock(&dev_priv->reservation_sem, true); + if (unlikely(ret != 0)) + return ret; + + res = &user_srf->srf.res; + + if (req->base.buffer_handle != SVGA3D_INVALID_ID) { + ret = vmw_user_bo_lookup(tfile, req->base.buffer_handle, + &res->backup, + &user_srf->backup_base); + if (ret == 0) { + if (res->backup->base.num_pages * PAGE_SIZE < + res->backup_size) { + DRM_ERROR("Surface backup buffer too small.\n"); + vmw_bo_unreference(&res->backup); + ret = -EINVAL; + goto out_unlock; + } else { + backup_handle = req->base.buffer_handle; + } + } + } else if (req->base.drm_surface_flags & + drm_vmw_surface_flag_create_buffer) + ret = vmw_user_bo_alloc(dev_priv, tfile, + res->backup_size, + req->base.drm_surface_flags & + drm_vmw_surface_flag_shareable, + &backup_handle, + &res->backup, + &user_srf->backup_base); + + if (unlikely(ret != 0)) { + vmw_resource_unreference(&res); + goto out_unlock; + } + + tmp = vmw_resource_reference(res); + ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime, + req->base.drm_surface_flags & + drm_vmw_surface_flag_shareable, + VMW_RES_SURFACE, + &vmw_user_surface_base_release, NULL); + + if (unlikely(ret != 0)) { + vmw_resource_unreference(&tmp); + vmw_resource_unreference(&res); + goto out_unlock; + } + + rep->handle = user_srf->prime.base.hash.key; + rep->backup_size = res->backup_size; + if (res->backup) { + rep->buffer_map_handle = + drm_vma_node_offset_addr(&res->backup->base.vma_node); + rep->buffer_size = res->backup->base.num_pages * PAGE_SIZE; + rep->buffer_handle = backup_handle; + } else { + rep->buffer_map_handle = 0; + rep->buffer_size = 0; + rep->buffer_handle = SVGA3D_INVALID_ID; + } + + vmw_resource_unreference(&res); + +out_unlock: + ttm_read_unlock(&dev_priv->reservation_sem); + return ret; +} + +/** + * vmw_gb_surface_reference_internal - Ioctl function implementing + * the user surface reference functionality. + * + * @dev: Pointer to a struct drm_device. + * @req: Pointer to user-space request surface arg. + * @rep: Pointer to response to user-space. + * @file_priv: Pointer to a drm file private structure. + */ +static int +vmw_gb_surface_reference_internal(struct drm_device *dev, + struct drm_vmw_surface_arg *req, + struct drm_vmw_gb_surface_ref_ext_rep *rep, + struct drm_file *file_priv) +{ + struct vmw_private *dev_priv = vmw_priv(dev); + struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; + struct vmw_surface *srf; + struct vmw_user_surface *user_srf; + struct ttm_base_object *base; + uint32_t backup_handle; + int ret = -EINVAL; + + ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid, + req->handle_type, &base); + if (unlikely(ret != 0)) + return ret; + + user_srf = container_of(base, struct vmw_user_surface, prime.base); + srf = &user_srf->srf; + if (!srf->res.backup) { + DRM_ERROR("Shared GB surface is missing a backup buffer.\n"); + goto out_bad_resource; + } + + mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */ + ret = vmw_user_bo_reference(tfile, srf->res.backup, &backup_handle); + mutex_unlock(&dev_priv->cmdbuf_mutex); + + if (unlikely(ret != 0)) { + DRM_ERROR("Could not add a reference to a GB surface " + "backup buffer.\n"); + (void) ttm_ref_object_base_unref(tfile, base->hash.key, + TTM_REF_USAGE); + goto out_bad_resource; + } + + rep->creq.base.svga3d_flags = SVGA3D_FLAGS_LOWER_32(srf->flags); + rep->creq.base.format = srf->format; + rep->creq.base.mip_levels = srf->mip_levels[0]; + rep->creq.base.drm_surface_flags = 0; + rep->creq.base.multisample_count = srf->multisample_count; + rep->creq.base.autogen_filter = srf->autogen_filter; + rep->creq.base.array_size = srf->array_size; + rep->creq.base.buffer_handle = backup_handle; + rep->creq.base.base_size = srf->base_size; + rep->crep.handle = user_srf->prime.base.hash.key; + rep->crep.backup_size = srf->res.backup_size; + rep->crep.buffer_handle = backup_handle; + rep->crep.buffer_map_handle = + drm_vma_node_offset_addr(&srf->res.backup->base.vma_node); + rep->crep.buffer_size = srf->res.backup->base.num_pages * PAGE_SIZE; + + rep->creq.version = drm_vmw_gb_surface_v1; + rep->creq.svga3d_flags_upper_32_bits = + SVGA3D_FLAGS_UPPER_32(srf->flags); + rep->creq.multisample_pattern = srf->multisample_pattern; + rep->creq.quality_level = srf->quality_level; + rep->creq.must_be_zero = 0; + +out_bad_resource: + ttm_base_object_unref(&base); + + return ret; +} diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h index 84e81b38ca18..68ff37d4c035 100644 --- a/include/uapi/drm/vmwgfx_drm.h +++ b/include/uapi/drm/vmwgfx_drm.h @@ -69,6 +69,8 @@ extern "C" { #define DRM_VMW_GB_SURFACE_REF 24 #define DRM_VMW_SYNCCPU 25 #define DRM_VMW_CREATE_EXTENDED_CONTEXT 26 +#define DRM_VMW_GB_SURFACE_CREATE_EXT 27 +#define DRM_VMW_GB_SURFACE_REF_EXT 28 /*************************************************************************/ /** @@ -1105,6 +1107,106 @@ struct drm_vmw_handle_close_arg { }; #define drm_vmw_unref_dmabuf_arg drm_vmw_handle_close_arg +/*************************************************************************/ +/** + * DRM_VMW_GB_SURFACE_CREATE_EXT - Create a host guest-backed surface. + * + * Allocates a surface handle and queues a create surface command + * for the host on the first use of the surface. The surface ID can + * be used as the surface ID in commands referencing the surface. + * + * This new command extends DRM_VMW_GB_SURFACE_CREATE by adding version + * parameter and 64 bit svga flag. + */ + +/** + * enum drm_vmw_surface_version + * + * @drm_vmw_surface_gb_v1: Corresponds to current gb surface format with + * svga3d surface flags split into 2, upper half and lower half. + */ +enum drm_vmw_surface_version { + drm_vmw_gb_surface_v1 +}; + +/** + * struct drm_vmw_gb_surface_create_ext_req + * + * @base: Surface create parameters. + * @version: Version of surface create ioctl. + * @svga3d_flags_upper_32_bits: Upper 32 bits of svga3d flags. + * @multisample_pattern: Multisampling pattern when msaa is supported. + * @quality_level: Precision settings for each sample. + * @must_be_zero: Reserved for future usage. + * + * Input argument to the DRM_VMW_GB_SURFACE_CREATE_EXT Ioctl. + * Part of output argument for the DRM_VMW_GB_SURFACE_REF_EXT Ioctl. + */ +struct drm_vmw_gb_surface_create_ext_req { + struct drm_vmw_gb_surface_create_req base; + enum drm_vmw_surface_version version; + uint32_t svga3d_flags_upper_32_bits; + SVGA3dMSPattern multisample_pattern; + SVGA3dMSQualityLevel quality_level; + uint64_t must_be_zero; +}; + +/** + * union drm_vmw_gb_surface_create_ext_arg + * + * @req: Input argument as described above. + * @rep: Output argument as described above. + * + * Argument to the DRM_VMW_GB_SURFACE_CREATE_EXT ioctl. + */ +union drm_vmw_gb_surface_create_ext_arg { + struct drm_vmw_gb_surface_create_rep rep; + struct drm_vmw_gb_surface_create_ext_req req; +}; + +/*************************************************************************/ +/** + * DRM_VMW_GB_SURFACE_REF_EXT - Reference a host surface. + * + * Puts a reference on a host surface with a given handle, as previously + * returned by the DRM_VMW_GB_SURFACE_CREATE_EXT ioctl. + * A reference will make sure the surface isn't destroyed while we hold + * it and will allow the calling client to use the surface handle in + * the command stream. + * + * On successful return, the Ioctl returns the surface information given + * to and returned from the DRM_VMW_GB_SURFACE_CREATE_EXT ioctl. + */ + +/** + * struct drm_vmw_gb_surface_ref_ext_rep + * + * @creq: The data used as input when the surface was created, as described + * above at "struct drm_vmw_gb_surface_create_ext_req" + * @crep: Additional data output when the surface was created, as described + * above at "struct drm_vmw_gb_surface_create_rep" + * + * Output Argument to the DRM_VMW_GB_SURFACE_REF_EXT ioctl. + */ +struct drm_vmw_gb_surface_ref_ext_rep { + struct drm_vmw_gb_surface_create_ext_req creq; + struct drm_vmw_gb_surface_create_rep crep; +}; + +/** + * union drm_vmw_gb_surface_reference_ext_arg + * + * @req: Input data as described above at "struct drm_vmw_surface_arg" + * @rep: Output data as described above at + * "struct drm_vmw_gb_surface_ref_ext_rep" + * + * Argument to the DRM_VMW_GB_SURFACE_REF Ioctl. + */ +union drm_vmw_gb_surface_reference_ext_arg { + struct drm_vmw_gb_surface_ref_ext_rep rep; + struct drm_vmw_surface_arg req; +}; + #if defined(__cplusplus) } #endif -- cgit v1.2.3 From 9b07b287aa3ef49695bfad59c1870cd942f579a8 Mon Sep 17 00:00:00 2001 From: Deepak Rawat Date: Wed, 20 Jun 2018 15:09:43 -0700 Subject: drm/vmwgfx: Expose SM4_1 param to user space A new param DRM_VMW_PARAM_SM4_1, is added for user space to determine availability of SM4.1. Minor version bump for SM4.1. Signed-off-by: Deepak Rawat Reviewed-by: Sinclair Yeh Reviewed-by: Brian Paul Reviewed-by: Thomas Hellstrom Signed-off-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 6 +++--- drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 3 +++ include/uapi/drm/vmwgfx_drm.h | 4 ++++ 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'include/uapi') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index a67b54e4fd50..f1b803d34c59 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -43,10 +43,10 @@ #include #define VMWGFX_DRIVER_NAME "vmwgfx" -#define VMWGFX_DRIVER_DATE "20180322" +#define VMWGFX_DRIVER_DATE "20180704" #define VMWGFX_DRIVER_MAJOR 2 -#define VMWGFX_DRIVER_MINOR 14 -#define VMWGFX_DRIVER_PATCHLEVEL 1 +#define VMWGFX_DRIVER_MINOR 15 +#define VMWGFX_DRIVER_PATCHLEVEL 0 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024) #define VMWGFX_MAX_RELOCATIONS 2048 diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index ac6da0da2824..e825192ca30e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -116,6 +116,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, case DRM_VMW_PARAM_DX: param->value = dev_priv->has_dx; break; + case DRM_VMW_PARAM_SM4_1: + param->value = dev_priv->has_sm4_1; + break; default: return -EINVAL; } diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h index 68ff37d4c035..399f58317cff 100644 --- a/include/uapi/drm/vmwgfx_drm.h +++ b/include/uapi/drm/vmwgfx_drm.h @@ -82,6 +82,9 @@ extern "C" { * * DRM_VMW_PARAM_OVERLAY_IOCTL: * Does the driver support the overlay ioctl. + * + * DRM_VMW_PARAM_SM4_1 + * SM4_1 support is enabled. */ #define DRM_VMW_PARAM_NUM_STREAMS 0 @@ -98,6 +101,7 @@ extern "C" { #define DRM_VMW_PARAM_SCREEN_TARGET 11 #define DRM_VMW_PARAM_DX 12 #define DRM_VMW_PARAM_HW_CAPS2 13 +#define DRM_VMW_PARAM_SM4_1 14 /** * enum drm_vmw_handle_type - handle type for ref ioctls -- cgit v1.2.3 From 2640c3facbd6e21e63c95f19588cc24913a263cd Mon Sep 17 00:00:00 2001 From: shaoyunl Date: Wed, 11 Jul 2018 22:32:50 -0400 Subject: drm/amdkfd: Handle VM faults in KFD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Pre-GFX9 the amdgpu ISR saves the vm-fault status and address per per-vmid. amdkfd needs to get the information from amdgpu through the new get_vm_fault_info interface. On GFX9 and later, all the required information is in the IH ring 2. amdkfd unmaps all queues from the faulting process and create new run-list without the guilty process 3. amdkfd notifies the runtime of the vm fault trap via EVENT_TYPE_MEMORY Signed-off-by: shaoyun liu Signed-off-by: Felix Kuehling Acked-by: Christian König Signed-off-by: Oded Gabbay --- drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c | 25 ++++++++++++--- drivers/gpu/drm/amd/amdkfd/cik_int.h | 2 ++ .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 17 ++++++++++ drivers/gpu/drm/amd/amdkfd/kfd_events.c | 37 ++++++++++++++++++++++ drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c | 18 +++++++++-- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 4 +++ include/uapi/linux/kfd_ioctl.h | 2 +- 7 files changed, 98 insertions(+), 7 deletions(-) (limited to 'include/uapi') diff --git a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c index 49df6c791cfc..cc33870e7edb 100644 --- a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c +++ b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c @@ -48,18 +48,19 @@ static bool cik_event_interrupt_isr(struct kfd_dev *dev, return ihre->source_id == CIK_INTSRC_CP_END_OF_PIPE || ihre->source_id == CIK_INTSRC_SDMA_TRAP || ihre->source_id == CIK_INTSRC_SQ_INTERRUPT_MSG || - ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE; + ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE || + ihre->source_id == CIK_INTSRC_GFX_PAGE_INV_FAULT || + ihre->source_id == CIK_INTSRC_GFX_MEM_PROT_FAULT; } static void cik_event_interrupt_wq(struct kfd_dev *dev, const uint32_t *ih_ring_entry) { - unsigned int pasid; const struct cik_ih_ring_entry *ihre = (const struct cik_ih_ring_entry *)ih_ring_entry; uint32_t context_id = ihre->data & 0xfffffff; - - pasid = (ihre->ring_id & 0xffff0000) >> 16; + unsigned int vmid = (ihre->ring_id & 0x0000ff00) >> 8; + unsigned int pasid = (ihre->ring_id & 0xffff0000) >> 16; if (pasid == 0) return; @@ -72,6 +73,22 @@ static void cik_event_interrupt_wq(struct kfd_dev *dev, kfd_signal_event_interrupt(pasid, context_id & 0xff, 8); else if (ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE) kfd_signal_hw_exception_event(pasid); + else if (ihre->source_id == CIK_INTSRC_GFX_PAGE_INV_FAULT || + ihre->source_id == CIK_INTSRC_GFX_MEM_PROT_FAULT) { + struct kfd_vm_fault_info info; + + kfd_process_vm_fault(dev->dqm, pasid); + + memset(&info, 0, sizeof(info)); + dev->kfd2kgd->get_vm_fault_info(dev->kgd, &info); + if (!info.page_addr && !info.status) + return; + + if (info.vmid == vmid) + kfd_signal_vm_fault_event(dev, pasid, &info); + else + kfd_signal_vm_fault_event(dev, pasid, NULL); + } } const struct kfd_event_interrupt_class event_interrupt_class_cik = { diff --git a/drivers/gpu/drm/amd/amdkfd/cik_int.h b/drivers/gpu/drm/amd/amdkfd/cik_int.h index 109298b9d507..a2079a04a673 100644 --- a/drivers/gpu/drm/amd/amdkfd/cik_int.h +++ b/drivers/gpu/drm/amd/amdkfd/cik_int.h @@ -37,6 +37,8 @@ struct cik_ih_ring_entry { #define CIK_INTSRC_DEQUEUE_COMPLETE 0xC6 #define CIK_INTSRC_SDMA_TRAP 0xE0 #define CIK_INTSRC_SQ_INTERRUPT_MSG 0xEF +#define CIK_INTSRC_GFX_PAGE_INV_FAULT 0x92 +#define CIK_INTSRC_GFX_MEM_PROT_FAULT 0x93 #endif diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index f2f81d26db0c..44fc2038770e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -1684,6 +1684,23 @@ void device_queue_manager_uninit(struct device_queue_manager *dqm) kfree(dqm); } +int kfd_process_vm_fault(struct device_queue_manager *dqm, + unsigned int pasid) +{ + struct kfd_process_device *pdd; + struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); + int ret = 0; + + if (!p) + return -EINVAL; + pdd = kfd_get_process_device_data(dqm->dev, p); + if (pdd) + ret = dqm->ops.evict_process_queues(dqm, &pdd->qpd); + kfd_unref_process(p); + + return ret; +} + #if defined(CONFIG_DEBUG_FS) static void seq_reg_dump(struct seq_file *m, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index 3d5a8332e8c0..b58a0e665ebc 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -963,3 +963,40 @@ void kfd_signal_hw_exception_event(unsigned int pasid) mutex_unlock(&p->event_mutex); kfd_unref_process(p); } + +void kfd_signal_vm_fault_event(struct kfd_dev *dev, unsigned int pasid, + struct kfd_vm_fault_info *info) +{ + struct kfd_event *ev; + uint32_t id; + struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); + struct kfd_hsa_memory_exception_data memory_exception_data; + + if (!p) + return; /* Presumably process exited. */ + memset(&memory_exception_data, 0, sizeof(memory_exception_data)); + memory_exception_data.gpu_id = dev->id; + memory_exception_data.failure.imprecise = 1; + /* Set failure reason */ + if (info) { + memory_exception_data.va = (info->page_addr) << PAGE_SHIFT; + memory_exception_data.failure.NotPresent = + info->prot_valid ? 1 : 0; + memory_exception_data.failure.NoExecute = + info->prot_exec ? 1 : 0; + memory_exception_data.failure.ReadOnly = + info->prot_write ? 1 : 0; + memory_exception_data.failure.imprecise = 0; + } + mutex_lock(&p->event_mutex); + + id = KFD_FIRST_NONSIGNAL_EVENT_ID; + idr_for_each_entry_continue(&p->event_idr, ev, id) + if (ev->type == KFD_EVENT_TYPE_MEMORY) { + ev->memory_exception_data = memory_exception_data; + set_event(ev); + } + + mutex_unlock(&p->event_mutex); + kfd_unref_process(p); +} diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c index 37029baa3346..d6b64e692760 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c @@ -57,7 +57,9 @@ static bool event_interrupt_isr_v9(struct kfd_dev *dev, return source_id == SOC15_INTSRC_CP_END_OF_PIPE || source_id == SOC15_INTSRC_SDMA_TRAP || source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG || - source_id == SOC15_INTSRC_CP_BAD_OPCODE; + source_id == SOC15_INTSRC_CP_BAD_OPCODE || + client_id == SOC15_IH_CLIENTID_VMC || + client_id == SOC15_IH_CLIENTID_UTCL2; } static void event_interrupt_wq_v9(struct kfd_dev *dev, @@ -82,7 +84,19 @@ static void event_interrupt_wq_v9(struct kfd_dev *dev, kfd_signal_hw_exception_event(pasid); else if (client_id == SOC15_IH_CLIENTID_VMC || client_id == SOC15_IH_CLIENTID_UTCL2) { - /* TODO */ + struct kfd_vm_fault_info info = {0}; + uint16_t ring_id = SOC15_RING_ID_FROM_IH_ENTRY(ih_ring_entry); + + info.vmid = vmid; + info.mc_id = client_id; + info.page_addr = ih_ring_entry[4] | + (uint64_t)(ih_ring_entry[5] & 0xf) << 32; + info.prot_valid = ring_id & 0x08; + info.prot_read = ring_id & 0x10; + info.prot_write = ring_id & 0x20; + + kfd_process_vm_fault(dev->dqm, pasid); + kfd_signal_vm_fault_event(dev, pasid, &info); } } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 5e3990bb4c4b..91a3368421b1 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -838,6 +838,7 @@ void device_queue_manager_uninit(struct device_queue_manager *dqm); struct kernel_queue *kernel_queue_init(struct kfd_dev *dev, enum kfd_queue_type type); void kernel_queue_uninit(struct kernel_queue *kq); +int kfd_process_vm_fault(struct device_queue_manager *dqm, unsigned int pasid); /* Process Queue Manager */ struct process_queue_node { @@ -964,6 +965,9 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p, uint64_t *event_page_offset, uint32_t *event_slot_index); int kfd_event_destroy(struct kfd_process *p, uint32_t event_id); +void kfd_signal_vm_fault_event(struct kfd_dev *dev, unsigned int pasid, + struct kfd_vm_fault_info *info); + void kfd_flush_tlb(struct kfd_process_device *pdd); int dbgdev_wave_reset_wavefronts(struct kfd_dev *dev, struct kfd_process *p); diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index b4f5073dbac2..46a54ab1e728 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -219,7 +219,7 @@ struct kfd_memory_exception_failure { __u32 NotPresent; /* Page not present or supervisor privilege */ __u32 ReadOnly; /* Write access to a read-only page */ __u32 NoExecute; /* Execute access to a page marked NX */ - __u32 pad; + __u32 imprecise; /* Can't determine the exact fault address */ }; /* memory exception data*/ -- cgit v1.2.3 From 0c119abad7f0d7987c3ce4ea76b30bde76d0436e Mon Sep 17 00:00:00 2001 From: Shaoyun Liu Date: Wed, 11 Jul 2018 22:32:53 -0400 Subject: drm/amd: Add kfd ioctl defines for hw_exception event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Shaoyun Liu Reviewed-by: Felix Kuehling Signed-off-by: Felix Kuehling Acked-by: Christian König Signed-off-by: Oded Gabbay --- include/uapi/linux/kfd_ioctl.h | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'include/uapi') diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index 46a54ab1e728..88d17c39dbf9 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -189,6 +189,15 @@ struct kfd_ioctl_dbg_wave_control_args { #define KFD_SIGNAL_EVENT_LIMIT 4096 +/* For kfd_event_data.hw_exception_data.reset_type. */ +#define KFD_HW_EXCEPTION_WHOLE_GPU_RESET 0 +#define KFD_HW_EXCEPTION_PER_ENGINE_RESET 1 + +/* For kfd_event_data.hw_exception_data.reset_cause. */ +#define KFD_HW_EXCEPTION_GPU_HANG 0 +#define KFD_HW_EXCEPTION_ECC 1 + + struct kfd_ioctl_create_event_args { __u64 event_page_offset; /* from KFD */ __u32 event_trigger_data; /* from KFD - signal events only */ @@ -230,10 +239,19 @@ struct kfd_hsa_memory_exception_data { __u32 pad; }; -/* Event data*/ +/* hw exception data */ +struct kfd_hsa_hw_exception_data { + uint32_t reset_type; + uint32_t reset_cause; + uint32_t memory_lost; + uint32_t gpu_id; +}; + +/* Event data */ struct kfd_event_data { union { struct kfd_hsa_memory_exception_data memory_exception_data; + struct kfd_hsa_hw_exception_data hw_exception_data; }; /* From KFD */ __u64 kfd_event_data_ext; /* pointer to an extension structure for future exception types */ -- cgit v1.2.3 From ce6058039bca7f1f11f1723549eec1bc069dcb28 Mon Sep 17 00:00:00 2001 From: Ayan Kumar Halder Date: Tue, 10 Jul 2018 14:18:54 +0100 Subject: drm/arm/malidp: Add modifier definitions for describing Arm Framebuffer Compression (AFBC). AFBC is a proprietary lossless image compression protocol and format. It provides fine-grained random access and minimizes the amount of data transferred between IP blocks. AFBC has several features which may be supported and/or used, which are represented using bits in the modifier. Not all combinations are valid, and different devices or use-cases may support different combinations. Changes from v2:- - Added ack by Maarten Lankhorst Signed-off-by: Rosen Zhelev Signed-off-by: Ayan Kumar halder Reviewed-by: Brian Starkey Reviewed-by: Liviu Dudau Reviewed-by: James (Qian) Wang Acked-by: Maarten Lankhorst Link: https://lkml.org/lkml/2018/7/10/360 --- include/uapi/drm/drm_fourcc.h | 83 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) (limited to 'include/uapi') diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index d5e52350a3aa..d43949b5bb3e 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -183,6 +183,7 @@ extern "C" { #define DRM_FORMAT_MOD_VENDOR_QCOM 0x05 #define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06 #define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07 +#define DRM_FORMAT_MOD_VENDOR_ARM 0x08 /* add more to the end as needed */ #define DRM_FORMAT_RESERVED ((1ULL << 56) - 1) @@ -485,6 +486,88 @@ extern "C" { */ #define DRM_FORMAT_MOD_BROADCOM_UIF fourcc_mod_code(BROADCOM, 6) +/* + * Arm Framebuffer Compression (AFBC) modifiers + * + * AFBC is a proprietary lossless image compression protocol and format. + * It provides fine-grained random access and minimizes the amount of data + * transferred between IP blocks. + * + * AFBC has several features which may be supported and/or used, which are + * represented using bits in the modifier. Not all combinations are valid, + * and different devices or use-cases may support different combinations. + */ +#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode) + +/* + * AFBC superblock size + * + * Indicates the superblock size(s) used for the AFBC buffer. The buffer + * size (in pixels) must be aligned to a multiple of the superblock size. + * Four lowest significant bits(LSBs) are reserved for block size. + */ +#define AFBC_FORMAT_MOD_BLOCK_SIZE_MASK 0xf +#define AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 (1ULL) +#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 (2ULL) + +/* + * AFBC lossless colorspace transform + * + * Indicates that the buffer makes use of the AFBC lossless colorspace + * transform. + */ +#define AFBC_FORMAT_MOD_YTR (1ULL << 4) + +/* + * AFBC block-split + * + * Indicates that the payload of each superblock is split. The second + * half of the payload is positioned at a predefined offset from the start + * of the superblock payload. + */ +#define AFBC_FORMAT_MOD_SPLIT (1ULL << 5) + +/* + * AFBC sparse layout + * + * This flag indicates that the payload of each superblock must be stored at a + * predefined position relative to the other superblocks in the same AFBC + * buffer. This order is the same order used by the header buffer. In this mode + * each superblock is given the same amount of space as an uncompressed + * superblock of the particular format would require, rounding up to the next + * multiple of 128 bytes in size. + */ +#define AFBC_FORMAT_MOD_SPARSE (1ULL << 6) + +/* + * AFBC copy-block restrict + * + * Buffers with this flag must obey the copy-block restriction. The restriction + * is such that there are no copy-blocks referring across the border of 8x8 + * blocks. For the subsampled data the 8x8 limitation is also subsampled. + */ +#define AFBC_FORMAT_MOD_CBR (1ULL << 7) + +/* + * AFBC tiled layout + * + * The tiled layout groups superblocks in 8x8 or 4x4 tiles, where all + * superblocks inside a tile are stored together in memory. 8x8 tiles are used + * for pixel formats up to and including 32 bpp while 4x4 tiles are used for + * larger bpp formats. The order between the tiles is scan line. + * When the tiled layout is used, the buffer size (in pixels) must be aligned + * to the tile size. + */ +#define AFBC_FORMAT_MOD_TILED (1ULL << 8) + +/* + * AFBC solid color blocks + * + * Indicates that the buffer makes use of solid-color blocks, whereby bandwidth + * can be reduced if a whole superblock is a single color. + */ +#define AFBC_FORMAT_MOD_SC (1ULL << 9) + #if defined(__cplusplus) } #endif -- cgit v1.2.3 From a7fe68a1e8e4bce007505f729bc33e427c540386 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Sat, 14 Jul 2018 19:05:58 -0400 Subject: drm/amd: Add CU-masking ioctl definition to kfd_ioctl.h Signed-off-by: Felix Kuehling Acked-by: Oded Gabbay Signed-off-by: Oded Gabbay --- include/uapi/linux/kfd_ioctl.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'include/uapi') diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index 88d17c39dbf9..01674b56e14f 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -76,6 +76,12 @@ struct kfd_ioctl_update_queue_args { __u32 queue_priority; /* to KFD */ }; +struct kfd_ioctl_set_cu_mask_args { + __u32 queue_id; /* to KFD */ + __u32 num_cu_mask; /* to KFD */ + __u64 cu_mask_ptr; /* to KFD */ +}; + /* For kfd_ioctl_set_memory_policy_args.default_policy and alternate_policy */ #define KFD_IOC_CACHE_POLICY_COHERENT 0 #define KFD_IOC_CACHE_POLICY_NONCOHERENT 1 @@ -466,7 +472,10 @@ struct kfd_ioctl_unmap_memory_from_gpu_args { #define AMDKFD_IOC_UNMAP_MEMORY_FROM_GPU \ AMDKFD_IOWR(0x19, struct kfd_ioctl_unmap_memory_from_gpu_args) +#define AMDKFD_IOC_SET_CU_MASK \ + AMDKFD_IOW(0x1A, struct kfd_ioctl_set_cu_mask_args) + #define AMDKFD_COMMAND_START 0x01 -#define AMDKFD_COMMAND_END 0x1A +#define AMDKFD_COMMAND_END 0x1B #endif -- cgit v1.2.3 From 964d0fbf6301d3dc8dfad19ffab5a06d002d27f1 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 6 Jul 2018 14:16:54 -0400 Subject: drm/amdgpu: Allow to create BO lists in CS ioctl v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change is to support MESA performace optimization. Modify CS IOCTL to allow its input as command buffer and an array of buffer handles to create a temporay bo list and then destroy it when IOCTL completes. This saves on calling for BO_LIST create and destry IOCTLs in MESA and by this improves performance. v2: Avoid inserting the temp list into idr struct. v3: Remove idr alloation from amdgpu_bo_list_create. Remove useless argument from amdgpu_cs_parser_fini Minor cosmetic stuff. v4: Revert amdgpu_bo_list_destroy back to static Signed-off-by: Andrey Grodzovsky Reviewed-by: Christian König Reviewed-by: Chunming Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 8 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 88 +++++++++++++++++------------ drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 48 +++++++++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 +- include/uapi/drm/amdgpu_drm.h | 1 + 5 files changed, 108 insertions(+), 40 deletions(-) (limited to 'include/uapi') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 53435da158c2..c6c1e8dc919f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -732,6 +732,14 @@ void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list, struct list_head *validated); void amdgpu_bo_list_put(struct amdgpu_bo_list *list); void amdgpu_bo_list_free(struct amdgpu_bo_list *list); +int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in, + struct drm_amdgpu_bo_list_entry **info_param); + +int amdgpu_bo_list_create(struct amdgpu_device *adev, + struct drm_file *filp, + struct drm_amdgpu_bo_list_entry *info, + unsigned num_entries, + struct amdgpu_bo_list **list); /* * GFX stuff diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c index 92be7f6de197..7679c068c89a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c @@ -55,15 +55,15 @@ static void amdgpu_bo_list_release_rcu(struct kref *ref) kfree_rcu(list, rhead); } -static int amdgpu_bo_list_create(struct amdgpu_device *adev, +int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp, struct drm_amdgpu_bo_list_entry *info, unsigned num_entries, - int *id) + struct amdgpu_bo_list **list_out) { - int r; - struct amdgpu_fpriv *fpriv = filp->driver_priv; struct amdgpu_bo_list *list; + int r; + list = kzalloc(sizeof(struct amdgpu_bo_list), GFP_KERNEL); if (!list) @@ -78,16 +78,7 @@ static int amdgpu_bo_list_create(struct amdgpu_device *adev, return r; } - /* idr alloc should be called only after initialization of bo list. */ - mutex_lock(&fpriv->bo_list_lock); - r = idr_alloc(&fpriv->bo_list_handles, list, 1, 0, GFP_KERNEL); - mutex_unlock(&fpriv->bo_list_lock); - if (r < 0) { - amdgpu_bo_list_free(list); - return r; - } - *id = r; - + *list_out = list; return 0; } @@ -263,55 +254,79 @@ void amdgpu_bo_list_free(struct amdgpu_bo_list *list) kfree(list); } -int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data, - struct drm_file *filp) +int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in, + struct drm_amdgpu_bo_list_entry **info_param) { + const void __user *uptr = u64_to_user_ptr(in->bo_info_ptr); const uint32_t info_size = sizeof(struct drm_amdgpu_bo_list_entry); - - struct amdgpu_device *adev = dev->dev_private; - struct amdgpu_fpriv *fpriv = filp->driver_priv; - union drm_amdgpu_bo_list *args = data; - uint32_t handle = args->in.list_handle; - const void __user *uptr = u64_to_user_ptr(args->in.bo_info_ptr); - struct drm_amdgpu_bo_list_entry *info; - struct amdgpu_bo_list *list; - int r; - info = kvmalloc_array(args->in.bo_number, - sizeof(struct drm_amdgpu_bo_list_entry), GFP_KERNEL); + info = kvmalloc_array(in->bo_number, info_size, GFP_KERNEL); if (!info) return -ENOMEM; /* copy the handle array from userspace to a kernel buffer */ r = -EFAULT; - if (likely(info_size == args->in.bo_info_size)) { - unsigned long bytes = args->in.bo_number * - args->in.bo_info_size; + if (likely(info_size == in->bo_info_size)) { + unsigned long bytes = in->bo_number * + in->bo_info_size; if (copy_from_user(info, uptr, bytes)) goto error_free; } else { - unsigned long bytes = min(args->in.bo_info_size, info_size); + unsigned long bytes = min(in->bo_info_size, info_size); unsigned i; - memset(info, 0, args->in.bo_number * info_size); - for (i = 0; i < args->in.bo_number; ++i) { + memset(info, 0, in->bo_number * info_size); + for (i = 0; i < in->bo_number; ++i) { if (copy_from_user(&info[i], uptr, bytes)) goto error_free; - uptr += args->in.bo_info_size; + uptr += in->bo_info_size; } } + *info_param = info; + return 0; + +error_free: + kvfree(info); + return r; +} + +int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_fpriv *fpriv = filp->driver_priv; + union drm_amdgpu_bo_list *args = data; + uint32_t handle = args->in.list_handle; + struct drm_amdgpu_bo_list_entry *info = NULL; + struct amdgpu_bo_list *list; + int r; + + r = amdgpu_bo_create_list_entry_array(&args->in, &info); + if (r) + goto error_free; + switch (args->in.operation) { case AMDGPU_BO_LIST_OP_CREATE: r = amdgpu_bo_list_create(adev, filp, info, args->in.bo_number, - &handle); + &list); if (r) goto error_free; + + mutex_lock(&fpriv->bo_list_lock); + r = idr_alloc(&fpriv->bo_list_handles, list, 1, 0, GFP_KERNEL); + mutex_unlock(&fpriv->bo_list_lock); + if (r < 0) { + amdgpu_bo_list_free(list); + return r; + } + + handle = r; break; case AMDGPU_BO_LIST_OP_DESTROY: @@ -345,6 +360,7 @@ int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data, return 0; error_free: - kvfree(info); + if (info) + kvfree(info); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 5a2a5ba29f9a..6d8df76b5a5d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -66,11 +66,35 @@ static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p, return 0; } -static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) +static int amdgpu_cs_bo_handles_chunk(struct amdgpu_cs_parser *p, + struct drm_amdgpu_bo_list_in *data) +{ + int r; + struct drm_amdgpu_bo_list_entry *info = NULL; + + r = amdgpu_bo_create_list_entry_array(data, &info); + if (r) + return r; + + r = amdgpu_bo_list_create(p->adev, p->filp, info, data->bo_number, + &p->bo_list); + if (r) + goto error_free; + + kvfree(info); + return 0; + +error_free: + if (info) + kvfree(info); + + return r; +} + +static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, union drm_amdgpu_cs *cs) { struct amdgpu_fpriv *fpriv = p->filp->driver_priv; struct amdgpu_vm *vm = &fpriv->vm; - union drm_amdgpu_cs *cs = data; uint64_t *chunk_array_user; uint64_t *chunk_array; unsigned size, num_ibs = 0; @@ -164,6 +188,19 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) break; + case AMDGPU_CHUNK_ID_BO_HANDLES: + size = sizeof(struct drm_amdgpu_bo_list_in); + if (p->chunks[i].length_dw * sizeof(uint32_t) < size) { + ret = -EINVAL; + goto free_partial_kdata; + } + + ret = amdgpu_cs_bo_handles_chunk(p, p->chunks[i].kdata); + if (ret) + goto free_partial_kdata; + + break; + case AMDGPU_CHUNK_ID_DEPENDENCIES: case AMDGPU_CHUNK_ID_SYNCOBJ_IN: case AMDGPU_CHUNK_ID_SYNCOBJ_OUT: @@ -534,7 +571,12 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, INIT_LIST_HEAD(&p->validated); - p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle); + /* p->bo_list could already be assigned if AMDGPU_CHUNK_ID_BO_HANDLES is present */ + if (!p->bo_list) + p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle); + else + mutex_lock(&p->bo_list->lock); + if (p->bo_list) { amdgpu_bo_list_get_list(p->bo_list, &p->validated); if (p->bo_list->first_userptr != p->bo_list->num_entries) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 06aede194bf8..529500c94675 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -69,9 +69,10 @@ * - 3.24.0 - Add high priority compute support for gfx9 * - 3.25.0 - Add support for sensor query info (stable pstate sclk/mclk). * - 3.26.0 - GFX9: Process AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE. + * - 3.27.0 - Add new chunk to to AMDGPU_CS to enable BO_LIST creation. */ #define KMS_DRIVER_MAJOR 3 -#define KMS_DRIVER_MINOR 26 +#define KMS_DRIVER_MINOR 27 #define KMS_DRIVER_PATCHLEVEL 0 int amdgpu_vram_limit = 0; diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 784b0fe470ee..1ceec56de015 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -516,6 +516,7 @@ struct drm_amdgpu_gem_va { #define AMDGPU_CHUNK_ID_DEPENDENCIES 0x03 #define AMDGPU_CHUNK_ID_SYNCOBJ_IN 0x04 #define AMDGPU_CHUNK_ID_SYNCOBJ_OUT 0x05 +#define AMDGPU_CHUNK_ID_BO_HANDLES 0x06 struct drm_amdgpu_cs_chunk { __u32 chunk_id; -- cgit v1.2.3 From 2a8536f6e8464b8988baa7db881f30721616b0da Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran Date: Tue, 5 Jun 2018 19:00:54 -0700 Subject: drm: add msm compressed format modifiers Qualcomm Snapdragon chipsets uses compressed format to optimize BW across multiple IP's. This change adds needed modifier support in drm for a simple 4x4 tile based compressed variants of base formats. Changes in v3: - Removed duplicate entry for DRM_FORMAT_MOD_QCOM_COMPRESSED (Rob Clark) Changes in v4: - Remove all modifiers aside from COMPRESSED, this includes tiled and 10-bit Signed-off-by: Jeykumar Sankaran Signed-off-by: Sean Paul Signed-off-by: Rob Clark --- include/uapi/drm/drm_fourcc.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'include/uapi') diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index d43949b5bb3e..721ab7e54d96 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -299,6 +299,19 @@ extern "C" { */ #define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1) +/* + * Qualcomm Compressed Format + * + * Refers to a compressed variant of the base format that is compressed. + * Implementation may be platform and base-format specific. + * + * Each macrotile consists of m x n (mostly 4 x 4) tiles. + * Pixel data pitch/stride is aligned with macrotile width. + * Pixel data height is aligned with macrotile height. + * Entire pixel data buffer is aligned with 4k(bytes). + */ +#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1) + /* Vivante framebuffer modifiers */ /* -- cgit v1.2.3