Snap for 10103804 from 9b05077bc12b7b13ad680bfaec35ddd3cff5dd93 to mainline-tzdata5-release

Change-Id: I1c48506ffb6ed31d3eb6c785fef21864a9dc0f5c
diff --git a/amdgpu.c b/amdgpu.c
index 5c891de..a3f5e45 100644
--- a/amdgpu.c
+++ b/amdgpu.c
@@ -10,6 +10,7 @@
 #include <drm_fourcc.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -345,6 +346,18 @@
 	return true;
 }
 
+static void amdgpu_preload(bool load)
+{
+	static void *handle;
+
+	if (load && !handle)
+		handle = dri_dlopen(DRI_PATH);
+	else if (!load && handle) {
+		dri_dlclose(handle);
+		handle = NULL;
+	}
+}
+
 static int amdgpu_init(struct driver *drv)
 {
 	struct amdgpu_priv *priv;
@@ -505,26 +518,44 @@
 				   uint64_t use_flags)
 {
 	int ret;
-	size_t num_planes;
+	uint32_t stride_align = 1;
 	uint32_t plane, stride;
 	union drm_amdgpu_gem_create gem_create = { { 0 } };
 	struct amdgpu_priv *priv = bo->drv->priv;
 
 	stride = drv_stride_from_format(format, width, 0);
-	num_planes = drv_num_planes_from_format(format);
 
-	/*
-	 * For multiplane formats, align the stride to 512 to ensure that subsample strides are 256
-	 * aligned. This uses more memory than necessary since the first plane only needs to be
-	 * 256 aligned, but it's acceptable for a short-term fix. It's probably safe for other gpu
-	 * families, but let's restrict it to Raven and Stoney for now (b/171013552, b/190484589).
-	 * This only applies to the Android YUV (multiplane) format.
-	 * */
-	if (format == DRM_FORMAT_YVU420_ANDROID && (priv->dev_info.family == AMDGPU_FAMILY_RV ||
-						    priv->dev_info.family == AMDGPU_FAMILY_CZ))
-		stride = ALIGN(stride, 512);
-	else
-		stride = ALIGN(stride, 256);
+	if (use_flags & BO_USE_HW_MASK) {
+		/* GFX9+ requires the stride to be aligned to 256 bytes */
+		stride_align = 256;
+		stride = ALIGN(stride, stride_align);
+
+		/* Android YV12 requires the UV stride to be half of the Y
+		 * stride.  Before GFX10, we can double the alignment for the
+		 * Y stride, which makes sure the UV stride is still aligned
+		 * to 256 bytes after halving.
+		 *
+		 * GFX10+ additionally requires the stride to be as small as
+		 * possible.  It is impossible to support the format in some
+		 * cases.  Instead, we force DRM_FORMAT_YVU420 and knowingly
+		 * vioate Android YV12 stride requirement.  This is done
+		 * because
+		 *
+		 *  - we would like to know what breaks, and
+		 *  - when used as a classic resource by virglrenderer, the
+		 *    requirement hopefully does not matter
+		 */
+		bool double_align = format == DRM_FORMAT_YVU420_ANDROID;
+		if (double_align && priv->dev_info.family >= AMDGPU_FAMILY_NV &&
+		    (use_flags & BO_USE_GPU_HW) && ((stride / stride_align) & 1)) {
+			drv_loge("allocating %dx%d YV12 bo (usage 0x%" PRIx64 ") with bad strides",
+				 width, height, use_flags);
+			format = DRM_FORMAT_YVU420;
+			double_align = false;
+		}
+		if (double_align)
+			stride = ALIGN(stride, stride_align * 2);
+	}
 
 	/*
 	 * Currently, allocator used by chrome aligns the height for Encoder/
@@ -536,7 +567,7 @@
 	if (use_flags & (BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER))
 		height = ALIGN(height, CHROME_HEIGHT_ALIGN);
 
-	drv_bo_from_format(bo, stride, height, format);
+	drv_bo_from_format(bo, stride, stride_align, height, format);
 
 	gem_create.in.bo_size =
 	    ALIGN(bo->meta.total_size, priv->dev_info.virtual_address_alignment);
@@ -651,19 +682,19 @@
 		return drv_gem_bo_destroy(bo);
 }
 
-static void *amdgpu_map_bo(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+static void *amdgpu_map_bo(struct bo *bo, struct vma *vma, uint32_t map_flags)
 {
 	void *addr = MAP_FAILED;
 	int ret;
 	union drm_amdgpu_gem_mmap gem_map = { { 0 } };
 	struct drm_amdgpu_gem_create_in bo_info = { 0 };
 	struct drm_amdgpu_gem_op gem_op = { 0 };
-	uint32_t handle = bo->handles[plane].u32;
+	uint32_t handle = bo->handles[0].u32;
 	struct amdgpu_linear_vma_priv *priv = NULL;
 	struct amdgpu_priv *drv_priv;
 
 	if (bo->priv)
-		return dri_bo_map(bo, vma, plane, map_flags);
+		return dri_bo_map(bo, vma, 0, map_flags);
 
 	drv_priv = bo->drv->priv;
 	gem_op.handle = handle;
@@ -788,6 +819,7 @@
 
 const struct backend backend_amdgpu = {
 	.name = "amdgpu",
+	.preload = amdgpu_preload,
 	.init = amdgpu_init,
 	.close = amdgpu_close,
 	.bo_create = amdgpu_create_bo,
diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc
index a67b811..a714798 100644
--- a/cros_gralloc/cros_gralloc_driver.cc
+++ b/cros_gralloc/cros_gralloc_driver.cc
@@ -26,6 +26,22 @@
 // DRM Card nodes start at 0
 #define DRM_CARD_NODE_START 0
 
+class cros_gralloc_driver_preloader
+{
+      public:
+	cros_gralloc_driver_preloader()
+	{
+		drv_preload(true);
+	}
+
+	~cros_gralloc_driver_preloader()
+	{
+		drv_preload(false);
+	}
+};
+
+static class cros_gralloc_driver_preloader cros_gralloc_driver_preloader;
+
 int memfd_create_wrapper(const char *name, unsigned int flags)
 {
 	int fd;
@@ -164,6 +180,7 @@
 	struct combination *combo;
 
 	if (mt8183_camera_quirk_ && (descriptor->use_flags & BO_USE_CAMERA_READ) &&
+	    !(descriptor->use_flags & BO_USE_SCANOUT) &&
 	    descriptor->drm_format == DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED) {
 		*out_use_flags = descriptor->use_flags;
 		*out_format = DRM_FORMAT_MTISP_SXYZW10;
diff --git a/cros_gralloc/cros_gralloc_helpers.cc b/cros_gralloc/cros_gralloc_helpers.cc
index a7c024c..8c86c66 100644
--- a/cros_gralloc/cros_gralloc_helpers.cc
+++ b/cros_gralloc/cros_gralloc_helpers.cc
@@ -56,10 +56,7 @@
 	 * equal to their size in bytes.
 	 */
 	case HAL_PIXEL_FORMAT_BLOB:
-	/*
-	 * TODO(b/259551816): re-enable after ANGLE and SwiftShader are updated.
-	 * case HAL_PIXEL_FORMAT_R8:
-	 */
+	case HAL_PIXEL_FORMAT_R8:
 		return DRM_FORMAT_R8;
 	case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
 		return DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED;
diff --git a/dri.c b/dri.c
index 5a37c46..5a30a77 100644
--- a/dri.c
+++ b/dri.c
@@ -190,6 +190,16 @@
 	.base = { __DRI_USE_INVALIDATE, 1 },
 };
 
+void *dri_dlopen(const char *dri_so_path)
+{
+	return dlopen(dri_so_path, RTLD_NOW | RTLD_GLOBAL);
+}
+
+void dri_dlclose(void *dri_so_handle)
+{
+	dlclose(dri_so_handle);
+}
+
 /*
  * The caller is responsible for setting drv->priv to a structure that derives from dri_driver.
  */
@@ -209,7 +219,7 @@
 	if (dri->fd < 0)
 		return -ENODEV;
 
-	dri->driver_handle = dlopen(dri_so_path, RTLD_NOW | RTLD_GLOBAL);
+	dri->driver_handle = dri_dlopen(dri_so_path);
 	if (!dri->driver_handle)
 		goto close_dri_fd;
 
@@ -257,7 +267,7 @@
 free_screen:
 	dri->core_extension->destroyScreen(dri->device);
 free_handle:
-	dlclose(dri->driver_handle);
+	dri_dlclose(dri->driver_handle);
 	dri->driver_handle = NULL;
 close_dri_fd:
 	close(dri->fd);
@@ -273,7 +283,7 @@
 
 	dri->core_extension->destroyContext(dri->context);
 	dri->core_extension->destroyScreen(dri->device);
-	dlclose(dri->driver_handle);
+	dri_dlclose(dri->driver_handle);
 	dri->driver_handle = NULL;
 	close(dri->fd);
 }
diff --git a/dri.h b/dri.h
index daadf30..8136f5c 100644
--- a/dri.h
+++ b/dri.h
@@ -26,6 +26,9 @@
 	const __DRIconfig **configs;
 };
 
+void *dri_dlopen(const char *dri_so_path);
+void dri_dlclose(void *dri_so_handle);
+
 int dri_init(struct driver *drv, const char *dri_so_path, const char *driver_suffix);
 void dri_close(struct driver *drv);
 int dri_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
diff --git a/drv.c b/drv.c
index 462b763..cbd7b4b 100644
--- a/drv.c
+++ b/drv.c
@@ -52,6 +52,35 @@
 extern const struct backend backend_udl;
 extern const struct backend backend_vkms;
 
+static const struct backend *drv_backend_list[] = {
+#ifdef DRV_AMDGPU
+	&backend_amdgpu,
+#endif
+#ifdef DRV_I915
+	&backend_i915,
+#endif
+#ifdef DRV_MSM
+	&backend_msm,
+#endif
+#ifdef DRV_VC4
+	&backend_vc4,
+#endif
+	&backend_evdi,	    &backend_komeda,	&backend_marvell, &backend_mediatek,
+	&backend_meson,	    &backend_nouveau,	&backend_radeon,  &backend_rockchip,
+	&backend_sun4i_drm, &backend_synaptics, &backend_udl,	  &backend_virtgpu,
+	&backend_vkms
+};
+
+void drv_preload(bool load)
+{
+	unsigned int i;
+	for (i = 0; i < ARRAY_SIZE(drv_backend_list); i++) {
+		const struct backend *b = drv_backend_list[i];
+		if (b->preload)
+			b->preload(load);
+	}
+}
+
 static const struct backend *drv_get_backend(int fd)
 {
 	drmVersionPtr drm_version;
@@ -62,27 +91,8 @@
 	if (!drm_version)
 		return NULL;
 
-	const struct backend *backend_list[] = {
-#ifdef DRV_AMDGPU
-		&backend_amdgpu,
-#endif
-#ifdef DRV_I915
-		&backend_i915,
-#endif
-#ifdef DRV_MSM
-		&backend_msm,
-#endif
-#ifdef DRV_VC4
-		&backend_vc4,
-#endif
-		&backend_evdi,	    &backend_komeda,	&backend_marvell, &backend_mediatek,
-		&backend_meson,	    &backend_nouveau,	&backend_radeon,  &backend_rockchip,
-		&backend_sun4i_drm, &backend_synaptics, &backend_udl,	  &backend_virtgpu,
-		&backend_vkms
-	};
-
-	for (i = 0; i < ARRAY_SIZE(backend_list); i++) {
-		const struct backend *b = backend_list[i];
+	for (i = 0; i < ARRAY_SIZE(drv_backend_list); i++) {
+		const struct backend *b = drv_backend_list[i];
 		if (!strcmp(drm_version->name, b->name)) {
 			drmFreeVersion(drm_version);
 			return b;
@@ -513,7 +523,7 @@
 	}
 
 	memcpy(mapping.vma->map_strides, bo->meta.strides, sizeof(mapping.vma->map_strides));
-	addr = drv->backend->bo_map(bo, mapping.vma, plane, map_flags);
+	addr = drv->backend->bo_map(bo, mapping.vma, map_flags);
 	if (addr == MAP_FAILED) {
 		*map_data = NULL;
 		free(mapping.vma);
diff --git a/drv.h b/drv.h
index 7e6316c..b824fc5 100644
--- a/drv.h
+++ b/drv.h
@@ -131,6 +131,8 @@
 	uint32_t refcount;
 };
 
+void drv_preload(bool load);
+
 struct driver *drv_create(int fd);
 
 void drv_destroy(struct driver *drv);
diff --git a/drv_helpers.c b/drv_helpers.c
index f4df4df..cd51881 100644
--- a/drv_helpers.c
+++ b/drv_helpers.c
@@ -250,18 +250,30 @@
 	return stride * drv_height_from_format(format, height, plane);
 }
 
-static uint32_t subsample_stride(uint32_t stride, uint32_t format, size_t plane)
+static uint32_t subsample_stride(uint32_t stride, uint32_t stride_align, uint32_t format,
+				 size_t plane)
 {
+	uint32_t plane_stride = stride;
+
 	if (plane != 0) {
 		switch (format) {
 		case DRM_FORMAT_YVU420:
 		case DRM_FORMAT_YVU420_ANDROID:
-			stride = DIV_ROUND_UP(stride, 2);
+			plane_stride = DIV_ROUND_UP(plane_stride, 2);
 			break;
 		}
 	}
 
-	return stride;
+	plane_stride = ALIGN(plane_stride, stride_align);
+
+	if (format == DRM_FORMAT_YVU420_ANDROID) {
+		if (plane != 0)
+			assert(plane_stride == ALIGN(stride / 2, 16));
+		else
+			assert(plane_stride % 16 == 0);
+	}
+
+	return plane_stride;
 }
 
 /*
@@ -269,14 +281,17 @@
  * the first plane, height and a format. This function assumes there is just
  * one kernel buffer per buffer object.
  */
-int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t aligned_height, uint32_t format)
+int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t stride_align,
+		       uint32_t aligned_height, uint32_t format)
 {
 	uint32_t padding[DRV_MAX_PLANES] = { 0 };
-	return drv_bo_from_format_and_padding(bo, stride, aligned_height, format, padding);
+	return drv_bo_from_format_and_padding(bo, stride, stride_align, aligned_height, format,
+					      padding);
 }
 
-int drv_bo_from_format_and_padding(struct bo *bo, uint32_t stride, uint32_t aligned_height,
-				   uint32_t format, uint32_t padding[DRV_MAX_PLANES])
+int drv_bo_from_format_and_padding(struct bo *bo, uint32_t stride, uint32_t stride_align,
+				   uint32_t aligned_height, uint32_t format,
+				   uint32_t padding[DRV_MAX_PLANES])
 {
 	size_t p, num_planes;
 	uint32_t offset = 0;
@@ -287,16 +302,18 @@
 	/*
 	 * HAL_PIXEL_FORMAT_YV12 requires that (see <system/graphics.h>):
 	 *  - the aligned height is same as the buffer's height.
-	 *  - the chroma stride is 16 bytes aligned, i.e., the luma's strides
-	 *    is 32 bytes aligned.
+	 *  - the luma stride is 16 bytes aligned
+	 *  - the chroma stride is ALIGN(luma_stride / 2, 16)
 	 */
 	if (format == DRM_FORMAT_YVU420_ANDROID) {
 		assert(aligned_height == bo->meta.height);
-		assert(stride == ALIGN(stride, 32));
+		/* force 16 if the caller has no requirement */
+		if (stride_align <= 1)
+			stride_align = 16;
 	}
 
 	for (p = 0; p < num_planes; p++) {
-		bo->meta.strides[p] = subsample_stride(stride, format, p);
+		bo->meta.strides[p] = subsample_stride(stride, stride_align, format, p);
 		bo->meta.sizes[p] =
 		    drv_size_from_format(format, bo->meta.strides[p], aligned_height, p) +
 		    padding[p];
@@ -368,7 +385,7 @@
 		return -errno;
 	}
 
-	drv_bo_from_format(bo, create_dumb.pitch, height, format);
+	drv_bo_from_format(bo, create_dumb.pitch, 1, height, format);
 
 	for (plane = 0; plane < bo->meta.num_planes; plane++)
 		bo->handles[plane].u32 = create_dumb.handle;
@@ -459,14 +476,14 @@
 	return 0;
 }
 
-void *drv_dumb_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+void *drv_dumb_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
 {
 	int ret;
 	size_t i;
 	struct drm_mode_map_dumb map_dumb;
 
 	memset(&map_dumb, 0, sizeof(map_dumb));
-	map_dumb.handle = bo->handles[plane].u32;
+	map_dumb.handle = bo->handles[0].u32;
 
 	ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb);
 	if (ret) {
@@ -475,8 +492,7 @@
 	}
 
 	for (i = 0; i < bo->meta.num_planes; i++)
-		if (bo->handles[i].u32 == bo->handles[plane].u32)
-			vma->length += bo->meta.sizes[i];
+		vma->length += bo->meta.sizes[i];
 
 	return mmap(0, vma->length, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
 		    map_dumb.offset);
diff --git a/drv_helpers.h b/drv_helpers.h
index edb69bf..0ea9ba9 100644
--- a/drv_helpers.h
+++ b/drv_helpers.h
@@ -21,9 +21,11 @@
 uint32_t drv_height_from_format(uint32_t format, uint32_t height, size_t plane);
 uint32_t drv_vertical_subsampling_from_format(uint32_t format, size_t plane);
 uint32_t drv_size_from_format(uint32_t format, uint32_t stride, uint32_t height, size_t plane);
-int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t aligned_height, uint32_t format);
-int drv_bo_from_format_and_padding(struct bo *bo, uint32_t stride, uint32_t aligned_height,
-				   uint32_t format, uint32_t padding[DRV_MAX_PLANES]);
+int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t stride_align,
+		       uint32_t aligned_height, uint32_t format);
+int drv_bo_from_format_and_padding(struct bo *bo, uint32_t stride, uint32_t stride_align,
+				   uint32_t aligned_height, uint32_t format,
+				   uint32_t padding[DRV_MAX_PLANES]);
 int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
 		       uint64_t use_flags);
 int drv_dumb_bo_create_ex(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
@@ -31,7 +33,7 @@
 int drv_dumb_bo_destroy(struct bo *bo);
 int drv_gem_bo_destroy(struct bo *bo);
 int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data);
-void *drv_dumb_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags);
+void *drv_dumb_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags);
 int drv_bo_munmap(struct bo *bo, struct vma *vma);
 int drv_get_prot(uint32_t map_flags);
 void drv_add_combination(struct driver *drv, uint32_t format, struct format_metadata *metadata,
diff --git a/drv_priv.h b/drv_priv.h
index d674876..a2ccdda 100644
--- a/drv_priv.h
+++ b/drv_priv.h
@@ -74,6 +74,7 @@
 
 struct backend {
 	char *name;
+	void (*preload)(bool load);
 	int (*init)(struct driver *drv);
 	void (*close)(struct driver *drv);
 	int (*bo_create)(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
@@ -90,7 +91,7 @@
 	/* Called on free if this bo is the last object referencing the contained GEM BOs */
 	int (*bo_destroy)(struct bo *bo);
 	int (*bo_import)(struct bo *bo, struct drv_import_fd_data *data);
-	void *(*bo_map)(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags);
+	void *(*bo_map)(struct bo *bo, struct vma *vma, uint32_t map_flags);
 	int (*bo_unmap)(struct bo *bo, struct vma *vma);
 	int (*bo_invalidate)(struct bo *bo, struct mapping *mapping);
 	int (*bo_flush)(struct bo *bo, struct mapping *mapping);
@@ -115,10 +116,12 @@
 #define BO_USE_SW_MASK (BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | \
 			BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY | BO_USE_FRONT_RENDERING)
 
+#define BO_USE_GPU_HW (BO_USE_RENDERING | BO_USE_TEXTURE | BO_USE_GPU_DATA_BUFFER)
+
 #define BO_USE_NON_GPU_HW (BO_USE_SCANOUT | BO_USE_CAMERA_WRITE | BO_USE_CAMERA_READ | \
 			   BO_USE_HW_VIDEO_ENCODER | BO_USE_HW_VIDEO_DECODER | BO_USE_SENSOR_DIRECT_DATA)
 
-#define BO_USE_HW_MASK	(BO_USE_NON_GPU_HW | BO_USE_RENDERING | BO_USE_TEXTURE | BO_USE_GPU_DATA_BUFFER)
+#define BO_USE_HW_MASK	(BO_USE_GPU_HW | BO_USE_NON_GPU_HW)
 
 #ifndef DRM_FORMAT_MOD_LINEAR
 #define DRM_FORMAT_MOD_LINEAR DRM_FORMAT_MOD_NONE
diff --git a/i915.c b/i915.c
index 4a33151..8619580 100644
--- a/i915.c
+++ b/i915.c
@@ -62,6 +62,7 @@
 	/*TODO : cleanup is_mtl to avoid adding variables for every new platforms */
 	bool is_mtl;
 	int32_t num_fences_avail;
+	bool has_mmap_offset;
 };
 
 static void i915_info_from_device_id(struct i915_device *i915)
@@ -412,7 +413,7 @@
 
 static int i915_init(struct driver *drv)
 {
-	int ret;
+	int ret, val;
 	struct i915_device *i915;
 	drm_i915_getparam_t get_param = { 0 };
 
@@ -449,9 +450,22 @@
 	ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
 	if (ret) {
 		drv_loge("Failed to get I915_PARAM_NUM_FENCES_AVAIL\n");
+		free(i915);
 		return -EINVAL;
 	}
 
+	memset(&get_param, 0, sizeof(get_param));
+	get_param.param = I915_PARAM_MMAP_GTT_VERSION;
+	get_param.value = &val;
+
+	ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param);
+	if (ret) {
+		drv_loge("Failed to get I915_PARAM_MMAP_GTT_VERSION\n");
+		free(i915);
+		return -EINVAL;
+	}
+	i915->has_mmap_offset = (val >= 4);
+
 	if (i915->graphics_version >= 12)
 		i915->has_hw_protection = 1;
 
@@ -616,7 +630,7 @@
 		 * aligning to 32 bytes here.
 		 */
 		uint32_t stride = ALIGN(width, 32);
-		return drv_bo_from_format(bo, stride, height, format);
+		return drv_bo_from_format(bo, stride, 1, height, format);
 	} else if (modifier == I915_FORMAT_MOD_Y_TILED_CCS) {
 		/*
 		 * For compressed surfaces, we need a color control surface
@@ -799,10 +813,11 @@
 	return 0;
 }
 
-static void *i915_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+static void *i915_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
 {
 	int ret;
 	void *addr = MAP_FAILED;
+	struct i915_device *i915 = bo->drv->priv;
 
 	if ((bo->meta.format_modifier == I915_FORMAT_MOD_Y_TILED_CCS) ||
 	    (bo->meta.format_modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS) ||
@@ -810,34 +825,46 @@
 		return MAP_FAILED;
 
 	if (bo->meta.tiling == I915_TILING_NONE) {
-		struct drm_i915_gem_mmap gem_map = { 0 };
-		/* TODO(b/118799155): We don't seem to have a good way to
-		 * detect the use cases for which WC mapping is really needed.
-		 * The current heuristic seems overly coarse and may be slowing
-		 * down some other use cases unnecessarily.
-		 *
-		 * For now, care must be taken not to use WC mappings for
-		 * Renderscript and camera use cases, as they're
-		 * performance-sensitive. */
-		if ((bo->meta.use_flags & BO_USE_SCANOUT) &&
-		    !(bo->meta.use_flags &
-		      (BO_USE_RENDERSCRIPT | BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)))
-			gem_map.flags = I915_MMAP_WC;
+		if (i915->has_mmap_offset) {
+			struct drm_i915_gem_mmap_offset gem_map = { 0 };
+			gem_map.handle = bo->handles[0].u32;
+			gem_map.flags = I915_MMAP_OFFSET_WB;
 
-		gem_map.handle = bo->handles[0].u32;
-		gem_map.offset = 0;
-		gem_map.size = bo->meta.total_size;
+			/* Get the fake offset back */
+			ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP_OFFSET, &gem_map);
+			if (ret == 0)
+				addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags),
+					    MAP_SHARED, bo->drv->fd, gem_map.offset);
+		} else {
+			struct drm_i915_gem_mmap gem_map = { 0 };
+			/* TODO(b/118799155): We don't seem to have a good way to
+			 * detect the use cases for which WC mapping is really needed.
+			 * The current heuristic seems overly coarse and may be slowing
+			 * down some other use cases unnecessarily.
+			 *
+			 * For now, care must be taken not to use WC mappings for
+			 * Renderscript and camera use cases, as they're
+			 * performance-sensitive. */
+			if ((bo->meta.use_flags & BO_USE_SCANOUT) &&
+			    !(bo->meta.use_flags &
+			      (BO_USE_RENDERSCRIPT | BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)))
+				gem_map.flags = I915_MMAP_WC;
 
-		ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_map);
-		/* DRM_IOCTL_I915_GEM_MMAP mmaps the underlying shm
-		 * file and returns a user space address directly, ie,
-		 * doesn't go through mmap. If we try that on a
-		 * dma-buf that doesn't have a shm file, i915.ko
-		 * returns ENXIO.  Fall through to
-		 * DRM_IOCTL_I915_GEM_MMAP_GTT in that case, which
-		 * will mmap on the drm fd instead. */
-		if (ret == 0)
-			addr = (void *)(uintptr_t)gem_map.addr_ptr;
+			gem_map.handle = bo->handles[0].u32;
+			gem_map.offset = 0;
+			gem_map.size = bo->meta.total_size;
+
+			ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_map);
+			/* DRM_IOCTL_I915_GEM_MMAP mmaps the underlying shm
+			 * file and returns a user space address directly, ie,
+			 * doesn't go through mmap. If we try that on a
+			 * dma-buf that doesn't have a shm file, i915.ko
+			 * returns ENXIO.  Fall through to
+			 * DRM_IOCTL_I915_GEM_MMAP_GTT in that case, which
+			 * will mmap on the drm fd instead. */
+			if (ret == 0)
+				addr = (void *)(uintptr_t)gem_map.addr_ptr;
+		}
 	}
 
 	if (addr == MAP_FAILED) {
diff --git a/mediatek.c b/mediatek.c
index f161b7d..113273b 100644
--- a/mediatek.c
+++ b/mediatek.c
@@ -201,7 +201,7 @@
 					 (32 / drv_vertical_subsampling_from_format(format, plane));
 		}
 
-		drv_bo_from_format_and_padding(bo, stride, aligned_height, format, padding);
+		drv_bo_from_format_and_padding(bo, stride, 1, aligned_height, format, padding);
 	} else {
 #ifdef SUPPORTS_YUV422
 		/*
@@ -212,7 +212,7 @@
 		if (format == DRM_FORMAT_NV12)
 			height = ALIGN(height, 16);
 #endif
-		drv_bo_from_format(bo, stride, height, format);
+		drv_bo_from_format(bo, stride, 1, height, format);
 
 #ifdef USE_EXTRA_PADDING_FOR_YVU420
 		/*
@@ -266,7 +266,7 @@
 						 ARRAY_SIZE(modifiers));
 }
 
-static void *mediatek_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+static void *mediatek_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
 {
 	int ret, prime_fd;
 	struct drm_mtk_gem_map_off gem_map = { 0 };
diff --git a/minigbm_helpers.c b/minigbm_helpers.c
index f91707c..d1da7c4 100644
--- a/minigbm_helpers.c
+++ b/minigbm_helpers.c
@@ -211,7 +211,7 @@
 	return 0;
 }
 
-PUBLIC int gbm_get_default_device_fd(void)
+static int gbm_get_default_device_fd(void)
 {
 	DIR *dir;
 	int ret, fd, dfd = -1;
@@ -329,6 +329,11 @@
 		if (fd >= 0) {
 			struct gbm_device *gbm = gbm_create_device(fd);
 			if (gbm) {
+				// DRM master might be taken by accident on a primary node even
+				// if master is not needed for GBM. Drop it so that programs
+				// that actually need DRM master (e.g. Chrome) won't be blocked.
+				if (type == DRM_NODE_PRIMARY && drmIsMaster(fd))
+					drmDropMaster(fd);
 				*out_fd = fd;
 				return gbm;
 			}
diff --git a/minigbm_helpers.h b/minigbm_helpers.h
index 500d97e..dbbb644 100644
--- a/minigbm_helpers.h
+++ b/minigbm_helpers.h
@@ -36,13 +36,7 @@
 				struct gbm_device_info *info);
 
 /*
- * Select "default" device to use for graphics memory allocator.
- */
-int gbm_get_default_device_fd(void);
-
-/*
- * Create "default" gbm device.  This can pick a different DRM device than
- * gbm_get_default_device_fd and should be preferred in most cases.
+ * Create "default" gbm device.
  */
 struct gbm_device *minigbm_create_default_device(int *out_fd);
 
diff --git a/msm.c b/msm.c
index 3a02f5d..0e86d95 100644
--- a/msm.c
+++ b/msm.c
@@ -151,7 +151,7 @@
 		stride = drv_stride_from_format(bo->meta.format, alignw, 0);
 
 		/* Calculate size and assign stride, size, offset to each plane based on format */
-		drv_bo_from_format(bo, stride, alignh, bo->meta.format);
+		drv_bo_from_format(bo, stride, 1, alignh, bo->meta.format);
 
 		/* For all RGB UBWC formats */
 		if (bo->meta.tiling == MSM_UBWC_TILING) {
@@ -352,7 +352,7 @@
 	return msm_bo_create_for_modifier(bo, width, height, format, combo->metadata.modifier);
 }
 
-static void *msm_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+static void *msm_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
 {
 	int ret;
 	struct drm_msm_gem_info req = { 0 };
diff --git a/rockchip.c b/rockchip.c
index 17478f3..2dc7146 100644
--- a/rockchip.c
+++ b/rockchip.c
@@ -136,7 +136,7 @@
 		uint32_t aligned_width = w_mbs * 16;
 		uint32_t aligned_height = h_mbs * 16;
 
-		drv_bo_from_format(bo, aligned_width, aligned_height, format);
+		drv_bo_from_format(bo, aligned_width, 1, aligned_height, format);
 		/*
 		 * drv_bo_from_format updates total_size. Add an extra data space for rockchip video
 		 * driver to store motion vectors.
@@ -166,7 +166,7 @@
 		else
 			stride = ALIGN(stride, 64);
 
-		drv_bo_from_format(bo, stride, height, format);
+		drv_bo_from_format(bo, stride, 1, height, format);
 	}
 
 	gem_create.size = bo->meta.total_size;
@@ -192,7 +192,7 @@
 						 ARRAY_SIZE(modifiers));
 }
 
-static void *rockchip_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+static void *rockchip_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
 {
 	int ret;
 	struct rockchip_private_map_data *priv;
diff --git a/vc4.c b/vc4.c
index 48f0870..d53fabf 100644
--- a/vc4.c
+++ b/vc4.c
@@ -64,7 +64,7 @@
 	 */
 	stride = drv_stride_from_format(format, width, 0);
 	stride = ALIGN(stride, 64);
-	drv_bo_from_format(bo, stride, height, format);
+	drv_bo_from_format(bo, stride, 1, height, format);
 
 	bo_create.size = bo->meta.total_size;
 
@@ -105,7 +105,7 @@
 	return vc4_bo_create_for_modifier(bo, width, height, format, modifier);
 }
 
-static void *vc4_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+static void *vc4_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
 {
 	int ret;
 	struct drm_vc4_mmap_bo bo_map = { 0 };
diff --git a/virtgpu_cross_domain.c b/virtgpu_cross_domain.c
index b94a4ae..45b5580 100644
--- a/virtgpu_cross_domain.c
+++ b/virtgpu_cross_domain.c
@@ -410,7 +410,7 @@
 	return 0;
 }
 
-static void *cross_domain_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+static void *cross_domain_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
 {
 	int ret;
 	struct drm_virtgpu_map gem_map = { 0 };
diff --git a/virtgpu_virgl.c b/virtgpu_virgl.c
index 22d4ee3..9474c40 100644
--- a/virtgpu_virgl.c
+++ b/virtgpu_virgl.c
@@ -455,7 +455,7 @@
 
 	if (virgl_supports_combination_natively(bo->drv, format, use_flags)) {
 		stride = drv_stride_from_format(format, width, 0);
-		drv_bo_from_format(bo, stride, height, format);
+		drv_bo_from_format(bo, stride, 1, height, format);
 	} else {
 		assert(virgl_supports_combination_through_emulation(bo->drv, format, use_flags));
 
@@ -505,7 +505,7 @@
 	return 0;
 }
 
-static void *virgl_3d_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+static void *virgl_3d_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
 {
 	int ret;
 	struct drm_virtgpu_map gem_map = { 0 };
@@ -696,7 +696,7 @@
 
 	cur_blob_id = atomic_fetch_add(&priv->next_blob_id, 1);
 	stride = drv_stride_from_format(bo->meta.format, bo->meta.width, 0);
-	drv_bo_from_format(bo, stride, bo->meta.height, bo->meta.format);
+	drv_bo_from_format(bo, stride, 1, bo->meta.height, bo->meta.format);
 	bo->meta.total_size = ALIGN(bo->meta.total_size, PAGE_SIZE);
 	bo->meta.tiling = blob_flags;
 
@@ -797,12 +797,12 @@
 		return drv_dumb_bo_destroy(bo);
 }
 
-static void *virgl_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
+static void *virgl_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags)
 {
 	if (params[param_3d].value)
-		return virgl_3d_bo_map(bo, vma, plane, map_flags);
+		return virgl_3d_bo_map(bo, vma, map_flags);
 	else
-		return drv_dumb_bo_map(bo, vma, plane, map_flags);
+		return drv_dumb_bo_map(bo, vma, map_flags);
 }
 
 static bool is_arc_screen_capture_bo(struct bo *bo)