From 5ed8cf2ba806632d32c6c626ece9c9c0bd8a84f7 Mon Sep 17 00:00:00 2001 From: Jeremy Szu Date: Tue, 10 Nov 2020 16:15:16 +0800 Subject: Make sure all fan(s) are controllable before using To fix LP: #1903653 - Make sure the fan sensor is readable - Make sure the fan is not controlled by graphic --- bin/fan_reaction_test.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'bin') diff --git a/bin/fan_reaction_test.py b/bin/fan_reaction_test.py index c37054b..367e8fb 100755 --- a/bin/fan_reaction_test.py +++ b/bin/fan_reaction_test.py @@ -29,9 +29,28 @@ import time class FanMonitor: """Device that reports fan RPM or something correlating to that.""" def __init__(self): - """Use heuristics to find something that we can read.""" - self._fan_paths = glob.glob('/sys/class/hwmon/hwmon*/fan*_input') - if not self._fan_paths: + """Looking for all system controllable fan(s).""" + hwmons = [] + for i in glob.glob('/sys/class/hwmon/hwmon*/fan*_enable'): + with open(i, 'r') as _file: + enable = _file.read().splitlines() + # Make sure the sensor of the fan is readable. + if enable[0] == '0': + continue + # Get the class of pci device of hwmon. + device = os.path.join(os.path.dirname(i), 'device') + pci_addr = os.path.basename(os.readlink(device)) + pci_class_path = '/sys/bus/pci/devices/%s/class' % pci_addr + with open(pci_class_path, 'r') as _file: + pci_class = _file.read().splitlines() + pci_device_class = (int(pci_class[0], base=16) >> 16) & 0xff + """Make sure the fan is not on graphic card""" + if pci_device_class == 3: + continue + # TODO: Check the control method by reading pwm[1-*]_enable + # It is a controlable fan. + hwmons.append(i) + if not hwmons: print('Fan monitoring interface not found in SysFS') raise SystemExit(0) @@ -43,7 +62,7 @@ class FanMonitor: fan_mon_name = os.path.relpath(p, '/sys/class/hwmon') result[fan_mon_name] = int(f.read()) except OSError: - print('Fan SysFS node dissappeared ({})'.format(p)) + print('Fan SysFS node disappeared ({})'.format(p)) return result def get_average_rpm(self, period): -- cgit v1.2.3 From 3bdf35602f3cde3e59e120668dec871c9edb0bba Mon Sep 17 00:00:00 2001 From: Jeremy Szu Date: Wed, 18 Nov 2020 16:25:30 +0800 Subject: Remove unreliable checking for hwmon/fan_* The kernel offical document mentioned: ``` All entries (except name) are optional, and should only be created in a given driver if the chip has the feature. ``` It's highly depends on the hwmon driver. Thus, remove the extra check and turn back to original desgin. --- bin/fan_reaction_test.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'bin') diff --git a/bin/fan_reaction_test.py b/bin/fan_reaction_test.py index 367e8fb..f1849f0 100755 --- a/bin/fan_reaction_test.py +++ b/bin/fan_reaction_test.py @@ -31,12 +31,12 @@ class FanMonitor: def __init__(self): """Looking for all system controllable fan(s).""" hwmons = [] - for i in glob.glob('/sys/class/hwmon/hwmon*/fan*_enable'): - with open(i, 'r') as _file: - enable = _file.read().splitlines() - # Make sure the sensor of the fan is readable. - if enable[0] == '0': - continue + # All entries (except name) under /sys/class/hwmon/hwmon/* are optional, + # and should only be created in a given driver if the chip has the feature. + # Use fan*_input is because the "thinkpad_hwmon" driver is report + # fan_input only. If there is any driver has different implementation + # then may need to check other entries in the future. + for i in glob.glob('/sys/class/hwmon/hwmon*/fan*_input'): # Get the class of pci device of hwmon. device = os.path.join(os.path.dirname(i), 'device') pci_addr = os.path.basename(os.readlink(device)) @@ -47,8 +47,6 @@ class FanMonitor: """Make sure the fan is not on graphic card""" if pci_device_class == 3: continue - # TODO: Check the control method by reading pwm[1-*]_enable - # It is a controlable fan. hwmons.append(i) if not hwmons: print('Fan monitoring interface not found in SysFS') -- cgit v1.2.3 From 0f361dd32270c5cab494627ae35354a8e51676c6 Mon Sep 17 00:00:00 2001 From: Jeremy Szu Date: Mon, 23 Nov 2020 14:27:06 +0800 Subject: Fix the exception if hwmon isn't controlled by PCI 1. To check the hwmon driver is controlled by PCI before accessing the class of pci device, the class field is mandatory in pci driver. 2. Handle the exception if failing to access pci device class. --- bin/fan_reaction_test.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'bin') diff --git a/bin/fan_reaction_test.py b/bin/fan_reaction_test.py index f1849f0..fba5eed 100755 --- a/bin/fan_reaction_test.py +++ b/bin/fan_reaction_test.py @@ -37,16 +37,22 @@ class FanMonitor: # fan_input only. If there is any driver has different implementation # then may need to check other entries in the future. for i in glob.glob('/sys/class/hwmon/hwmon*/fan*_input'): - # Get the class of pci device of hwmon. device = os.path.join(os.path.dirname(i), 'device') - pci_addr = os.path.basename(os.readlink(device)) - pci_class_path = '/sys/bus/pci/devices/%s/class' % pci_addr - with open(pci_class_path, 'r') as _file: - pci_class = _file.read().splitlines() - pci_device_class = (int(pci_class[0], base=16) >> 16) & 0xff - """Make sure the fan is not on graphic card""" - if pci_device_class == 3: - continue + device_path = os.path.realpath(device) + # Get the class of pci device of hwmon whether is GPU. + if "pci" in device_path: + pci_addr = os.path.basename(device_path) + pci_class_path = '/sys/bus/pci/devices/%s/class' % pci_addr + try: + with open(pci_class_path, 'r') as _file: + pci_class = _file.read().splitlines() + pci_device_class = (int(pci_class[0], base=16) >> 16) & 0xff + """Make sure the fan is not on graphic card""" + if pci_device_class == 3: + continue + except OSError: + print('Not able to access {}'.format(pci_class_path)) + continue hwmons.append(i) if not hwmons: print('Fan monitoring interface not found in SysFS') -- cgit v1.2.3 From 5e83920b425a72bb31ef3ca522319c244ee7ab6e Mon Sep 17 00:00:00 2001 From: Jeremy Szu Date: Fri, 27 Nov 2020 17:09:18 +0800 Subject: Fix missing _fan_paths --- bin/fan_reaction_test.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'bin') diff --git a/bin/fan_reaction_test.py b/bin/fan_reaction_test.py index fba5eed..1f31923 100755 --- a/bin/fan_reaction_test.py +++ b/bin/fan_reaction_test.py @@ -29,14 +29,15 @@ import time class FanMonitor: """Device that reports fan RPM or something correlating to that.""" def __init__(self): - """Looking for all system controllable fan(s).""" + """Use heuristics to find something that we can read.""" hwmons = [] + self._fan_paths = glob.glob('/sys/class/hwmon/hwmon*/fan*_input') # All entries (except name) under /sys/class/hwmon/hwmon/* are optional, # and should only be created in a given driver if the chip has the feature. # Use fan*_input is because the "thinkpad_hwmon" driver is report # fan_input only. If there is any driver has different implementation # then may need to check other entries in the future. - for i in glob.glob('/sys/class/hwmon/hwmon*/fan*_input'): + for i in self._fan_paths: device = os.path.join(os.path.dirname(i), 'device') device_path = os.path.realpath(device) # Get the class of pci device of hwmon whether is GPU. -- cgit v1.2.3 From c1e651c906af5d6c64f58ec745aac1e711a05201 Mon Sep 17 00:00:00 2001 From: Jeremy Szu Date: Mon, 4 Jan 2021 19:30:46 +0800 Subject: Add test cases for fan_reaction_test.py --- bin/fan_reaction_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'bin') diff --git a/bin/fan_reaction_test.py b/bin/fan_reaction_test.py index 1f31923..6441457 100755 --- a/bin/fan_reaction_test.py +++ b/bin/fan_reaction_test.py @@ -42,8 +42,7 @@ class FanMonitor: device_path = os.path.realpath(device) # Get the class of pci device of hwmon whether is GPU. if "pci" in device_path: - pci_addr = os.path.basename(device_path) - pci_class_path = '/sys/bus/pci/devices/%s/class' % pci_addr + pci_class_path = os.path.join(device, 'class') try: with open(pci_class_path, 'r') as _file: pci_class = _file.read().splitlines() -- cgit v1.2.3 From 350ca9e240d4b4c767bb71c1b9f9a4b22b309f2a Mon Sep 17 00:00:00 2001 From: Jeremy Szu Date: Tue, 5 Jan 2021 11:44:34 +0800 Subject: Rebase the new test coverage from Sylvain * Rebase the new test coverage from Sylvain as https://code.launchpad.net/~os369510/plainbox-provider-checkbox/+git/plainbox-provider-checkbox/+merge/393535/comments/1041502 but keep to use the soft-link from sysfs. --- bin/fan_reaction_test.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) mode change 100755 => 100644 bin/fan_reaction_test.py (limited to 'bin') diff --git a/bin/fan_reaction_test.py b/bin/fan_reaction_test.py old mode 100755 new mode 100644 index 6441457..3b2257e --- a/bin/fan_reaction_test.py +++ b/bin/fan_reaction_test.py @@ -30,10 +30,11 @@ class FanMonitor: """Device that reports fan RPM or something correlating to that.""" def __init__(self): """Use heuristics to find something that we can read.""" - hwmons = [] + self.hwmons = [] self._fan_paths = glob.glob('/sys/class/hwmon/hwmon*/fan*_input') - # All entries (except name) under /sys/class/hwmon/hwmon/* are optional, - # and should only be created in a given driver if the chip has the feature. + # All entries (except name) under /sys/class/hwmon/hwmon/* are optional + # and should only be created in a given driver if the chip has + # the feature. # Use fan*_input is because the "thinkpad_hwmon" driver is report # fan_input only. If there is any driver has different implementation # then may need to check other entries in the future. @@ -46,21 +47,22 @@ class FanMonitor: try: with open(pci_class_path, 'r') as _file: pci_class = _file.read().splitlines() - pci_device_class = (int(pci_class[0], base=16) >> 16) & 0xff + pci_device_class = ( + int(pci_class[0], base=16) >> 16) & 0xff """Make sure the fan is not on graphic card""" if pci_device_class == 3: continue except OSError: print('Not able to access {}'.format(pci_class_path)) continue - hwmons.append(i) - if not hwmons: + self.hwmons.append(i) + if not self.hwmons: print('Fan monitoring interface not found in SysFS') raise SystemExit(0) def get_rpm(self): result = {} - for p in self._fan_paths: + for p in self.hwmons: try: with open(p, 'rt') as f: fan_mon_name = os.path.relpath(p, '/sys/class/hwmon') -- cgit v1.2.3