diff options
author | Noralf Trønnes <noralf@tronnes.org> | 2019-02-25 09:42:32 -0500 |
---|---|---|
committer | Noralf Trønnes <noralf@tronnes.org> | 2019-03-04 09:32:21 -0500 |
commit | 9d5645ad1b979c99326e13ac51e1826ffe60aaec (patch) | |
tree | 31513f9a5bd35f5b572ef7bdd3d91870607b05a0 | |
parent | 2afd9fcba6b168ab4fa5c38680f98147a745d31c (diff) |
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: Noralf Trønnes <noralf@tronnes.org>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190225144232.20761-8-noralf@tronnes.org
-rw-r--r-- | drivers/gpu/drm/tinydrm/hx8357d.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/tinydrm/ili9225.c | 23 | ||||
-rw-r--r-- | drivers/gpu/drm/tinydrm/ili9341.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/tinydrm/mi0283qt.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/tinydrm/mipi-dbi.c | 42 | ||||
-rw-r--r-- | drivers/gpu/drm/tinydrm/repaper.c | 46 | ||||
-rw-r--r-- | drivers/gpu/drm/tinydrm/st7586.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/tinydrm/st7735r.c | 9 |
8 files changed, 139 insertions, 32 deletions
diff --git a/drivers/gpu/drm/tinydrm/hx8357d.c b/drivers/gpu/drm/tinydrm/hx8357d.c index e9b9e08fafc7..fab961dded87 100644 --- a/drivers/gpu/drm/tinydrm/hx8357d.c +++ b/drivers/gpu/drm/tinydrm/hx8357d.c | |||
@@ -50,13 +50,16 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, | |||
50 | { | 50 | { |
51 | struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); | 51 | struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); |
52 | u8 addr_mode; | 52 | u8 addr_mode; |
53 | int ret; | 53 | int ret, idx; |
54 | |||
55 | if (!drm_dev_enter(pipe->crtc.dev, &idx)) | ||
56 | return; | ||
54 | 57 | ||
55 | DRM_DEBUG_KMS("\n"); | 58 | DRM_DEBUG_KMS("\n"); |
56 | 59 | ||
57 | ret = mipi_dbi_poweron_conditional_reset(mipi); | 60 | ret = mipi_dbi_poweron_conditional_reset(mipi); |
58 | if (ret < 0) | 61 | if (ret < 0) |
59 | return; | 62 | goto out_exit; |
60 | if (ret == 1) | 63 | if (ret == 1) |
61 | goto out_enable; | 64 | goto out_enable; |
62 | 65 | ||
@@ -172,6 +175,8 @@ out_enable: | |||
172 | } | 175 | } |
173 | mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); | 176 | mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); |
174 | mipi_dbi_enable_flush(mipi, crtc_state, plane_state); | 177 | mipi_dbi_enable_flush(mipi, crtc_state, plane_state); |
178 | out_exit: | ||
179 | drm_dev_exit(idx); | ||
175 | } | 180 | } |
176 | 181 | ||
177 | static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = { | 182 | static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = { |
diff --git a/drivers/gpu/drm/tinydrm/ili9225.c b/drivers/gpu/drm/tinydrm/ili9225.c index 4d387a07c48b..0e9fde47b53b 100644 --- a/drivers/gpu/drm/tinydrm/ili9225.c +++ b/drivers/gpu/drm/tinydrm/ili9225.c | |||
@@ -89,13 +89,16 @@ static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) | |||
89 | bool swap = mipi->swap_bytes; | 89 | bool swap = mipi->swap_bytes; |
90 | u16 x_start, y_start; | 90 | u16 x_start, y_start; |
91 | u16 x1, x2, y1, y2; | 91 | u16 x1, x2, y1, y2; |
92 | int ret = 0; | 92 | int idx, ret = 0; |
93 | bool full; | 93 | bool full; |
94 | void *tr; | 94 | void *tr; |
95 | 95 | ||
96 | if (!mipi->enabled) | 96 | if (!mipi->enabled) |
97 | return; | 97 | return; |
98 | 98 | ||
99 | if (!drm_dev_enter(fb->dev, &idx)) | ||
100 | return; | ||
101 | |||
99 | full = width == fb->width && height == fb->height; | 102 | full = width == fb->width && height == fb->height; |
100 | 103 | ||
101 | DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); | 104 | 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) | |||
158 | err_msg: | 161 | err_msg: |
159 | if (ret) | 162 | if (ret) |
160 | dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret); | 163 | dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret); |
164 | |||
165 | drm_dev_exit(idx); | ||
161 | } | 166 | } |
162 | 167 | ||
163 | static void ili9225_pipe_update(struct drm_simple_display_pipe *pipe, | 168 | 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, | |||
191 | .y1 = 0, | 196 | .y1 = 0, |
192 | .y2 = fb->height, | 197 | .y2 = fb->height, |
193 | }; | 198 | }; |
194 | int ret; | 199 | int ret, idx; |
195 | u8 am_id; | 200 | u8 am_id; |
196 | 201 | ||
202 | if (!drm_dev_enter(pipe->crtc.dev, &idx)) | ||
203 | return; | ||
204 | |||
197 | DRM_DEBUG_KMS("\n"); | 205 | DRM_DEBUG_KMS("\n"); |
198 | 206 | ||
199 | mipi_dbi_hw_reset(mipi); | 207 | mipi_dbi_hw_reset(mipi); |
@@ -207,7 +215,7 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
207 | ret = ili9225_command(mipi, ILI9225_POWER_CONTROL_1, 0x0000); | 215 | ret = ili9225_command(mipi, ILI9225_POWER_CONTROL_1, 0x0000); |
208 | if (ret) { | 216 | if (ret) { |
209 | DRM_DEV_ERROR(dev, "Error sending command %d\n", ret); | 217 | DRM_DEV_ERROR(dev, "Error sending command %d\n", ret); |
210 | return; | 218 | goto out_exit; |
211 | } | 219 | } |
212 | ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x0000); | 220 | ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x0000); |
213 | ili9225_command(mipi, ILI9225_POWER_CONTROL_3, 0x0000); | 221 | ili9225_command(mipi, ILI9225_POWER_CONTROL_3, 0x0000); |
@@ -280,6 +288,8 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
280 | 288 | ||
281 | mipi->enabled = true; | 289 | mipi->enabled = true; |
282 | ili9225_fb_dirty(fb, &rect); | 290 | ili9225_fb_dirty(fb, &rect); |
291 | out_exit: | ||
292 | drm_dev_exit(idx); | ||
283 | } | 293 | } |
284 | 294 | ||
285 | static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe) | 295 | 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) | |||
288 | 298 | ||
289 | DRM_DEBUG_KMS("\n"); | 299 | DRM_DEBUG_KMS("\n"); |
290 | 300 | ||
301 | /* | ||
302 | * This callback is not protected by drm_dev_enter/exit since we want to | ||
303 | * turn off the display on regular driver unload. It's highly unlikely | ||
304 | * that the underlying SPI controller is gone should this be called after | ||
305 | * unplug. | ||
306 | */ | ||
307 | |||
291 | if (!mipi->enabled) | 308 | if (!mipi->enabled) |
292 | return; | 309 | return; |
293 | 310 | ||
diff --git a/drivers/gpu/drm/tinydrm/ili9341.c b/drivers/gpu/drm/tinydrm/ili9341.c index 850ce9ed6dd2..d15f85e837ae 100644 --- a/drivers/gpu/drm/tinydrm/ili9341.c +++ b/drivers/gpu/drm/tinydrm/ili9341.c | |||
@@ -56,13 +56,16 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, | |||
56 | { | 56 | { |
57 | struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); | 57 | struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); |
58 | u8 addr_mode; | 58 | u8 addr_mode; |
59 | int ret; | 59 | int ret, idx; |
60 | |||
61 | if (!drm_dev_enter(pipe->crtc.dev, &idx)) | ||
62 | return; | ||
60 | 63 | ||
61 | DRM_DEBUG_KMS("\n"); | 64 | DRM_DEBUG_KMS("\n"); |
62 | 65 | ||
63 | ret = mipi_dbi_poweron_conditional_reset(mipi); | 66 | ret = mipi_dbi_poweron_conditional_reset(mipi); |
64 | if (ret < 0) | 67 | if (ret < 0) |
65 | return; | 68 | goto out_exit; |
66 | if (ret == 1) | 69 | if (ret == 1) |
67 | goto out_enable; | 70 | goto out_enable; |
68 | 71 | ||
@@ -128,6 +131,8 @@ out_enable: | |||
128 | addr_mode |= ILI9341_MADCTL_BGR; | 131 | addr_mode |= ILI9341_MADCTL_BGR; |
129 | mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); | 132 | mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); |
130 | mipi_dbi_enable_flush(mipi, crtc_state, plane_state); | 133 | mipi_dbi_enable_flush(mipi, crtc_state, plane_state); |
134 | out_exit: | ||
135 | drm_dev_exit(idx); | ||
131 | } | 136 | } |
132 | 137 | ||
133 | static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = { | 138 | static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = { |
diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c index 7aee05586e92..c6dc31084a4e 100644 --- a/drivers/gpu/drm/tinydrm/mi0283qt.c +++ b/drivers/gpu/drm/tinydrm/mi0283qt.c | |||
@@ -58,13 +58,16 @@ static void mi0283qt_enable(struct drm_simple_display_pipe *pipe, | |||
58 | { | 58 | { |
59 | struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); | 59 | struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); |
60 | u8 addr_mode; | 60 | u8 addr_mode; |
61 | int ret; | 61 | int ret, idx; |
62 | |||
63 | if (!drm_dev_enter(pipe->crtc.dev, &idx)) | ||
64 | return; | ||
62 | 65 | ||
63 | DRM_DEBUG_KMS("\n"); | 66 | DRM_DEBUG_KMS("\n"); |
64 | 67 | ||
65 | ret = mipi_dbi_poweron_conditional_reset(mipi); | 68 | ret = mipi_dbi_poweron_conditional_reset(mipi); |
66 | if (ret < 0) | 69 | if (ret < 0) |
67 | return; | 70 | goto out_exit; |
68 | if (ret == 1) | 71 | if (ret == 1) |
69 | goto out_enable; | 72 | goto out_enable; |
70 | 73 | ||
@@ -136,6 +139,8 @@ out_enable: | |||
136 | addr_mode |= ILI9341_MADCTL_BGR; | 139 | addr_mode |= ILI9341_MADCTL_BGR; |
137 | mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); | 140 | mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); |
138 | mipi_dbi_enable_flush(mipi, crtc_state, plane_state); | 141 | mipi_dbi_enable_flush(mipi, crtc_state, plane_state); |
142 | out_exit: | ||
143 | drm_dev_exit(idx); | ||
139 | } | 144 | } |
140 | 145 | ||
141 | static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = { | 146 | static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = { |
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c index 5c848f975ebe..34d544f6e52d 100644 --- a/drivers/gpu/drm/tinydrm/mipi-dbi.c +++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c | |||
@@ -220,13 +220,16 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) | |||
220 | unsigned int height = rect->y2 - rect->y1; | 220 | unsigned int height = rect->y2 - rect->y1; |
221 | unsigned int width = rect->x2 - rect->x1; | 221 | unsigned int width = rect->x2 - rect->x1; |
222 | bool swap = mipi->swap_bytes; | 222 | bool swap = mipi->swap_bytes; |
223 | int ret = 0; | 223 | int idx, ret = 0; |
224 | bool full; | 224 | bool full; |
225 | void *tr; | 225 | void *tr; |
226 | 226 | ||
227 | if (!mipi->enabled) | 227 | if (!mipi->enabled) |
228 | return; | 228 | return; |
229 | 229 | ||
230 | if (!drm_dev_enter(fb->dev, &idx)) | ||
231 | return; | ||
232 | |||
230 | full = width == fb->width && height == fb->height; | 233 | full = width == fb->width && height == fb->height; |
231 | 234 | ||
232 | DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); | 235 | 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) | |||
253 | err_msg: | 256 | err_msg: |
254 | if (ret) | 257 | if (ret) |
255 | dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret); | 258 | dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret); |
259 | |||
260 | drm_dev_exit(idx); | ||
256 | } | 261 | } |
257 | 262 | ||
258 | /** | 263 | /** |
@@ -307,10 +312,16 @@ void mipi_dbi_enable_flush(struct mipi_dbi *mipi, | |||
307 | .y1 = 0, | 312 | .y1 = 0, |
308 | .y2 = fb->height, | 313 | .y2 = fb->height, |
309 | }; | 314 | }; |
315 | int idx; | ||
316 | |||
317 | if (!drm_dev_enter(&mipi->drm, &idx)) | ||
318 | return; | ||
310 | 319 | ||
311 | mipi->enabled = true; | 320 | mipi->enabled = true; |
312 | mipi_dbi_fb_dirty(fb, &rect); | 321 | mipi_dbi_fb_dirty(fb, &rect); |
313 | backlight_enable(mipi->backlight); | 322 | backlight_enable(mipi->backlight); |
323 | |||
324 | drm_dev_exit(idx); | ||
314 | } | 325 | } |
315 | EXPORT_SYMBOL(mipi_dbi_enable_flush); | 326 | EXPORT_SYMBOL(mipi_dbi_enable_flush); |
316 | 327 | ||
@@ -320,6 +331,10 @@ static void mipi_dbi_blank(struct mipi_dbi *mipi) | |||
320 | u16 height = drm->mode_config.min_height; | 331 | u16 height = drm->mode_config.min_height; |
321 | u16 width = drm->mode_config.min_width; | 332 | u16 width = drm->mode_config.min_width; |
322 | size_t len = width * height * 2; | 333 | size_t len = width * height * 2; |
334 | int idx; | ||
335 | |||
336 | if (!drm_dev_enter(drm, &idx)) | ||
337 | return; | ||
323 | 338 | ||
324 | memset(mipi->tx_buf, 0, len); | 339 | memset(mipi->tx_buf, 0, len); |
325 | 340 | ||
@@ -329,6 +344,8 @@ static void mipi_dbi_blank(struct mipi_dbi *mipi) | |||
329 | (height >> 8) & 0xFF, (height - 1) & 0xFF); | 344 | (height >> 8) & 0xFF, (height - 1) & 0xFF); |
330 | mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, | 345 | mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, |
331 | (u8 *)mipi->tx_buf, len); | 346 | (u8 *)mipi->tx_buf, len); |
347 | |||
348 | drm_dev_exit(idx); | ||
332 | } | 349 | } |
333 | 350 | ||
334 | /** | 351 | /** |
@@ -343,6 +360,9 @@ void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe) | |||
343 | { | 360 | { |
344 | struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); | 361 | struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); |
345 | 362 | ||
363 | if (!mipi->enabled) | ||
364 | return; | ||
365 | |||
346 | DRM_DEBUG_KMS("\n"); | 366 | DRM_DEBUG_KMS("\n"); |
347 | 367 | ||
348 | mipi->enabled = false; | 368 | mipi->enabled = false; |
@@ -991,11 +1011,16 @@ static ssize_t mipi_dbi_debugfs_command_write(struct file *file, | |||
991 | u8 val, cmd = 0, parameters[64]; | 1011 | u8 val, cmd = 0, parameters[64]; |
992 | char *buf, *pos, *token; | 1012 | char *buf, *pos, *token; |
993 | unsigned int i; | 1013 | unsigned int i; |
994 | int ret; | 1014 | int ret, idx; |
1015 | |||
1016 | if (!drm_dev_enter(&mipi->drm, &idx)) | ||
1017 | return -ENODEV; | ||
995 | 1018 | ||
996 | buf = memdup_user_nul(ubuf, count); | 1019 | buf = memdup_user_nul(ubuf, count); |
997 | if (IS_ERR(buf)) | 1020 | if (IS_ERR(buf)) { |
998 | return PTR_ERR(buf); | 1021 | ret = PTR_ERR(buf); |
1022 | goto err_exit; | ||
1023 | } | ||
999 | 1024 | ||
1000 | /* strip trailing whitespace */ | 1025 | /* strip trailing whitespace */ |
1001 | for (i = count - 1; i > 0; i--) | 1026 | for (i = count - 1; i > 0; i--) |
@@ -1031,6 +1056,8 @@ static ssize_t mipi_dbi_debugfs_command_write(struct file *file, | |||
1031 | 1056 | ||
1032 | err_free: | 1057 | err_free: |
1033 | kfree(buf); | 1058 | kfree(buf); |
1059 | err_exit: | ||
1060 | drm_dev_exit(idx); | ||
1034 | 1061 | ||
1035 | return ret < 0 ? ret : count; | 1062 | return ret < 0 ? ret : count; |
1036 | } | 1063 | } |
@@ -1039,8 +1066,11 @@ static int mipi_dbi_debugfs_command_show(struct seq_file *m, void *unused) | |||
1039 | { | 1066 | { |
1040 | struct mipi_dbi *mipi = m->private; | 1067 | struct mipi_dbi *mipi = m->private; |
1041 | u8 cmd, val[4]; | 1068 | u8 cmd, val[4]; |
1069 | int ret, idx; | ||
1042 | size_t len; | 1070 | size_t len; |
1043 | int ret; | 1071 | |
1072 | if (!drm_dev_enter(&mipi->drm, &idx)) | ||
1073 | return -ENODEV; | ||
1044 | 1074 | ||
1045 | for (cmd = 0; cmd < 255; cmd++) { | 1075 | for (cmd = 0; cmd < 255; cmd++) { |
1046 | if (!mipi_dbi_command_is_read(mipi, cmd)) | 1076 | 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) | |||
1071 | seq_printf(m, "%*phN\n", (int)len, val); | 1101 | seq_printf(m, "%*phN\n", (int)len, val); |
1072 | } | 1102 | } |
1073 | 1103 | ||
1104 | drm_dev_exit(idx); | ||
1105 | |||
1074 | return 0; | 1106 | return 0; |
1075 | } | 1107 | } |
1076 | 1108 | ||
diff --git a/drivers/gpu/drm/tinydrm/repaper.c b/drivers/gpu/drm/tinydrm/repaper.c index b1acf5aebe32..3f3632457079 100644 --- a/drivers/gpu/drm/tinydrm/repaper.c +++ b/drivers/gpu/drm/tinydrm/repaper.c | |||
@@ -533,8 +533,14 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb) | |||
533 | struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; | 533 | struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; |
534 | struct repaper_epd *epd = drm_to_epd(fb->dev); | 534 | struct repaper_epd *epd = drm_to_epd(fb->dev); |
535 | struct drm_rect clip; | 535 | struct drm_rect clip; |
536 | int idx, ret = 0; | ||
536 | u8 *buf = NULL; | 537 | u8 *buf = NULL; |
537 | int ret = 0; | 538 | |
539 | if (!epd->enabled) | ||
540 | return 0; | ||
541 | |||
542 | if (!drm_dev_enter(fb->dev, &idx)) | ||
543 | return -ENODEV; | ||
538 | 544 | ||
539 | /* repaper can't do partial updates */ | 545 | /* repaper can't do partial updates */ |
540 | clip.x1 = 0; | 546 | clip.x1 = 0; |
@@ -542,17 +548,16 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb) | |||
542 | clip.y1 = 0; | 548 | clip.y1 = 0; |
543 | clip.y2 = fb->height; | 549 | clip.y2 = fb->height; |
544 | 550 | ||
545 | if (!epd->enabled) | ||
546 | return 0; | ||
547 | |||
548 | repaper_get_temperature(epd); | 551 | repaper_get_temperature(epd); |
549 | 552 | ||
550 | DRM_DEBUG("Flushing [FB:%d] st=%ums\n", fb->base.id, | 553 | DRM_DEBUG("Flushing [FB:%d] st=%ums\n", fb->base.id, |
551 | epd->factored_stage_time); | 554 | epd->factored_stage_time); |
552 | 555 | ||
553 | buf = kmalloc_array(fb->width, fb->height, GFP_KERNEL); | 556 | buf = kmalloc_array(fb->width, fb->height, GFP_KERNEL); |
554 | if (!buf) | 557 | if (!buf) { |
555 | return -ENOMEM; | 558 | ret = -ENOMEM; |
559 | goto out_exit; | ||
560 | } | ||
556 | 561 | ||
557 | if (import_attach) { | 562 | if (import_attach) { |
558 | ret = dma_buf_begin_cpu_access(import_attach->dmabuf, | 563 | ret = dma_buf_begin_cpu_access(import_attach->dmabuf, |
@@ -621,6 +626,8 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb) | |||
621 | 626 | ||
622 | out_free: | 627 | out_free: |
623 | kfree(buf); | 628 | kfree(buf); |
629 | out_exit: | ||
630 | drm_dev_exit(idx); | ||
624 | 631 | ||
625 | return ret; | 632 | return ret; |
626 | } | 633 | } |
@@ -650,7 +657,10 @@ static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
650 | struct spi_device *spi = epd->spi; | 657 | struct spi_device *spi = epd->spi; |
651 | struct device *dev = &spi->dev; | 658 | struct device *dev = &spi->dev; |
652 | bool dc_ok = false; | 659 | bool dc_ok = false; |
653 | int i, ret; | 660 | int i, ret, idx; |
661 | |||
662 | if (!drm_dev_enter(pipe->crtc.dev, &idx)) | ||
663 | return; | ||
654 | 664 | ||
655 | DRM_DEBUG_DRIVER("\n"); | 665 | DRM_DEBUG_DRIVER("\n"); |
656 | 666 | ||
@@ -689,7 +699,7 @@ static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
689 | if (!i) { | 699 | if (!i) { |
690 | DRM_DEV_ERROR(dev, "timeout waiting for panel to become ready.\n"); | 700 | DRM_DEV_ERROR(dev, "timeout waiting for panel to become ready.\n"); |
691 | power_off(epd); | 701 | power_off(epd); |
692 | return; | 702 | goto out_exit; |
693 | } | 703 | } |
694 | 704 | ||
695 | repaper_read_id(spi); | 705 | repaper_read_id(spi); |
@@ -700,7 +710,7 @@ static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
700 | else | 710 | else |
701 | dev_err(dev, "wrong COG ID 0x%02x\n", ret); | 711 | dev_err(dev, "wrong COG ID 0x%02x\n", ret); |
702 | power_off(epd); | 712 | power_off(epd); |
703 | return; | 713 | goto out_exit; |
704 | } | 714 | } |
705 | 715 | ||
706 | /* Disable OE */ | 716 | /* Disable OE */ |
@@ -713,7 +723,7 @@ static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
713 | else | 723 | else |
714 | DRM_DEV_ERROR(dev, "panel is reported broken\n"); | 724 | DRM_DEV_ERROR(dev, "panel is reported broken\n"); |
715 | power_off(epd); | 725 | power_off(epd); |
716 | return; | 726 | goto out_exit; |
717 | } | 727 | } |
718 | 728 | ||
719 | /* Power saving mode */ | 729 | /* Power saving mode */ |
@@ -753,7 +763,7 @@ static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
753 | if (ret < 0) { | 763 | if (ret < 0) { |
754 | DRM_DEV_ERROR(dev, "failed to read chip (%d)\n", ret); | 764 | DRM_DEV_ERROR(dev, "failed to read chip (%d)\n", ret); |
755 | power_off(epd); | 765 | power_off(epd); |
756 | return; | 766 | goto out_exit; |
757 | } | 767 | } |
758 | 768 | ||
759 | if (ret & 0x40) { | 769 | if (ret & 0x40) { |
@@ -765,7 +775,7 @@ static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
765 | if (!dc_ok) { | 775 | if (!dc_ok) { |
766 | DRM_DEV_ERROR(dev, "dc/dc failed\n"); | 776 | DRM_DEV_ERROR(dev, "dc/dc failed\n"); |
767 | power_off(epd); | 777 | power_off(epd); |
768 | return; | 778 | goto out_exit; |
769 | } | 779 | } |
770 | 780 | ||
771 | /* | 781 | /* |
@@ -776,6 +786,8 @@ static void repaper_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
776 | 786 | ||
777 | epd->enabled = true; | 787 | epd->enabled = true; |
778 | epd->partial = false; | 788 | epd->partial = false; |
789 | out_exit: | ||
790 | drm_dev_exit(idx); | ||
779 | } | 791 | } |
780 | 792 | ||
781 | static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe) | 793 | static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe) |
@@ -784,6 +796,16 @@ static void repaper_pipe_disable(struct drm_simple_display_pipe *pipe) | |||
784 | struct spi_device *spi = epd->spi; | 796 | struct spi_device *spi = epd->spi; |
785 | unsigned int line; | 797 | unsigned int line; |
786 | 798 | ||
799 | /* | ||
800 | * This callback is not protected by drm_dev_enter/exit since we want to | ||
801 | * turn off the display on regular driver unload. It's highly unlikely | ||
802 | * that the underlying SPI controller is gone should this be called after | ||
803 | * unplug. | ||
804 | */ | ||
805 | |||
806 | if (!epd->enabled) | ||
807 | return; | ||
808 | |||
787 | DRM_DEBUG_DRIVER("\n"); | 809 | DRM_DEBUG_DRIVER("\n"); |
788 | 810 | ||
789 | epd->enabled = false; | 811 | epd->enabled = false; |
diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c index 6e92de809b63..d99957bac532 100644 --- a/drivers/gpu/drm/tinydrm/st7586.c +++ b/drivers/gpu/drm/tinydrm/st7586.c | |||
@@ -119,12 +119,14 @@ static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb, | |||
119 | static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) | 119 | static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) |
120 | { | 120 | { |
121 | struct mipi_dbi *mipi = drm_to_mipi_dbi(fb->dev); | 121 | struct mipi_dbi *mipi = drm_to_mipi_dbi(fb->dev); |
122 | int start, end; | 122 | int start, end, idx, ret = 0; |
123 | int ret = 0; | ||
124 | 123 | ||
125 | if (!mipi->enabled) | 124 | if (!mipi->enabled) |
126 | return; | 125 | return; |
127 | 126 | ||
127 | if (!drm_dev_enter(fb->dev, &idx)) | ||
128 | return; | ||
129 | |||
128 | /* 3 pixels per byte, so grow clip to nearest multiple of 3 */ | 130 | /* 3 pixels per byte, so grow clip to nearest multiple of 3 */ |
129 | rect->x1 = rounddown(rect->x1, 3); | 131 | rect->x1 = rounddown(rect->x1, 3); |
130 | rect->x2 = roundup(rect->x2, 3); | 132 | rect->x2 = roundup(rect->x2, 3); |
@@ -152,6 +154,8 @@ static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) | |||
152 | err_msg: | 154 | err_msg: |
153 | if (ret) | 155 | if (ret) |
154 | dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret); | 156 | dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret); |
157 | |||
158 | drm_dev_exit(idx); | ||
155 | } | 159 | } |
156 | 160 | ||
157 | static void st7586_pipe_update(struct drm_simple_display_pipe *pipe, | 161 | static void st7586_pipe_update(struct drm_simple_display_pipe *pipe, |
@@ -184,14 +188,17 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
184 | .y1 = 0, | 188 | .y1 = 0, |
185 | .y2 = fb->height, | 189 | .y2 = fb->height, |
186 | }; | 190 | }; |
187 | int ret; | 191 | int idx, ret; |
188 | u8 addr_mode; | 192 | u8 addr_mode; |
189 | 193 | ||
194 | if (!drm_dev_enter(pipe->crtc.dev, &idx)) | ||
195 | return; | ||
196 | |||
190 | DRM_DEBUG_KMS("\n"); | 197 | DRM_DEBUG_KMS("\n"); |
191 | 198 | ||
192 | ret = mipi_dbi_poweron_reset(mipi); | 199 | ret = mipi_dbi_poweron_reset(mipi); |
193 | if (ret) | 200 | if (ret) |
194 | return; | 201 | goto out_exit; |
195 | 202 | ||
196 | mipi_dbi_command(mipi, ST7586_AUTO_READ_CTRL, 0x9f); | 203 | mipi_dbi_command(mipi, ST7586_AUTO_READ_CTRL, 0x9f); |
197 | mipi_dbi_command(mipi, ST7586_OTP_RW_CTRL, 0x00); | 204 | mipi_dbi_command(mipi, ST7586_OTP_RW_CTRL, 0x00); |
@@ -244,12 +251,21 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
244 | st7586_fb_dirty(fb, &rect); | 251 | st7586_fb_dirty(fb, &rect); |
245 | 252 | ||
246 | mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON); | 253 | mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON); |
254 | out_exit: | ||
255 | drm_dev_exit(idx); | ||
247 | } | 256 | } |
248 | 257 | ||
249 | static void st7586_pipe_disable(struct drm_simple_display_pipe *pipe) | 258 | static void st7586_pipe_disable(struct drm_simple_display_pipe *pipe) |
250 | { | 259 | { |
251 | struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); | 260 | struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); |
252 | 261 | ||
262 | /* | ||
263 | * This callback is not protected by drm_dev_enter/exit since we want to | ||
264 | * turn off the display on regular driver unload. It's highly unlikely | ||
265 | * that the underlying SPI controller is gone should this be called after | ||
266 | * unplug. | ||
267 | */ | ||
268 | |||
253 | DRM_DEBUG_KMS("\n"); | 269 | DRM_DEBUG_KMS("\n"); |
254 | 270 | ||
255 | if (!mipi->enabled) | 271 | if (!mipi->enabled) |
diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c index 0f8a346026ac..022e9849b95b 100644 --- a/drivers/gpu/drm/tinydrm/st7735r.c +++ b/drivers/gpu/drm/tinydrm/st7735r.c | |||
@@ -44,14 +44,17 @@ static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
44 | struct drm_plane_state *plane_state) | 44 | struct drm_plane_state *plane_state) |
45 | { | 45 | { |
46 | struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); | 46 | struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); |
47 | int ret; | 47 | int ret, idx; |
48 | u8 addr_mode; | 48 | u8 addr_mode; |
49 | 49 | ||
50 | if (!drm_dev_enter(pipe->crtc.dev, &idx)) | ||
51 | return; | ||
52 | |||
50 | DRM_DEBUG_KMS("\n"); | 53 | DRM_DEBUG_KMS("\n"); |
51 | 54 | ||
52 | ret = mipi_dbi_poweron_reset(mipi); | 55 | ret = mipi_dbi_poweron_reset(mipi); |
53 | if (ret) | 56 | if (ret) |
54 | return; | 57 | goto out_exit; |
55 | 58 | ||
56 | msleep(150); | 59 | msleep(150); |
57 | 60 | ||
@@ -102,6 +105,8 @@ static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
102 | msleep(20); | 105 | msleep(20); |
103 | 106 | ||
104 | mipi_dbi_enable_flush(mipi, crtc_state, plane_state); | 107 | mipi_dbi_enable_flush(mipi, crtc_state, plane_state); |
108 | out_exit: | ||
109 | drm_dev_exit(idx); | ||
105 | } | 110 | } |
106 | 111 | ||
107 | static const struct drm_simple_display_pipe_funcs jd_t18003_t01_pipe_funcs = { | 112 | static const struct drm_simple_display_pipe_funcs jd_t18003_t01_pipe_funcs = { |