Skip to content

Instantly share code, notes, and snippets.

@andy-shev
Last active August 1, 2018 20:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andy-shev/b85c5129fcfe63cb88849805e5a7e3a4 to your computer and use it in GitHub Desktop.
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
#!/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