1#!/usr/bin/env python3
2
3import os,sys
4import optparse
5import subprocess
6import re
7import operator
8
9# map of Workaround names -> (list of platforms)
10workarounds = {}
11verbose = False
12
13def find_nth(haystack, needle, n):
14	start = haystack.find(needle)
15	while start >= 0 and n > 1:
16		start = haystack.find(needle, start + len(needle))
17		n -= 1
18	return start
19
20valid_platforms = ('ctg', 'elk', 'ilk', 'snb', 'ivb', 'vlv', 'hsw', 'bdw',
21		   'chv', 'skl', 'bxt', 'kbl')
22def parse_platforms(line, p):
23	l =  p.split(',')
24	for p in l:
25		if p not in valid_platforms:
26			sys.stdout.write("warning: %s\n" % line)
27			sys.stdout.write("unknown platform %s\n" % p)
28	return l
29
30wa_re = re.compile('(?P<name>W[aA][A-Z0-9][a-zA-Z0-9_]+):(?P<platforms>[a-z,]+)')
31waname_re = re.compile('(?P<name>W[aA][A-Z0-9][a-zA-Z0-9_]+)')
32def parse(me):
33	for line in me.splitlines():
34		match = wa_re.search(str(line))
35		if not match:
36			if not verbose:
37				continue
38
39			# Those lines come from a git grep that looks for Wa
40			# names, so if we don't match wa_re here it's because
41			# no platform has been specified
42			name = waname_re.search(line).group('name')
43			path = line[:find_nth(line, ':', 2)]
44			sys.stdout.write("warning: %s\n" % line)
45			sys.stdout.write("%s: no platform for %s\n"
46					 % (path, name))
47			continue
48
49		wa_name = match.group('name')
50		platforms = match.group('platforms')
51
52		if wa_name in workarounds:
53			platforms = parse_platforms(line, platforms)
54			for p in platforms:
55				if not p in workarounds[wa_name]:
56					workarounds[wa_name].append(p)
57		else:
58			workarounds[wa_name] = parse_platforms(line, platforms)
59
60
61def execute(cmd):
62	p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
63			     stderr=subprocess.PIPE)
64	out, err = p.communicate()
65	return out, err
66
67def parse_options(args):
68	usage = "Usage: list-workarounds [options] path-to-kernel -k path-to-kernel -m path-to-mesa"
69	parser = optparse.OptionParser(usage, version=1.0)
70
71	parser.add_option("-k", "--kernel-path", dest="kernel_path", default=None,
72			  help="path to kernel")
73
74	parser.add_option("-m", "--mesa-path", dest="mesa_path", default=None,
75			  help="path to mesa")
76
77	parser.add_option("-v", "--verbose", action="store_true",
78			  dest="verbose", default=False,
79			  help="be more verbose")
80
81	parser.add_option("-p", "--platform", dest="platform", default=None,
82			  help="List workarounds for the specified platform")
83
84	(options, args) = parser.parse_args()
85	return (options, args)
86
87def print_workarounds(project_root, driver_dir, project):
88	olddir = os.getcwd()
89	os.chdir(project_root)
90	work_arounds, err = execute(['git', 'grep', '-n',
91				     '-e', 'W[aA][A-Z0-9][a-zA-Z0-9_]\+',
92				     driver_dir])
93	os.chdir(olddir)
94	if err:
95		print(err)
96		sys.exit(1)
97
98	parse(work_arounds)
99	print("\nList of workarounds found in %s:" % project)
100	for wa in sorted(workarounds.keys()):
101		if not options.platform:
102			print("%s: %s" % (wa, ', '.join(workarounds[wa])))
103		elif options.platform in workarounds[wa]:
104			print(wa)
105
106
107if __name__ == '__main__':
108	(options, args) = parse_options(sys.argv)
109	verbose = options.verbose
110	kernel_path = None
111
112	if not len(args) and options.kernel_path == None and options.mesa_path == None:
113		sys.stderr.write("error: A path to either a kernel tree or Mesa is required\n")
114		sys.exit(1)
115
116	if len(args):
117		kernel_path = args[0]
118	elif options.kernel_path != None:
119		kernel_path = options.kernel_path
120
121	if kernel_path != None:
122	# --- list Kernel workarounds if path is provided ---
123		kconfig = os.path.join(kernel_path, 'Kconfig')
124		if not os.path.isfile(kconfig):
125			sys.stderr.write("error: %s does not point to a kernel tree \n"
126							% kernel_path)
127			sys.exit(1)
128
129		i915_dir = os.path.join('drivers', 'gpu', 'drm', 'i915')
130		print_workarounds(kernel_path, i915_dir, "kernel")
131
132	# --- list mesa workarounds if path is provided ---
133	if options.mesa_path != None:
134		# reset workarounds array
135		workarounds = {}
136
137		mesa_path = options.mesa_path
138		i965_dir = os.path.join('src', 'mesa', 'drivers', 'dri', 'i965')
139		mesa_dir = os.path.join(mesa_path, i965_dir)
140		if not os.path.exists(mesa_dir):
141			sys.stderr.write("error: %s does not point to a valid mesa path \n"
142							% mesa_path)
143			sys.exit(1)
144
145		print_workarounds(mesa_path, i965_dir, "Mesa")
146