1
Description: Ignore VSYNC change uevents from omapfb, as they happen at each vsync and thus keep waking up udevd (including rules processing), upstart, and other parts of the system 60 times a second.
2
Author: Martin Pitt <martin.pitt@ubuntu.com>
3
Forwarded: Heck, don't ever show this embarassing hack to anyone. Except if that anyone is an omapfb author, then please don't stop showing this to them until they fix the driver :-)
4
Bug-Ubuntu: https://launchpad.net/bugs/1234743
6
Index: systemd/src/libudev/libudev-monitor.c
7
===================================================================
8
--- systemd.orig/src/libudev/libudev-monitor.c 2013-02-20 02:32:41.900839006 +0100
9
+++ systemd/src/libudev/libudev-monitor.c 2013-10-17 11:38:56.216374114 +0200
14
+/* return uint32_t for the first 4 characters in s */
15
+#define str2word(s) ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3])
18
* udev_monitor_filter_update:
19
* @udev_monitor: monitor
23
if (udev_list_get_entry(&udev_monitor->filter_subsystem_list) == NULL &&
25
+ /* we always need a filter chain for kernel monitors to get rid
26
+ * of the omapfb VSYNC uevents */
27
+ udev_monitor->snl.nl.nl_groups != UDEV_MONITOR_KERNEL &&
29
udev_list_get_entry(&udev_monitor->filter_tag_list) == NULL)
35
bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, magic));
37
/* jump if magic matches */
38
bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, UDEV_MONITOR_MAGIC, 1, 0);
40
+ /* jump over our whole omapfb/VSYNC check if magic matches */
41
+ bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, UDEV_MONITOR_MAGIC, 10, 0);
43
+ /* filter out omapfb change VSYNC uevents (LP #1234743); they look like
44
+change@/devices/platform/omapfb\x00ACTION=change\x00DEVPATH=/devices/platform/omapfb\x00SUBSYSTEM=platform\x00VSYNC=1737775695800\x00DRIVER=omapfb\x00MODALIAS=platform:omapfb\x00SEQNUM=8909\x00
46
+ Matching on the VSYNC attribute is a bit finicky, as its exact
47
+ position in the packet might not be reliable. The real VSYNC uevents
48
+ have packets of ~ 170 bytes length (varying with the string length of
49
+ VSYNC= and SEQNUM), while a simple synthetic
50
+ "echo change | tee /sys/devices/platform/omapfb/uevent" only has 150.
51
+ So we instead just compare the length of the packet and use 160 as a divider.
52
+ As we don't generally care about that device at all, this logic does
53
+ not need to be rock solid, though -- if we would just ignore all
54
+ change events from that device nothing should break.
57
+ /* if the event is shorter than 160 bytes, it can't be omapfb/VSYNC, jump to "pass" */
58
+ bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_LEN, 0);
59
+ bpf_jmp(ins, &i, BPF_JMP|BPF_JGE|BPF_K, 160, 0, 7);
61
+ /* check if it is a change event; if not, jump to "pass" */
62
+ bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, 0);
63
+ bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, str2word("chan"), 0, 5);
65
+ /* check if it is from omapfb */
66
+ bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, 24);
67
+ bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, str2word("/oma"), 0, 3);
68
+ bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, 28);
69
+ bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, str2word("pfb\0"), 0, 1);
71
+ /* we found the omapfb change uevent, reject it */
72
+ bpf_stmt(ins, &i, BPF_RET|BPF_K, 0);
73
+#endif /* omapfb filter hack on __arm__ */
75
/* wrong magic, pass packet */
76
bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff);