Commit b8f0009b authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-fixes-2022-06-30' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes



A NULL pointer dereference fix for vc4, and 3 patches to improve the
sysfb device behaviour when removing conflicting framebuffers

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Maxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20220630072404.2fa4z3nk5h5q34ci@houat
parents 078a3be7 ee7a69aa
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -13,6 +13,12 @@ EDD Interfaces
.. kernel-doc:: drivers/firmware/edd.c
   :internal:

Generic System Framebuffers Interface
-------------------------------------

.. kernel-doc:: drivers/firmware/sysfb.c
   :export:

Intel Stratix10 SoC Service Layer
---------------------------------
Some features of the Intel Stratix10 SoC require a level of privilege
+50 −8
Original line number Diff line number Diff line
@@ -34,21 +34,59 @@
#include <linux/screen_info.h>
#include <linux/sysfb.h>

static struct platform_device *pd;
static DEFINE_MUTEX(disable_lock);
static bool disabled;

static bool sysfb_unregister(void)
{
	if (IS_ERR_OR_NULL(pd))
		return false;

	platform_device_unregister(pd);
	pd = NULL;

	return true;
}

/**
 * sysfb_disable() - disable the Generic System Framebuffers support
 *
 * This disables the registration of system framebuffer devices that match the
 * generic drivers that make use of the system framebuffer set up by firmware.
 *
 * It also unregisters a device if this was already registered by sysfb_init().
 *
 * Context: The function can sleep. A @disable_lock mutex is acquired to serialize
 *          against sysfb_init(), that registers a system framebuffer device.
 */
void sysfb_disable(void)
{
	mutex_lock(&disable_lock);
	sysfb_unregister();
	disabled = true;
	mutex_unlock(&disable_lock);
}
EXPORT_SYMBOL_GPL(sysfb_disable);

static __init int sysfb_init(void)
{
	struct screen_info *si = &screen_info;
	struct simplefb_platform_data mode;
	struct platform_device *pd;
	const char *name;
	bool compatible;
	int ret;
	int ret = 0;

	mutex_lock(&disable_lock);
	if (disabled)
		goto unlock_mutex;

	/* try to create a simple-framebuffer device */
	compatible = sysfb_parse_mode(si, &mode);
	if (compatible) {
		ret = sysfb_create_simplefb(si, &mode);
		if (!ret)
			return 0;
		pd = sysfb_create_simplefb(si, &mode);
		if (!IS_ERR(pd))
			goto unlock_mutex;
	}

	/* if the FB is incompatible, create a legacy framebuffer device */
@@ -60,8 +98,10 @@ static __init int sysfb_init(void)
		name = "platform-framebuffer";

	pd = platform_device_alloc(name, 0);
	if (!pd)
		return -ENOMEM;
	if (!pd) {
		ret = -ENOMEM;
		goto unlock_mutex;
	}

	sysfb_apply_efi_quirks(pd);

@@ -73,9 +113,11 @@ static __init int sysfb_init(void)
	if (ret)
		goto err;

	return 0;
	goto unlock_mutex;
err:
	platform_device_put(pd);
unlock_mutex:
	mutex_unlock(&disable_lock);
	return ret;
}

+8 −8
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ __init bool sysfb_parse_mode(const struct screen_info *si,
	return false;
}

__init int sysfb_create_simplefb(const struct screen_info *si,
__init struct platform_device *sysfb_create_simplefb(const struct screen_info *si,
						     const struct simplefb_platform_data *mode)
{
	struct platform_device *pd;
@@ -76,7 +76,7 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
		base |= (u64)si->ext_lfb_base << 32;
	if (!base || (u64)(resource_size_t)base != base) {
		printk(KERN_DEBUG "sysfb: inaccessible VRAM base\n");
		return -EINVAL;
		return ERR_PTR(-EINVAL);
	}

	/*
@@ -93,7 +93,7 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
	length = mode->height * mode->stride;
	if (length > size) {
		printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n");
		return -EINVAL;
		return ERR_PTR(-EINVAL);
	}
	length = PAGE_ALIGN(length);

@@ -104,11 +104,11 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
	res.start = base;
	res.end = res.start + length - 1;
	if (res.end <= res.start)
		return -EINVAL;
		return ERR_PTR(-EINVAL);

	pd = platform_device_alloc("simple-framebuffer", 0);
	if (!pd)
		return -ENOMEM;
		return ERR_PTR(-ENOMEM);

	sysfb_apply_efi_quirks(pd);

@@ -124,10 +124,10 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
	if (ret)
		goto err_put_device;

	return 0;
	return pd;

err_put_device:
	platform_device_put(pd);

	return ret;
	return ERR_PTR(ret);
}
+6 −3
Original line number Diff line number Diff line
@@ -17,12 +17,15 @@

void vc4_perfmon_get(struct vc4_perfmon *perfmon)
{
	struct vc4_dev *vc4 = perfmon->dev;
	struct vc4_dev *vc4;

	if (!perfmon)
		return;

	vc4 = perfmon->dev;
	if (WARN_ON_ONCE(vc4->is_vc5))
		return;

	if (perfmon)
	refcount_inc(&perfmon->refcnt);
}

+12 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/sysfb.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/vt.h>
@@ -1752,6 +1753,17 @@ int remove_conflicting_framebuffers(struct apertures_struct *a,
		do_free = true;
	}

	/*
	 * If a driver asked to unregister a platform device registered by
	 * sysfb, then can be assumed that this is a driver for a display
	 * that is set up by the system firmware and has a generic driver.
	 *
	 * Drivers for devices that don't have a generic driver will never
	 * ask for this, so let's assume that a real driver for the display
	 * was already probed and prevent sysfb to register devices later.
	 */
	sysfb_disable();

	mutex_lock(&registration_lock);
	do_remove_conflicting_framebuffers(a, name, primary);
	mutex_unlock(&registration_lock);
Loading