Message ID | 20190125150300.33268-1-noralf@tronnes.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/fb-helper: generic: Fix drm_fbdev_client_restore() | expand |
> Fix by using drm_fb_helper_lastclose() which checks if fbdev is in use. > static int drm_fbdev_client_restore(struct drm_client_dev *client) > { > - struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); > - > - drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper); > + drm_fb_helper_lastclose(client->dev); > > return 0; > } Hmm, at least the drm_fb_helper_lastclose() version I'm looking at (branch drm-misc-next) just calls drm_fb_helper_restore_fbdev_mode_unlocked without any check ... cheers, Gerd
Den 28.01.2019 07.48, skrev Gerd Hoffmann: >> Fix by using drm_fb_helper_lastclose() which checks if fbdev is in use. > >> static int drm_fbdev_client_restore(struct drm_client_dev *client) >> { >> - struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); >> - >> - drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper); >> + drm_fb_helper_lastclose(client->dev); >> >> return 0; >> } > > Hmm, at least the drm_fb_helper_lastclose() version I'm looking at > (branch drm-misc-next) just calls > drm_fb_helper_restore_fbdev_mode_unlocked without any check ... > drm_fb_helper_lastclose() uses drm_device->fb_helper which is NULL if fbdev is not in use, from docs: /** * @fb_helper: * * Pointer to the fbdev emulation structure. * Set by drm_fb_helper_init() and cleared by drm_fb_helper_fini(). And drm_fb_helper_restore_fbdev_mode_unlocked() has a NULL check. Noralf.
On Mon, Jan 28, 2019 at 11:25:28AM +0100, Noralf Trønnes wrote: > > > Den 28.01.2019 07.48, skrev Gerd Hoffmann: > >> Fix by using drm_fb_helper_lastclose() which checks if fbdev is in use. > > > >> static int drm_fbdev_client_restore(struct drm_client_dev *client) > >> { > >> - struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); > >> - > >> - drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper); > >> + drm_fb_helper_lastclose(client->dev); > >> > >> return 0; > >> } > > > > Hmm, at least the drm_fb_helper_lastclose() version I'm looking at > > (branch drm-misc-next) just calls > > drm_fb_helper_restore_fbdev_mode_unlocked without any check ... > > > > drm_fb_helper_lastclose() uses drm_device->fb_helper which is NULL if > fbdev is not in use, Ah, ok. In contrast drm_fb_helper_from_client() never returns NULL. Missed that detail. Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Den 28.01.2019 12.49, skrev Gerd Hoffmann: > On Mon, Jan 28, 2019 at 11:25:28AM +0100, Noralf Trønnes wrote: >> >> >> Den 28.01.2019 07.48, skrev Gerd Hoffmann: >>>> Fix by using drm_fb_helper_lastclose() which checks if fbdev is in use. >>> >>>> static int drm_fbdev_client_restore(struct drm_client_dev *client) >>>> { >>>> - struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); >>>> - >>>> - drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper); >>>> + drm_fb_helper_lastclose(client->dev); >>>> >>>> return 0; >>>> } >>> >>> Hmm, at least the drm_fb_helper_lastclose() version I'm looking at >>> (branch drm-misc-next) just calls >>> drm_fb_helper_restore_fbdev_mode_unlocked without any check ... >>> >> >> drm_fb_helper_lastclose() uses drm_device->fb_helper which is NULL if >> fbdev is not in use, > > Ah, ok. In contrast drm_fb_helper_from_client() never returns NULL. > Missed that detail. > > Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> > Applied, thanks for your review. Noralf.
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 31fcf94bf825..c5c79986f9c5 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -3185,9 +3185,7 @@ static void drm_fbdev_client_unregister(struct drm_client_dev *client) static int drm_fbdev_client_restore(struct drm_client_dev *client) { - struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client); - - drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper); + drm_fb_helper_lastclose(client->dev); return 0; }
If fbdev setup has failed, lastclose will give a NULL pointer deref: [ 77.794295] [drm:drm_lastclose] [ 77.794414] [drm:drm_lastclose] driver lastclose completed [ 77.794660] Unable to handle kernel NULL pointer dereference at virtual address 00000014 [ 77.809460] pgd = b376b71b [ 77.818275] [00000014] *pgd=175ba831, *pte=00000000, *ppte=00000000 [ 77.830813] Internal error: Oops: 17 [#1] ARM [ 77.840963] Modules linked in: mi0283qt mipi_dbi tinydrm raspberrypi_hwmon gpio_backlight backlight snd_bcm2835(C) bcm2835_rng rng_core [ 77.865203] CPU: 0 PID: 527 Comm: lt-modetest Tainted: G C 5.0.0-rc1+ #1 [ 77.879525] Hardware name: BCM2835 [ 77.889185] PC is at restore_fbdev_mode+0x20/0x164 [ 77.900261] LR is at drm_fb_helper_restore_fbdev_mode_unlocked+0x54/0x9c [ 78.002446] Process lt-modetest (pid: 527, stack limit = 0x7a3d5c14) [ 78.291030] Backtrace: [ 78.300815] [<c04f2d0c>] (restore_fbdev_mode) from [<c04f4708>] (drm_fb_helper_restore_fbdev_mode_unlocked+0x54/0x9c) [ 78.319095] r9:d8a8a288 r8:d891acf0 r7:d7697910 r6:00000000 r5:d891ac00 r4:d891ac00 [ 78.334432] [<c04f46b4>] (drm_fb_helper_restore_fbdev_mode_unlocked) from [<c04f47e8>] (drm_fbdev_client_restore+0x18/0x20) [ 78.353296] r8:d76978c0 r7:d7697910 r6:d7697950 r5:d7697800 r4:d891ac00 r3:c04f47d0 [ 78.368689] [<c04f47d0>] (drm_fbdev_client_restore) from [<c051b6b4>] (drm_client_dev_restore+0x7c/0xc0) [ 78.385982] [<c051b638>] (drm_client_dev_restore) from [<c04f8fd0>] (drm_lastclose+0xc4/0xd4) [ 78.402332] r8:d76978c0 r7:d7471080 r6:c0e0c088 r5:d8a85e00 r4:d7697800 [ 78.416688] [<c04f8f0c>] (drm_lastclose) from [<c04f9088>] (drm_release+0xa8/0x10c) [ 78.431929] r5:d8a85e00 r4:d7697800 [ 78.442989] [<c04f8fe0>] (drm_release) from [<c02640c4>] (__fput+0x104/0x1c8) [ 78.457740] r8:d5ccea10 r7:d96cfb10 r6:00000008 r5:d74c1b90 r4:d8a8a280 [ 78.472043] [<c0263fc0>] (__fput) from [<c02641ec>] (____fput+0x18/0x1c) [ 78.486363] r10:00000006 r9:d7722000 r8:c01011c4 r7:00000000 r6:c0ebac6c r5:d892a340 [ 78.501869] r4:d8a8a280 [ 78.512002] [<c02641d4>] (____fput) from [<c013ef1c>] (task_work_run+0x98/0xac) [ 78.527186] [<c013ee84>] (task_work_run) from [<c010cc54>] (do_work_pending+0x4f8/0x570) [ 78.543238] r7:d7722030 r6:00000004 r5:d7723fb0 r4:00000000 [ 78.556825] [<c010c75c>] (do_work_pending) from [<c0101034>] (slow_work_pending+0xc/0x20) [ 78.674256] ---[ end trace 70d3a60cf739be3b ]--- Fix by using drm_fb_helper_lastclose() which checks if fbdev is in use. Fixes: 9060d7f49376 ("drm/fb-helper: Finish the generic fbdev emulation") Cc: stable@vger.kernel.org Signed-off-by: Noralf Trønnes <noralf@tronnes.org> --- drivers/gpu/drm/drm_fb_helper.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)