diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/pcie.yaml b/device/accton/x86_64-accton_as4630_54pe-r0/pcie.yaml new file mode 100644 index 0000000000..c7e99c8678 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/pcie.yaml @@ -0,0 +1,167 @@ +- bus: '00' + dev: '00' + fn: '0' + id: '1980' + name: 'Host bridge: Intel Corporation Atom Processor C3000 Series System Agent (rev + 11)' +- bus: '00' + dev: '04' + fn: '0' + id: 19a1 + name: 'Host bridge: Intel Corporation Atom Processor C3000 Series Error Registers + (rev 11)' +- bus: '00' + dev: '05' + fn: '0' + id: 19a2 + name: 'Generic system peripheral [0807]: Intel Corporation Atom Processor C3000 + Series Root Complex Event Collector (rev 11)' +- bus: '00' + dev: '06' + fn: '0' + id: 19a3 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated QAT + Root Port (rev 11)' +- bus: '00' + dev: 09 + fn: '0' + id: 19a4 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #0 (rev 11)' +- bus: '00' + dev: 0b + fn: '0' + id: 19a6 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #2 (rev 11)' +- bus: '00' + dev: 0e + fn: '0' + id: 19a8 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #4 (rev 11)' +- bus: '00' + dev: '10' + fn: '0' + id: 19aa + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #6 (rev 11)' +- bus: '00' + dev: '12' + fn: '0' + id: 19ac + name: 'System peripheral: Intel Corporation Atom Processor C3000 Series SMBus Contoller + - Host (rev 11)' +- bus: '00' + dev: '13' + fn: '0' + id: 19b2 + name: 'SATA controller: Intel Corporation Atom Processor C3000 Series SATA Controller + 0 (rev 11)' +- bus: '00' + dev: '15' + fn: '0' + id: 19d0 + name: 'USB controller: Intel Corporation Atom Processor C3000 Series USB 3.0 xHCI + Controller (rev 11)' +- bus: '00' + dev: '16' + fn: '0' + id: 19d1 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated LAN + Root Port #0 (rev 11)' +- bus: '00' + dev: '17' + fn: '0' + id: 19d2 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated LAN + Root Port #1 (rev 11)' +- bus: '00' + dev: '18' + fn: '0' + id: 19d3 + name: 'Communication controller: Intel Corporation Atom Processor C3000 Series ME + HECI 1 (rev 11)' +- bus: '00' + dev: 1a + fn: '0' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1a + fn: '1' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1a + fn: '2' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1c + fn: '0' + id: 19db + name: 'SD Host controller: Intel Corporation Device 19db (rev 11)' +- bus: '00' + dev: 1f + fn: '0' + id: 19dc + name: 'ISA bridge: Intel Corporation Atom Processor C3000 Series LPC or eSPI (rev + 11)' +- bus: '00' + dev: 1f + fn: '1' + id: 19dd + name: 'Memory controller: Intel Corporation Atom Processor C3000 Series Primary + to Side Band (P2SB) Bridge (rev 11)' +- bus: '00' + dev: 1f + fn: '2' + id: 19de + name: 'Memory controller: Intel Corporation Atom Processor C3000 Series Power Management + Controller (rev 11)' +- bus: '00' + dev: 1f + fn: '4' + id: 19df + name: 'SMBus: Intel Corporation Atom Processor C3000 Series SMBus controller (rev + 11)' +- bus: '00' + dev: 1f + fn: '5' + id: 19e0 + name: 'Serial bus controller [0c80]: Intel Corporation Atom Processor C3000 Series + SPI Controller (rev 11)' +- bus: '01' + dev: '00' + fn: '0' + id: 19e2 + name: 'Co-processor: Intel Corporation Atom Processor C3000 Series QuickAssist Technology + (rev 11)' +- bus: '05' + dev: '00' + fn: '0' + id: b371 + name: 'Ethernet controller: Broadcom Inc. and subsidiaries BCM56371 Switch ASIC + (rev 03)' +- bus: '06' + dev: '00' + fn: '0' + id: 15c2 + name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane + (rev 11)' +- bus: '06' + dev: '00' + fn: '1' + id: 15c2 + name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane + (rev 11)' +- bus: 08 + dev: '00' + fn: '0' + id: 15e5 + name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 1GbE (rev + 11)' diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pd-plugin.json b/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pd-plugin.json index 0abf66aab7..77dfdc8276 100644 --- a/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pd-plugin.json +++ b/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pd-plugin.json @@ -33,11 +33,11 @@ { "i2c": { - "valmap": { "F2B":"EXHAUST", "B2F":"INTAKE" } + "valmap": { "F2B":"exhaust", "B2F":"intake" } } }, - "PSU_FAN_MAX_SPEED":"18000" + "PSU_FAN_MAX_SPEED":"26688" }, "FAN": @@ -46,7 +46,7 @@ { "i2c": { - "valmap": {"1":"EXHAUST", "0":"INTAKE"} + "valmap": {"1":"exhaust", "0":"intake"} } }, diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pddf-device.json b/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pddf-device.json index 34013b2a84..95da95496c 100644 --- a/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pddf-device.json +++ b/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pddf-device.json @@ -5,7 +5,7 @@ "num_fantrays":3, "num_fans_pertray":1, "num_ports":54, - "num_temps": 3, + "num_temps": 4, "pddf_dev_types": { "description":"AS4630 - 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", @@ -211,6 +211,21 @@ } }, + "TEMP4" : + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP4"}, + "dev_attr": { "display_name":"coretemp-isa-0000"}, + "i2c": + { + "path_info": {"sysfs_base_path": "/sys/class/hwmon/hwmon1"}, + "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"} + ] + } + }, "CPLD1": { @@ -251,15 +266,15 @@ "SYS_LED": { "dev_info": { "device_type":"LED", "device_name":"SYS_LED"}, - "dev_attr": { "index":"0"}, + "dev_attr": { "index":"0", "flag": "rw"}, "i2c" : { "attr_list": [ - {"attr_name":"STATUS_LED_COLOR_GREEN", "bits" : "7:5", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_GREEN_BLINK", "bits" : "7:5", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_AMBER", "bits" : "7:5", "descr" : "", "value" : "0x4", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_AMBER_BLINK", "bits" : "7:5", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_OFF", "bits" : "7:5", "descr" : "", "value" : "0x7", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"} + {"attr_name":"green", "bits" : "7:5", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"green_blink", "bits" : "7:5", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"amber", "bits" : "7:5", "descr" : "", "value" : "0x4", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"amber_blink", "bits" : "7:5", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"off", "bits" : "7:5", "descr" : "", "value" : "0x7", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"} ] } }, @@ -268,13 +283,13 @@ "PSU1_LED": { "dev_info": { "device_type":"LED", "device_name":"PSU_LED"}, - "dev_attr": { "index":"0"}, + "dev_attr": { "index":"0", "flag": "r"}, "i2c" : { "attr_list": [ - {"attr_name":"STATUS_LED_COLOR_GREEN", "bits" : "1:0", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_AMBER", "bits" : "1:0", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_OFF", "bits" : "1:0", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"} + {"attr_name":"green", "bits" : "1:0", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"amber", "bits" : "1:0", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"off", "bits" : "1:0", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"} ] } }, @@ -282,13 +297,13 @@ "PSU2_LED": { "dev_info": { "device_type":"LED", "device_name":"PSU_LED"}, - "dev_attr": { "index":"1"}, + "dev_attr": { "index":"1", "flag": "r"}, "i2c" : { "attr_list": [ - {"attr_name":"STATUS_LED_COLOR_GREEN", "bits" : "7:6", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, - {"attr_name":"STATUS_LED_COLOR_AMBER", "bits" : "7:6", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, - {"attr_name":"STATUS_LED_COLOR_OFF", "bits" : "7:6", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"} + {"attr_name":"green", "bits" : "7:6", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, + {"attr_name":"amber", "bits" : "7:6", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, + {"attr_name":"off", "bits" : "7:6", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"} ] } }, @@ -296,13 +311,13 @@ "FAN_LED": { "dev_info": { "device_type":"LED", "device_name":"FAN_LED"}, - "dev_attr": { "index":"0"}, + "dev_attr": { "index":"0", "flag": "r"}, "i2c" : { "attr_list": [ - {"attr_name":"STATUS_LED_COLOR_GREEN", "bits" : "3:2", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, - {"attr_name":"STATUS_LED_COLOR_AMBER", "bits" : "3:2", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, - {"attr_name":"STATUS_LED_COLOR_OFF", "bits" : "3:2", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"} + {"attr_name":"green", "bits" : "3:2", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, + {"attr_name":"amber", "bits" : "3:2", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, + {"attr_name":"off", "bits" : "3:2", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"} ] } }, @@ -336,7 +351,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"} ] } }, @@ -387,7 +406,11 @@ { "attr_name":"psu_i_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, { "attr_name":"psu_p_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, { "attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_temp1_input", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} + { "attr_name":"psu_temp1_input", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_v_out_max", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa5", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_v_out_min", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa4", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_p_out_max", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_temp1_high_threshold", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa8", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} ] } }, @@ -592,7 +615,9 @@ "topo_info": { "parent_bus":"0x16", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, "attr_list": [ - { "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + { "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x3", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x2", "attr_cmpval":"0x0", "attr_len":"1"} ] } }, @@ -630,7 +655,9 @@ "topo_info": { "parent_bus":"0x17", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, "attr_list": [ - { "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"} + { "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x7", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x5", "attr_cmpval":"0x0", "attr_len":"1"} ] } } diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/platform.json b/device/accton/x86_64-accton_as4630_54pe-r0/platform.json new file mode 100644 index 0000000000..72461beac3 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/platform.json @@ -0,0 +1,785 @@ +{ + "chassis": { + "name": "4630-54PE", + "thermal_manager":false, + "status_led": { + "controllable": true, + "colors": ["STATUS_LED_COLOR_GREEN", "STATUS_LED_COLOR_GREEN_BLINK", "STATUS_LED_COLOR_AMBER", "STATUS_LED_COLOR_AMBER_BLINK", "STATUS_LED_COLOR_OFF"] + }, + "components": [ + { + "name": "CPLD1" + }, + { + "name": "BIOS" + } + ], + "fans": [ + { + "name": "FAN-1", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-2", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-3", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ], + "fan_drawers":[ + { + "name": "FanTray1", + "status_led": { + "controllable": false + }, + "num_fans" : 1, + "fans": [ + { + "name": "FAN-1", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ] + }, + { + "name": "FanTray2", + "status_led": { + "controllable": false + }, + "num_fans" : 1, + "fans": [ + { + "name": "FAN-2", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ] + }, + { + "name": "FanTray3", + "status_led": { + "controllable": false + }, + "num_fans" : 1, + "fans": [ + { + "name": "FAN-3", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ] + } + ], + "psus": [ + { + "name": "PSU-1", + "status_led": { + "controllable": true, + "colors": ["STATUS_LED_COLOR_GREEN", "STATUS_LED_COLOR_AMBER", "STATUS_LED_COLOR_OFF"] + }, + "fans": [ + { + "name": "PSU-1 FAN-1" + } + ], + "thermals": [ + { + "name": "PSU-1 temp sensor 1", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + } + ] + }, + { + "name": "PSU-2", + "status_led": { + "controllable": true, + "colors": ["STATUS_LED_COLOR_GREEN", "STATUS_LED_COLOR_AMBER", "STATUS_LED_COLOR_OFF"] + }, + "fans": [ + { + "name": "PSU-2 FAN-1" + } + ], + "thermals": [ + { + "name": "PSU-2 temp sensor 1", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + } + ] + } + ], + "thermals": [ + { + "name": "Temp sensor 1", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "Temp sensor 2", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "Temp sensor 3", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "Temp sensor 4", + "controllable": false, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + } + ], + "sfps": [ + { + "name": "Ethernet0" + }, + { + "name": "Ethernet1" + }, + { + "name": "Ethernet2" + }, + { + "name": "Ethernet3" + }, + { + "name": "Ethernet4" + }, + { + "name": "Ethernet5" + }, + { + "name": "Ethernet6" + }, + { + "name": "Ethernet7" + }, + { + "name": "Ethernet8" + }, + { + "name": "Ethernet9" + }, + { + "name": "Ethernet10" + }, + { + "name": "Ethernet11" + }, + { + "name": "Ethernet12" + }, + { + "name": "Ethernet13" + }, + { + "name": "Ethernet14" + }, + { + "name": "Ethernet15" + }, + { + "name": "Ethernet16" + }, + { + "name": "Ethernet17" + }, + { + "name": "Ethernet18" + }, + { + "name": "Ethernet19" + }, + { + "name": "Ethernet20" + }, + { + "name": "Ethernet21" + }, + { + "name": "Ethernet22" + }, + { + "name": "Ethernet23" + }, + { + "name": "Ethernet24" + }, + { + "name": "Ethernet25" + }, + { + "name": "Ethernet26" + }, + { + "name": "Ethernet27" + }, + { + "name": "Ethernet28" + }, + { + "name": "Ethernet29" + }, + { + "name": "Ethernet30" + }, + { + "name": "Ethernet31" + }, + { + "name": "Ethernet32" + }, + { + "name": "Ethernet33" + }, + { + "name": "Ethernet34" + }, + { + "name": "Ethernet35" + }, + { + "name": "Ethernet36" + }, + { + "name": "Ethernet37" + }, + { + "name": "Ethernet38" + }, + { + "name": "Ethernet39" + }, + { + "name": "Ethernet40" + }, + { + "name": "Ethernet41" + }, + { + "name": "Ethernet42" + }, + { + "name": "Ethernet43" + }, + { + "name": "Ethernet44" + }, + { + "name": "Ethernet45" + }, + { + "name": "Ethernet46" + }, + { + "name": "Ethernet47" + }, + { + "name": "Ethernet48" + }, + { + "name": "Ethernet49" + }, + { + "name": "Ethernet50" + }, + { + "name": "Ethernet51" + }, + { + "name": "Ethernet52" + }, + { + "name": "Ethernet56" + } + ] + }, + "interfaces": { + "Ethernet0": { + "index": "1", + "lanes": "26", + "breakout_modes": { + "1x1G": ["Eth1(Port1)"] + } + }, + + "Ethernet1": { + "index": "2", + "lanes": "25", + "breakout_modes": { + "1x1G": ["Eth2(Port2)"] + } + }, + + "Ethernet2": { + "index": "3", + "lanes": "28", + "breakout_modes": { + "1x1G": ["Eth3(Port3)"] + } + }, + + "Ethernet3": { + "index": "4", + "lanes": "27", + "breakout_modes": { + "1x1G": ["Eth4(Port4)"] + } + }, + + "Ethernet4": { + "index": "5", + "lanes": "30", + "breakout_modes": { + "1x1G": ["Eth5(Port5)"] + } + }, + + "Ethernet5": { + "index": "6", + "lanes": "29", + "breakout_modes": { + "1x1G": ["Eth6(Port6)"] + } + }, + + "Ethernet6": { + "index": "7", + "lanes": "32", + "breakout_modes": { + "1x1G": ["Eth7(Port7)"] + } + }, + + "Ethernet7": { + "index": "8", + "lanes": "31", + "breakout_modes": { + "1x1G": ["Eth8(Port8)"] + } + }, + + "Ethernet8": { + "index": "9", + "lanes": "38", + "breakout_modes": { + "1x1G": ["Eth9(Port9)"] + } + }, + + "Ethernet9": { + "index": "10", + "lanes": "37", + "breakout_modes": { + "1x1G": ["Eth10(Port10)"] + } + }, + + "Ethernet10": { + "index": "11", + "lanes": "40", + "breakout_modes": { + "1x1G": ["Eth11(Port11)"] + } + }, + + "Ethernet11": { + "index": "12", + "lanes": "39", + "breakout_modes": { + "1x1G": ["Eth12(Port12)"] + } + }, + + "Ethernet12": { + "index": "13", + "lanes": "34", + "breakout_modes": { + "1x1G": ["Eth13(Port13)"] + } + }, + + "Ethernet13": { + "index": "14", + "lanes": "33", + "breakout_modes": { + "1x1G": ["Eth14(Port14)"] + } + }, + + "Ethernet14": { + "index": "15", + "lanes": "36", + "breakout_modes": { + "1x1G": ["Eth15(Port15)"] + } + }, + + "Ethernet15": { + "index": "16", + "lanes": "35", + "breakout_modes": { + "1x1G": ["Eth16(Port16)"] + } + }, + + "Ethernet16": { + "index": "17", + "lanes": "46", + "breakout_modes": { + "1x1G": ["Eth17(Port17)"] + } + }, + + "Ethernet17": { + "index": "18", + "lanes": "45", + "breakout_modes": { + "1x1G": ["Eth18(Port18)"] + } + }, + + "Ethernet18": { + "index": "19", + "lanes": "48", + "breakout_modes": { + "1x1G": ["Eth19(Port19)"] + } + }, + + "Ethernet19": { + "index": "20", + "lanes": "47", + "breakout_modes": { + "1x1G": ["Eth20(Port20)"] + } + }, + + "Ethernet20": { + "index": "21", + "lanes": "42", + "breakout_modes": { + "1x1G": ["Eth21(Port21)"] + } + }, + + "Ethernet21": { + "index": "22", + "lanes": "41", + "breakout_modes": { + "1x1G": ["Eth22(Port22)"] + } + }, + + "Ethernet22": { + "index": "23", + "lanes": "44", + "breakout_modes": { + "1x1G": ["Eth23(Port23)"] + } + }, + + "Ethernet23": { + "index": "24", + "lanes": "43", + "breakout_modes": { + "1x1G": ["Eth24(Port24)"] + } + }, + + "Ethernet24": { + "index": "25", + "lanes": "2", + "breakout_modes": { + "1x1G": ["Eth25(Port25)"] + } + }, + + "Ethernet25": { + "index": "26", + "lanes": "1", + "breakout_modes": { + "1x1G": ["Eth26(Port26)"] + } + }, + + "Ethernet26": { + "index": "27", + "lanes": "4", + "breakout_modes": { + "1x1G": ["Eth27(Port27)"] + } + }, + + "Ethernet27": { + "index": "28", + "lanes": "3", + "breakout_modes": { + "1x1G": ["Eth28(Port28)"] + } + }, + + "Ethernet28": { + "index": "29", + "lanes": "6", + "breakout_modes": { + "1x1G": ["Eth29(Port29)"] + } + }, + + "Ethernet29": { + "index": "30", + "lanes": "5", + "breakout_modes": { + "1x1G": ["Eth30(Port30)"] + } + }, + + "Ethernet30": { + "index": "31", + "lanes": "8", + "breakout_modes": { + "1x1G": ["Eth31(Port31)"] + } + }, + + "Ethernet31": { + "index": "32", + "lanes": "7", + "breakout_modes": { + "1x1G": ["Eth32(Port32)"] + } + }, + + "Ethernet32": { + "index": "33", + "lanes": "10", + "breakout_modes": { + "1x1G": ["Eth33(Port33)"] + } + }, + + "Ethernet33": { + "index": "34", + "lanes": "9", + "breakout_modes": { + "1x1G": ["Eth34(Port34)"] + } + }, + + "Ethernet34": { + "index": "35", + "lanes": "12", + "breakout_modes": { + "1x1G": ["Eth35(Port35)"] + } + }, + + "Ethernet35": { + "index": "36", + "lanes": "11", + "breakout_modes": { + "1x1G": ["Eth36(Port36)"] + } + }, + + "Ethernet36": { + "index": "37", + "lanes": "14", + "breakout_modes": { + "1x1G": ["Eth37(Port37)"] + } + }, + + "Ethernet37": { + "index": "38", + "lanes": "13", + "breakout_modes": { + "1x1G": ["Eth38(Port38)"] + } + }, + + "Ethernet38": { + "index": "39", + "lanes": "16", + "breakout_modes": { + "1x1G": ["Eth39(Port39)"] + } + }, + + "Ethernet39": { + "index": "40", + "lanes": "15", + "breakout_modes": { + "1x1G": ["Eth40(Port40)"] + } + }, + + "Ethernet40": { + "index": "41", + "lanes": "18", + "breakout_modes": { + "1x1G": ["Eth41(Port41)"] + } + }, + + "Ethernet41": { + "index": "42", + "lanes": "17", + "breakout_modes": { + "1x1G": ["Eth42(Port42)"] + } + }, + + "Ethernet42": { + "index": "43", + "lanes": "20", + "breakout_modes": { + "1x1G": ["Eth43(Port43)"] + } + }, + + "Ethernet43": { + "index": "44", + "lanes": "19", + "breakout_modes": { + "1x1G": ["Eth44(Port44)"] + } + }, + + "Ethernet44": { + "index": "45", + "lanes": "22", + "breakout_modes": { + "1x1G": ["Eth45(Port45)"] + } + }, + + "Ethernet45": { + "index": "46", + "lanes": "21", + "breakout_modes": { + "1x1G": ["Eth46(Port46)"] + } + }, + + "Ethernet46": { + "index": "47", + "lanes": "24", + "breakout_modes": { + "1x1G": ["Eth47(Port47)"] + } + }, + + "Ethernet47": { + "index": "48", + "lanes": "23", + "breakout_modes": { + "1x1G": ["Eth48(Port48)"] + } + }, + + "Ethernet48": { + "index": "49", + "lanes": "67", + "breakout_modes": { + "1x25G[10G]": ["Eth49(Port49)"] + } + }, + + "Ethernet49": { + "index": "50", + "lanes": "66", + "breakout_modes": { + "1x25G[10G]": ["Eth50(Port50)"] + } + }, + + "Ethernet50": { + "index": "51", + "lanes": "65", + "breakout_modes": { + "1x25G[10G]": ["Eth51(Port51)"] + } + }, + + "Ethernet51": { + "index": "52", + "lanes": "68", + "breakout_modes": { + "1x25G[10G]": ["Eth52(Port52)"] + } + }, + "Ethernet52": { + "index": "53,53,53,53", + "lanes": "73,74,75,76", + "breakout_modes": { + "1x100G[40G]": ["Eth53(Port53)"], + "2x50G": ["Eth53/1(Port53)", "Eth53/2(Port53)"], + "4x25G[10G]": ["Eth53/1(Port53)", "Eth53/2(Port53)", "Eth53/3(Port53)", "Eth53/4(Port53)"] + } + }, + + "Ethernet56": { + "index": "54,54,54,54", + "lanes": "69,70,71,72", + "breakout_modes": { + "1x100G[40G]": ["Eth54(Port54)"], + "2x50G": ["Eth54/1(Port54)", "Eth54/2(Port54)"], + "4x25G[10G]": ["Eth54/1(Port54)", "Eth54/2(Port54)", "Eth54/3(Port54)", "Eth54/4(Port54)"] + } + } + } +} diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/platform_components.json b/device/accton/x86_64-accton_as4630_54pe-r0/platform_components.json new file mode 100644 index 0000000000..c1465e1374 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/platform_components.json @@ -0,0 +1,10 @@ +{ + "chassis": { + "4630-54PE-O-AC-F": { + "component": { + "CPLD1": { }, + "BIOS": { } + } + } + } +} \ No newline at end of file diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as4630_54pe-r0/pmon_daemon_control.json index a3b204e20d..44bad64942 100644 --- a/device/accton/x86_64-accton_as4630_54pe-r0/pmon_daemon_control.json +++ b/device/accton/x86_64-accton_as4630_54pe-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_as4630_54pe-r0/system_health_monitoring_config.json b/device/accton/x86_64-accton_as4630_54pe-r0/system_health_monitoring_config.json index 61f624ee34..deb3745e14 100644 --- a/device/accton/x86_64-accton_as4630_54pe-r0/system_health_monitoring_config.json +++ b/device/accton/x86_64-accton_as4630_54pe-r0/system_health_monitoring_config.json @@ -1,17 +1,13 @@ { "services_to_ignore": [], "devices_to_ignore": [ - "asic", - "psu.voltage", - "psu.temperature", - "PSU1_FAN1.speed", - "PSU2_FAN1.speed" + "asic" ], "user_defined_checkers": [], "polling_interval": 60, "led_color": { - "fault": "STATUS_LED_COLOR_AMBER", - "normal": "STATUS_LED_COLOR_GREEN", - "booting": "STATUS_LED_COLOR_GREEN_BLINK" + "fault": "amber", + "normal": "green", + "booting": "green_blink" } } diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-pddf-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-pddf-platform-monitor.service new file mode 100644 index 0000000000..99bca2684f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-pddf-platform-monitor.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS4630-54PE Platform Monitoring service +Before=pmon.service +After=pddf-platform-init.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as4630_54pe_pddf_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/chassis.py index 1dfca24ab3..8ec7deb95a 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/chassis.py @@ -10,10 +10,14 @@ import sys 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 = 2 +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): """ @@ -26,6 +30,7 @@ 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() def __initialize_components(self): from sonic_platform.component import Component @@ -68,3 +73,57 @@ def get_status_led(self): 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 + if port in range(1, 49): + return SfpBase.SFP_PORT_TYPE_BIT_RJ45 + elif port in range(49, 53): + return SfpBase.SFP_PORT_TYPE_BIT_SFP | SfpBase.SFP_PORT_TYPE_BIT_SFP_PLUS | SfpBase.SFP_PORT_TYPE_BIT_SFP28 + else: + return SfpBase.SFP_PORT_TYPE_BIT_QSFP | SfpBase.SFP_PORT_TYPE_BIT_QSFP_PLUS | SfpBase.SFP_PORT_TYPE_BIT_QSFP28 + + 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_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_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/as4630-54pe/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/component.py index 2659d16f1c..a30b4630e0 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/component.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/component.py @@ -8,6 +8,8 @@ ############################################################################# 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: @@ -82,4 +84,85 @@ def install_firmware(self, image_path): Returns: A boolean, True if install successfully, False if not """ - raise NotImplementedError + ret, output = getstatusoutput_noshell(["tar", "-C", "/tmp", "-xzf", image_path ] ) + if ret != 0 : + print("Installation failed because of wrong image package") + return False + + if os.path.exists("/tmp/install.json") is False: + 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/as4630-54pe/sonic_platform/event.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/event.py index d5dac6d7f7..1a2f60dbb6 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/event.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/event.py @@ -1,11 +1,21 @@ 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 ''' @@ -46,15 +56,54 @@ def get_sfp_event(self, timeout=2000): if changed_ports != 0: for sfp in self._sfp_list: i=sfp.get_position_in_parent() - 1 - if (changed_ports & (1 << i)): - if (bitmap & (1 << i)) == 0: - port_dict[i+1] = '0' - else: - port_dict[i+1] = '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/as4630-54pe/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/fan.py index ef8deaffb6..b9be5e3ca3 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/fan.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/fan.py @@ -6,6 +6,7 @@ except ImportError as e: raise ImportError(str(e) + "- required module not found") +FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3"] class Fan(PddfFan): """PDDF Platform-Specific Fan class""" @@ -24,25 +25,53 @@ def get_direction(self): A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST depending on fan direction """ + direction = 'N/A' if self.is_psu_fan: 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: + return direction 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] \ + 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/as4630-54pe/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/fan_drawer.py index 3b9bb607f6..eae95191e1 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/fan_drawer.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/fan_drawer.py @@ -15,3 +15,26 @@ 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/as4630-54pe/sonic_platform/helper.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/helper.py new file mode 100644 index 0000000000..f6adee3098 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/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/as4630-54pe/sonic_platform/pcie.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/pcie.py new file mode 100644 index 0000000000..73d3627dbf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/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/as4630-54pe/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/psu.py index f002f5e039..c748605476 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/psu.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/psu.py @@ -10,42 +10,121 @@ 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_capacity(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 + """ + 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: + string: Model/part number of device + """ + model = super().get_model() + if model and model.strip() == "": + return None + + return model + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + serial = super().get_serial() + if serial and serial.strip() == "": + return None + + return serial + + def get_voltage(self): """ - Gets the capacity (maximum output power) of the PSU in watts + Retrieves current PSU voltage output Returns: - An integer, the capacity of PSU + A float number, the output voltage in volts, + e.g. 12.1 """ - return (self.PLATFORM_PSU_CAPACITY) + if self.get_status() is not True: + return 0.0 - def get_type(self): + return super().get_voltage() + + def get_current(self): """ - Gets the type of the PSU + Retrieves present electric current supplied by PSU Returns: - A string, the type of PSU (AC/DC) + A float number, electric current in amperes, + e.g. 15.4 """ - ptype = "AC" - # Currently the platform supports only AC type of PSUs - #try: - #import sonic_platform.platform - #ch=sonic_platform.platform.Platform().get_chassis() - #e=ch.sys_eeprom.read_eeprom() - #ret, prod_name = ch.sys_eeprom.get_tlv_field(e,0x21) - #if ret: - #prod_name = prod_name[2] - ##print("Product name is {}".format(prod_name)) - #if '48V' in prod_name: - #ptype = 'DC' - #except Exception as e: - #print("Error while trying to read syseeprom to get PSU type") + 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() + + def get_maximum_supplied_power(self): + """ + Retrieves current energy supplied by PSU + Returns: + A float number, the power in watts, + e.g. 302.6 + """ + device = "PSU{}".format(self.psu_index) + output = self.pddf_obj.get_attr_name_output(device, "psu_p_out_max") + if not output: + return 0.0 + + p_out = output['status'] + + # power is returned in micro watts + return float(p_out)/1000 - return ptype diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/sfp.py index c9fb07d636..534834d878 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/sfp.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/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,10 +14,197 @@ 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_reset_status(self): + if self.sfp_type == "QSFP28": + return super().get_reset_status() + return False + + def reset(self): + if self.sfp_type == "QSFP28": + return super().reset() + return False + + 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" + """ + if self.sfp_type != "SFP28" and self.sfp_type != "QSFP28": + return "Not implemented" + 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/as4630-54pe/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/thermal.py index 77d6ec7ae8..3dd096567e 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/thermal.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/thermal.py @@ -3,10 +3,55 @@ 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 = { + 'Temp sensor 1' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'Temp sensor 2' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'Temp sensor 3' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'Temp sensor 4' : { + HIGH_THRESHOLD : '71.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '91.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): """PDDF Platform-Specific Thermal class""" @@ -14,4 +59,196 @@ 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: + 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/as4630-54pe/utils/accton_as4630_54pe_pddf_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_pddf_monitor.py index 6bbaeaa06d..5e8a5210e8 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_pddf_monitor.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_pddf_monitor.py @@ -207,14 +207,24 @@ def manage_fans(self): fan_fail_list[i] = 0 if sum(fan_fail_list) == NUM_FANS: + logging.critical( + 'Alarm for all fan faulty/absent is detected, disable PoE') + cmd_str = ["i2cset", "-f", "-y", "16", "0x20", "0x06", "0x0", "0x0", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff", "0xFE", "i"] + getstatusoutput_noshell(cmd_str) # Disable PoE + # Critical: Either all the fans are faulty or they are removed, shutdown the system logging.critical('Alarm for all fan faulty/absent is detected') - logging.critical("Alarm for all fan faulty/absent is detected, reset DUT") - cmd_str = ["i2cset", "-y", "-f", "3", "0x60", "0x4", "0xE4"] + logging.critical("Alarm for all fan faulty/absent is detected, shutdown DUT") + + # Sync log buffer to disk + cmd_str = ["sync"] + getstatusoutput_noshell(cmd_str) + cmd_str = ["/sbin/fstrim", "-av"] + getstatusoutput_noshell(cmd_str) + time.sleep(3) + + cmd_str = ["i2cset", "-y", "-f", "3", "0x60", "0x4", "0x74"] time.sleep(2) - getstatusoutput_noshell('sync') - getstatusoutput_noshell('sync') - getstatusoutput_noshell('sync') getstatusoutput_noshell(cmd_str) elif sum(fan_fail_list) != 0: # Set the 100% speed only for first fan failure detection @@ -243,8 +253,13 @@ def manage_fans(self): if temp[0] >= 70000: # LM77-48 # critical case*/ + logging.critical( + 'Alarm-Critical for temperature critical is detected, disable PoE') + cmd_str = ["i2cset", "-f", "-y", "16", "0x20", "0x06", "0x0", "0x0", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff", "0xFE", "i"] + getstatusoutput_noshell(cmd_str) # Disable PoE + logging.critical('Alarm for temperature critical is detected') - logging.critical("Alarm-Critical for temperature critical is detected, reset DUT") + logging.critical("Alarm-Critical for temperature critical is detected, shutdown DUT") # Update the reboot cause file to reflect that critical temperature # has been crossed. Upon next boot, the contents of this file will # be used to determine the cause of the previous reboot @@ -255,10 +270,14 @@ def manage_fans(self): if status: logging.warning('Reboot cause file not updated. {}'.format(output)) - cmd_str = ["i2cset", "-y", "-f", "3", "0x60", "0x4", "0xE4"] - getstatusoutput_noshell('sync') - getstatusoutput_noshell('sync') - getstatusoutput_noshell('sync') + # Sync log buffer to disk + cmd_str = ["sync"] + getstatusoutput_noshell(cmd_str) + cmd_str = ["/sbin/fstrim", "-av"] + getstatusoutput_noshell(cmd_str) + time.sleep(3) + + cmd_str = ["i2cset", "-y", "-f", "3", "0x60", "0x4", "0x74"] time.sleep(3) getstatusoutput_noshell(cmd_str) diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py index b954da8726..0c55036ddf 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py @@ -16,21 +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_as4630_54pe_util.py [-h] [-d] [-f] {install,clean,api,api_clean,threshold} ... + +AS4630-54PE 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,api,api_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 time import os +import argparse +from sonic_py_common.general import getstatusoutput_noshell PROJECT_NAME = 'as4630_54pe' version = '0.0.1' @@ -97,40 +106,48 @@ def main(): global DEBUG global args global FORCE + global THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH + + util_parser = argparse.ArgumentParser(description="AS4630-54PE 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 len(sys.argv)<2: - show_help() - - options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', - 'debug', - 'force', - ]) 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 @@ -382,5 +399,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/as4630-54pe/utils/handle_mgmt_interface.sh b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/handle_mgmt_interface.sh index e1acd16a01..19eae1716d 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/handle_mgmt_interface.sh +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/handle_mgmt_interface.sh @@ -1,9 +1,7 @@ #!/bin/bash -#Due to the hardware design, as4630-54pe use "eth2" instead of "eth0" as management interface. -#Rename netdev "eth0" and "eth2" to swap original "eth2" to "eth0". - -ifconfig eth0 down -ip link set eth0 name eth3 -ip link set eth2 name eth0 -ifconfig eth0 up +# Re-install the igb and ixgbe again to make the NIC sequence follow the udev rule +modprobe -r igb +modprobe -r ixgbe +modprobe igb +modprobe ixgbe diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/rules b/platform/broadcom/sonic-platform-modules-accton/debian/rules index 6d9c78bcb1..241b1be9d6 100755 --- a/platform/broadcom/sonic-platform-modules-accton/debian/rules +++ b/platform/broadcom/sonic-platform-modules-accton/debian/rules @@ -70,11 +70,15 @@ binary-indep: dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/local/bin; \ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ - dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} etc/udev/rules.d; \ + if [ -d $(MOD_SRC_DIR)/$${mod}/$(UDEV_DIR) ]; then \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} etc/udev/rules.d; \ + fi; \ cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ - cp $(MOD_SRC_DIR)/$${mod}/$(UDEV_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/etc/udev/rules.d/; \ + if [ -f $(MOD_SRC_DIR)/$${mod}/$(UDEV_DIR)/* ]; then \ + cp $(MOD_SRC_DIR)/$${mod}/$(UDEV_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/etc/udev/rules.d/; \ + fi; \ $(PYTHON3) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ done) # Resuming debhelper scripts diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as4630-54pe.postinst b/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as4630-54pe.postinst index 1a87abf9ad..1d2161e4e5 100644 --- a/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as4630-54pe.postinst +++ b/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as4630-54pe.postinst @@ -7,4 +7,8 @@ systemctl enable pddf-platform-init.service systemctl start pddf-platform-init.service systemctl enable as4630-54pe-pddf-platform-monitor.service systemctl start as4630-54pe-pddf-platform-monitor.service +systemctl enable as4630-54pe-platform-handle-mgmt-interface.service +systemctl start as4630-54pe-platform-handle-mgmt-interface.service /usr/local/bin/restart_ixgbe.sh +systemctl enable as4630-54pe-platform-handle-mgmt-interface.service +systemctl start as4630-54pe-platform-handle-mgmt-interface.service