Last active
August 1, 2018 20:41
-
-
Save andy-shev/b85c5129fcfe63cb88849805e5a7e3a4 to your computer and use it in GitHub Desktop.
IRQ flag mismatch logic in __setup_irq() in Linux kernel for shared interrupts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python -tt | |
# -*- coding: UTF-8 -*- | |
# vim: ts=4 sw=4 et ai si | |
from __future__ import print_function | |
import sys | |
import os | |
import itertools | |
__author__ = "Andy Shevchenko" | |
__license__ = "GPL v2" | |
PROG = os.path.basename(sys.argv[0]) | |
FLAGS = ( | |
"SHARED", # Shared | |
"TRIG", # Trigger type | |
"ONESHOT", # One short | |
"PERCPU", # Per CPU | |
) | |
# Leftmost requires the rest to be the same | |
RULES = ( | |
("SHARED", "SHARED", "TRIG", "ONESHOT"), | |
("PERCPU", "PERCPU"), | |
) | |
def codebase(old, new): | |
shared = 1 << FLAGS.index("SHARED") | |
trig = 1 << FLAGS.index("TRIG") | |
oneshot = 1 << FLAGS.index("ONESHOT") | |
percpu = 1 << FLAGS.index("PERCPU") | |
# if (!((old->flags & new->flags) & IRQF_SHARED) || | |
# (oldtype != (new->flags & IRQF_TRIGGER_MASK)) || | |
# ((old->flags ^ new->flags) & IRQF_ONESHOT)) | |
# goto mismatch; | |
# | |
# if ((old->flags & IRQF_PERCPU) != | |
# (new->flags & IRQF_PERCPU)) | |
# goto mismatch; | |
if (not ((old & new) & shared) or | |
((old & trig) != (new & trig)) or | |
((old ^ new) & oneshot)): | |
return False | |
if (old & percpu) != (new & percpu): | |
return False | |
return True | |
def algo(old, new, rules): | |
shared = 1 << FLAGS.index("SHARED") | |
if not (old & shared) and not (new & shared): | |
return False | |
for rule in rules: | |
c = rule[0] | |
if (old & c) or (new & c): | |
for x in rule[1:]: | |
if (old & x) != (new & x): | |
return False | |
return True | |
def comment(old, new): | |
shared = 1 << FLAGS.index("SHARED") | |
trig = 1 << FLAGS.index("TRIG") | |
oneshot = 1 << FLAGS.index("ONESHOT") | |
percpu = 1 << FLAGS.index("PERCPU") | |
# /* | |
# * Can't share interrupts unless both agree to and are | |
# * the same type (level, edge, polarity). So both flag | |
# * fields must have IRQF_SHARED set and the bits which | |
# * set the trigger type must match. Also all must | |
# * agree on ONESHOT. | |
# */ | |
if (old & shared) != (new & shared): | |
return False | |
if not (old & shared): | |
return False | |
if (old & trig) != (new & trig): | |
return False | |
if (old & oneshot) != (new & oneshot): | |
return False | |
if (old & percpu) != (new & percpu): | |
return False | |
return True | |
def conv(flags, value): | |
if value: | |
x = '|'.join(flags[bit] for bit in range(len(flags)) if (value & (1 << bit))) | |
else: | |
x = "NONE" | |
return "%-2d %-30s" % (value, x) | |
def go(flags, rules): | |
for old, new in itertools.permutations(range(1 << len(flags)), 2): | |
real = codebase(old, new) | |
a = algo(old, new, rules) | |
wish = comment(old, new) | |
if (real != wish) or (a != real): | |
print(conv(flags, old), conv(flags, new), "\t", real, "\t", wish, "\t", a) | |
def main(argv): | |
flags = FLAGS | |
rules = [[1 << FLAGS.index(y) for y in x] for x in RULES] | |
go(flags, rules) | |
if __name__ == "__main__": | |
sys.exit(main(sys.argv)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment