Commit 9d5645ad authored by Noralf Trønnes's avatar Noralf Trønnes
Browse files

drm/tinydrm: Use drm_dev_enter/exit()



This protects device resources from use after device removal.

There are 3 ways for driver-device unbinding to happen:
- The driver module is unloaded causing the driver to be unregistered.
  This can't happen as long as there are open file handles because a
  reference is taken on the module.
- The device is removed (Device Tree overlay unloading).
  This can happen at any time.
- The driver sysfs unbind file can be used to unbind the driver from the
  device. This can happen any time.

v2: Since drm_atomic_helper_shutdown() has to be called after
    drm_dev_unplug() we don't want do block ->disable after unplug.

Signed-off-by: default avatarNoralf Trønnes <noralf@tronnes.org>
Acked-by: default avatarGerd Hoffmann <kraxel@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190225144232.20761-8-noralf@tronnes.org
parent 2afd9fcb
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -50,13 +50,16 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe,
{
	struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev);
	u8 addr_mode;
	int ret;
	int ret, idx;

	if (!drm_dev_enter(pipe->crtc.dev, &idx))
		return;

	DRM_DEBUG_KMS("\n");

	ret = mipi_dbi_poweron_conditional_reset(mipi);
	if (ret < 0)
		return;
		goto out_exit;
	if (ret == 1)
		goto out_enable;

@@ -172,6 +175,8 @@ out_enable:
	}
	mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
	mipi_dbi_enable_flush(mipi, crtc_state, plane_state);
out_exit:
	drm_dev_exit(idx);
}

static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = {
+20 −3
Original line number Diff line number Diff line
@@ -89,13 +89,16 @@ static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
	bool swap = mipi->swap_bytes;
	u16 x_start, y_start;
	u16 x1, x2, y1, y2;
	int ret = 0;
	int idx, ret = 0;
	bool full;
	void *tr;

	if (!mipi->enabled)
		return;

	if (!drm_dev_enter(fb->dev, &idx))
		return;

	full = width == fb->width && height == fb->height;

	DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
@@ -158,6 +161,8 @@ static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
err_msg:
	if (ret)
		dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);

	drm_dev_exit(idx);
}

static void ili9225_pipe_update(struct drm_simple_display_pipe *pipe,
@@ -191,9 +196,12 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
		.y1 = 0,
		.y2 = fb->height,
	};
	int ret;
	int ret, idx;
	u8 am_id;

	if (!drm_dev_enter(pipe->crtc.dev, &idx))
		return;

	DRM_DEBUG_KMS("\n");

	mipi_dbi_hw_reset(mipi);
@@ -207,7 +215,7 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
	ret = ili9225_command(mipi, ILI9225_POWER_CONTROL_1, 0x0000);
	if (ret) {
		DRM_DEV_ERROR(dev, "Error sending command %d\n", ret);
		return;
		goto out_exit;
	}
	ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x0000);
	ili9225_command(mipi, ILI9225_POWER_CONTROL_3, 0x0000);
@@ -280,6 +288,8 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,

	mipi->enabled = true;
	ili9225_fb_dirty(fb, &rect);
out_exit:
	drm_dev_exit(idx);
}

static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe)
@@ -288,6 +298,13 @@ static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe)

	DRM_DEBUG_KMS("\n");

	/*
	 * This callback is not protected by drm_dev_enter/exit since we want to
	 * turn off the display on regular driver unload. It's highly unlikely
	 * that the underlying SPI controller is gone should this be called after
	 * unplug.
	 */

	if (!mipi->enabled)
		return;

+7 −2
Original line number Diff line number Diff line
@@ -56,13 +56,16 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe,
{
	struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev);
	u8 addr_mode;
	int ret;
	int ret, idx;

	if (!drm_dev_enter(pipe->crtc.dev, &idx))
		return;

	DRM_DEBUG_KMS("\n");

	ret = mipi_dbi_poweron_conditional_reset(mipi);
	if (ret < 0)
		return;
		goto out_exit;
	if (ret == 1)
		goto out_enable;

@@ -128,6 +131,8 @@ out_enable:
	addr_mode |= ILI9341_MADCTL_BGR;
	mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
	mipi_dbi_enable_flush(mipi, crtc_state, plane_state);
out_exit:
	drm_dev_exit(idx);
}

static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = {
+7 −2
Original line number Diff line number Diff line
@@ -58,13 +58,16 @@ static void mi0283qt_enable(struct drm_simple_display_pipe *pipe,
{
	struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev);
	u8 addr_mode;
	int ret;
	int ret, idx;

	if (!drm_dev_enter(pipe->crtc.dev, &idx))
		return;

	DRM_DEBUG_KMS("\n");

	ret = mipi_dbi_poweron_conditional_reset(mipi);
	if (ret < 0)
		return;
		goto out_exit;
	if (ret == 1)
		goto out_enable;

@@ -136,6 +139,8 @@ out_enable:
	addr_mode |= ILI9341_MADCTL_BGR;
	mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
	mipi_dbi_enable_flush(mipi, crtc_state, plane_state);
out_exit:
	drm_dev_exit(idx);
}

static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = {
+37 −5
Original line number Diff line number Diff line
@@ -220,13 +220,16 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
	unsigned int height = rect->y2 - rect->y1;
	unsigned int width = rect->x2 - rect->x1;
	bool swap = mipi->swap_bytes;
	int ret = 0;
	int idx, ret = 0;
	bool full;
	void *tr;

	if (!mipi->enabled)
		return;

	if (!drm_dev_enter(fb->dev, &idx))
		return;

	full = width == fb->width && height == fb->height;

	DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
@@ -253,6 +256,8 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
err_msg:
	if (ret)
		dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);

	drm_dev_exit(idx);
}

/**
@@ -307,10 +312,16 @@ void mipi_dbi_enable_flush(struct mipi_dbi *mipi,
		.y1 = 0,
		.y2 = fb->height,
	};
	int idx;

	if (!drm_dev_enter(&mipi->drm, &idx))
		return;

	mipi->enabled = true;
	mipi_dbi_fb_dirty(fb, &rect);
	backlight_enable(mipi->backlight);

	drm_dev_exit(idx);
}
EXPORT_SYMBOL(mipi_dbi_enable_flush);

@@ -320,6 +331,10 @@ static void mipi_dbi_blank(struct mipi_dbi *mipi)
	u16 height = drm->mode_config.min_height;
	u16 width = drm->mode_config.min_width;
	size_t len = width * height * 2;
	int idx;

	if (!drm_dev_enter(drm, &idx))
		return;

	memset(mipi->tx_buf, 0, len);

@@ -329,6 +344,8 @@ static void mipi_dbi_blank(struct mipi_dbi *mipi)
			 (height >> 8) & 0xFF, (height - 1) & 0xFF);
	mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START,
			     (u8 *)mipi->tx_buf, len);

	drm_dev_exit(idx);
}

/**
@@ -343,6 +360,9 @@ void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe)
{
	struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev);

	if (!mipi->enabled)
		return;

	DRM_DEBUG_KMS("\n");

	mipi->enabled = false;
@@ -991,11 +1011,16 @@ static ssize_t mipi_dbi_debugfs_command_write(struct file *file,
	u8 val, cmd = 0, parameters[64];
	char *buf, *pos, *token;
	unsigned int i;
	int ret;
	int ret, idx;

	if (!drm_dev_enter(&mipi->drm, &idx))
		return -ENODEV;

	buf = memdup_user_nul(ubuf, count);
	if (IS_ERR(buf))
		return PTR_ERR(buf);
	if (IS_ERR(buf)) {
		ret = PTR_ERR(buf);
		goto err_exit;
	}

	/* strip trailing whitespace */
	for (i = count - 1; i > 0; i--)
@@ -1031,6 +1056,8 @@ static ssize_t mipi_dbi_debugfs_command_write(struct file *file,

err_free:
	kfree(buf);
err_exit:
	drm_dev_exit(idx);

	return ret < 0 ? ret : count;
}
@@ -1039,8 +1066,11 @@ static int mipi_dbi_debugfs_command_show(struct seq_file *m, void *unused)
{
	struct mipi_dbi *mipi = m->private;
	u8 cmd, val[4];
	int ret, idx;
	size_t len;
	int ret;

	if (!drm_dev_enter(&mipi->drm, &idx))
		return -ENODEV;

	for (cmd = 0; cmd < 255; cmd++) {
		if (!mipi_dbi_command_is_read(mipi, cmd))
@@ -1071,6 +1101,8 @@ static int mipi_dbi_debugfs_command_show(struct seq_file *m, void *unused)
		seq_printf(m, "%*phN\n", (int)len, val);
	}

	drm_dev_exit(idx);

	return 0;
}

Loading