Commit c9d197ec authored by Todd Brandt's avatar Todd Brandt Committed by Rafael J. Wysocki
Browse files

pm-graph: v5.12, fixes



- fix S3 suspend fail double run by using fp.flush to /sys/power/state
- when running turbostat print the return value
- handle case where html files have binary data
- max issues in summary-issues is now 100 (in case there are thousands)
- add backup to dmidecode, use /sys/class/dmi/id/ in case /dev/mem fails
- update summary page to use full mode (disk-platform instead of disk)

Signed-off-by: default avatarTodd Brandt <todd.e.brandt@intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 64c6a36d
Loading
Loading
Loading
Loading
+65 −37
Original line number Diff line number Diff line
@@ -86,7 +86,7 @@ def ascii(text):
#	 store system values and test parameters
class SystemValues:
	title = 'SleepGraph'
	version = '5.11'
	version = '5.12'
	ansi = False
	rs = 0
	display = ''
@@ -1181,8 +1181,8 @@ class SystemValues:
		cmd = self.getExec('turbostat')
		rawout = keyline = valline = ''
		fullcmd = '%s -q -S echo freeze > %s' % (cmd, self.powerfile)
		fp = Popen(['sh', '-c', fullcmd], stdout=PIPE, stderr=PIPE).stderr
		for line in fp:
		fp = Popen(['sh', '-c', fullcmd], stdout=PIPE, stderr=PIPE)
		for line in fp.stderr:
			line = ascii(line)
			rawout += line
			if keyline and valline:
@@ -1191,13 +1191,13 @@ class SystemValues:
				keyline = line.strip().split()
			elif keyline:
				valline = line.strip().split()
		fp.close()
		fp.wait()
		if not keyline or not valline or len(keyline) != len(valline):
			errmsg = 'unrecognized turbostat output:\n'+rawout.strip()
			self.vprint(errmsg)
			if not self.verbose:
				pprint(errmsg)
			return ''
			return (fp.returncode, '')
		if self.verbose:
			pprint(rawout.strip())
		out = []
@@ -1207,7 +1207,7 @@ class SystemValues:
			if key == 'SYS%LPI' and not s0ixready and re.match('^[0\.]*$', val):
				continue
			out.append('%s=%s' % (key, val))
		return '|'.join(out)
		return (fp.returncode, '|'.join(out))
	def netfixon(self, net='both'):
		cmd = self.getExec('netfix')
		if not cmd:
@@ -4343,7 +4343,8 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
		list[mode]['data'].append([data['host'], data['kernel'],
			data['time'], tVal[0], tVal[1], data['url'], res,
			data['issues'], data['sus_worst'], data['sus_worsttime'],
			data['res_worst'], data['res_worsttime'], pkgpc10, syslpi, wifi])
			data['res_worst'], data['res_worsttime'], pkgpc10, syslpi, wifi,
			(data['fullmode'] if 'fullmode' in data else mode)])
		idx = len(list[mode]['data']) - 1
		if res.startswith('fail in'):
			res = 'fail'
@@ -4449,7 +4450,7 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
				elif idx == iMed[i]:
					tHigh[i] = ' id="%smed" class=medval title="Median"' % tag
			html += td.format("%d" % (list[mode]['data'].index(d) + 1)) # row
			html += td.format(mode)										# mode
			html += td.format(d[15])									# mode
			html += td.format(d[0])										# host
			html += td.format(d[1])										# kernel
			html += td.format(d[2])										# time
@@ -5524,7 +5525,9 @@ def executeSuspend(quiet=False):
			if ((mode == 'freeze') or (sv.memmode == 's2idle')) \
				and sv.haveTurbostat():
				# execution will pause here
				turbo = sv.turbostat(s0ixready)
				retval, turbo = sv.turbostat(s0ixready)
				if retval != 0:
					tdata['error'] ='turbostat returned %d' % retval
				if turbo:
					tdata['turbo'] = turbo
			else:
@@ -5532,6 +5535,7 @@ def executeSuspend(quiet=False):
				pf.write(mode)
				# execution will pause here
				try:
					pf.flush()
					pf.close()
				except Exception as e:
					tdata['error'] = str(e)
@@ -5702,6 +5706,40 @@ def getModes():
		fp.close()
	return modes

def dmidecode_backup(out, fatal=False):
	cpath, spath, info = '/proc/cpuinfo', '/sys/class/dmi/id', {
		'bios-vendor': 'bios_vendor',
		'bios-version': 'bios_version',
		'bios-release-date': 'bios_date',
		'system-manufacturer': 'sys_vendor',
		'system-product-name': 'product_name',
		'system-version': 'product_version',
		'system-serial-number': 'product_serial',
		'baseboard-manufacturer': 'board_vendor',
		'baseboard-product-name': 'board_name',
		'baseboard-version': 'board_version',
		'baseboard-serial-number': 'board_serial',
		'chassis-manufacturer': 'chassis_vendor',
		'chassis-version': 'chassis_version',
		'chassis-serial-number': 'chassis_serial',
	}
	for key in info:
		if key not in out:
			val = sysvals.getVal(os.path.join(spath, info[key])).strip()
			if val and val.lower() != 'to be filled by o.e.m.':
				out[key] = val
	if 'processor-version' not in out and os.path.exists(cpath):
		with open(cpath, 'r') as fp:
			for line in fp:
				m = re.match('^model\s*name\s*\:\s*(?P<c>.*)', line)
				if m:
					out['processor-version'] = m.group('c').strip()
					break
	if fatal and len(out) < 1:
		doError('dmidecode failed to get info from %s or %s' % \
			(sysvals.mempath, spath))
	return out

# Function: dmidecode
# Description:
#	 Read the bios tables and pull out system info
@@ -5712,6 +5750,8 @@ def getModes():
#	 A dict object with all available key/values
def dmidecode(mempath, fatal=False):
	out = dict()
	if(not (os.path.exists(mempath) and os.access(mempath, os.R_OK))):
		return dmidecode_backup(out, fatal)

	# the list of values to retrieve, with hardcoded (type, idx)
	info = {
@@ -5727,24 +5767,14 @@ def dmidecode(mempath, fatal=False):
		'baseboard-version': (2, 6),
		'baseboard-serial-number': (2, 7),
		'chassis-manufacturer': (3, 4),
		'chassis-type': (3, 5),
		'chassis-version': (3, 6),
		'chassis-serial-number': (3, 7),
		'processor-manufacturer': (4, 7),
		'processor-version': (4, 16),
	}
	if(not os.path.exists(mempath)):
		if(fatal):
			doError('file does not exist: %s' % mempath)
		return out
	if(not os.access(mempath, os.R_OK)):
		if(fatal):
			doError('file is not readable: %s' % mempath)
		return out

	# by default use legacy scan, but try to use EFI first
	memaddr = 0xf0000
	memsize = 0x10000
	memaddr, memsize = 0xf0000, 0x10000
	for ep in ['/sys/firmware/efi/systab', '/proc/efi/systab']:
		if not os.path.exists(ep) or not os.access(ep, os.R_OK):
			continue
@@ -5765,11 +5795,7 @@ def dmidecode(mempath, fatal=False):
		fp.seek(memaddr)
		buf = fp.read(memsize)
	except:
		if(fatal):
			doError('DMI table is unreachable, sorry')
		else:
			pprint('WARNING: /dev/mem is not readable, ignoring DMI data')
			return out
		return dmidecode_backup(out, fatal)
	fp.close()

	# search for either an SM table or DMI table
@@ -5785,10 +5811,7 @@ def dmidecode(mempath, fatal=False):
			break
		i += 16
	if base == 0 and length == 0 and num == 0:
		if(fatal):
			doError('Neither SMBIOS nor DMI were found')
		else:
			return out
		return dmidecode_backup(out, fatal)

	# read in the SM or DMI table
	try:
@@ -5796,11 +5819,7 @@ def dmidecode(mempath, fatal=False):
		fp.seek(base)
		buf = fp.read(length)
	except:
		if(fatal):
			doError('DMI table is unreachable, sorry')
		else:
			pprint('WARNING: /dev/mem is not readable, ignoring DMI data')
			return out
		return dmidecode_backup(out, fatal)
	fp.close()

	# scan the table for the values we want
@@ -6272,7 +6291,10 @@ def find_in_html(html, start, end, firstonly=True):
	return out

def data_from_html(file, outpath, issues, fulldetail=False):
	try:
		html = open(file, 'r').read()
	except:
		html = ascii(open(file, 'rb').read())
	sysvals.htmlfile = os.path.relpath(file, outpath)
	# extract general info
	suspend = find_in_html(html, 'Kernel Suspend', 'ms')
@@ -6307,6 +6329,7 @@ def data_from_html(file, outpath, issues, fulldetail=False):
		d.end = 999999999
		d.dmesgtext = log.split('\n')
		tp = d.extractErrorInfo()
		if len(issues) < 100:
			for msg in tp.msglist:
				sysvals.errorSummary(issues, msg)
		if stmp[2] == 'freeze':
@@ -6325,6 +6348,11 @@ def data_from_html(file, outpath, issues, fulldetail=False):
		line = find_in_html(log, '# netfix ', '\n')
		if line:
			extra['netfix'] = line
		line = find_in_html(log, '# command ', '\n')
		if line:
			m = re.match('.* -m (?P<m>\S*).*', line)
			if m:
				extra['fullmode'] = m.group('m')
	low = find_in_html(html, 'freeze time: <b>', ' ms</b>')
	for lowstr in ['waking', '+']:
		if not low: