input: touchscreen: fix kernel crash in fb_notifier_callback function
authorYakir Yang <ykk@rock-chips.com>
Fri, 22 Apr 2016 02:47:39 +0000 (10:47 +0800)
committerGerrit Code Review <gerrit@rock-chips.com>
Fri, 22 Apr 2016 04:00:03 +0000 (12:00 +0800)
fb_event would only carry the data number in some special notify action,
other actions wouldn't carry an valid data number, and in this case
kernel would crash, logs like:

[    4.129846] Unable to handle kernel paging request at virtual address 200000000000
......
[    4.164618] Hardware name: Rockchip RK3399 Evaluation Board v1 (Chrome OS) (DT)
[    4.184624] PC is at fb_notifier_callback+0x28/0xac
[    4.189497] LR is at notifier_call_chain+0x74/0xb4
[    4.194279] pc : [<ffffffc0005e1468>] lr : [<ffffffc0000b5ba4>] pstate: 20000045
......
[    5.703780] [<ffffffc0005e1468>] fb_notifier_callback+0x28/0xac
[    5.709690] [<ffffffc0000b5ba4>] notifier_call_chain+0x74/0xb4
[    5.715504] [<ffffffc0000b5e70>] __blocking_notifier_call_chain+0x48/0x64
[    5.722280] [<ffffffc0000b5ea0>] blocking_notifier_call_chain+0x14/0x1c
[    5.728885] [<ffffffc00036fd98>] fb_notifier_call_chain+0x20/0x28
[    5.734969] [<ffffffc0003726c0>] register_framebuffer+0x218/0x250
[    5.741054] [<ffffffc0003b7598>] drm_fb_helper_initial_config+0x2f8/0x374
[    5.747832] [<ffffffc0003e056c>] rockchip_drm_fbdev_init+0xa8/0xe8
[    5.754002] [<ffffffc0003dba24>] rockchip_drm_load+0x1e4/0x25c

Change-Id: I3314315a31bbab43489fca85dabc4c6511fc9dee
Signed-off-by: Yakir Yang <ykk@rock-chips.com>
drivers/input/touchscreen/tp_suspend.h

index bf23e868e7703b5911407508528f8e7db0c494a5..b900ee530a2a82db04741efd0ac83115908251bd 100644 (file)
@@ -25,7 +25,7 @@ static inline int fb_notifier_callback(struct notifier_block *self,
 {
        struct tp_device *tp;
        struct fb_event *event = data;
-       int blank_mode = *((int *)event->data);
+       int blank_mode;
        int ret = 0;
 
        tp = container_of(self, struct tp_device, fb_notif);
@@ -34,24 +34,23 @@ static inline int fb_notifier_callback(struct notifier_block *self,
 
        mutex_lock(&tp->ops_lock);
 
-       if (action == FB_EARLY_EVENT_BLANK) {
-               switch (blank_mode) {
-               case FB_BLANK_UNBLANK:
-                       break;
-               default:
+       switch (action) {
+       case FB_EARLY_EVENT_BLANK:
+               blank_mode = *((int *)event->data);
+               if (blank_mode != FB_BLANK_UNBLANK)
                        ret = tp->tp_suspend(tp);
-                       break;
-               }
-       }
-       else if (action == FB_EVENT_BLANK) {
-               switch (blank_mode) {
-               case FB_BLANK_UNBLANK:
+               break;
+
+       case FB_EVENT_BLANK:
+               blank_mode = *((int *)event->data);
+               if (blank_mode == FB_BLANK_UNBLANK)
                        tp->tp_resume(tp);
-                       break;
-               default:
-                       break;
-               }
+               break;
+
+       default:
+               break;
        }
+
        mutex_unlock(&tp->ops_lock);
 
        if (ret < 0)