From 7151647304ab4d67a5e7d8d182e0601144b3a5d6 Mon Sep 17 00:00:00 2001 From: roger530-ho Date: Mon, 16 Oct 2023 07:24:26 +0000 Subject: [PATCH] [AS7816-64X] Apply community PR. --- .../led_proc_init.soc | 2 +- .../media_settings.json | 644 ++++++++++++++++++ .../x86_64-accton_as7816_64x-r0/pcie.yaml | 465 +++++++++++++ .../pddf/pd-plugin.json | 6 +- .../pddf/pddf-device.json | 148 +++- .../x86_64-accton_as7816_64x-r0/platform.json | 324 +++++++-- .../platform_components.json | 15 + .../plugins/eeprom.py | 20 - .../plugins/psuutil.py | 60 -- .../plugins/sfputil.py | 269 -------- .../plugins/ssd_util.py | 24 + .../pmon_daemon_control.json | 3 +- .../sonic_platform/eeprom.py | 6 +- .../sonic_platform/helper.py | 8 +- .../system_health_monitoring_config.json | 10 +- .../as7816-64x/modules/Makefile | 4 +- .../as7816-64x/modules/accton_psu_api.h | 1 + .../as7816-64x/modules/accton_psu_defs.h | 1 + .../as7816-64x/modules/pddf_custom_psu.c | 273 ++++++++ .../as7816-64x-platform-monitor.service | 2 +- .../as7816-pddf-platform-monitor.service | 2 +- .../as7816-64x/sonic_platform/chassis.py | 118 ++-- .../as7816-64x/sonic_platform/component.py | 208 ++++++ .../as7816-64x/sonic_platform/event.py | 109 +++ .../as7816-64x/sonic_platform/fan.py | 60 +- .../as7816-64x/sonic_platform/fan_drawer.py | 24 + .../as7816-64x/sonic_platform/helper.py | 368 ++++++++++ .../as7816-64x/sonic_platform/pcie.py | 19 + .../as7816-64x/sonic_platform/psu.py | 99 ++- .../as7816-64x/sonic_platform/sfp.py | 180 +++++ .../as7816-64x/sonic_platform/thermal.py | 282 ++++++++ .../utils/accton_as7816_64x_util.py | 261 +++++-- .../utils/accton_as7816_pddf_monitor.py | 154 +++-- 33 files changed, 3586 insertions(+), 583 deletions(-) create mode 100644 device/accton/x86_64-accton_as7816_64x-r0/media_settings.json create mode 100644 device/accton/x86_64-accton_as7816_64x-r0/pcie.yaml create mode 100644 device/accton/x86_64-accton_as7816_64x-r0/platform_components.json delete mode 100644 device/accton/x86_64-accton_as7816_64x-r0/plugins/eeprom.py delete mode 100755 device/accton/x86_64-accton_as7816_64x-r0/plugins/psuutil.py delete mode 100644 device/accton/x86_64-accton_as7816_64x-r0/plugins/sfputil.py create mode 100755 device/accton/x86_64-accton_as7816_64x-r0/plugins/ssd_util.py create mode 120000 platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/accton_psu_api.h create mode 120000 platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/accton_psu_defs.h create mode 100644 platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/pddf_custom_psu.c create mode 100644 platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/component.py create mode 100644 platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/event.py create mode 100644 platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/helper.py create mode 100644 platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/pcie.py diff --git a/device/accton/x86_64-accton_as7816_64x-r0/led_proc_init.soc b/device/accton/x86_64-accton_as7816_64x-r0/led_proc_init.soc index 75a36c6f9c..0496652361 100755 --- a/device/accton/x86_64-accton_as7816_64x-r0/led_proc_init.soc +++ b/device/accton/x86_64-accton_as7816_64x-r0/led_proc_init.soc @@ -148,7 +148,7 @@ led 3 prog \ 84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -led auto on +#led auto on led 0 start led 1 start led 2 start diff --git a/device/accton/x86_64-accton_as7816_64x-r0/media_settings.json b/device/accton/x86_64-accton_as7816_64x-r0/media_settings.json new file mode 100644 index 0000000000..0c658a2898 --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/media_settings.json @@ -0,0 +1,644 @@ +{ + "PORT_MEDIA_SETTINGS": { + "1": { + "Default": { + "preemphasis": { + "lane0": "0x1c4503", + "lane1": "0x1c4503", + "lane2": "0x1c4503", + "lane3": "0x1c4503" + } + } + }, + "2": { + "Default": { + "preemphasis": { + "lane0": "0x1c4503", + "lane1": "0x1c4503", + "lane2": "0x1c4503", + "lane3": "0x1c4503" + } + } + }, + "3": { + "Default": { + "preemphasis": { + "lane0": "0x1c4503", + "lane1": "0x1c4503", + "lane2": "0x1c4503", + "lane3": "0x1c4503" + } + } + }, + "4": { + "Default": { + "preemphasis": { + "lane0": "0x1c4503", + "lane1": "0x1c4503", + "lane2": "0x1c4503", + "lane3": "0x1c4503" + } + } + }, + "5": { + "Default": { + "preemphasis": { + "lane0": "0x1b4603", + "lane1": "0x1b4603", + "lane2": "0x1b4603", + "lane3": "0x1b4603" + } + } + }, + "6": { + "Default": { + "preemphasis": { + "lane0": "0x1c4503", + "lane1": "0x1c4503", + "lane2": "0x1c4503", + "lane3": "0x1c4503" + } + } + }, + "7": { + "Default": { + "preemphasis": { + "lane0": "0x174a03", + "lane1": "0x174a03", + "lane2": "0x174a03", + "lane3": "0x174a03" + } + } + }, + "8": { + "Default": { + "preemphasis": { + "lane0": "0x194803", + "lane1": "0x1b4603", + "lane2": "0x174a03", + "lane3": "0x174a03" + } + } + }, + "9": { + "Default": { + "preemphasis": { + "lane0": "0x1c4503", + "lane1": "0x1c4503", + "lane2": "0x1c4503", + "lane3": "0x1c4503" + } + } + }, + "10": { + "Default": { + "preemphasis": { + "lane0": "0x1c4503", + "lane1": "0x1c4503", + "lane2": "0x1c4503", + "lane3": "0x1d4403" + } + } + }, + "11": { + "Default": { + "preemphasis": { + "lane0": "0x1a4703", + "lane1": "0x1a4703", + "lane2": "0x1a4703", + "lane3": "0x1a4703" + } + } + }, + "12": { + "Default": { + "preemphasis": { + "lane0": "0x1b4603", + "lane1": "0x1b4603", + "lane2": "0x1a4703", + "lane3": "0x1b4603" + } + } + }, + "13": { + "Default": { + "preemphasis": { + "lane0": "0x154c03", + "lane1": "0x154c03", + "lane2": "0x154c03", + "lane3": "0x154c03" + } + } + }, + "14": { + "Default": { + "preemphasis": { + "lane0": "0x154c03", + "lane1": "0x154c03", + "lane2": "0x154c03", + "lane3": "0x154c03" + } + } + }, + "15": { + "Default": { + "preemphasis": { + "lane0": "0x154c03", + "lane1": "0x154c03", + "lane2": "0x154c03", + "lane3": "0x154c03" + } + } + }, + "16": { + "Default": { + "preemphasis": { + "lane0": "0x154c03", + "lane1": "0x154c03", + "lane2": "0x154c03", + "lane3": "0x154c03" + } + } + }, + "17": { + "Default": { + "preemphasis": { + "lane0": "0x154901", + "lane1": "0x124901", + "lane2": "0x124903", + "lane3": "0x144900" + } + } + }, + "18": { + "Default": { + "preemphasis": { + "lane0": "0x154900", + "lane1": "0x124904", + "lane2": "0x124901", + "lane3": "0x144902" + } + } + }, + "19": { + "Default": { + "preemphasis": { + "lane0": "0x154900", + "lane1": "0x124900", + "lane2": "0x124903", + "lane3": "0x144902" + } + } + }, + "20": { + "Default": { + "preemphasis": { + "lane0": "0x154903", + "lane1": "0x124904", + "lane2": "0x124904", + "lane3": "0x144904" + } + } + }, + "21": { + "Default": { + "preemphasis": { + "lane0": "0x194803", + "lane1": "0x194803", + "lane2": "0x194803", + "lane3": "0x194803" + } + } + }, + "22": { + "Default": { + "preemphasis": { + "lane0": "0x194803", + "lane1": "0x194803", + "lane2": "0x194803", + "lane3": "0x194803" + } + } + }, + "23": { + "Default": { + "preemphasis": { + "lane0": "0x1c4503", + "lane1": "0x1c4503", + "lane2": "0x1c4503", + "lane3": "0x1c4503" + } + } + }, + "24": { + "Default": { + "preemphasis": { + "lane0": "0x1e4303", + "lane1": "0x1e4303", + "lane2": "0x1d4403", + "lane3": "0x1e4303" + } + } + }, + "25": { + "Default": { + "preemphasis": { + "lane0": "0x154906", + "lane1": "0x154904", + "lane2": "0x154903", + "lane3": "0x154903" + } + } + }, + "26": { + "Default": { + "preemphasis": { + "lane0": "0x174902", + "lane1": "0x174902", + "lane2": "0x174902", + "lane3": "0x174904" + } + } + }, + "27": { + "Default": { + "preemphasis": { + "lane0": "0x1a4703", + "lane1": "0x184903", + "lane2": "0x184903", + "lane3": "0x1a4703" + } + } + }, + "28": { + "Default": { + "preemphasis": { + "lane0": "0x1a4703", + "lane1": "0x1a4703", + "lane2": "0x1a4703", + "lane3": "0x1a4703" + } + } + }, + "29": { + "Default": { + "preemphasis": { + "lane0": "0x1a4505", + "lane1": "0x1a4505", + "lane2": "0x1a4505", + "lane3": "0x1a4505" + } + } + }, + "30": { + "Default": { + "preemphasis": { + "lane0": "0x1b4603", + "lane1": "0x1b4603", + "lane2": "0x1b4603", + "lane3": "0x1b4603" + } + } + }, + "31": { + "Default": { + "preemphasis": { + "lane0": "0x1a4604", + "lane1": "0x1a4604", + "lane2": "0x1a4604", + "lane3": "0x1a4604" + } + } + }, + "32": { + "Default": { + "preemphasis": { + "lane0": "0x1b4504", + "lane1": "0x1b4504", + "lane2": "0x1a4703", + "lane3": "0x1b4504" + } + } + }, + "33": { + "Default": { + "preemphasis": { + "lane0": "0x1c4503", + "lane1": "0x1c4404", + "lane2": "0x1c4503", + "lane3": "0x1c4404" + } + } + }, + "34": { + "Default": { + "preemphasis": { + "lane0": "0x1c4503", + "lane1": "0x1c4503", + "lane2": "0x1c4503", + "lane3": "0x1c4503" + } + } + }, + "35": { + "Default": { + "preemphasis": { + "lane0": "0x1a4703", + "lane1": "0x1a4604", + "lane2": "0x1a4703", + "lane3": "0x1a4703" + } + } + }, + "36": { + "Default": { + "preemphasis": { + "lane0": "0x1c4503", + "lane1": "0x1b4603", + "lane2": "0x1b4603", + "lane3": "0x1b4603" + } + } + }, + "37": { + "Default": { + "preemphasis": { + "lane0": "0x1b4603", + "lane1": "0x1b4603", + "lane2": "0x1a4703", + "lane3": "0x1b4603" + } + } + }, + "38": { + "Default": { + "preemphasis": { + "lane0": "0x194803", + "lane1": "0x194803", + "lane2": "0x194803", + "lane3": "0x194803" + } + } + }, + "39": { + "Default": { + "preemphasis": { + "lane0": "0x164903", + "lane1": "0x164903", + "lane2": "0x164903", + "lane3": "0x164903" + } + } + }, + "40": { + "Default": { + "preemphasis": { + "lane0": "0x164901", + "lane1": "0x184901", + "lane2": "0x184901", + "lane3": "0x184901" + } + } + }, + "41": { + "Default": { + "preemphasis": { + "lane0": "0x1c4503", + "lane1": "0x1c4503", + "lane2": "0x1c4503", + "lane3": "0x1c4404" + } + } + }, + "42": { + "Default": { + "preemphasis": { + "lane0": "0x1b4603", + "lane1": "0x1a4703", + "lane2": "0x1b4603", + "lane3": "0x1c4503" + } + } + }, + "43": { + "Default": { + "preemphasis": { + "lane0": "0x1a4703", + "lane1": "0x1a4703", + "lane2": "0x1a4703", + "lane3": "0x1a4703" + } + } + }, + "44": { + "Default": { + "preemphasis": { + "lane0": "0x1b4603", + "lane1": "0x1b4603", + "lane2": "0x1a4703", + "lane3": "0x1b4603" + } + } + }, + "45": { + "Default": { + "preemphasis": { + "lane0": "0x184902", + "lane1": "0x184902", + "lane2": "0x154902", + "lane3": "0x184902" + } + } + }, + "46": { + "Default": { + "preemphasis": { + "lane0": "0x154900", + "lane1": "0x154900", + "lane2": "0x154900", + "lane3": "0x154900" + } + } + }, + "47": { + "Default": { + "preemphasis": { + "lane0": "0x174900", + "lane1": "0x174900", + "lane2": "0x154900", + "lane3": "0x174904" + } + } + }, + "48": { + "Default": { + "preemphasis": { + "lane0": "0x154903", + "lane1": "0x154903", + "lane2": "0x154903", + "lane3": "0x154903" + } + } + }, + "49": { + "Default": { + "preemphasis": { + "lane0": "0x184902", + "lane1": "0x164902", + "lane2": "0x164902", + "lane3": "0x144900" + } + } + }, + "50": { + "Default": { + "preemphasis": { + "lane0": "0x174901", + "lane1": "0x144902", + "lane2": "0x144902", + "lane3": "0x144903" + } + } + }, + "51": { + "Default": { + "preemphasis": { + "lane0": "0x184901", + "lane1": "0x174901", + "lane2": "0x164903", + "lane3": "0x154904" + } + } + }, + "52": { + "Default": { + "preemphasis": { + "lane0": "0x154903", + "lane1": "0x154903", + "lane2": "0x134903", + "lane3": "0x144904" + } + } + }, + "53": { + "Default": { + "preemphasis": { + "lane0": "0x1c4503", + "lane1": "0x1e4204", + "lane2": "0x1c4503", + "lane3": "0x1d4304" + } + } + }, + "54": { + "Default": { + "preemphasis": { + "lane0": "0x1a4703", + "lane1": "0x1a4703", + "lane2": "0x1a4703", + "lane3": "0x1a4703" + } + } + }, + "55": { + "Default": { + "preemphasis": { + "lane0": "0x194803", + "lane1": "0x194803", + "lane2": "0x194803", + "lane3": "0x194803" + } + } + }, + "56": { + "Default": { + "preemphasis": { + "lane0": "0x194803", + "lane1": "0x194803", + "lane2": "0x184903", + "lane3": "0x194803" + } + } + }, + "57": { + "Default": { + "preemphasis": { + "lane0": "0x184903", + "lane1": "0x184903", + "lane2": "0x184903", + "lane3": "0x184903" + } + } + }, + "58": { + "Default": { + "preemphasis": { + "lane0": "0x194803", + "lane1": "0x194803", + "lane2": "0x184903", + "lane3": "0x194803" + } + } + }, + "59": { + "Default": { + "preemphasis": { + "lane0": "0x1a4703", + "lane1": "0x1a4703", + "lane2": "0x1a4703", + "lane3": "0x1a4703" + } + } + }, + "60": { + "Default": { + "preemphasis": { + "lane0": "0x1a4703", + "lane1": "0x1a4703", + "lane2": "0x1a4703", + "lane3": "0x1a4703" + } + } + }, + "61": { + "Default": { + "preemphasis": { + "lane0": "0x1a4703", + "lane1": "0x1a4703", + "lane2": "0x1a4703", + "lane3": "0x1a4505" + } + } + }, + "62": { + "Default": { + "preemphasis": { + "lane0": "0x1b4603", + "lane1": "0x1b4603", + "lane2": "0x1b4603", + "lane3": "0x1b4603" + } + } + }, + "63": { + "Default": { + "preemphasis": { + "lane0": "0x1c4404", + "lane1": "0x1c4404", + "lane2": "0x1b4504", + "lane3": "0x1c4404" + } + } + }, + "64": { + "Default": { + "preemphasis": { + "lane0": "0x1b4504", + "lane1": "0x1b4504", + "lane2": "0x1a4703", + "lane3": "0x1b4504" + } + } + } + } +} diff --git a/device/accton/x86_64-accton_as7816_64x-r0/pcie.yaml b/device/accton/x86_64-accton_as7816_64x-r0/pcie.yaml new file mode 100644 index 0000000000..a021e60ab8 --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/pcie.yaml @@ -0,0 +1,465 @@ +- bus: '00' + dev: '00' + fn: '0' + id: 6f00 + name: 'Host bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2 + (rev 03)' +- bus: '00' + dev: '01' + fn: '0' + id: 6f02 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '01' + fn: '1' + id: 6f03 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 1 (rev 03)' +- bus: '00' + dev: '02' + fn: '0' + id: 6f04 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '02' + fn: '1' + id: 6f05 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '02' + fn: '2' + id: 6f06 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '02' + fn: '3' + id: 6f07 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 2 (rev 03)' +- bus: '00' + dev: '03' + fn: '0' + id: 6f08 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '03' + fn: '1' + id: 6f09 + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '03' + fn: '2' + id: 6f0a + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '03' + fn: '3' + id: 6f0b + name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI + Express Root Port 3 (rev 03)' +- bus: '00' + dev: '05' + fn: '0' + id: 6f28 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Map/VTd_Misc/System Management (rev 03)' +- bus: '00' + dev: '05' + fn: '1' + id: 6f29 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO Hot Plug (rev 03)' +- bus: '00' + dev: '05' + fn: '2' + id: 6f2a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D IIO RAS/Control Status/Global Errors (rev 03)' +- bus: '00' + dev: '05' + fn: '4' + id: 6f2c + name: 'PIC: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC (rev + 03)' +- bus: '00' + dev: '14' + fn: '0' + id: 8c31 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + xHCI (rev 05)' +- bus: '00' + dev: '16' + fn: '0' + id: 8c3a + name: 'Communication controller: Intel Corporation 8 Series/C220 Series Chipset + Family MEI Controller #1 (rev 04)' +- bus: '00' + dev: '16' + fn: '1' + id: 8c3b + name: 'Communication controller: Intel Corporation 8 Series/C220 Series Chipset + Family MEI Controller #2 (rev 04)' +- bus: '00' + dev: 1c + fn: '0' + id: 8c10 + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #1 (rev d5)' +- bus: '00' + dev: 1c + fn: '1' + id: 8c12 + name: 'PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express + Root Port #2 (rev d5)' +- bus: '00' + dev: 1d + fn: '0' + id: 8c26 + name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB + EHCI #1 (rev 05)' +- bus: '00' + dev: 1f + fn: '0' + id: 8c54 + name: 'ISA bridge: Intel Corporation C224 Series Chipset Family Server Standard + SKU LPC Controller (rev 05)' +- bus: '00' + dev: 1f + fn: '2' + id: 8c02 + name: 'SATA controller: Intel Corporation 8 Series/C220 Series Chipset Family 6-port + SATA Controller 1 [AHCI mode] (rev 05)' +- bus: '00' + dev: 1f + fn: '3' + id: 8c22 + name: 'SMBus: Intel Corporation 8 Series/C220 Series Chipset Family SMBus Controller + (rev 05)' +- bus: '03' + dev: '00' + fn: '0' + id: 6f50 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 0' +- bus: '03' + dev: '00' + fn: '1' + id: 6f51 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 1' +- bus: '03' + dev: '00' + fn: '2' + id: 6f52 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 2' +- bus: '03' + dev: '00' + fn: '3' + id: 6f53 + name: 'System peripheral: Intel Corporation Xeon Processor D Family QuickData Technology + Register DMA Channel 3' +- bus: '05' + dev: '00' + fn: '0' + id: 15ab + name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane' +- bus: '05' + dev: '00' + fn: '1' + id: 15ab + name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane' +- bus: '07' + dev: '00' + fn: '0' + id: b970 + name: 'Ethernet controller: Broadcom Inc. and subsidiaries Device b970 (rev 11)' +- bus: 0b + dev: '00' + fn: '0' + id: 165f + name: 'Ethernet controller: Broadcom Inc. and subsidiaries NetXtreme BCM5720 2-port + Gigabit Ethernet PCIe' +- bus: ff + dev: 0b + fn: '0' + id: 6f81 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '1' + id: 6f36 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '2' + id: 6f37 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link 0/1 (rev 03)' +- bus: ff + dev: 0b + fn: '3' + id: 6f76 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R3 QPI Link Debug (rev 03)' +- bus: ff + dev: 0c + fn: '0' + id: 6fe0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '1' + id: 6fe1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '2' + id: 6fe2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0c + fn: '3' + id: 6fe3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '0' + id: 6ff8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '4' + id: 6ffc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '5' + id: 6ffd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: 0f + fn: '6' + id: 6ffe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Caching Agent (rev 03)' +- bus: ff + dev: '10' + fn: '0' + id: 6f1d + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '1' + id: 6f34 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D R2PCIe Agent (rev 03)' +- bus: ff + dev: '10' + fn: '5' + id: 6f1e + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '6' + id: 6f7d + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '10' + fn: '7' + id: 6f1f + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Ubox (rev 03)' +- bus: ff + dev: '12' + fn: '0' + id: 6fa0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '12' + fn: '1' + id: 6f30 + name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Home Agent 0 (rev 03)' +- bus: ff + dev: '13' + fn: '0' + id: 6fa8 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '1' + id: 6f71 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Target Address/Thermal/RAS (rev 03)' +- bus: ff + dev: '13' + fn: '2' + id: 6faa + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '3' + id: 6fab + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '4' + id: 6fac + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '5' + id: 6fad + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel Target Address Decoder (rev 03)' +- bus: ff + dev: '13' + fn: '6' + id: 6fae + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Broadcast (rev 03)' +- bus: ff + dev: '13' + fn: '7' + id: 6faf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Global Broadcast (rev 03)' +- bus: ff + dev: '14' + fn: '0' + id: 6fb0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '1' + id: 6fb1 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Thermal Control (rev 03)' +- bus: ff + dev: '14' + fn: '2' + id: 6fb2 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 0 Error (rev 03)' +- bus: ff + dev: '14' + fn: '3' + id: 6fb3 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 1 Error (rev 03)' +- bus: ff + dev: '14' + fn: '4' + id: 6fbc + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '5' + id: 6fbd + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '6' + id: 6fbe + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '14' + fn: '7' + id: 6fbf + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D DDRIO Channel 0/1 Interface (rev 03)' +- bus: ff + dev: '15' + fn: '0' + id: 6fb4 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '1' + id: 6fb5 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Thermal Control (rev 03)' +- bus: ff + dev: '15' + fn: '2' + id: 6fb6 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 2 Error (rev 03)' +- bus: ff + dev: '15' + fn: '3' + id: 6fb7 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Memory Controller 0 - Channel 3 Error (rev 03)' +- bus: ff + dev: 1e + fn: '0' + id: 6f98 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '1' + id: 6f99 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '2' + id: 6f9a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '3' + id: 6fc0 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1e + fn: '4' + id: 6f9c + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '0' + id: 6f88 + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' +- bus: ff + dev: 1f + fn: '2' + id: 6f8a + name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon + D Power Control Unit (rev 03)' diff --git a/device/accton/x86_64-accton_as7816_64x-r0/pddf/pd-plugin.json b/device/accton/x86_64-accton_as7816_64x-r0/pddf/pd-plugin.json index eae22f99e3..edb5a5ad9a 100644 --- a/device/accton/x86_64-accton_as7816_64x-r0/pddf/pd-plugin.json +++ b/device/accton/x86_64-accton_as7816_64x-r0/pddf/pd-plugin.json @@ -32,11 +32,11 @@ { "i2c": { - "valmap": { "F2B":"EXHAUST", "B2F":"INTAKE" } + "valmap": { "F2B":"exhaust", "B2F":"intake" } } }, - "PSU_FAN_MAX_SPEED":"18000" + "PSU_FAN_MAX_SPEED":"26688" }, "FAN": @@ -45,7 +45,7 @@ { "i2c": { - "valmap": {"1":"INTAKE", "0":"EXHAUST"} + "valmap": {"1":"intake", "0":"exhaust"} } }, diff --git a/device/accton/x86_64-accton_as7816_64x-r0/pddf/pddf-device.json b/device/accton/x86_64-accton_as7816_64x-r0/pddf/pddf-device.json index f373f39601..2c1590a4b1 100644 --- a/device/accton/x86_64-accton_as7816_64x-r0/pddf/pddf-device.json +++ b/device/accton/x86_64-accton_as7816_64x-r0/pddf/pddf-device.json @@ -5,7 +5,7 @@ "num_fantrays":4, "num_fans_pertray":2, "num_ports":64, - "num_temps": 6, + "num_temps":11, "pddf_dev_types": { "description":"AS7816-64X - Below is the list of supported PDDF device types (chip names) for various components. If any component uses some other driver, we will create the client using 'echo > /new_device' method", @@ -52,7 +52,8 @@ ], "custom_kos": [ - "pddf_custom_fan" + "pddf_custom_fan", + "pddf_custom_psu" ] @@ -177,7 +178,11 @@ { "attr_name":"psu_i_out", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, { "attr_name":"psu_p_out", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, { "attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_temp1_input", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} + { "attr_name":"psu_temp1_input", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_v_out_max", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0xa5", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_v_out_min", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0xa4", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_p_out_max", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_temp1_high_threshold", "attr_devaddr":"0x5b", "attr_devtype":"pmbus", "attr_offset":"0xa8", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} ] } }, @@ -226,7 +231,11 @@ { "attr_name":"psu_i_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, { "attr_name":"psu_p_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, { "attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_temp1_input", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} + { "attr_name":"psu_temp1_input", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_v_out_max", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa5", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_v_out_min", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa4", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_p_out_max", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_temp1_high_threshold", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa8", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} ] } }, @@ -406,6 +415,81 @@ ] } }, + "TEMP7" : + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP7"}, + "dev_attr": { "display_name":"CPU_Package_temp"}, + "i2c": + { + "path_info": {"sysfs_base_path": "/sys/class/hwmon/hwmon0"}, + "attr_list": + [ + { "attr_name": "temp1_high_crit_threshold", "drv_attr_name":"temp1_crit"}, + { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + { "attr_name": "temp1_input"} + ] + } + }, + "TEMP8" : + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP8"}, + "dev_attr": { "display_name":"CPU_Core_0_temp"}, + "i2c": + { + "path_info": {"sysfs_base_path": "/sys/class/hwmon/hwmon0"}, + "attr_list": + [ + { "attr_name": "temp1_high_crit_threshold", "drv_attr_name":"temp2_crit"}, + { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp2_max"}, + { "attr_name": "temp1_input", "drv_attr_name":"temp2_input"} + ] + } + }, + "TEMP9" : + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP9"}, + "dev_attr": { "display_name":"CPU_Core_1_temp"}, + "i2c": + { + "path_info": {"sysfs_base_path": "/sys/class/hwmon/hwmon0"}, + "attr_list": + [ + { "attr_name": "temp1_high_crit_threshold", "drv_attr_name":"temp3_crit"}, + { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp3_max"}, + { "attr_name": "temp1_input", "drv_attr_name":"temp3_input"} + ] + } + }, + "TEMP10" : + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP10"}, + "dev_attr": { "display_name":"CPU_Core_2_temp"}, + "i2c": + { + "path_info": {"sysfs_base_path": "/sys/class/hwmon/hwmon0"}, + "attr_list": + [ + { "attr_name": "temp1_high_crit_threshold", "drv_attr_name":"temp4_crit"}, + { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp4_max"}, + { "attr_name": "temp1_input", "drv_attr_name":"temp4_input"} + ] + } + }, + "TEMP11" : + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP11"}, + "dev_attr": { "display_name":"CPU_Core_3_temp"}, + "i2c": + { + "path_info": {"sysfs_base_path": "/sys/class/hwmon/hwmon0"}, + "attr_list": + [ + { "attr_name": "temp1_high_crit_threshold", "drv_attr_name":"temp5_crit"}, + { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp5_max"}, + { "attr_name": "temp1_input", "drv_attr_name":"temp5_input"} + ] + } + }, "CPLD1": { "dev_info": { "device_type":"CPLD", "device_name":"CPLD1", "device_parent":"MUX3"}, @@ -3178,12 +3262,12 @@ "LOC_LED": { "dev_info": { "device_type":"LED", "device_name":"LOC_LED"}, - "dev_attr": { "index":"0"}, + "dev_attr": { "index":"0", "flag":"rw"}, "i2c" : { "attr_list": [ - {"attr_name":"STATUS_LED_COLOR_AMBER", "descr" : "Amber", "bits" : "4", "value" : "0x0", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_OFF", "descr" : "Off", "bits" : "4", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"} + {"attr_name":"amber", "descr" : "Amber", "bits" : "4", "value" : "0x0", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"off", "descr" : "Off", "bits" : "4", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"} ] } }, @@ -3191,15 +3275,57 @@ "DIAG_LED": { "dev_info": { "device_type":"LED", "device_name":"DIAG_LED"}, + "dev_attr": { "index":"0", "flag":"rw"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"green", "descr" : "Green", "bits" : "1:0", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"red", "descr" : "Red" ,"bits" : "1:0", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"off", "descr" : "Off" ,"bits" : "1:0", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"} + ] + } + + }, + + "PSU1_LED": + { + "dev_info": { "device_type":"LED", "device_name":"PSU_LED"}, "dev_attr": { "index":"0"}, "i2c" : { "attr_list": [ - {"attr_name":"STATUS_LED_COLOR_GREEN", "descr" : "Green", "bits" : "1:0", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_RED", "descr" : "Red" ,"bits" : "1:0", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_OFF", "descr" : "Off" ,"bits" : "1:0", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"} + {"attr_name":"green", "descr": "Green", "bits" : "1:0", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, + {"attr_name":"amber", "descr": "Amber", "bits" : "1:0", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, + {"attr_name":"off", "descr": "Off", "bits" : "1:0", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"} ] } + }, + + "PSU2_LED": + { + "dev_info": { "device_type":"LED", "device_name":"PSU_LED"}, + "dev_attr": { "index":"1"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"green", "descr": "Green", "bits" : "3:2", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, + {"attr_name":"amber", "descr": "Amber", "bits" : "3:2", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, + {"attr_name":"off", "descr": "Off", "bits" : "3:2", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"} + ] + } + }, - } + "FAN_LED": + { + "dev_info": { "device_type":"LED", "device_name":"FAN_LED"}, + "dev_attr": { "index":"0"}, + "i2c" : { + "attr_list": + [ + {"attr_name":"green", "descr": "Green", "bits" : "3:2", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"amber", "descr": "Amber", "bits" : "3:2", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"off", "descr": "Off", "bits" : "3:2", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"} + ] + } + } } diff --git a/device/accton/x86_64-accton_as7816_64x-r0/platform.json b/device/accton/x86_64-accton_as7816_64x-r0/platform.json index aa0f78a032..d130985395 100755 --- a/device/accton/x86_64-accton_as7816_64x-r0/platform.json +++ b/device/accton/x86_64-accton_as7816_64x-r0/platform.json @@ -1,6 +1,11 @@ { "chassis": { "name": "7816-64X", + "thermal_manager":false, + "status_led": { + "controllable": true, + "colors": ["green", "red", "off"] + }, "components": [ { "name": "CPLD1" @@ -15,88 +20,222 @@ "name": "CPLD4" }, { - "name": "BIOS" - } - ], - "fans": [ - { - "name": "FAN-1F" - }, - { - "name": "FAN-1R" + "name": "CPLD5" }, { - "name": "FAN-2F" + "name": "CPLD6" }, { - "name": "FAN-2R" - }, - { - "name": "FAN-3F" - }, - { - "name": "FAN-3R" - }, - { - "name": "FAN-4F" - }, + "name": "BIOS" + } + ], + "fans": [ { - "name": "FAN-4R" + "name": "FAN-1F", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-1R", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-2F", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-2R", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-3F", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-3R", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-4F", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-4R", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } } - ], + ], "fan_drawers":[ { "name": "FanTray1", + "status_led": { + "controllable": false + }, "num_fans" : 2, "fans": [ { - "name": "FAN-1F" + "name": "FAN-1F", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } }, { - "name": "FAN-1R" + "name": "FAN-1R", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } } ] }, { "name": "FanTray2", + "status_led": { + "controllable": false + }, "num_fans" : 2, "fans": [ { - "name": "FAN-2F" + "name": "FAN-2F", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } }, { - "name": "FAN-2R" + "name": "FAN-2R", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } } ] }, { "name": "FanTray3", + "status_led": { + "controllable": false + }, "num_fans" : 2, "fans": [ { - "name": "FAN-3F" + "name": "FAN-3F", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } }, { - "name": "FAN-3R" + "name": "FAN-3R", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } } ] }, { "name": "FanTray4", + "status_led": { + "controllable": false + }, "num_fans" : 2, "fans": [ { - "name": "FAN-4F" + "name": "FAN-4F", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } }, { - "name": "FAN-4R" + "name": "FAN-4R", + "speed": { + "controllable": true, + "minimum": 18 + }, + "status_led": { + "controllable": false + } } ] } - ], + ], "psus": [ { "name": "PSU-1", + "status_led": { + "controllable": true, + "colors": ["green", "amber", "off"] + }, "fans": [ { "name": "PSU-1 FAN-1" @@ -104,12 +243,19 @@ ], "thermals": [ { - "name": "PSU-1 temp sensor 1" + "name": "PSU-1 temp sensor 1", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false } ] }, { "name": "PSU-2", + "status_led": { + "controllable": true, + "colors": ["green", "amber", "off"] + }, "fans": [ { "name": "PSU-2 FAN-1" @@ -117,31 +263,109 @@ ], "thermals": [ { - "name": "PSU-2 temp sensor 2" + "name": "PSU-2 temp sensor 2", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false } ] } ], "thermals": [ { - "name": "Temp sensor 1" - }, - { - "name": "Temp sensor 2" - }, - { - "name": "Temp sensor 3" - }, - { - "name": "Temp sensor 4" - }, - { - "name": "Temp sensor 5" - }, - { - "name": "Temp sensor 6" + "name": "FB_1_temp(0x4D)", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + }, + { + "name": "FB_2_temp(0x4E)", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + }, + { + "name": "MB_MAC_temp(0x48)", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "MB_RearCenter_temp(0x49)", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "MB_RightCenter_temp(0x4A)", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "CpuBoard_temp(0x4B)", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "CPU_Package_temp", + "controllable": false, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "CPU_Core_0_temp", + "controllable": false, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "CPU_Core_1_temp", + "controllable": false, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "CPU_Core_2_temp", + "controllable": false, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + }, + { + "name": "CPU_Core_3_temp", + "controllable": false, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true } ], + "modules": [], "sfps": [ { "name": "Ethernet0" diff --git a/device/accton/x86_64-accton_as7816_64x-r0/platform_components.json b/device/accton/x86_64-accton_as7816_64x-r0/platform_components.json new file mode 100644 index 0000000000..17bdcb0851 --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/platform_components.json @@ -0,0 +1,15 @@ +{ + "chassis": { + "7816-64X-O-AC-F-R": { + "component": { + "CPLD1": { }, + "CPLD2": { }, + "CPLD3": { }, + "CPLD4": { }, + "CPLD5": { }, + "CPLD6": { }, + "BIOS": { } + } + } + } +} diff --git a/device/accton/x86_64-accton_as7816_64x-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as7816_64x-r0/plugins/eeprom.py deleted file mode 100644 index 4241483d68..0000000000 --- a/device/accton/x86_64-accton_as7816_64x-r0/plugins/eeprom.py +++ /dev/null @@ -1,20 +0,0 @@ -try: - import binascii - import time - import optparse - import warnings - import os - import sys - from sonic_eeprom import eeprom_base - from sonic_eeprom import eeprom_tlvinfo - import subprocess -except ImportError as e: - raise ImportError(str(e) + "- required module not found") - - -class board(eeprom_tlvinfo.TlvInfoDecoder): - _TLV_INFO_MAX_LEN = 256 - - def __init__(self, name, path, cpld_root, ro): - self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom" - super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/accton/x86_64-accton_as7816_64x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as7816_64x-r0/plugins/psuutil.py deleted file mode 100755 index b05cf3e477..0000000000 --- a/device/accton/x86_64-accton_as7816_64x-r0/plugins/psuutil.py +++ /dev/null @@ -1,60 +0,0 @@ -############################################################################# -# Accton -# -# Module contains an implementation of SONiC PSU Base API and -# provides the PSUs status which are available in the platform -# -############################################################################# - -import os.path - -try: - from sonic_psu.psu_base import PsuBase -except ImportError as e: - raise ImportError(str(e) + "- required module not found") - - -class PsuUtil(PsuBase): - """Platform-specific PSUutil class""" - - def __init__(self): - PsuBase.__init__(self) - - self.psu_path = "/sys/bus/i2c/devices/" - self.psu_presence = "/psu_present" - self.psu_oper_status = "/psu_power_good" - self.psu_mapping = { - 1: "10-0053", - 2: "9-0050", - } - - def get_num_psus(self): - return len(self.psu_mapping) - - def get_psu_status(self, index): - if index is None: - return False - - status = 0 - node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status - try: - with open(node, 'r') as power_status: - status = int(power_status.read()) - except IOError: - return False - - return status == 1 - - def get_psu_presence(self, index): - if index is None: - return False - - status = 0 - node = self.psu_path + self.psu_mapping[index] + self.psu_presence - try: - with open(node, 'r') as presence_status: - status = int(presence_status.read()) - except IOError: - return False - - return status == 1 diff --git a/device/accton/x86_64-accton_as7816_64x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as7816_64x-r0/plugins/sfputil.py deleted file mode 100644 index 0520799d38..0000000000 --- a/device/accton/x86_64-accton_as7816_64x-r0/plugins/sfputil.py +++ /dev/null @@ -1,269 +0,0 @@ -try: - import time - import string - from ctypes import create_string_buffer - from sonic_sfp.sfputilbase import SfpUtilBase -except ImportError as e: - raise ImportError(str(e) + "- required module not found") - -# from xcvrd -SFP_STATUS_INSERTED = '1' -SFP_STATUS_REMOVED = '0' - - -class SfpUtil(SfpUtilBase): - """Platform specific SfpUtill class""" - - _port_start = 1 - _port_end = 64 - ports_in_block = 64 - - _port_to_eeprom_mapping = {} - port_to_i2c_mapping = { - 61: 25, - 62: 26, - 63: 27, - 64: 28, - 55: 29, - 56: 30, - 53: 31, - 54: 32, - 9: 33, - 10: 34, - 11: 35, - 12: 36, - 1: 37, - 2: 38, - 3: 39, - 4: 40, - 6: 41, - 5: 42, - 8: 43, - 7: 44, - 13: 45, - 14: 46, - 15: 47, - 16: 48, - 17: 49, - 18: 50, - 19: 51, - 20: 52, - 25: 53, - 26: 54, - 27: 55, - 28: 56, - 29: 57, - 30: 58, - 31: 59, - 32: 60, - 21: 61, - 22: 62, - 23: 63, - 24: 64, - 41: 65, - 42: 66, - 43: 67, - 44: 68, - 33: 69, - 34: 70, - 35: 71, - 36: 72, - 45: 73, - 46: 74, - 47: 75, - 48: 76, - 37: 77, - 38: 78, - 39: 79, - 40: 80, - 57: 81, - 58: 82, - 59: 83, - 60: 84, - 49: 85, - 50: 86, - 51: 87, - 52: 88, } - - _qsfp_ports = list(range(0, ports_in_block + 1)) - - def __init__(self): - eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' - for x in range(self.port_start, self.port_end + 1): - port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x]) - self._port_to_eeprom_mapping[x] = port_eeprom_path - SfpUtilBase.__init__(self) - - def reset(self, port_num): - # Check for invalid port_num - if port_num < self.port_start or port_num > self.port_end: - return False - path = "/sys/bus/i2c/devices/19-0060/module_reset_{0}" - port_ps = path.format(port_num) - - try: - reg_file = open(port_ps, 'w') - except IOError as e: - print("Error: unable to open file: %s" % str(e)) - return False - - # HW will clear reset after set. - reg_file.seek(0) - reg_file.write('1') - reg_file.close() - return True - - def get_presence(self, port_num): - # Check for invalid port_num - if port_num < self.port_start or port_num > self.port_end: - return False - - path = "/sys/bus/i2c/devices/19-0060/module_present_{0}" - port_ps = path.format(port_num) - - reg_value = '0' - try: - reg_file = open(port_ps) - reg_value = reg_file.readline().rstrip() - reg_file.close() - except IOError as e: - print("Error: unable to access file: %s" % str(e)) - return False - - if reg_value == '1': - return True - - return False - - @property - def port_start(self): - return self._port_start - - @property - def port_end(self): - return self._port_end - - @property - def qsfp_ports(self): - return list(range(0, self.ports_in_block + 1)) - - @property - def port_to_eeprom_mapping(self): - return self._port_to_eeprom_mapping - - def get_low_power_mode(self, port_num): - # Check for invalid port_num - if port_num < self._port_start or port_num > self._port_end: - return False - - try: - eeprom = None - - if not self.get_presence(port_num): - return False - - eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") - eeprom.seek(93) - lpmode = ord(eeprom.read(1)) - - if ((lpmode & 0x3) == 0x3): - return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1 - else: - # High Power Mode if one of the following conditions is matched: - # 1. "Power override" bit is 0 - # 2. "Power override" bit is 1 and "Power set" bit is 0 - return False - except IOError as e: - print("Error: unable to open file: %s" % str(e)) - return False - finally: - if eeprom is not None: - eeprom.close() - time.sleep(0.01) - - def set_low_power_mode(self, port_num, lpmode): - # Check for invalid port_num - if port_num < self._port_start or port_num > self._port_end: - return False - - try: - eeprom = None - - if not self.get_presence(port_num): - return False # Port is not present, unable to set the eeprom - - # Fill in write buffer - regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode - buffer = create_string_buffer(1) - buffer[0] = chr(regval) - - # Write to eeprom - eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") - eeprom.seek(93) - eeprom.write(buffer[0]) - return True - except IOError as e: - print("Error: unable to open file: %s" % str(e)) - return False - finally: - if eeprom is not None: - eeprom.close() - time.sleep(0.01) - - @property - def _get_present_bitmap(self): - nodes = [] - - cpld_path = "/sys/bus/i2c/devices/19-0060/" - nodes.append(cpld_path + "module_present_all") - - bitmap = "" - for node in nodes: - try: - reg_file = open(node) - - except IOError as e: - print("Error: unable to open file: %s" % str(e)) - return False - bitmap += reg_file.readline().rstrip() + " " - reg_file.close() - - rev = bitmap.split(" ") - rev = "".join(rev[::-1]) - return int(rev, 16) - - data = {'valid': 0, 'last': 0, 'present': 0} - - def get_transceiver_change_event(self, timeout=2000): - now = time.time() - port_dict = {} - port = 0 - - if timeout < 1000: - timeout = 1000 - timeout = (timeout) / float(1000) # Convert to secs - - if now < (self.data['last'] + timeout) and self.data['valid']: - return True, {} - - reg_value = self._get_present_bitmap - reg_value = ~reg_value - changed_ports = self.data['present'] ^ reg_value - if changed_ports: - for port in range(self.port_start, self.port_end+1): - # Mask off the bit corresponding to our port - mask = (1 << (port - 1)) - if changed_ports & mask: - if (reg_value & mask) == 0: - port_dict[port] = SFP_STATUS_REMOVED - else: - port_dict[port] = SFP_STATUS_INSERTED - - # Update cache - self.data['present'] = reg_value - self.data['last'] = now - self.data['valid'] = 1 - return True, port_dict - else: - return True, {} - return False, {} diff --git a/device/accton/x86_64-accton_as7816_64x-r0/plugins/ssd_util.py b/device/accton/x86_64-accton_as7816_64x-r0/plugins/ssd_util.py new file mode 100755 index 0000000000..4b173c5e38 --- /dev/null +++ b/device/accton/x86_64-accton_as7816_64x-r0/plugins/ssd_util.py @@ -0,0 +1,24 @@ +# ssd_util.py +# +# Platform-specific SSD interface for SONiC +## + +try: + from sonic_platform_base.sonic_ssd.ssd_generic import SsdUtil as MainSsdUtil +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +NOT_AVAILABLE = "N/A" + +class SsdUtil(MainSsdUtil): + """Platform-specific SsdUtil class""" + + def __init__(self, diskdev): + super(SsdUtil, self).__init__(diskdev) + + # If it has no vendor tool to read SSD information, + # ssd_util.py will use generic SSD information + # for vendor SSD information. + if self.vendor_ssd_info == NOT_AVAILABLE: + self.vendor_ssd_info = self.ssd_info + diff --git a/device/accton/x86_64-accton_as7816_64x-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as7816_64x-r0/pmon_daemon_control.json index a3b204e20d..44bad64942 100644 --- a/device/accton/x86_64-accton_as7816_64x-r0/pmon_daemon_control.json +++ b/device/accton/x86_64-accton_as7816_64x-r0/pmon_daemon_control.json @@ -1,5 +1,4 @@ { - "skip_ledd": true, - "skip_pcied": true + "skip_ledd": true } diff --git a/device/accton/x86_64-accton_as7816_64x-r0/sonic_platform/eeprom.py b/device/accton/x86_64-accton_as7816_64x-r0/sonic_platform/eeprom.py index c87f01c50a..aef3ead849 100644 --- a/device/accton/x86_64-accton_as7816_64x-r0/sonic_platform/eeprom.py +++ b/device/accton/x86_64-accton_as7816_64x-r0/sonic_platform/eeprom.py @@ -6,7 +6,7 @@ from io import StringIO else: from cStringIO import StringIO - + from sonic_platform_base.sonic_eeprom import eeprom_tlvinfo except ImportError as e: raise ImportError(str(e) + "- required module not found") @@ -33,7 +33,7 @@ def __parse_output(self, decode_output): for line in lines: try: match = re.search( - '(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+)', line) + '(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)(.+)', line) if match is not None: idx = match.group(1) value = match.group(3).rstrip('\0') @@ -129,6 +129,6 @@ def get_serial(self): def get_mac(self): return self._eeprom.get('0x24', NULL) - + def get_product_name(self): return self._eeprom.get('0x21', NULL) diff --git a/device/accton/x86_64-accton_as7816_64x-r0/sonic_platform/helper.py b/device/accton/x86_64-accton_as7816_64x-r0/sonic_platform/helper.py index b19fab85de..fdbd0f46a0 100644 --- a/device/accton/x86_64-accton_as7816_64x-r0/sonic_platform/helper.py +++ b/device/accton/x86_64-accton_as7816_64x-r0/sonic_platform/helper.py @@ -1,8 +1,8 @@ import os import struct -import subprocess from mmap import * from sonic_py_common import device_info +from sonic_py_common.general import getstatusoutput_noshell HOST_CHK_CMD = ["docker"] EMPTY_STRING = "" @@ -14,7 +14,11 @@ def __init__(self): (self.platform, self.hwsku) = device_info.get_platform_and_hwsku() def is_host(self): - return subprocess.call(HOST_CHK_CMD) == 0 + try: + status, output = getstatusoutput_noshell(HOST_CHK_CMD) + return status == 0 + except Exception: + return False def pci_get_value(self, resource, offset): status = True diff --git a/device/accton/x86_64-accton_as7816_64x-r0/system_health_monitoring_config.json b/device/accton/x86_64-accton_as7816_64x-r0/system_health_monitoring_config.json index 92be29dfde..7e3fdbf953 100644 --- a/device/accton/x86_64-accton_as7816_64x-r0/system_health_monitoring_config.json +++ b/device/accton/x86_64-accton_as7816_64x-r0/system_health_monitoring_config.json @@ -1,15 +1,13 @@ { "services_to_ignore": [], "devices_to_ignore": [ - "asic", - "psu.temperature" - + "asic" ], "user_defined_checkers": [], "polling_interval": 60, "led_color": { - "fault": "STATUS_LED_COLOR_RED", - "normal": "STATUS_LED_COLOR_GREEN", - "booting": "STATUS_LED_COLOR_GREEN" + "fault": "red", + "normal": "green", + "booting": "green" } } diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/Makefile index 3e3a9ac38a..9dd8ba6856 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/Makefile +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/Makefile @@ -1,6 +1,8 @@ obj-m:=x86-64-accton-as7816-64x-fan.o x86-64-accton-as7816-64x-leds.o \ - x86-64-accton-as7816-64x-psu.o accton_i2c_cpld.o ym2651y.o pddf_custom_fan.o + x86-64-accton-as7816-64x-psu.o accton_i2c_cpld.o ym2651y.o pddf_custom_fan.o \ + pddf_custom_psu.o CFLAGS_pddf_custom_fan.o := -I$(M)/../../../../pddf/i2c/modules/include +CFLAGS_pddf_custom_psu.o := -I$(M)/../../../../pddf/i2c/modules/include KBUILD_EXTRA_SYMBOLS := $(M)/../../../../pddf/i2c/Module.symvers.PDDF diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/accton_psu_api.h b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/accton_psu_api.h new file mode 120000 index 0000000000..a6b156930a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/accton_psu_api.h @@ -0,0 +1 @@ +../../common/modules/accton_psu_api.h \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/accton_psu_defs.h b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/accton_psu_defs.h new file mode 120000 index 0000000000..96202b3ead --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/accton_psu_defs.h @@ -0,0 +1 @@ +../../common/modules/accton_psu_defs.h \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/pddf_custom_psu.c b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/pddf_custom_psu.c new file mode 100644 index 0000000000..4d2f3849f3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/modules/pddf_custom_psu.c @@ -0,0 +1,273 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_psu_defs.h" + +extern PSU_SYSFS_ATTR_DATA access_psu_serial_num; +extern PSU_SYSFS_ATTR_DATA access_psu_v_out; + +#define MAX_MODEL_NAME 10 +#define MAX_SERIAL_NUMBER 19 + +#define PSU_REG_VOUT_MODE 0x20 +#define PSU_REG_READ_VOUT 0x8B + +enum psu_type { + PSU_TYPE_AC_D850AB_5A, + PSU_TYPE_AC_D850AB_5B, + PSU_TYPE_AC_YM2851F, + PSU_TYPE_DC_YM2851J +}; + +struct model_name_info { + enum psu_type type; + u8 offset; + u8 length; + u8 chk_length; + char* model_name; +}; + +struct serial_number_info { + enum psu_type type; + u8 offset; + u8 length; + u8 chk_length; + char* serial_number; +}; + +struct model_name_info models[] = { + { PSU_TYPE_AC_D850AB_5A, 0x15, 10, 10, "D850AB-5 A" }, + { PSU_TYPE_AC_D850AB_5B, 0x15, 10, 10, "D850AB-5 B" }, + { PSU_TYPE_AC_YM2851F, 0x20, 8, 8, "YM-2851F" }, + { PSU_TYPE_DC_YM2851J, 0x20, 8, 8, "YM-2851J" } +}; + +struct serial_number_info serials[] = { + { PSU_TYPE_AC_D850AB_5A, 0x2e, 11, 11, "D850AB-5 A" }, + { PSU_TYPE_AC_D850AB_5B, 0x2e, 11, 11, "D850AB-5 B" }, + { PSU_TYPE_AC_YM2851F, 0x35, 18, 18, "YM-2851F" }, + { PSU_TYPE_DC_YM2851J, 0x35, 18, 18, "YM-2851J" } +}; + +struct pddf_psu_data { + char model_name[MAX_MODEL_NAME+1]; + char serial_number[MAX_SERIAL_NUMBER+1]; +}; + +static int pddf_psu_read_byte(struct i2c_client *client, u8 reg) +{ + int result = 0; + int retry_count = 10; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_byte_data(client, reg); + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + break; + } + + return result; +} + +static int pddf_psu_read_word(struct i2c_client *client, u8 reg) +{ + int result = 0; + int retry_count = 10; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_word_data(client, reg); + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + break; + } + + return result; +} + +static int pddf_psu_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int result = 0; + int retry_count = 10; + + while (retry_count) { + retry_count--; + + result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(result < 0)) { + msleep(10); + continue; + } + + if (unlikely(result != data_len)) { + result = -EIO; + msleep(10); + continue; + } + + result = 0; + break; + } + + return result; +} + +ssize_t pddf_get_custom_psu_serial_num(struct device *dev, struct device_attribute *da, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct pddf_psu_data data; + int i, status; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + memset(data.serial_number, 0, sizeof(data.serial_number)); + + status = pddf_psu_read_block(client, models[i].offset, + data.model_name, models[i].length); + if (status < 0) { + data.model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x%x)\n", + client->addr, models[i].offset); + return status; + } + else { + data.model_name[models[i].length] = '\0'; + } + + /* Determine if the model name is known, if not, read next index + */ + if (strncmp(data.model_name, models[i].model_name, models[i].chk_length) == 0) { + status = pddf_psu_read_block(client, serials[i].offset, + data.serial_number, serials[i].length); + + if (status < 0) { + data.serial_number[0] = '\0'; + dev_dbg(&client->dev, "unable to read serial num from (0x%x) offset(0x%x)\n", + client->addr, serials[i].offset); + return status; + } + else { + data.serial_number[serials[i].length] = '\0'; + return sprintf(buf, "%s\n", data.serial_number); + } + + return 0; + } + else { + data.serial_number[0] = '\0'; + } + } + + return -ENODATA; +} + +static int twos_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t show_vout_linear(char *buf, u8 vout_mode, u16 read_vout) +{ + int exponent = 0, mantissa = read_vout; + int multiplier = 1000; + + exponent = twos_complement_to_int(vout_mode, 5, 0x1f); + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_vout_literal(char *buf, u16 read_vout) +{ + int exponent, mantissa; + int multiplier = 1000; + + exponent = twos_complement_to_int(read_vout >> 11, 5, 0x1F); + mantissa = twos_complement_to_int(read_vout & 0x7FF, 11, 0x7FF); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +ssize_t pddf_get_custom_psu_v_out(struct device *dev, struct device_attribute *da, char *buf) +{ + u8 reg = 0; + u8 vout_mode = 0xFF; + u16 read_vout = 0; + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + + reg = PSU_REG_VOUT_MODE; /* PMBus VOUT_MODE */ + status = pddf_psu_read_byte(client, reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", reg, status); + return status; + } + else { + vout_mode = status; + } + + reg = PSU_REG_READ_VOUT; /* PMBus READ_VOUT */ + status = pddf_psu_read_word(client, reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", reg, status); + return status; + } + else { + read_vout = status; + } + + if ((vout_mode & 0xE0) == 0x20) { + return -ENODATA; + } + else if (!(vout_mode & 0xE0)) { + /* Linear mode */ + return show_vout_linear(buf, vout_mode, read_vout); + } + else { + /* Default literal format */ + return show_vout_literal(buf, read_vout); + } +} + +static int __init pddf_custom_psu_init(void) +{ + access_psu_serial_num.show = pddf_get_custom_psu_serial_num; + access_psu_serial_num.do_get = NULL; + + access_psu_v_out.show = pddf_get_custom_psu_v_out; + access_psu_v_out.do_get = NULL; + + return 0; +} + +static void __exit pddf_custom_psu_exit(void) +{ + return; +} + +MODULE_AUTHOR("Broadcom"); +MODULE_DESCRIPTION("pddf custom psu api"); +MODULE_LICENSE("GPL"); + +module_init(pddf_custom_psu_init); +module_exit(pddf_custom_psu_exit); diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-64x-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-64x-platform-monitor.service index f361642e69..e9005d1477 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-64x-platform-monitor.service +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-64x-platform-monitor.service @@ -1,6 +1,6 @@ [Unit] Description=Accton AS7816-64X Platform Monitoring service -Before=pmon.service +Before=pmon.service system-health.service After=as7816-64x-platform-init.service Requires=as7816-64x-platform-init.service DefaultDependencies=no diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-pddf-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-pddf-platform-monitor.service index 7b6db7ddac..825a76fded 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-pddf-platform-monitor.service +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-pddf-platform-monitor.service @@ -1,6 +1,6 @@ [Unit] Description=Accton AS7816-64X Platform Monitoring service -Before=pmon.service +Before=pmon.service system-health.service After=pddf-platform-init.service DefaultDependencies=no diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/chassis.py index c597c0d8bb..4b79ff1c74 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/chassis.py @@ -8,59 +8,39 @@ try: import sys - import time from sonic_platform_pddf_base.pddf_chassis import PddfChassis + from .event import SfpEvent + from .helper import APIHelper except ImportError as e: raise ImportError(str(e) + "- required module not found") +NUM_COMPONENT = 7 +HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/" +PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/" +REBOOT_CAUSE_FILE = "reboot-cause.txt" class Chassis(PddfChassis): """ PDDF Platform-specific Chassis class """ + SYSLED_DEV_NAME = "DIAG_LED" + def __init__(self, pddf_data=None, pddf_plugin_data=None): PddfChassis.__init__(self, pddf_data, pddf_plugin_data) + self.__initialize_components() + self._sfpevent = SfpEvent(self.get_all_sfps()) + self._api_helper = APIHelper() - # Provide the functions/variables below for which implementation is to be overwritten - sfp_change_event_data = {'valid': 0, 'last': 0, 'present': 0} - def get_change_event(self, timeout=2000): - now = time.time() - port_dict = {} - change_dict = {} - change_dict['sfp'] = port_dict - - if timeout < 1000: - timeout = 1000 - timeout = timeout / float(1000) # Convert to secs - - if now < (self.sfp_change_event_data['last'] + timeout) and self.sfp_change_event_data['valid']: - return True, change_dict - - bitmap = 0 - for i in range(64): - modpres = self.get_sfp(i+1).get_presence() - if modpres: - bitmap = bitmap | (1 << i) - - changed_ports = self.sfp_change_event_data['present'] ^ bitmap - if changed_ports: - for i in range(64): - if (changed_ports & (1 << i)): - if (bitmap & (1 << i)) == 0: - port_dict[i+1] = '0' - else: - port_dict[i+1] = '1' - - - # Update teh cache dict - self.sfp_change_event_data['present'] = bitmap - self.sfp_change_event_data['last'] = now - self.sfp_change_event_data['valid'] = 1 - return True, change_dict - else: - return True, change_dict + def __initialize_components(self): + from sonic_platform.component import Component + for index in range(NUM_COMPONENT): + component = Component(index) + self._component_list.append(component) + # Provide the functions/variables below for which implementation is to be overwritten + def get_change_event(self, timeout=0): + return self._sfpevent.get_sfp_event(timeout) def get_sfp(self, index): """ @@ -84,3 +64,63 @@ def get_sfp(self, index): sys.stderr.write("SFP index {} out of range (1-{})\n".format( index, len(self._sfp_list))) return sfp + + def initizalize_system_led(self): + return + + def get_status_led(self): + return self.get_system_led(self.SYSLED_DEV_NAME) + + def set_status_led(self, color): + return self.set_system_led(self.SYSLED_DEV_NAME, color) + + def get_port_or_cage_type(self, port): + from sonic_platform_base.sfp_base import SfpBase + return SfpBase.SFP_PORT_TYPE_BIT_QSFP28 + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + If the agent cannot determine the parent-relative position + for some reason, or if the associated value of + entPhysicalContainedIn is'0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device + or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + + reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) + sw_reboot_cause = self._api_helper.read_txt_file( + reboot_cause_path) or "Unknown" + + + return ('REBOOT_CAUSE_NON_HARDWARE', sw_reboot_cause) + + def get_revision(self): + """ + Retrieves the hardware revision of the device + + Returns: + string: Revision value of device + """ + return self._eeprom.revision_str() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/component.py new file mode 100644 index 0000000000..5dd3700692 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/component.py @@ -0,0 +1,208 @@ +############################################################################# +# +# Component contains an implementation of SONiC Platform Base API and +# provides the components firmware management function +# +############################################################################# + +try: + import os + import json + from sonic_platform_base.component_base import ComponentBase + from sonic_py_common.general import getstatusoutput_noshell +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +CPLD_ADDR_MAPPING = { + "CPLD1": ['19', '0x60'], + "CPLD2": ['20', '0x62'], + "CPLD3": ['21', '0x64'], + "CPLD4": ['22', '0x66'], + "CPLD5": ['17', '0x68'] +} +SYSFS_PATH = "/sys/bus/i2c/devices/" +BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" +COMPONENT_LIST= [ + ("CPLD1", "CPLD 1"), + ("CPLD2", "CPLD 2"), + ("CPLD3", "CPLD 3"), + ("CPLD4", "CPLD 4"), + ("CPLD5", "CPLD FAN"), + ("CPLD6", "CPLD CPU"), + ("BIOS", "Basic Input/Output System") + +] + +class Component(ComponentBase): + """Platform-specific Component class""" + + DEVICE_TYPE = "component" + + def __init__(self, component_index=0): + self.index = component_index + self.name = self.get_name() + + def __get_bios_version(self): + # Retrieves the BIOS firmware version + try: + with open(BIOS_VERSION_PATH, 'r') as fd: + bios_version = fd.read() + return bios_version.strip() + except Exception as e: + return None + + def __get_cpld_version(self): + # Retrieves the CPLD firmware version + cpld_version = dict() + for cpld_name in CPLD_ADDR_MAPPING: + cmd = ["i2cget", "-f", "-y", CPLD_ADDR_MAPPING[cpld_name][0], CPLD_ADDR_MAPPING[cpld_name][1], "0x1"] + status, value = getstatusoutput_noshell(cmd) + if not status: + cpld_version_raw = value.rstrip() + cpld_version[cpld_name] = "{}".format(int(cpld_version_raw,16)) + + return cpld_version + + def __get_cpld_cpu_version(self): + try: + cpu_version = dict() + cmd = ["i2cget", "-f", "-y", "0", "0x65", "0x01"] + status, output1 = getstatusoutput_noshell(cmd) + if status == 0 : + cmd = ["i2cget", "-f", "-y", "0", "0x65", "0xff"] + status, output2 = getstatusoutput_noshell(cmd) + if status == 0 : + cpu_version = "{}{}{}".format(output1[2:],".",output2[2:]) + else : + cpu_version = 'None' + else : + cpu_version = 'None' + except Exception as e: + cpu_version = 'None' + + return cpu_version + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return COMPONENT_LIST[self.index][0] + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return COMPONENT_LIST[self.index][1] + + def get_firmware_version(self): + """ + Retrieves the firmware version of module + Returns: + string: The firmware versions of the module + """ + fw_version = None + + if self.name == "BIOS": + fw_version = self.__get_bios_version() + elif "CPLD6" in self.name: + fw_version =self.__get_cpld_cpu_version() + elif "CPLD" in self.name: + cpld_version = self.__get_cpld_version() + fw_version = cpld_version.get(self.name) + + return fw_version + + def install_firmware(self, image_path): + """ + Install firmware to module + Args: + image_path: A string, path to firmware image + Returns: + A boolean, True if install successfully, False if not + """ + ret, output = getstatusoutput_noshell(["tar", "-C", "/tmp", "-xzf", image_path ] ) + if ret != 0 : + print("Installation failed because of wrong image package") + return False + + if False == os.path.exists("/tmp/install.json") : + print("Installation failed without jsonfile") + return False + + input_file = open ('/tmp/install.json') + json_array = json.load(input_file) + ret = 1 + for item in json_array: + if item.get('id')==None or item.get('path')==None: + continue + if self.name == item['id'] and item['path'] and item.get('cpu'): + print( "Find", item['id'], item['path'], item['cpu'] ) + ret, output = getstatusoutput_noshell(["/tmp/run_install.sh", item['id'], item['path'], item['cpu'] ]) + if ret==0: + break + elif self.name == item['id'] and item['path']: + print( "Find", item['id'], item['path'] ) + ret, output = getstatusoutput_noshell(["/tmp/run_install.sh", item['id'], item['path'] ]) + if ret==0: + break + + if ret==0: + return True + else : + return False + + def get_presence(self): + """ + Retrieves the presence of the device + Returns: + bool: True if device is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return 'N/A' + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return 'N/A' + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return True + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + If the agent cannot determine the parent-relative position + for some reason, or if the associated value of + entPhysicalContainedIn is'0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device + or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/event.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/event.py new file mode 100644 index 0000000000..1a2f60dbb6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/event.py @@ -0,0 +1,109 @@ +try: + import time + from sonic_py_common.logger import Logger + from .sfp import Sfp +except ImportError as e: + raise ImportError(repr(e) + " - required module not found") + +POLL_INTERVAL_IN_SEC = 1 + +# SFP errors that will block eeprom accessing +SFP_BLOCKING_ERRORS = [ + Sfp.SFP_ERROR_BIT_I2C_STUCK, + Sfp.SFP_ERROR_BIT_BAD_EEPROM, + Sfp.SFP_ERROR_BIT_UNSUPPORTED_CABLE, + Sfp.SFP_ERROR_BIT_HIGH_TEMP, + Sfp.SFP_ERROR_BIT_BAD_CABLE +] + +class SfpEvent: + ''' Listen to insert/remove sfp events ''' + + def __init__(self, sfp_list): + self._sfp_list = sfp_list + self._logger = Logger() + self._sfp_change_event_data = {'present': 0} + + def get_presence_bitmap(self): + bitmap = 0 + for sfp in self._sfp_list: + modpres = sfp.get_presence() + i=sfp.get_position_in_parent() - 1 + if modpres: + bitmap = bitmap | (1 << i) + return bitmap + + def get_sfp_event(self, timeout=2000): + port_dict = {} + change_dict = {} + change_dict['sfp'] = port_dict + + if timeout < 1000: + cd_ms = 1000 + else: + cd_ms = timeout + + while cd_ms > 0: + bitmap = self.get_presence_bitmap() + changed_ports = self._sfp_change_event_data['present'] ^ bitmap + if changed_ports != 0: + break + time.sleep(POLL_INTERVAL_IN_SEC) + # timeout=0 means wait for event forever + if timeout != 0: + cd_ms = cd_ms - POLL_INTERVAL_IN_SEC * 1000 + + if changed_ports != 0: + for sfp in self._sfp_list: + i=sfp.get_position_in_parent() - 1 + if (changed_ports & (1 << i)) == 0: + continue + + if (bitmap & (1 << i)) == 0: + port_dict[i+1] = '0' + else: + # sfp.refresh_optoe_dev_class() + sfp_state_bits = self.get_sfp_state_bits(sfp, True) + sfp_state_bits = self.check_sfp_blocking_errors(sfp_state_bits) + + port_dict[i+1] = str(sfp_state_bits) + + # Update the cache dict + self._sfp_change_event_data['present'] = bitmap + return True, change_dict + else: + return True, change_dict + + def get_sfp_state_bits(self, sfp, present): + sfp_state_bits = 0 + + if present is True: + sfp_state_bits |= Sfp.SFP_STATUS_BIT_INSERTED + else: + return sfp_state_bits + + status = sfp.validate_eeprom() + if status is None: + sfp_state_bits |= Sfp.SFP_ERROR_BIT_I2C_STUCK + return sfp_state_bits + elif status is not True: + sfp_state_bits |= Sfp.SFP_ERROR_BIT_BAD_EEPROM + return sfp_state_bits + + status = sfp.validate_temperature() + if status is None: + sfp_state_bits |= Sfp.SFP_ERROR_BIT_I2C_STUCK + return sfp_state_bits + elif status is not True: + sfp_state_bits |= Sfp.SFP_ERROR_BIT_HIGH_TEMP + return sfp_state_bits + + return sfp_state_bits + + def check_sfp_blocking_errors(self, sfp_state_bits): + for i in SFP_BLOCKING_ERRORS: + if (i & sfp_state_bits) == 0: + continue + sfp_state_bits |= Sfp.SFP_ERROR_BIT_BLOCKING + + return sfp_state_bits diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/fan.py index 2db163c7d2..c7d5c86dc8 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/fan.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/fan.py @@ -6,6 +6,8 @@ except ImportError as e: raise ImportError(str(e) + "- required module not found") +FAN_NAME_LIST = ["FAN-1F", "FAN-1R", "FAN-2F", "FAN-2R", + "FAN-3F", "FAN-3R", "FAN-4F", "FAN-4R"] class Fan(PddfFan): """PDDF Platform-Specific Fan class""" @@ -30,21 +32,49 @@ def get_direction(self): direction = self.FAN_DIRECTION_EXHAUST else: - idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index - attr = "fan" + str(idx) + "_direction" - output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr) - if not output: - return False - - mode = output['mode'] - val = output['status'] - - val = val.rstrip() - vmap = self.plugin_data['FAN']['direction'][mode]['valmap'] - if val in vmap: - direction = vmap[val] - else: - direction = val + direction = super().get_direction() + if direction is not None and len(direction) > 0: + direction = 'N/A' return direction + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + fan_name = FAN_NAME_LIST[(self.fantray_index-1)*2 + self.fan_index-1] \ + if not self.is_psu_fan \ + else "PSU-{} FAN-{}".format(self.fans_psu_index, self.fan_index) + + return fan_name + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return 'N/A' + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return 'N/A' + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + if self.is_psu_fan: + return super().get_speed() + else: + return super().get_target_speed() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/fan_drawer.py index 3b9bb607f6..09c1048b51 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/fan_drawer.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/fan_drawer.py @@ -15,3 +15,27 @@ def __init__(self, tray_idx, pddf_data=None, pddf_plugin_data=None): PddfFanDrawer.__init__(self, tray_idx, pddf_data, pddf_plugin_data) # Provide the functions/variables below for which implementation is to be overwritten + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantray_index) + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return 'N/A' + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return 'N/A' diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/helper.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/helper.py new file mode 100644 index 0000000000..f6adee3098 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/helper.py @@ -0,0 +1,368 @@ +import os +import struct +import json +import fcntl +from mmap import * +from sonic_py_common import device_info +from sonic_py_common import logger +from threading import Lock +from typing import cast +from sonic_py_common.general import getstatusoutput_noshell_pipe +from sonic_py_common.general import getstatusoutput_noshell + +HOST_CHK_CMD = ["docker"] +EMPTY_STRING = "" + + +class APIHelper(): + + def __init__(self): + (self.platform, self.hwsku) = device_info.get_platform_and_hwsku() + + def is_host(self): + try: + status, output = getstatusoutput_noshell(HOST_CHK_CMD) + return status == 0 + except Exception: + return False + + def pci_get_value(self, resource, offset): + status = True + result = "" + try: + fd = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + mm.seek(int(offset)) + read_data_stream = mm.read(4) + result = struct.unpack('I', read_data_stream) + except Exception: + status = False + return status, result + + def run_interactive_command(self, cmd): + try: + os.system(cmd) + except Exception: + return False + return True + + def read_txt_file(self, file_path): + try: + with open(file_path, 'r', errors='replace') as fd: + data = fd.read() + ret = data.strip() + if len(ret) > 0: + return ret + except IOError: + pass + return None + + def write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except IOError: + return False + return True + + def ipmi_raw(self, netfn, cmd): + status = True + result = "" + try: + err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'raw', str(netfn), str(cmd)]) + if err == [0]: + result = raw_data.strip() + else: + status = False + except Exception: + status = False + return status, result + + def ipmi_fru_id(self, id, key=None): + status = True + result = "" + try: + if (key is None): + err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'fru', 'print', str(id)]) + else: + err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'fru', 'print', str(id)], ['grep', str(key)]) + if err == [0] or err == [0, 0]: + result = raw_data.strip() + else: + status = False + except Exception: + status = False + return status, result + + def ipmi_set_ss_thres(self, id, threshold_key, value): + status = True + result = "" + try: + err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'sensor', 'thresh', str(id), str(threshold_key), str(value)]) + if err == [0]: + result = raw_data.strip() + else: + status = False + except Exception: + status = False + return status, result + + +class FileLock: + """ + Due to pmon docker not installing the py-filelock, this class + implements a simple file lock feature. + Ref: https://github.com/tox-dev/py-filelock/blob/main/src/filelock/ + """ + + def __init__(self, lock_file): + self._lock_file = lock_file + self._thread_lock = Lock() + self.is_locked = False + + def acquire(self): + with self._thread_lock: + if self.is_locked: + return + + fd = os.open(self._lock_file, flags=(os.O_RDWR | os.O_CREAT | os.O_TRUNC)) + fcntl.flock(fd, fcntl.LOCK_EX) + self._lock_file_fd = fd + self.is_locked = True + + def release(self): + with self._thread_lock: + if self.is_locked: + fd = cast(int, self._lock_file_fd) + self._lock_file_fd = None + fcntl.flock(fd, fcntl.LOCK_UN) + os.close(fd) + self.is_locked = False + + def __enter__(self): + self.acquire() + return self + + def __exit__(self, exc_type, exc_val, traceback): + self.release() + + def __del__(self): + self.release() + + +DEVICE_THRESHOLD_JSON_PATH = "/tmp/device_threshold.json" + +class DeviceThreshold: + HIGH_THRESHOLD = 'high_threshold' + LOW_THRESHOLD = 'low_threshold' + HIGH_CRIT_THRESHOLD = 'high_critical_threshold' + LOW_CRIT_THRESHOLD = 'low_critical_threshold' + NOT_AVAILABLE = 'N/A' + + def __init__(self, th_name = NOT_AVAILABLE): + self.flock = FileLock("{}.lock".format(DEVICE_THRESHOLD_JSON_PATH)) + self.name = th_name + self.__log = logger.Logger(log_identifier="DeviceThreshold") + + self.__db_data = {} + self.__db_mtime = 0 + + def __reload_db(self): + try: + db_data = {} + with self.flock: + with open(DEVICE_THRESHOLD_JSON_PATH, "r") as db_file: + db_data = json.load(db_file) + except Exception as e: + self.__log.log_warning('{}'.format(str(e))) + return None + + return db_data + + def __get_data(self, field): + """ + Retrieves data frome JSON file by field + + Args : + field: String + + Returns: + A string if getting is successfully, 'N/A' if not + """ + if os.path.exists(DEVICE_THRESHOLD_JSON_PATH): + new_mtime = os.path.getmtime(DEVICE_THRESHOLD_JSON_PATH) + if new_mtime != self.__db_mtime: + new_data = self.__reload_db() + if new_data is not None: + self.__db_data = new_data + self.__db_mtime = new_mtime + + if self.name not in self.__db_data.keys(): + return self.NOT_AVAILABLE + + if field not in self.__db_data[self.name].keys(): + return self.NOT_AVAILABLE + + return self.__db_data[self.name][field] + + def __set_data(self, field, new_val): + """ + Set data to JSON file by field + + Args : + field: String + new_val: String + + Returns: + A boolean, True if setting is set successfully, False if not + """ + if self.name not in self.__db_data.keys(): + self.__db_data[self.name] = {} + + old_val = self.__db_data[self.name].get(field, None) + if old_val is not None and old_val == new_val: + return True + + self.__db_data[self.name][field] = new_val + + try: + with self.flock: + db_data = {} + mode = "r+" if os.path.exists(DEVICE_THRESHOLD_JSON_PATH) else "w+" + with open(DEVICE_THRESHOLD_JSON_PATH, mode) as db_file: + if mode == "r+": + db_data = json.load(db_file) + + if self.name not in db_data.keys(): + db_data[self.name] = {} + + db_data[self.name][field] = new_val + + if mode == "r+": + db_file.seek(0) + # erase old data + db_file.truncate(0) + # write all data + json.dump(db_data, db_file, indent=4) + self.__db_mtime = os.path.getmtime(DEVICE_THRESHOLD_JSON_PATH) + except Exception as e: + self.__log.log_error('{}'.format(str(e))) + return False + + return True + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature from JSON file. + + Returns: + string : the high threshold temperature of thermal, + e.g. "30.125" + """ + return self.__get_data(self.HIGH_THRESHOLD) + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + Args : + temperature: A string of temperature, e.g. "30.125" + Returns: + A boolean, True if threshold is set successfully, False if not + """ + if isinstance(temperature, str) is not True: + raise TypeError('The parameter requires string type.') + + try: + if temperature != self.NOT_AVAILABLE: + float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(self.HIGH_THRESHOLD, temperature) + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature from JSON file. + + Returns: + string : the low threshold temperature of thermal, + e.g. "30.125" + """ + return self.__get_data(self.LOW_THRESHOLD) + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + Args : + temperature: A string of temperature, e.g. "30.125" + Returns: + A boolean, True if threshold is set successfully, False if not + """ + if isinstance(temperature, str) is not True: + raise TypeError('The parameter requires string type.') + + try: + if temperature != self.NOT_AVAILABLE: + float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(self.LOW_THRESHOLD, temperature) + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature from JSON file. + + Returns: + string : the high critical threshold temperature of thermal, + e.g. "30.125" + """ + return self.__get_data(self.HIGH_CRIT_THRESHOLD) + + def set_high_critical_threshold(self, temperature): + """ + Sets the high critical threshold temperature of thermal + Args : + temperature: A string of temperature, e.g. "30.125" + Returns: + A boolean, True if threshold is set successfully, False if not + """ + if isinstance(temperature, str) is not True: + raise TypeError('The parameter requires string type.') + + try: + if temperature != self.NOT_AVAILABLE: + float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(self.HIGH_CRIT_THRESHOLD, temperature) + + def get_low_critical_threshold(self): + """ + Retrieves the low critical threshold temperature from JSON file. + + Returns: + string : the low critical threshold temperature of thermal, + e.g. "30.125" + """ + return self.__get_data(self.LOW_CRIT_THRESHOLD) + + def set_low_critical_threshold(self, temperature): + """ + Sets the low critical threshold temperature of thermal + Args : + temperature: A string of temperature, e.g. "30.125" + Returns: + A boolean, True if threshold is set successfully, False if not + """ + if isinstance(temperature, str) is not True: + raise TypeError('The parameter requires string type.') + + try: + if temperature != self.NOT_AVAILABLE: + float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(self.LOW_CRIT_THRESHOLD, temperature) diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/pcie.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/pcie.py new file mode 100644 index 0000000000..73d3627dbf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/pcie.py @@ -0,0 +1,19 @@ +############################################################################# +# Edgecore +# +# Module contains an implementation of SONiC Platform Base API and +# provides the fan status which are available in the platform +# Base PCIe class +############################################################################# + +try: + from sonic_platform_base.sonic_pcie.pcie_common import PcieUtil +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Pcie(PcieUtil): + """Edgecore Platform-specific PCIe class""" + + def __init__(self, platform_path): + PcieUtil.__init__(self, platform_path) \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/psu.py index 46a1396597..0e9490f1d9 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/psu.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/psu.py @@ -11,25 +11,102 @@ class Psu(PddfPsu): """PDDF Platform-Specific PSU class""" - PLATFORM_PSU_CAPACITY = 1200 - def __init__(self, index, pddf_data=None, pddf_plugin_data=None): PddfPsu.__init__(self, index, pddf_data, pddf_plugin_data) # Provide the functions/variables below for which implementation is to be overwritten - def get_maximum_supplied_power(self): + def get_name(self): + return "PSU-{}".format(self.psu_index) + + def get_revision(self): + """ + Retrieves the hardware revision of the device + + Returns: + string: Revision value of device + """ + return 'N/A' + + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + Returns: + A float number, the high threshold temperature of PSU in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 """ - Retrieves the maximum supplied power by PSU (or PSU capacity) + threshold = super().get_temperature_high_threshold() + + for psu_thermal_idx in range(self.num_psu_thermals): + try: + tmp = self._thermal_list[psu_thermal_idx].get_high_threshold() + if threshold > tmp or threshold == 0.0: + threshold = tmp + except Exception: + pass + + return threshold + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: - A float number, the maximum power output in Watts. - e.g. 1200.1 + string: Model/part number of device """ - return float(self.PLATFORM_PSU_CAPACITY) + model = super().get_model() + if model and model.strip() == "": + return None - def get_type(self): + return model + + def get_serial(self): """ - Gets the type of the PSU + Retrieves the serial number of the device + Returns: - A string, the type of PSU (AC/DC) + string: Serial number of device """ - return "AC" + serial = super().get_serial() + if serial and serial.strip() == "": + return None + + return serial + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + if self.get_status() is not True: + return 0.0 + + return super().get_voltage() + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, electric current in amperes, + e.g. 15.4 + """ + if self.get_status() is not True: + return 0.0 + + return super().get_current() + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, + e.g. 302.6 + """ + if self.get_status() is not True: + return 0.0 + + return super().get_power() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/sfp.py index d9b6e491be..759bfe8db5 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/sfp.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/sfp.py @@ -1,7 +1,10 @@ #!/usr/bin/env python try: + import natsort from sonic_platform_pddf_base.pddf_sfp import PddfSfp + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper + from sonic_py_common import device_info except ImportError as e: raise ImportError (str(e) + "- required module not found") @@ -11,7 +14,184 @@ class Sfp(PddfSfp): PDDF Platform-Specific Sfp class """ + SFP_TYPE_CODE_LIST = [ + 0x03, # SFP/SFP+/SFP28 + 0x0b # DWDM-SFP/SFP+ + ] + QSFP_TYPE_CODE_LIST = [ + 0x0c, # QSFP + 0x0d, # QSFP+ or later + 0x11, # QSFP28 or later + 0xe1 # QSFP28 EDFA + ] + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): PddfSfp.__init__(self, index, pddf_data, pddf_plugin_data) + self.index = self.port_index # Provide the functions/variables below for which implementation is to be overwritten + def get_position_in_parent(self): + """Retrieves 1-based relative physical position in parent device.""" + return self.port_index + + def __get_path_to_port_config_file(self): + platform, hwsku = device_info.get_platform_and_hwsku() + hwsku_path = "/".join(["/usr/share/sonic/platform",hwsku]) + return "/".join([hwsku_path, "port_config.ini"]) + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings( + self.__get_path_to_port_config_file()) + + logical_port_list = sfputil_helper.logical + logical_port_list = natsort.natsorted(logical_port_list) + name = logical_port_list[self.port_index-1] or "Unknown" + + return name + + def __validate_eeprom_sfp(self): + checksum_test = 0 + eeprom_raw = self.read_eeprom(0, 96) + if eeprom_raw is None: + return None + + for i in range(0, 63): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[63]: + return False + + checksum_test = 0 + for i in range(64, 95): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[95]: + return False + + api = self.get_xcvr_api() + if api is None: + return False + + if api.is_flat_memory(): + return True + + checksum_test = 0 + eeprom_raw = self.read_eeprom(384, 96) + if eeprom_raw is None: + return None + + for i in range(0, 95): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[95]: + return False + + return True + + def __validate_eeprom_qsfp(self): + checksum_test = 0 + eeprom_raw = self.read_eeprom(128, 96) + if eeprom_raw is None: + return None + + for i in range(0, 63): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[63]: + return False + + checksum_test = 0 + for i in range(64, 95): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[95]: + return False + + api = self.get_xcvr_api() + if api is None: + return False + + if api.is_flat_memory(): + return True + + return True + + def validate_eeprom(self): + id_byte_raw = self.read_eeprom(0, 1) + if id_byte_raw is None: + return None + + id = id_byte_raw[0] + if id in self.QSFP_TYPE_CODE_LIST: + return self.__validate_eeprom_qsfp() + elif id in self.SFP_TYPE_CODE_LIST: + return self.__validate_eeprom_sfp() + else: + return False + + def validate_temperature(self): + temperature = self.get_temperature() + if temperature is None: + return None + + threshold_dict = self.get_transceiver_threshold_info() + if threshold_dict is None: + return None + + if isinstance(temperature, float) is not True: + return True + + if isinstance(threshold_dict['temphighalarm'], float) is not True: + return True + + return threshold_dict['temphighalarm'] > temperature + + def __get_error_description(self): + if not self.get_presence(): + return self.SFP_STATUS_UNPLUGGED + + err_stat = self.SFP_STATUS_BIT_INSERTED + + status = self.validate_eeprom() + if status is not True: + err_stat = (err_stat | self.SFP_ERROR_BIT_BAD_EEPROM) + + status = self.validate_temperature() + if status is not True: + err_stat = (err_stat | self.SFP_ERROR_BIT_HIGH_TEMP) + + if err_stat is self.SFP_STATUS_BIT_INSERTED: + return self.SFP_STATUS_OK + else: + err_desc = '' + cnt = 0 + for key in self.SFP_ERROR_BIT_TO_DESCRIPTION_DICT: + if (err_stat & key) != 0: + if cnt > 0: + err_desc = err_desc + "|" + cnt = cnt + 1 + err_desc = err_desc + self.SFP_ERROR_BIT_TO_DESCRIPTION_DICT[key] + + return err_desc + + def get_error_description(self): + """ + Retrives the error descriptions of the SFP module + Returns: + String that represents the current error descriptions of vendor specific errors + In case there are multiple errors, they should be joined by '|', + like: "Bad EEPROM|Unsupported cable" + """ + try: + ret = super().get_error_description() + if ret is not None: + return ret + except NotImplementedError: + pass + return self.__get_error_description() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/thermal.py index 77d6ec7ae8..b7d585c278 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/thermal.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/sonic_platform/thermal.py @@ -3,9 +3,96 @@ try: from sonic_platform_pddf_base.pddf_thermal import PddfThermal + from .helper import DeviceThreshold except ImportError as e: raise ImportError(str(e) + "- required module not found") +NOT_AVAILABLE = DeviceThreshold.NOT_AVAILABLE +HIGH_THRESHOLD = DeviceThreshold.HIGH_THRESHOLD +LOW_THRESHOLD = DeviceThreshold.LOW_THRESHOLD +HIGH_CRIT_THRESHOLD = DeviceThreshold.HIGH_CRIT_THRESHOLD +LOW_CRIT_THRESHOLD = DeviceThreshold.LOW_CRIT_THRESHOLD + +DEFAULT_THRESHOLD = { + 'FB_1_temp(0x4D)' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'FB_2_temp(0x4E)' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'MB_MAC_temp(0x48)' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'MB_RearCenter_temp(0x49)' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'MB_RightCenter_temp(0x4A)' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'CpuBoard_temp(0x4B)' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'CPU_Package_temp' : { + HIGH_THRESHOLD : '82.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '104.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'CPU_Core_0_temp' : { + HIGH_THRESHOLD : '82.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '104.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'CPU_Core_1_temp' : { + HIGH_THRESHOLD : '82.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '104.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'CPU_Core_2_temp' : { + HIGH_THRESHOLD : '82.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '104.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'CPU_Core_3_temp' : { + HIGH_THRESHOLD : '82.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '104.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'PSU-1 temp sensor 1' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'PSU-2 temp sensor 1' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + } +} class Thermal(PddfThermal): @@ -13,5 +100,200 @@ class Thermal(PddfThermal): def __init__(self, index, pddf_data=None, pddf_plugin_data=None, is_psu_thermal=False, psu_index=0): PddfThermal.__init__(self, index, pddf_data, pddf_plugin_data, is_psu_thermal, psu_index) + # Threshold Configuration + self.__conf = DeviceThreshold(self.get_name()) + # Default threshold. + self.__default_threshold = DEFAULT_THRESHOLD[self.get_name()] + self.min_temperature = None + self.max_temperature = None # Provide the functions/variables below for which implementation is to be overwritten + def get_name(self): + if self.is_psu_thermal: + return "PSU-{0} temp sensor 1".format(self.thermals_psu_index) + else: + if 'dev_attr' in self.thermal_obj.keys(): + if 'display_name' in self.thermal_obj['dev_attr']: + return str(self.thermal_obj['dev_attr']['display_name']) + + # In case of errors + return "Temp sensor {0}".format(self.thermal_index) + + def get_status(self): + get_temp=self.get_temperature() + + if get_temp is not None: + return True if get_temp else False + + def get_temperature(self): + current = super().get_temperature() + + if self.min_temperature is None or \ + current < self.min_temperature: + self.min_temperature = current + + if self.max_temperature is None or \ + current > self.max_temperature: + self.max_temperature = current + + return current + + def set_high_threshold(self, temperature): + try: + value = float(temperature) + except Exception: + return False + + # The new value can not be more than the default value. + default_value = self.__default_threshold[HIGH_THRESHOLD] + if default_value != NOT_AVAILABLE: + if value > float(default_value): + return False + + try: + self.__conf.set_high_threshold(str(value)) + except Exception: + return False + + return True + + def get_high_threshold(self): + value = self.__conf.get_high_threshold() + if value != NOT_AVAILABLE: + return float(value) + + default_value = self.__default_threshold[HIGH_THRESHOLD] + if default_value != NOT_AVAILABLE: + return float(default_value) + + raise NotImplementedError + + def set_low_threshold(self, temperature): + try: + value = float(temperature) + except Exception: + return False + + # The new value can not be less than the default value. + default_value = self.__default_threshold[LOW_THRESHOLD] + if default_value != NOT_AVAILABLE: + if value < float(default_value): + return False + + try: + self.__conf.set_low_threshold(str(value)) + except Exception: + return False + + return True + + def get_low_threshold(self): + value = self.__conf.get_low_threshold() + if value != NOT_AVAILABLE: + return float(value) + + default_value = self.__default_threshold[LOW_THRESHOLD] + if default_value != NOT_AVAILABLE: + return float(default_value) + + raise NotImplementedError + + def set_high_critical_threshold(self, temperature): + try: + value = float(temperature) + except Exception: + return False + + # The new value can not be more than the default value. + default_value = self.__default_threshold[HIGH_CRIT_THRESHOLD] + if default_value != NOT_AVAILABLE: + if value > float(default_value): + return False + + try: + self.__conf.set_high_critical_threshold(str(value)) + except Exception: + return False + + return True + + def get_high_critical_threshold(self): + value = self.__conf.get_high_critical_threshold() + if value != NOT_AVAILABLE: + return float(value) + + default_value = self.__default_threshold[HIGH_CRIT_THRESHOLD] + if default_value != NOT_AVAILABLE: + return float(default_value) + + raise NotImplementedError + + def set_low_critical_threshold(self, temperature): + try: + value = float(temperature) + except Exception: + return False + + # The new value can not be less than the default value. + default_value = self.__default_threshold[LOW_CRIT_THRESHOLD] + if default_value != NOT_AVAILABLE: + if value < float(default_value): + return False + + try: + self.__conf.set_low_critical_threshold(str(value)) + except Exception: + return False + + return True + + def get_low_critical_threshold(self): + value = self.__conf.get_low_critical_threshold() + if value != NOT_AVAILABLE: + return float(value) + + default_value = self.__default_threshold[LOW_CRIT_THRESHOLD] + if default_value != NOT_AVAILABLE: + return float(default_value) + + raise NotImplementedError + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return 'N/A' + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return 'N/A' + + def get_minimum_recorded(self): + """ + Retrieves the minimum recorded temperature of thermal + Returns: + A float number, the minimum recorded temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.min_temperature is None: + self.get_temperature() + + return self.min_temperature + + def get_maximum_recorded(self): + """ + Retrieves the maximum recorded temperature of thermal + Returns: + A float number, the maximum recorded temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.max_temperature is None: + self.get_temperature() + + return self.max_temperature diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_64x_util.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_64x_util.py index 5ab3d8f20e..55ed10c3be 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_64x_util.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_64x_util.py @@ -16,22 +16,30 @@ # along with this program. If not, see . """ -Usage: %(scriptName)s [options] command object -options: - -h | --help : this help message - -d | --debug : run with debug mode - -f | --force : ignore error during installation or clean -command: - install : install drivers and generate related sysfs nodes - clean : uninstall drivers and remove related sysfs nodes +usage: accton_as7816_64x_util.py [-h] [-d] [-f] {install,clean,threshold} ... + +AS7816-64X Platform Utility + +optional arguments: + -h, --help show this help message and exit + -d, --debug run with debug mode + -f, --force ignore error during installation or clean + +Utility Command: + {install,clean,threshold} + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + api : install SONiC platform API + api_clean : uninstall SONiC platform API + threshold : modify thermal threshold """ import subprocess -import getopt import sys import logging import re import time import os +import argparse from sonic_py_common.general import getstatusoutput_noshell @@ -56,42 +64,48 @@ def main(): global DEBUG global args global FORCE + global THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH - if len(sys.argv)<2: - show_help() - - options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', - 'debug', - 'force', - ]) + util_parser = argparse.ArgumentParser(description="AS7816-64X Platform Utility") + util_parser.add_argument("-d", "--debug", dest='debug', action='store_true', default=False, + help="run with debug mode") + util_parser.add_argument("-f", "--force", dest='force', action='store_true', default=False, + help="ignore error during installation or clean") + subcommand = util_parser.add_subparsers(dest='cmd', title='Utility Command', required=True) + subcommand.add_parser('install', help=': install drivers and generate related sysfs nodes') + subcommand.add_parser('clean', help=': uninstall drivers and remove related sysfs nodes') + subcommand.add_parser('api', help=': install SONiC platform API') + subcommand.add_parser('api_clean', help=': uninstall SONiC platform API') + threshold_parser = subcommand.add_parser('threshold', help=': modify thermal threshold') + threshold_parser.add_argument("-l", dest='list', action='store_true', default=False, + help="list avaliable thermal") + threshold_parser.add_argument("-t", dest='thermal', type=str, metavar='THERMAL_NAME', + help="thermal name, ex: -t 'Temp sensor 1'") + threshold_parser.add_argument("-ht", dest='high_threshold', type=restricted_float, + metavar='THRESHOLD_VALUE', + help="high threshold: %.1f ~ %.1f" % (THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH)) + threshold_parser.add_argument("-hct", dest='high_crit_threshold', type=restricted_float, + metavar='THRESHOLD_VALUE', + help="high critical threshold : %.1f ~ %.1f" % (THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH)) + args = util_parser.parse_args() + if DEBUG == True: - print(options) print(args) print(len(sys.argv)) - for opt, arg in options: - if opt in ('-h', '--help'): - show_help() - elif opt in ('-d', '--debug'): - DEBUG = True - logging.basicConfig(level=logging.INFO) - elif opt in ('-f', '--force'): - FORCE = 1 - else: - logging.info('no option') - for arg in args: - if arg == 'install': - do_install() - elif arg == 'clean': - do_uninstall() - elif arg == 'api': - do_sonic_platform_install() - elif arg == 'api_clean': - do_sonic_platform_clean() - - else: - show_help() - + DEBUG = args.debug + FORCE = 1 if args.force else 0 + + if args.cmd == 'install': + do_install() + elif args.cmd == 'clean': + do_uninstall() + elif args.cmd == 'api': + do_sonic_platform_install() + elif args.cmd == 'api_clean': + do_sonic_platform_clean() + elif args.cmd == 'threshold': + do_threshold() return 0 @@ -150,7 +164,7 @@ def driver_check(): kos = [ 'modprobe i2c_dev', -'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe i2c_mux_pca954x', 'modprobe optoe', 'modprobe accton_i2c_cpld' , 'modprobe ym2651y' , @@ -256,6 +270,14 @@ def device_install(): if FORCE == 0: return status + # set all pca954x idle_disconnect + cmd = 'echo -2 | tee /sys/bus/i2c/drivers/pca954x/*-00*/idle_state' + status, output = log_os_system(cmd, 1) + if status: + print(output) + if FORCE == 0: + return status + for i in range(0,len(sfp_map)): path = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device" status, output =log_os_system("echo optoe1 0x50 > " + path, 1) @@ -394,5 +416,162 @@ def device_exist(): ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) return not(ret1 or ret2) +THRESHOLD_RANGE_LOW = 30.0 +THRESHOLD_RANGE_HIGH = 110.0 +# Code to initialize chassis object +init_chassis_code = \ + "import sonic_platform.platform\n"\ + "platform = sonic_platform.platform.Platform()\n"\ + "chassis = platform.get_chassis()\n\n" + +# Looking for thermal +looking_for_thermal_code = \ + "thermal = None\n"\ + "all_thermals = chassis.get_all_thermals()\n"\ + "for psu in chassis.get_all_psus():\n"\ + " all_thermals += psu.get_all_thermals()\n"\ + "for tmp in all_thermals:\n"\ + " if '{}' == tmp.get_name():\n"\ + " thermal = tmp\n"\ + " break\n"\ + "if thermal == None:\n"\ + " print('{} not found!')\n"\ + " exit(1)\n\n" + +def avaliable_thermals(): + global init_chassis_code + + get_all_thermal_name_code = \ + "thermal_list = []\n"\ + "all_thermals = chassis.get_all_thermals()\n"\ + "for psu in chassis.get_all_psus():\n"\ + " all_thermals += psu.get_all_thermals()\n"\ + "for tmp in all_thermals:\n"\ + " thermal_list.append(tmp.get_name())\n"\ + "print(str(thermal_list)[1:-1])\n" + + all_code = "{}{}".format(init_chassis_code, get_all_thermal_name_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + if status != 0: + return "" + return output + +def restricted_float(x): + global THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH + + try: + x = float(x) + except ValueError: + raise argparse.ArgumentTypeError("%r not a floating-point literal" % (x,)) + + if x < THRESHOLD_RANGE_LOW or x > THRESHOLD_RANGE_HIGH: + raise argparse.ArgumentTypeError("%r not in range [%.1f ~ %.1f]" % + (x, THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH)) + + return x + +def get_high_threshold(name): + global init_chassis_code, looking_for_thermal_code + + get_high_threshold_code = \ + "try:\n"\ + " print(thermal.get_high_threshold())\n"\ + " exit(0)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the get_high_threshold method!')\n"\ + " exit(1)" + + all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(name, name), + get_high_threshold_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + if status == 1: + return None + + return float(output) + +def get_high_crit_threshold(name): + global init_chassis_code, looking_for_thermal_code + + get_high_crit_threshold_code = \ + "try:\n"\ + " print(thermal.get_high_critical_threshold())\n"\ + " exit(0)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the get_high_critical_threshold method!')\n"\ + " exit(1)" + + all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(name, name), + get_high_crit_threshold_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + if status == 1: + return None + + return float(output) + +def do_threshold(): + global args, init_chassis_code, looking_for_thermal_code + + if args.list: + print("Thermals: " + avaliable_thermals()) + return + + if args.thermal is None: + print("The following arguments are required: -t") + return + + set_threshold_code = "" + if args.high_threshold is not None: + if args.high_crit_threshold is not None and \ + args.high_threshold >= args.high_crit_threshold: + print("Invalid Threshold!(High threshold can not be more than " \ + "or equal to high critical threshold.)") + exit(1) + + high_crit = get_high_crit_threshold(args.thermal) + if high_crit is not None and \ + args.high_threshold >= high_crit: + print("Invalid Threshold!(High threshold can not be more than " \ + "or equal to high critical threshold.)") + exit(1) + + set_threshold_code += \ + "try:\n"\ + " if thermal.set_high_threshold({}) is False:\n"\ + " print('{}: set_high_threshold failure!')\n"\ + " exit(1)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the set_high_threshold method!')\n"\ + "print('Apply the new high threshold successfully.')\n"\ + "\n".format(args.high_threshold, args.thermal) + + if args.high_crit_threshold is not None: + high = get_high_threshold(args.thermal) + if high is not None and \ + args.high_crit_threshold <= high: + print("Invalid Threshold!(High critical threshold can not " \ + "be less than or equal to high threshold.)") + exit(1) + + set_threshold_code += \ + "try:\n"\ + " if thermal.set_high_critical_threshold({}) is False:\n"\ + " print('{}: set_high_critical_threshold failure!')\n"\ + " exit(1)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the set_high_critical_threshold method!')\n"\ + "print('Apply the new high critical threshold successfully.')\n"\ + "\n".format(args.high_crit_threshold, args.thermal) + + if set_threshold_code == "": + return + + all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(args.thermal, args.thermal), set_threshold_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + print(output) + if __name__ == "__main__": main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_pddf_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_pddf_monitor.py index 8d64cc9617..576fd34e98 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_pddf_monitor.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_pddf_monitor.py @@ -30,7 +30,8 @@ import logging.config import time # this is only being used as part of the example import signal - from sonic_platform import platform + from sonic_platform import platform, fan + from collections import namedtuple except ImportError as e: raise ImportError('%s - required module not found' % str(e)) @@ -38,6 +39,61 @@ VERSION = '1.0' FUNCTION_NAME = 'accton_as7816_monitor' DUTY_MAX = 100 +DUTY_DEF = 40 + +FANDUTY_BY_LEVEL={ + 'LV_5' : DUTY_DEF, + 'LV_7' : 52, + 'LV_9' : 64, + 'LV_B' : 76, + 'LV_D' : 88, + 'LV_F' : DUTY_MAX, +} +FANLEVEL_BY_DUTY={ + DUTY_DEF : 'LV_5', + 52 : 'LV_7', + 64 : 'LV_9', + 76 : 'LV_B', + 88 : 'LV_D', + DUTY_MAX : 'LV_F', +} + +NA_L = 0 +NA_H = 999999 +Threshold = namedtuple('Threshold', ['val', 'next_lv']) + +UP_TH_F2B = { #order :0x4D,0x4E,0x48,0x49,0x4A,0x4B + 'LV_5': Threshold([36000,38000,57000,60000,40000,39000], 'LV_7'), + 'LV_7': Threshold([43000,44000,62000,64000,46000,45000], 'LV_B'), + 'LV_9': Threshold([ NA_L, NA_L, NA_L, NA_L, NA_L, NA_L], 'LV_B'), # NA, force to change level. + 'LV_B': Threshold([48000,49000, NA_H, NA_H,51000,49000], 'LV_D'), + 'LV_D': Threshold([53000,54000,67000,70000,55000,54000], 'LV_F'), + 'LV_F': Threshold([ NA_H, NA_H, NA_H, NA_H, NA_H, NA_H], 'LV_F') # Won't go any higher. +} +DOWN_TH_F2B = { + 'LV_5': Threshold([ NA_L, NA_L, NA_L, NA_L, NA_L, NA_L], 'LV_5'), # Won't go any lower. + 'LV_7': Threshold([34000,36000,55000,58000,38000,37000], 'LV_5'), + 'LV_9': Threshold([ NA_H, NA_H, NA_H, NA_H, NA_H, NA_H], 'LV_7'), # NA, force to change level. + 'LV_B': Threshold([40000,41000,60000,62000,43000,42000], 'LV_7'), + 'LV_D': Threshold([46000,47000,65000,68000,49000,47000], 'LV_B'), + 'LV_F': Threshold([51000,52000, NA_H, NA_H,53000,52000], 'LV_D') +} +UP_TH_B2F = { + 'LV_5': Threshold([26000,26000,52000,41000,34000,27000], 'LV_7'), + 'LV_7': Threshold([31000,31000, NA_H, NA_H,38000,32000], 'LV_9'), + 'LV_9': Threshold([37000,36000,57000,48000,42000,37000], 'LV_B'), + 'LV_B': Threshold([42000,42000,61000,52000,46000,42000], 'LV_D'), + 'LV_D': Threshold([47000,47000,66000,57000,51000,47000], 'LV_F'), + 'LV_F': Threshold([ NA_H, NA_H, NA_H, NA_H, NA_H, NA_H], 'LV_F') # Won't go any higher. +} +DOWN_TH_B2F = { + 'LV_5': Threshold([NA_L,NA_L,NA_L,NA_L,NA_L,NA_L], 'LV_5'), # Won't go any lower. + 'LV_7': Threshold([24000,24000,50000,39000,32000,25000], 'LV_5'), + 'LV_9': Threshold([29000,29000,55000,45000,36000,30000], 'LV_7'), + 'LV_B': Threshold([34000,34000, NA_H, NA_H,40000,35000], 'LV_9'), + 'LV_D': Threshold([40000,40000,59000,50000,44000,40000], 'LV_B'), + 'LV_F': Threshold([45000,45000,63000,55000,48000,45000], 'LV_D') +} platform_chassis = None THERMAL_NUM_ON_MAIN_BROAD = 6 @@ -48,35 +104,26 @@ temp_test_data = 0 -def get_thermal_avg_temp(): - global platform_chassis +def get_temperature(thermal): global test_temp_list global test_temp global temp_test_data global test_temp_revert - sum_temp = 0 if test_temp == 0: - for x in range(THERMAL_NUM_ON_MAIN_BROAD): - sum_temp = sum_temp + platform_chassis.get_thermal(x).get_temperature()*1000 - - else: - for x in range(THERMAL_NUM_ON_MAIN_BROAD): - sum_temp = sum_temp + test_temp_list[x] + return thermal.get_temperature() * 1000 - avg = sum_temp/THERMAL_NUM_ON_MAIN_BROAD + idx = thermal.get_position_in_parent() - 1 + temp = test_temp_list[idx] + temp_test_data - if test_temp == 1: + if idx == THERMAL_NUM_ON_MAIN_BROAD - 1: if test_temp_revert == 0: temp_test_data = temp_test_data+2000 else: temp_test_data = temp_test_data-2000 - - avg = avg + temp_test_data - - avg = (avg/1000)*1000 # round down for hysteresis. - - return avg + temp = (temp/1000)*1000 + logging.debug('set test temp %d to thermal%d', temp, idx) + return temp # Make a class we can use to capture stdout and sterr in the log @@ -85,10 +132,16 @@ class accton_as7816_monitor(object): _ori_temp = 0 _new_perc = 0 _ori_perc = 0 - THERMAL_NUM_ON_MAIN_BROAD = 6 def __init__(self, log_file, log_level): """Needs a logger and a logger level.""" + global platform_chassis + self.thermals = platform_chassis.get_all_thermals() + self.fans = platform_chassis.get_all_fans() + self.is_fan_f2b = self.fans[0].get_direction().lower() == fan.Fan.FAN_DIRECTION_EXHAUST + self.up_th = UP_TH_F2B if self.is_fan_f2b == True else UP_TH_B2F + self.down_th = DOWN_TH_F2B if self.is_fan_f2b == True else DOWN_TH_B2F + # set up logging to file logging.basicConfig( filename=log_file, @@ -109,46 +162,53 @@ def __init__(self, log_file, log_level): logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) def manage_fans(self): - global platform_chassis FAN_NUM = 2 FAN_TRAY_NUM = 4 - max_duty = DUTY_MAX - fan_policy = { - 0: [52, 0, 43000], - 1: [63, 43000, 46000], - 2: [75, 46000, 52000], - 3: [88, 52000, 57000], - 4: [max_duty, 57000, 100000], - } for x in range(FAN_TRAY_NUM * FAN_NUM): - if not platform_chassis.get_fan(x).get_status() or not platform_chassis.get_fan(x).get_speed_rpm(): - logging.debug('INFO. SET new_perc to %d (FAN stauts is None/Fault. fan_num:%d)', max_duty, x+1) - platform_chassis.get_fan(0).set_speed(max_duty) + if not self.fans[x].get_status() or not self.fans[x].get_speed_rpm(): + logging.debug('INFO. SET new_perc to %d (FAN stauts is None/Fault. fan_num:%d)', DUTY_MAX, x+1) + self.fans[0].set_speed(DUTY_MAX) return True # Find if current duty matched any of define duty. # If not, set it to highest one. - #cur_duty_cycle = fan.get_fan_duty_cycle() - cur_duty_cycle = platform_chassis.get_fan(0).get_speed() - new_duty_cycle = cur_duty_cycle - for x in range(0, len(fan_policy)): - if cur_duty_cycle == fan_policy[x][0]: + cur_duty_cycle = self.fans[0].get_speed() + fanlevel = FANLEVEL_BY_DUTY.get(cur_duty_cycle, 'LV_F') + + # decide target level by thermal sensor input. + can_level_up = False + can_level_down = True + skip_monitor = ['CPU_Package_temp', 'CPU_Core_0_temp', + 'CPU_Core_1_temp', 'CPU_Core_2_temp', + 'CPU_Core_3_temp'] + for thermal in self.thermals: + if thermal.get_name() in skip_monitor: + continue + temp = get_temperature(thermal) + th_idx= thermal.get_position_in_parent() - 1 + high = self.up_th[fanlevel].val[th_idx] + low = self.down_th[fanlevel].val[th_idx] + # perform level up if anyone is higher than high_th. + if temp >= high: + can_level_up = True break - if x == len(fan_policy): - platform_chassis.get_fan(0).set_speed(fan_policy[0][0]) - cur_duty_cycle = max_duty - - # Decide fan duty by if avg of sensors falls into any of fan_policy{} - get_temp = get_thermal_avg_temp() + # cancel level down if anyone is higher than low_th. + if temp > low: + can_level_down = False + + if can_level_up: + next_fanlevel = self.up_th[fanlevel].next_lv + elif can_level_down: + next_fanlevel = self.down_th[fanlevel].next_lv + else: + next_fanlevel = fanlevel + new_duty_cycle = FANDUTY_BY_LEVEL.get(next_fanlevel, DUTY_MAX) - for x in range(0, len(fan_policy)): - y = len(fan_policy) - x - 1 # checked from highest - if get_temp > fan_policy[y][1] and get_temp < fan_policy[y][2]: - new_duty_cycle = fan_policy[y][0] if(new_duty_cycle != cur_duty_cycle): - platform_chassis.get_fan(0).set_speed(new_duty_cycle) + logging.debug(f'set fanduty from {cur_duty_cycle} to {new_duty_cycle}') + self.fans[0].set_speed(new_duty_cycle) return True