DellEMC: S6100, S6000 - Enable thermalctld, Platform API implementation and fixes (#6438)
**- Why I did it** To incorporate the below changes in DellEMC S6100, S6000 platforms. - S6100, S6000: - Enable 'thermalctld' - Implement DeviceBase methods (presence, status, model, serial) for Fantray and Component - Implement ‘get_position_in_parent’, ‘is_replaceable’ methods for all device types - Implement ‘get_status’ method for Fantray - Implement ‘get_temperature’, ‘get_temperature_high_threshold’, ‘get_voltage_high_threshold’, ‘get_voltage_low_threshold’ methods for PSU - Implement ‘get_status_led’, ‘set_status_led’ methods for Chassis - SFP: - Make EEPROM read both Python2 and Python3 compatible - Fix ‘get_tx_disable_channel’ method’s return type - Implement ‘tx_disable’, ‘tx_disable_channel’ and ‘set_power_override’ methods - S6000: - Move PSU thermal sensors from Chassis to respective PSU - Make available the data of both Fans present in each Fantray **- How I did it** - Remove 'skip_thermalctld:true' in pmon_daemon_control.json - Implement the platform API methods in the respective device files - Use `bytearray` for data read from transceiver EEPROM - Change return type of 'get_tx_disable_channel' to match specification in sonic_platform_common/sfp_base.py
This commit is contained in:
parent
85a6314424
commit
fa89c6dd8f
@ -1,4 +1,3 @@
|
|||||||
{
|
{
|
||||||
"skip_ledd": true,
|
"skip_ledd": true
|
||||||
"skip_thermalctld": true
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
{
|
{
|
||||||
"skip_ledd": true,
|
"skip_ledd": true
|
||||||
"skip_thermalctld": true
|
|
||||||
}
|
}
|
||||||
|
@ -174,6 +174,9 @@
|
|||||||
/* Mailbox PowerOn Reason */
|
/* Mailbox PowerOn Reason */
|
||||||
#define TRACK_POWERON_REASON 0x05FF
|
#define TRACK_POWERON_REASON 0x05FF
|
||||||
|
|
||||||
|
/* System Status LED */
|
||||||
|
#define SYSTEM_STATUS_LED 0x04DF
|
||||||
|
|
||||||
/* CPU Set IO Modules */
|
/* CPU Set IO Modules */
|
||||||
#define CPU_IOM1_CTRL_FLAG 0x04D9
|
#define CPU_IOM1_CTRL_FLAG 0x04D9
|
||||||
#define CPU_IOM2_CTRL_FLAG 0x04DA
|
#define CPU_IOM2_CTRL_FLAG 0x04DA
|
||||||
@ -607,6 +610,44 @@ static ssize_t show_mb_poweron_reason(struct device *dev,
|
|||||||
return sprintf(buf, "0x%x\n", ret);
|
return sprintf(buf, "0x%x\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* System Status LED */
|
||||||
|
static ssize_t set_sys_status_led(struct device *dev,
|
||||||
|
struct device_attribute *devattr, const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
unsigned int dev_data = 0;
|
||||||
|
struct smf_data *data = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (data->kind == z9100smf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
err = kstrtouint(buf, 16, &dev_data);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = smf_write_reg(data, SYSTEM_STATUS_LED, dev_data);
|
||||||
|
if(err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_sys_status_led(struct device *dev,
|
||||||
|
struct device_attribute *devattr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned int ret = 0;
|
||||||
|
struct smf_data *data = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (data->kind == z9100smf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = smf_read_reg(data, SYSTEM_STATUS_LED);
|
||||||
|
if(ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return sprintf(buf, "0x%x\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
/* FANIN ATTR */
|
/* FANIN ATTR */
|
||||||
static ssize_t
|
static ssize_t
|
||||||
show_fan_label(struct device *dev, struct device_attribute *attr, char *buf)
|
show_fan_label(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
@ -2081,12 +2122,17 @@ static SENSOR_DEVICE_ATTR(smf_poweron_reason, S_IRUGO,
|
|||||||
static SENSOR_DEVICE_ATTR(mb_poweron_reason, S_IRUGO|S_IWUSR,
|
static SENSOR_DEVICE_ATTR(mb_poweron_reason, S_IRUGO|S_IWUSR,
|
||||||
show_mb_poweron_reason, set_mb_poweron_reason, 0);
|
show_mb_poweron_reason, set_mb_poweron_reason, 0);
|
||||||
|
|
||||||
|
/* System Status LED */
|
||||||
|
static SENSOR_DEVICE_ATTR(sys_status_led, S_IRUGO|S_IWUSR,
|
||||||
|
show_sys_status_led, set_sys_status_led, 0);
|
||||||
|
|
||||||
static struct attribute *smf_dell_attrs[] = {
|
static struct attribute *smf_dell_attrs[] = {
|
||||||
&sensor_dev_attr_smf_version.dev_attr.attr,
|
&sensor_dev_attr_smf_version.dev_attr.attr,
|
||||||
&sensor_dev_attr_smf_firmware_ver.dev_attr.attr,
|
&sensor_dev_attr_smf_firmware_ver.dev_attr.attr,
|
||||||
&sensor_dev_attr_smf_reset_reason.dev_attr.attr,
|
&sensor_dev_attr_smf_reset_reason.dev_attr.attr,
|
||||||
&sensor_dev_attr_smf_poweron_reason.dev_attr.attr,
|
&sensor_dev_attr_smf_poweron_reason.dev_attr.attr,
|
||||||
&sensor_dev_attr_mb_poweron_reason.dev_attr.attr,
|
&sensor_dev_attr_mb_poweron_reason.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_sys_status_led.dev_attr.attr,
|
||||||
&sensor_dev_attr_fan_tray_presence.dev_attr.attr,
|
&sensor_dev_attr_fan_tray_presence.dev_attr.attr,
|
||||||
&sensor_dev_attr_fan1_airflow.dev_attr.attr,
|
&sensor_dev_attr_fan1_airflow.dev_attr.attr,
|
||||||
&sensor_dev_attr_fan3_airflow.dev_attr.attr,
|
&sensor_dev_attr_fan3_airflow.dev_attr.attr,
|
||||||
|
@ -24,7 +24,7 @@ except ImportError as e:
|
|||||||
|
|
||||||
MAX_S6000_FANTRAY = 3
|
MAX_S6000_FANTRAY = 3
|
||||||
MAX_S6000_PSU = 2
|
MAX_S6000_PSU = 2
|
||||||
MAX_S6000_THERMAL = 10
|
MAX_S6000_THERMAL = 6
|
||||||
MAX_S6000_COMPONENT = 4
|
MAX_S6000_COMPONENT = 4
|
||||||
|
|
||||||
|
|
||||||
@ -44,6 +44,8 @@ class Chassis(ChassisBase):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ChassisBase.__init__(self)
|
ChassisBase.__init__(self)
|
||||||
|
self.status_led_reg = "system_led"
|
||||||
|
self.supported_led_color = ['green', 'blinking green', 'amber', 'blinking amber']
|
||||||
# Initialize SFP list
|
# Initialize SFP list
|
||||||
self.PORT_START = 0
|
self.PORT_START = 0
|
||||||
self.PORT_END = 31
|
self.PORT_END = 31
|
||||||
@ -101,13 +103,30 @@ class Chassis(ChassisBase):
|
|||||||
try:
|
try:
|
||||||
with open(mb_reg_file, 'r') as fd:
|
with open(mb_reg_file, 'r') as fd:
|
||||||
rv = fd.read()
|
rv = fd.read()
|
||||||
except Exception as error:
|
except IOError:
|
||||||
rv = 'ERR'
|
rv = 'ERR'
|
||||||
|
|
||||||
rv = rv.rstrip('\r\n')
|
rv = rv.rstrip('\r\n')
|
||||||
rv = rv.lstrip(" ")
|
rv = rv.lstrip(" ")
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
def _set_cpld_register(self, reg_name, value):
|
||||||
|
# On successful write, returns the value will be written on
|
||||||
|
# reg_name and on failure returns 'ERR'
|
||||||
|
rv = 'ERR'
|
||||||
|
cpld_reg_file = self.CPLD_DIR+'/'+reg_name
|
||||||
|
|
||||||
|
if (not os.path.isfile(cpld_reg_file)):
|
||||||
|
return rv
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(cpld_reg_file, 'w') as fd:
|
||||||
|
rv = fd.write(str(value))
|
||||||
|
except IOError:
|
||||||
|
rv = 'ERR'
|
||||||
|
|
||||||
|
return rv
|
||||||
|
|
||||||
def _nvram_write(self, offset, val):
|
def _nvram_write(self, offset, val):
|
||||||
resource = "/dev/nvram"
|
resource = "/dev/nvram"
|
||||||
fd = os.open(resource, os.O_RDWR)
|
fd = os.open(resource, os.O_RDWR)
|
||||||
@ -179,6 +198,23 @@ class Chassis(ChassisBase):
|
|||||||
"""
|
"""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
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 Chassis is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
def get_base_mac(self):
|
def get_base_mac(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the base MAC address for the chassis
|
Retrieves the base MAC address for the chassis
|
||||||
@ -305,4 +341,41 @@ class Chassis(ChassisBase):
|
|||||||
return True, ret_dict
|
return True, ret_dict
|
||||||
return False, ret_dict
|
return False, ret_dict
|
||||||
|
|
||||||
|
def set_status_led(self, color):
|
||||||
|
"""
|
||||||
|
Sets the state of the system LED
|
||||||
|
|
||||||
|
Args:
|
||||||
|
color: A string representing the color with which to set the
|
||||||
|
system LED
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if system LED state is set successfully, False if not
|
||||||
|
"""
|
||||||
|
if color not in self.supported_led_color:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Change color string format to the one used by driver
|
||||||
|
color = color.replace('amber', 'yellow')
|
||||||
|
color = color.replace('blinking ', 'blink_')
|
||||||
|
rv = self._set_cpld_register(self.status_led_reg, color)
|
||||||
|
if (rv != 'ERR'):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_status_led(self):
|
||||||
|
"""
|
||||||
|
Gets the state of the system LED
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string, one of the valid LED color strings which could be vendor
|
||||||
|
specified.
|
||||||
|
"""
|
||||||
|
status_led = self._get_cpld_register(self.status_led_reg)
|
||||||
|
if (status_led != 'ERR'):
|
||||||
|
status_led = status_led.replace('yellow', 'amber')
|
||||||
|
status_led = status_led.replace('blink_', 'blinking ')
|
||||||
|
return status_led
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
@ -29,8 +29,8 @@ class Component(ComponentBase):
|
|||||||
"booting")],
|
"booting")],
|
||||||
["System-CPLD", "Used for managing CPU board devices and power"],
|
["System-CPLD", "Used for managing CPU board devices and power"],
|
||||||
["Master-CPLD", ("Used for managing Fan, PSU, system LEDs, QSFP "
|
["Master-CPLD", ("Used for managing Fan, PSU, system LEDs, QSFP "
|
||||||
"modules (1-16)")],
|
"modules (17-32)")],
|
||||||
["Slave-CPLD", "Used for managing QSFP modules (17-32)"]
|
["Slave-CPLD", "Used for managing QSFP modules (1-16)"]
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, component_index):
|
def __init__(self, component_index):
|
||||||
@ -90,6 +90,55 @@ class Component(ComponentBase):
|
|||||||
"""
|
"""
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
"""
|
||||||
|
Retrieves the part number of the component
|
||||||
|
Returns:
|
||||||
|
string: Part number of component
|
||||||
|
"""
|
||||||
|
return 'NA'
|
||||||
|
|
||||||
|
def get_serial(self):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the component
|
||||||
|
Returns:
|
||||||
|
string: Serial number of component
|
||||||
|
"""
|
||||||
|
return 'NA'
|
||||||
|
|
||||||
|
def get_presence(self):
|
||||||
|
"""
|
||||||
|
Retrieves the presence of the component
|
||||||
|
Returns:
|
||||||
|
bool: True if present, False if not
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_status(self):
|
||||||
|
"""
|
||||||
|
Retrieves the operational status of the component
|
||||||
|
Returns:
|
||||||
|
bool: True if component is operating properly, False if not
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
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 component is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
def get_description(self):
|
def get_description(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the description of the component
|
Retrieves the description of the component
|
||||||
|
@ -36,8 +36,8 @@ psu_eeprom_format = [
|
|||||||
('Fab Rev', 's', 2)
|
('Fab Rev', 's', 2)
|
||||||
]
|
]
|
||||||
|
|
||||||
# Fan eeprom fields in format required by EepromDecoder
|
# FanTray eeprom fields in format required by EepromDecoder
|
||||||
fan_eeprom_format = [
|
fantray_eeprom_format = [
|
||||||
('PPID', 's', 20), ('DPN Rev', 's', 3), ('Service Tag', 's', 7),
|
('PPID', 's', 20), ('DPN Rev', 's', 3), ('Service Tag', 's', 7),
|
||||||
('Part Number', 's', 10), ('Part Num Revision', 's', 3),
|
('Part Number', 's', 10), ('Part Num Revision', 's', 3),
|
||||||
('Mfg Test', 's', 2), ('Redundant copy', 's', 83),
|
('Mfg Test', 's', 2), ('Redundant copy', 's', 83),
|
||||||
@ -51,10 +51,10 @@ class Eeprom(TlvInfoDecoder):
|
|||||||
|
|
||||||
I2C_DIR = "/sys/class/i2c-adapter/"
|
I2C_DIR = "/sys/class/i2c-adapter/"
|
||||||
|
|
||||||
def __init__(self, is_psu=False, psu_index=0, is_fan=False, fan_index=0):
|
def __init__(self, is_psu=False, psu_index=0, is_fantray=False, fantray_index=0):
|
||||||
self.is_psu_eeprom = is_psu
|
self.is_psu_eeprom = is_psu
|
||||||
self.is_fan_eeprom = is_fan
|
self.is_fantray_eeprom = is_fantray
|
||||||
self.is_sys_eeprom = not (is_psu | is_fan)
|
self.is_sys_eeprom = not (is_psu | is_fantray)
|
||||||
|
|
||||||
if self.is_sys_eeprom:
|
if self.is_sys_eeprom:
|
||||||
self.start_offset = 0
|
self.start_offset = 0
|
||||||
@ -71,10 +71,10 @@ class Eeprom(TlvInfoDecoder):
|
|||||||
+ "i2c-1/1-005{}/eeprom".format(2 - self.index)
|
+ "i2c-1/1-005{}/eeprom".format(2 - self.index)
|
||||||
self.format = psu_eeprom_format
|
self.format = psu_eeprom_format
|
||||||
else:
|
else:
|
||||||
self.index = fan_index
|
self.index = fantray_index
|
||||||
self.eeprom_path = self.I2C_DIR \
|
self.eeprom_path = self.I2C_DIR \
|
||||||
+ "i2c-11/11-005{}/eeprom".format(4 - self.index)
|
+ "i2c-11/11-005{}/eeprom".format(4 - self.index)
|
||||||
self.format = fan_eeprom_format
|
self.format = fantray_eeprom_format
|
||||||
EepromDecoder.__init__(self, self.eeprom_path, self.format,
|
EepromDecoder.__init__(self, self.eeprom_path, self.format,
|
||||||
self.start_offset, '', True)
|
self.start_offset, '', True)
|
||||||
self._load_device_eeprom()
|
self._load_device_eeprom()
|
||||||
|
@ -13,7 +13,6 @@ try:
|
|||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
from sonic_platform_base.fan_base import FanBase
|
from sonic_platform_base.fan_base import FanBase
|
||||||
from sonic_platform.eeprom import Eeprom
|
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
@ -25,33 +24,37 @@ MAX_S6000_FAN_SPEED = 19000
|
|||||||
class Fan(FanBase):
|
class Fan(FanBase):
|
||||||
"""DellEMC Platform-specific Fan class"""
|
"""DellEMC Platform-specific Fan class"""
|
||||||
|
|
||||||
CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0/"
|
|
||||||
I2C_DIR = "/sys/class/i2c-adapter/"
|
I2C_DIR = "/sys/class/i2c-adapter/"
|
||||||
|
FAN_DEV_MAPPING = {
|
||||||
|
1: {1: ("i2c-11/11-002a", 1), 2: ("i2c-11/11-002a", 2)},
|
||||||
|
2: {1: ("i2c-11/11-0029", 3), 2: ("i2c-11/11-0029", 4)},
|
||||||
|
3: {1: ("i2c-11/11-0029", 1), 2: ("i2c-11/11-0029", 2)}
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, fan_index, psu_fan=False, dependency=None):
|
def __init__(self, fantray_index=1, fan_index=1,
|
||||||
|
psu_index=1, psu_fan=False, dependency=None):
|
||||||
self.is_psu_fan = psu_fan
|
self.is_psu_fan = psu_fan
|
||||||
self.is_driver_initialized = True
|
self.is_driver_initialized = True
|
||||||
|
|
||||||
if not self.is_psu_fan:
|
if not self.is_psu_fan:
|
||||||
# Fan is 1-based in DellEMC platforms
|
# Fan is 1-based in DellEMC platforms
|
||||||
self.index = fan_index + 1
|
self.fantray_index = fantray_index
|
||||||
self.fan_presence_reg = "fan_prs"
|
|
||||||
self.fan_led_reg = "fan{}_led".format(fan_index)
|
|
||||||
self.get_fan_speed_reg = self.I2C_DIR + "i2c-11/11-0029/" +\
|
|
||||||
"fan{}_input".format(self.index)
|
|
||||||
self.set_fan_speed_reg = self.I2C_DIR + "i2c-11/11-0029/" +\
|
|
||||||
"fan{}_target".format(self.index)
|
|
||||||
self.eeprom = Eeprom(is_fan=True, fan_index=self.index)
|
|
||||||
self.max_fan_speed = MAX_S6000_FAN_SPEED
|
|
||||||
self.supported_led_color = ['off', 'green', 'amber']
|
|
||||||
else:
|
|
||||||
self.index = fan_index
|
self.index = fan_index
|
||||||
self.dependency = dependency
|
self.dependency = dependency
|
||||||
|
self.get_fan_speed_reg = self.I2C_DIR +\
|
||||||
|
"{}/fan{}_input".format(*self.FAN_DEV_MAPPING[fantray_index][fan_index])
|
||||||
self.set_fan_speed_reg = self.I2C_DIR +\
|
self.set_fan_speed_reg = self.I2C_DIR +\
|
||||||
"i2c-1/1-005{}/fan1_target".format(10 - self.index)
|
"{}/fan{}_target".format(*self.FAN_DEV_MAPPING[fantray_index][fan_index])
|
||||||
|
self.max_fan_speed = MAX_S6000_FAN_SPEED
|
||||||
|
else:
|
||||||
|
self.psu_index = psu_index
|
||||||
|
self.index = 1
|
||||||
|
self.dependency = dependency
|
||||||
|
self.set_fan_speed_reg = self.I2C_DIR +\
|
||||||
|
"i2c-1/1-005{}/fan1_target".format(10 - self.psu_index)
|
||||||
|
|
||||||
hwmon_dir = self.I2C_DIR +\
|
hwmon_dir = self.I2C_DIR +\
|
||||||
"i2c-1/1-005{}/hwmon/".format(10 - self.index)
|
"i2c-1/1-005{}/hwmon/".format(10 - self.psu_index)
|
||||||
try:
|
try:
|
||||||
hwmon_node = os.listdir(hwmon_dir)[0]
|
hwmon_node = os.listdir(hwmon_dir)[0]
|
||||||
except OSError:
|
except OSError:
|
||||||
@ -61,43 +64,6 @@ class Fan(FanBase):
|
|||||||
self.get_fan_speed_reg = hwmon_dir + hwmon_node + '/fan1_input'
|
self.get_fan_speed_reg = hwmon_dir + hwmon_node + '/fan1_input'
|
||||||
self.max_fan_speed = MAX_S6000_PSU_FAN_SPEED
|
self.max_fan_speed = MAX_S6000_PSU_FAN_SPEED
|
||||||
|
|
||||||
def _get_cpld_register(self, reg_name):
|
|
||||||
# On successful read, returns the value read from given
|
|
||||||
# reg_name and on failure returns 'ERR'
|
|
||||||
rv = 'ERR'
|
|
||||||
cpld_reg_file = self.CPLD_DIR + reg_name
|
|
||||||
|
|
||||||
if (not os.path.isfile(cpld_reg_file)):
|
|
||||||
return rv
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(cpld_reg_file, 'r') as fd:
|
|
||||||
rv = fd.read()
|
|
||||||
except:
|
|
||||||
rv = 'ERR'
|
|
||||||
|
|
||||||
rv = rv.rstrip('\r\n')
|
|
||||||
rv = rv.lstrip(" ")
|
|
||||||
return rv
|
|
||||||
|
|
||||||
def _set_cpld_register(self, reg_name, value):
|
|
||||||
# On successful write, returns the value will be written on
|
|
||||||
# reg_name and on failure returns 'ERR'
|
|
||||||
rv = 'ERR'
|
|
||||||
cpld_reg_file = self.CPLD_DIR + reg_name
|
|
||||||
|
|
||||||
if (not os.path.isfile(cpld_reg_file)):
|
|
||||||
print("open error")
|
|
||||||
return rv
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(cpld_reg_file, 'w') as fd:
|
|
||||||
rv = fd.write(str(value))
|
|
||||||
except:
|
|
||||||
rv = 'ERR'
|
|
||||||
|
|
||||||
return rv
|
|
||||||
|
|
||||||
def _get_i2c_register(self, reg_file):
|
def _get_i2c_register(self, reg_file):
|
||||||
# On successful read, returns the value read from given
|
# On successful read, returns the value read from given
|
||||||
# reg_name and on failure returns 'ERR'
|
# reg_name and on failure returns 'ERR'
|
||||||
@ -155,9 +121,9 @@ class Fan(FanBase):
|
|||||||
string: The name of the Fan
|
string: The name of the Fan
|
||||||
"""
|
"""
|
||||||
if not self.is_psu_fan:
|
if not self.is_psu_fan:
|
||||||
return "FanTray{}-Fan1".format(self.index)
|
return "FanTray{}-Fan{}".format(self.fantray_index, self.index)
|
||||||
else:
|
else:
|
||||||
return "PSU{} Fan".format(self.index)
|
return "PSU{} Fan".format(self.psu_index)
|
||||||
|
|
||||||
def get_presence(self):
|
def get_presence(self):
|
||||||
"""
|
"""
|
||||||
@ -166,42 +132,23 @@ class Fan(FanBase):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: True if Fan is present, False if not
|
bool: True if Fan is present, False if not
|
||||||
"""
|
"""
|
||||||
status = False
|
return self.dependency.get_presence()
|
||||||
if self.is_psu_fan:
|
|
||||||
return self.dependency.get_presence()
|
|
||||||
|
|
||||||
fan_presence = self._get_cpld_register(self.fan_presence_reg)
|
|
||||||
if (fan_presence != 'ERR'):
|
|
||||||
fan_presence = int(fan_presence,16) & self.index
|
|
||||||
if fan_presence:
|
|
||||||
status = True
|
|
||||||
|
|
||||||
return status
|
|
||||||
|
|
||||||
def get_model(self):
|
def get_model(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the part number of the Fan
|
Retrieves the part number of the Fan
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
string: Part number of Fan
|
string: Part number of Fan
|
||||||
"""
|
"""
|
||||||
if not self.is_psu_fan:
|
return 'NA'
|
||||||
return self.eeprom.get_part_number()
|
|
||||||
else:
|
|
||||||
return 'NA'
|
|
||||||
|
|
||||||
def get_serial(self):
|
def get_serial(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the serial number of the Fan
|
Retrieves the serial number of the Fan
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
string: Serial number of Fan
|
string: Serial number of Fan
|
||||||
"""
|
"""
|
||||||
# Sample Serial number format "US-01234D-54321-25A-0123-A00"
|
return 'NA'
|
||||||
if not self.is_psu_fan:
|
|
||||||
return self.eeprom.get_serial_number()
|
|
||||||
else:
|
|
||||||
return 'NA'
|
|
||||||
|
|
||||||
def get_status(self):
|
def get_status(self):
|
||||||
"""
|
"""
|
||||||
@ -218,6 +165,23 @@ class Fan(FanBase):
|
|||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
Returns:
|
||||||
|
integer: The 1-based relative physical position in parent
|
||||||
|
device or -1 if cannot determine the position
|
||||||
|
"""
|
||||||
|
return self.index
|
||||||
|
|
||||||
|
def is_replaceable(self):
|
||||||
|
"""
|
||||||
|
Indicate whether Fan is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
def get_direction(self):
|
def get_direction(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the fan airflow direction
|
Retrieves the fan airflow direction
|
||||||
@ -234,11 +198,10 @@ class Fan(FanBase):
|
|||||||
if self.is_psu_fan:
|
if self.is_psu_fan:
|
||||||
direction = {1: self.FAN_DIRECTION_EXHAUST, 2: self.FAN_DIRECTION_INTAKE,
|
direction = {1: self.FAN_DIRECTION_EXHAUST, 2: self.FAN_DIRECTION_INTAKE,
|
||||||
3: self.FAN_DIRECTION_EXHAUST, 4: self.FAN_DIRECTION_INTAKE}
|
3: self.FAN_DIRECTION_EXHAUST, 4: self.FAN_DIRECTION_INTAKE}
|
||||||
fan_direction = self.dependency.eeprom.airflow_fan_type()
|
|
||||||
else:
|
else:
|
||||||
direction = {1: self.FAN_DIRECTION_EXHAUST, 2: self.FAN_DIRECTION_INTAKE}
|
direction = {1: self.FAN_DIRECTION_EXHAUST, 2: self.FAN_DIRECTION_INTAKE}
|
||||||
fan_direction = self.eeprom.airflow_fan_type()
|
|
||||||
|
|
||||||
|
fan_direction = self.dependency.eeprom.airflow_fan_type()
|
||||||
return direction.get(fan_direction, self.FAN_DIRECTION_NOT_APPLICABLE)
|
return direction.get(fan_direction, self.FAN_DIRECTION_NOT_APPLICABLE)
|
||||||
|
|
||||||
def get_speed(self):
|
def get_speed(self):
|
||||||
@ -282,8 +245,8 @@ class Fan(FanBase):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: True if set success, False if fail.
|
bool: True if set success, False if fail.
|
||||||
"""
|
"""
|
||||||
fan_set = (speed * self.max_fan_speed)/ 100
|
fan_set = (speed * self.max_fan_speed) // 100
|
||||||
rv = self._set_i2c_register(self.set_fan_speed_reg , fan_set)
|
rv = self._set_i2c_register(self.set_fan_speed_reg, fan_set)
|
||||||
if (rv != 'ERR'):
|
if (rv != 'ERR'):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
@ -298,16 +261,9 @@ class Fan(FanBase):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: True if set success, False if fail.
|
bool: True if set success, False if fail.
|
||||||
"""
|
"""
|
||||||
if self.is_psu_fan or (color not in self.supported_led_color):
|
# No LED available for FanTray and PSU Fan
|
||||||
return False
|
# Return True to avoid thermalctld alarm.
|
||||||
if(color == self.STATUS_LED_COLOR_AMBER):
|
return True
|
||||||
color = 'yellow'
|
|
||||||
|
|
||||||
rv = self._set_cpld_register(self.fan_led_reg ,color)
|
|
||||||
if (rv != 'ERR'):
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_status_led(self):
|
def get_status_led(self):
|
||||||
"""
|
"""
|
||||||
@ -316,18 +272,8 @@ class Fan(FanBase):
|
|||||||
Returns:
|
Returns:
|
||||||
A string, one of the predefined STATUS_LED_COLOR_* strings.
|
A string, one of the predefined STATUS_LED_COLOR_* strings.
|
||||||
"""
|
"""
|
||||||
if self.is_psu_fan:
|
# No LED available for FanTray and PSU Fan
|
||||||
# No LED available for PSU Fan
|
return None
|
||||||
return None
|
|
||||||
|
|
||||||
fan_led = self._get_cpld_register(self.fan_led_reg)
|
|
||||||
if (fan_led != 'ERR'):
|
|
||||||
if (fan_led == 'yellow'):
|
|
||||||
return self.STATUS_LED_COLOR_AMBER
|
|
||||||
else:
|
|
||||||
return fan_led
|
|
||||||
else:
|
|
||||||
return self.STATUS_LED_COLOR_OFF
|
|
||||||
|
|
||||||
def get_target_speed(self):
|
def get_target_speed(self):
|
||||||
"""
|
"""
|
||||||
|
@ -9,26 +9,176 @@
|
|||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
import os
|
||||||
|
|
||||||
from sonic_platform_base.fan_drawer_base import FanDrawerBase
|
from sonic_platform_base.fan_drawer_base import FanDrawerBase
|
||||||
|
from sonic_platform.eeprom import Eeprom
|
||||||
from sonic_platform.fan import Fan
|
from sonic_platform.fan import Fan
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
MAX_S6000_FANS_PER_FANTRAY = 2
|
||||||
|
|
||||||
|
|
||||||
class FanDrawer(FanDrawerBase):
|
class FanDrawer(FanDrawerBase):
|
||||||
"""DellEMC Platform-specific Fan class"""
|
"""DellEMC Platform-specific Fan Drawer class"""
|
||||||
|
|
||||||
|
CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0/"
|
||||||
|
|
||||||
def __init__(self, fantray_index):
|
def __init__(self, fantray_index):
|
||||||
|
|
||||||
FanDrawerBase.__init__(self)
|
FanDrawerBase.__init__(self)
|
||||||
# FanTray is 1-based in DellEMC platforms
|
# FanTray is 1-based in DellEMC platforms
|
||||||
self.fantrayindex = fantray_index + 1
|
self.index = fantray_index + 1
|
||||||
self._fan_list.append(Fan(fantray_index))
|
self.eeprom = Eeprom(is_fantray=True, fantray_index=self.index)
|
||||||
|
self.fantray_presence_reg = "fan_prs"
|
||||||
|
self.fantray_led_reg = "fan{}_led".format(self.index - 1)
|
||||||
|
self.supported_led_color = ['off', 'green', 'amber']
|
||||||
|
|
||||||
|
for i in range(1, MAX_S6000_FANS_PER_FANTRAY+1):
|
||||||
|
self._fan_list.append(Fan(fantray_index=self.index, fan_index=i, dependency=self))
|
||||||
|
|
||||||
|
def _get_cpld_register(self, reg_name):
|
||||||
|
# On successful read, returns the value read from given
|
||||||
|
# reg_name and on failure returns 'ERR'
|
||||||
|
rv = 'ERR'
|
||||||
|
cpld_reg_file = self.CPLD_DIR + reg_name
|
||||||
|
|
||||||
|
if (not os.path.isfile(cpld_reg_file)):
|
||||||
|
return rv
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(cpld_reg_file, 'r') as fd:
|
||||||
|
rv = fd.read()
|
||||||
|
except IOError:
|
||||||
|
rv = 'ERR'
|
||||||
|
|
||||||
|
rv = rv.rstrip('\r\n')
|
||||||
|
rv = rv.lstrip(" ")
|
||||||
|
return rv
|
||||||
|
|
||||||
|
def _set_cpld_register(self, reg_name, value):
|
||||||
|
# On successful write, returns the value will be written on
|
||||||
|
# reg_name and on failure returns 'ERR'
|
||||||
|
rv = 'ERR'
|
||||||
|
cpld_reg_file = self.CPLD_DIR + reg_name
|
||||||
|
|
||||||
|
if (not os.path.isfile(cpld_reg_file)):
|
||||||
|
return rv
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(cpld_reg_file, 'w') as fd:
|
||||||
|
rv = fd.write(str(value))
|
||||||
|
except IOError:
|
||||||
|
rv = 'ERR'
|
||||||
|
|
||||||
|
return rv
|
||||||
|
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the fan drawer name
|
Retrieves the Fandrawer name
|
||||||
Returns:
|
Returns:
|
||||||
string: The name of the device
|
string: The name of the device
|
||||||
"""
|
"""
|
||||||
return "FanTray{}".format(self.fantrayindex)
|
return "FanTray{}".format(self.index)
|
||||||
|
|
||||||
|
def get_presence(self):
|
||||||
|
"""
|
||||||
|
Retrieves the presence of the Fandrawer
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if Fandrawer is present, False if not
|
||||||
|
"""
|
||||||
|
presence = False
|
||||||
|
|
||||||
|
fantray_presence = self._get_cpld_register(self.fantray_presence_reg)
|
||||||
|
if (fantray_presence != 'ERR'):
|
||||||
|
fantray_presence = int(fantray_presence, 16) & (1 << (self.index - 1))
|
||||||
|
if fantray_presence:
|
||||||
|
presence = True
|
||||||
|
|
||||||
|
return presence
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
"""
|
||||||
|
Retrieves the part number of the Fandrawer
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string: Part number of Fandrawer
|
||||||
|
"""
|
||||||
|
return self.eeprom.get_part_number()
|
||||||
|
|
||||||
|
def get_serial(self):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the Fandrawer
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string: Serial number of Fandrawer
|
||||||
|
"""
|
||||||
|
# Sample Serial number format "US-01234D-54321-25A-0123-A00"
|
||||||
|
return self.eeprom.get_serial_number()
|
||||||
|
|
||||||
|
def get_status(self):
|
||||||
|
"""
|
||||||
|
Retrieves the operational status of the Fandrawer
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if Fandrawer is operating properly, False if not
|
||||||
|
"""
|
||||||
|
status = True
|
||||||
|
for fan in self.get_all_fans():
|
||||||
|
status &= fan.get_status()
|
||||||
|
|
||||||
|
return status
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
Returns:
|
||||||
|
integer: The 1-based relative physical position in parent
|
||||||
|
device or -1 if cannot determine the position
|
||||||
|
"""
|
||||||
|
return self.index
|
||||||
|
|
||||||
|
def is_replaceable(self):
|
||||||
|
"""
|
||||||
|
Indicate whether this fan drawer is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def set_status_led(self, color):
|
||||||
|
"""
|
||||||
|
Set led to expected color
|
||||||
|
Args:
|
||||||
|
color: A string representing the color with which to set the
|
||||||
|
fandrawer status LED
|
||||||
|
Returns:
|
||||||
|
bool: True if set success, False if fail.
|
||||||
|
"""
|
||||||
|
if color not in self.supported_led_color:
|
||||||
|
return False
|
||||||
|
if color == self.STATUS_LED_COLOR_AMBER:
|
||||||
|
color = 'yellow'
|
||||||
|
|
||||||
|
rv = self._set_cpld_register(self.fantray_led_reg, color)
|
||||||
|
if (rv != 'ERR'):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_status_led(self):
|
||||||
|
"""
|
||||||
|
Gets the state of the fandrawer status LED
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string, one of the predefined STATUS_LED_COLOR_* strings.
|
||||||
|
"""
|
||||||
|
fantray_led = self._get_cpld_register(self.fantray_led_reg)
|
||||||
|
if (fantray_led != 'ERR'):
|
||||||
|
if (fantray_led == 'yellow'):
|
||||||
|
return self.STATUS_LED_COLOR_AMBER
|
||||||
|
else:
|
||||||
|
return fantray_led
|
||||||
|
else:
|
||||||
|
return self.STATUS_LED_COLOR_OFF
|
||||||
|
@ -15,9 +15,12 @@ try:
|
|||||||
from sonic_platform_base.psu_base import PsuBase
|
from sonic_platform_base.psu_base import PsuBase
|
||||||
from sonic_platform.eeprom import Eeprom
|
from sonic_platform.eeprom import Eeprom
|
||||||
from sonic_platform.fan import Fan
|
from sonic_platform.fan import Fan
|
||||||
|
from sonic_platform.thermal import Thermal
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
MAX_S6000_THERMALS_PER_PSU = 2
|
||||||
|
|
||||||
|
|
||||||
class Psu(PsuBase):
|
class Psu(PsuBase):
|
||||||
"""DellEMC Platform-specific PSU class"""
|
"""DellEMC Platform-specific PSU class"""
|
||||||
@ -53,7 +56,10 @@ class Psu(PsuBase):
|
|||||||
|
|
||||||
self.eeprom = Eeprom(is_psu=True, psu_index=self.index)
|
self.eeprom = Eeprom(is_psu=True, psu_index=self.index)
|
||||||
|
|
||||||
self._fan_list.append(Fan(self.index, psu_fan=True, dependency=self))
|
self._fan_list.append(Fan(psu_index=self.index, psu_fan=True, dependency=self))
|
||||||
|
for i in range(1, MAX_S6000_THERMALS_PER_PSU+1):
|
||||||
|
self._thermal_list.append(Thermal(psu_index=self.index, thermal_index=i,
|
||||||
|
psu_thermal=True, dependency=self))
|
||||||
|
|
||||||
def _get_cpld_register(self, reg_name):
|
def _get_cpld_register(self, reg_name):
|
||||||
# On successful read, returns the value read from given
|
# On successful read, returns the value read from given
|
||||||
@ -171,6 +177,23 @@ class Psu(PsuBase):
|
|||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
Returns:
|
||||||
|
integer: The 1-based relative physical position in parent
|
||||||
|
device or -1 if cannot determine the position
|
||||||
|
"""
|
||||||
|
return self.index
|
||||||
|
|
||||||
|
def is_replaceable(self):
|
||||||
|
"""
|
||||||
|
Indicate whether PSU is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
def get_voltage(self):
|
def get_voltage(self):
|
||||||
"""
|
"""
|
||||||
Retrieves current PSU voltage output
|
Retrieves current PSU voltage output
|
||||||
@ -266,3 +289,50 @@ class Psu(PsuBase):
|
|||||||
# In S6000, the firmware running in the PSU controls the LED
|
# In S6000, the firmware running in the PSU controls the LED
|
||||||
# and the PSU LED state cannot be changed from CPU.
|
# and the PSU LED state cannot be changed from CPU.
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def get_temperature(self):
|
||||||
|
"""
|
||||||
|
Retrieves current temperature reading from PSU
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A float number of current temperature in Celsius up to
|
||||||
|
nearest thousandth of one degree Celsius, e.g. 30.125
|
||||||
|
"""
|
||||||
|
if self.get_presence():
|
||||||
|
return self.get_thermal(0).get_temperature()
|
||||||
|
else:
|
||||||
|
return 0.0
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
if self.get_presence():
|
||||||
|
return self.get_thermal(0).get_high_threshold()
|
||||||
|
else:
|
||||||
|
return 0.0
|
||||||
|
|
||||||
|
def get_voltage_high_threshold(self):
|
||||||
|
"""
|
||||||
|
Retrieves the high threshold PSU voltage output
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A float number, the high threshold output voltage in volts,
|
||||||
|
e.g. 12.1
|
||||||
|
"""
|
||||||
|
return 12.6
|
||||||
|
|
||||||
|
def get_voltage_low_threshold(self):
|
||||||
|
"""
|
||||||
|
Retrieves the low threshold PSU voltage output
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A float number, the low threshold output voltage in volts,
|
||||||
|
e.g. 12.1
|
||||||
|
"""
|
||||||
|
return 11.4
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import re
|
import re
|
||||||
|
import struct
|
||||||
import time
|
import time
|
||||||
from sonic_platform_base.sfp_base import SfpBase
|
from sonic_platform_base.sfp_base import SfpBase
|
||||||
from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId
|
from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId
|
||||||
@ -27,6 +28,9 @@ INFO_OFFSET = 128
|
|||||||
DOM_OFFSET = 0
|
DOM_OFFSET = 0
|
||||||
DOM_OFFSET1 = 384
|
DOM_OFFSET1 = 384
|
||||||
|
|
||||||
|
QSFP_CONTROL_OFFSET = 86
|
||||||
|
QSFP_POWEROVERRIDE_OFFSET = 93
|
||||||
|
|
||||||
cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)',
|
cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)',
|
||||||
'Length OM1(m)', 'Length Cable Assembly(m)')
|
'Length OM1(m)', 'Length Cable Assembly(m)')
|
||||||
|
|
||||||
@ -108,7 +112,7 @@ class Sfp(SfpBase):
|
|||||||
sfp_control, sfp_ctrl_idx):
|
sfp_control, sfp_ctrl_idx):
|
||||||
SfpBase.__init__(self)
|
SfpBase.__init__(self)
|
||||||
self.sfp_type = sfp_type
|
self.sfp_type = sfp_type
|
||||||
self.index = index
|
self.index = index + 1
|
||||||
self.eeprom_path = eeprom_path
|
self.eeprom_path = eeprom_path
|
||||||
self.sfp_control = sfp_control
|
self.sfp_control = sfp_control
|
||||||
self.sfp_ctrl_idx = sfp_ctrl_idx
|
self.sfp_ctrl_idx = sfp_ctrl_idx
|
||||||
@ -132,9 +136,10 @@ class Sfp(SfpBase):
|
|||||||
eeprom.close()
|
eeprom.close()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
raw = bytearray(raw)
|
||||||
try:
|
try:
|
||||||
for n in range(0, num_bytes):
|
for n in range(0, num_bytes):
|
||||||
eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2)
|
eeprom_raw[n] = hex(raw[n])[2:].zfill(2)
|
||||||
except BaseException:
|
except BaseException:
|
||||||
eeprom.close()
|
eeprom.close()
|
||||||
return None
|
return None
|
||||||
@ -588,40 +593,14 @@ class Sfp(SfpBase):
|
|||||||
"""
|
"""
|
||||||
Retrieves the TX disabled channels in this SFP
|
Retrieves the TX disabled channels in this SFP
|
||||||
"""
|
"""
|
||||||
tx_disable = None
|
tx_disable_channel = 0
|
||||||
tx_disable_list = []
|
|
||||||
|
|
||||||
tx_disable_data = self._get_eeprom_data('tx_disable')
|
tx_disable = self.get_tx_disable()
|
||||||
if (tx_disable_data is not None):
|
for channel, disable in enumerate(tx_disable):
|
||||||
tx_disable = tx_disable_data['data']['Tx1Disable']['value']
|
if disable:
|
||||||
if (tx_disable == 'On'):
|
tx_disable_channel |= 1 << channel
|
||||||
tx_disable_list.append(1)
|
|
||||||
else:
|
|
||||||
tx_disable_list.append(0)
|
|
||||||
tx_disable = tx_disable_data['data']['Tx2Disable']['value']
|
|
||||||
if (tx_disable == 'On'):
|
|
||||||
tx_disable_list.append(1)
|
|
||||||
else:
|
|
||||||
tx_disable_list.append(0)
|
|
||||||
tx_disable = tx_disable_data['data']['Tx3Disable']['value']
|
|
||||||
if (tx_disable == 'On'):
|
|
||||||
tx_disable_list.append(1)
|
|
||||||
else:
|
|
||||||
tx_disable_list.append(0)
|
|
||||||
tx_disable = tx_disable_data['data']['Tx4Disable']['value']
|
|
||||||
if (tx_disable == 'On'):
|
|
||||||
tx_disable_list.append(1)
|
|
||||||
else:
|
|
||||||
tx_disable_list.append(0)
|
|
||||||
|
|
||||||
bit4 = int(tx_disable_list[3]) * 8
|
return tx_disable_channel
|
||||||
bit3 = int(tx_disable_list[2]) * 4
|
|
||||||
bit2 = int(tx_disable_list[1]) * 2
|
|
||||||
bit1 = int(tx_disable_list[0]) * 1
|
|
||||||
|
|
||||||
tx_disable_channel = hex(bit4 + bit3 + bit2 + bit1)
|
|
||||||
|
|
||||||
return tx_disable_channel
|
|
||||||
|
|
||||||
def get_lpmode(self):
|
def get_lpmode(self):
|
||||||
"""
|
"""
|
||||||
@ -722,7 +701,6 @@ class Sfp(SfpBase):
|
|||||||
|
|
||||||
return rx_power_list
|
return rx_power_list
|
||||||
|
|
||||||
|
|
||||||
def get_tx_power(self):
|
def get_tx_power(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the TX power of this SFP
|
Retrieves the TX power of this SFP
|
||||||
@ -822,19 +800,68 @@ class Sfp(SfpBase):
|
|||||||
"""
|
"""
|
||||||
Disable SFP TX for all channels
|
Disable SFP TX for all channels
|
||||||
"""
|
"""
|
||||||
return False
|
eeprom = None
|
||||||
|
tx_disable_value = 0xf if tx_disable else 0x0
|
||||||
|
|
||||||
|
try:
|
||||||
|
eeprom = open(self.eeprom_path, "r+b")
|
||||||
|
eeprom.seek(QSFP_CONTROL_OFFSET)
|
||||||
|
eeprom.write(struct.pack('B', tx_disable_value))
|
||||||
|
except IOError:
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
if eeprom is not None:
|
||||||
|
eeprom.close()
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def tx_disable_channel(self, channel, disable):
|
def tx_disable_channel(self, channel, disable):
|
||||||
"""
|
"""
|
||||||
Sets the tx_disable for specified SFP channels
|
Sets the tx_disable for specified SFP channels
|
||||||
"""
|
"""
|
||||||
return False
|
eeprom = None
|
||||||
|
current_state = self.get_tx_disable_channel()
|
||||||
|
|
||||||
|
if disable:
|
||||||
|
tx_disable_value = current_state | channel
|
||||||
|
else:
|
||||||
|
tx_disable_value = current_state & (~channel)
|
||||||
|
|
||||||
|
try:
|
||||||
|
eeprom = open(self.eeprom_path, "r+b")
|
||||||
|
eeprom.seek(QSFP_CONTROL_OFFSET)
|
||||||
|
eeprom.write(struct.pack('B', tx_disable_value))
|
||||||
|
except IOError:
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
if eeprom is not None:
|
||||||
|
eeprom.close()
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def set_power_override(self, power_override, power_set):
|
def set_power_override(self, power_override, power_set):
|
||||||
"""
|
"""
|
||||||
Sets SFP power level using power_override and power_set
|
Sets SFP power level using power_override and power_set
|
||||||
"""
|
"""
|
||||||
return False
|
eeprom = None
|
||||||
|
power_override_bit = 0x1 if power_override else 0
|
||||||
|
power_set_bit = 0x2 if power_set else 0
|
||||||
|
value = power_override_bit | power_set_bit
|
||||||
|
|
||||||
|
try:
|
||||||
|
eeprom = open(self.eeprom_path, "r+b")
|
||||||
|
eeprom.seek(QSFP_POWEROVERRIDE_OFFSET)
|
||||||
|
eeprom.write(struct.pack('B', value))
|
||||||
|
except IOError:
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
if eeprom is not None:
|
||||||
|
eeprom.close()
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def get_status(self):
|
def get_status(self):
|
||||||
"""
|
"""
|
||||||
@ -848,3 +875,20 @@ class Sfp(SfpBase):
|
|||||||
status = True
|
status = True
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
Returns:
|
||||||
|
integer: The 1-based relative physical position in parent
|
||||||
|
device or -1 if cannot determine the position
|
||||||
|
"""
|
||||||
|
return self.index
|
||||||
|
|
||||||
|
def is_replaceable(self):
|
||||||
|
"""
|
||||||
|
Indicate whether this device is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
@ -13,7 +13,6 @@ try:
|
|||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
from sonic_platform_base.thermal_base import ThermalBase
|
from sonic_platform_base.thermal_base import ThermalBase
|
||||||
from sonic_platform.psu import Psu
|
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
raise ImportError(str(e) + "- required module not found")
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
@ -34,11 +33,20 @@ class Thermal(ThermalBase):
|
|||||||
'PSU1-Sensor 1', 'PSU1-Sensor 2', 'PSU2-Sensor 1',
|
'PSU1-Sensor 1', 'PSU1-Sensor 2', 'PSU2-Sensor 1',
|
||||||
'PSU2-Sensor 2', 'CPU Core 0', 'CPU Core 1')
|
'PSU2-Sensor 2', 'CPU Core 0', 'CPU Core 1')
|
||||||
|
|
||||||
def __init__(self, thermal_index):
|
def __init__(self, thermal_index,
|
||||||
self.index = thermal_index + 1
|
psu_index=1, psu_thermal=False, dependency=None):
|
||||||
self.is_psu_thermal = False
|
self.is_psu_thermal = psu_thermal
|
||||||
|
self.dependency = dependency
|
||||||
self.is_driver_initialized = True
|
self.is_driver_initialized = True
|
||||||
self.dependency = None
|
|
||||||
|
if self.is_psu_thermal:
|
||||||
|
self.index = (2 * psu_index) + thermal_index + 2
|
||||||
|
else:
|
||||||
|
# CPU thermal
|
||||||
|
if thermal_index > 3:
|
||||||
|
self.index = thermal_index + 5
|
||||||
|
else:
|
||||||
|
self.index = thermal_index + 1
|
||||||
|
|
||||||
if self.index < 9:
|
if self.index < 9:
|
||||||
i2c_path = self.I2C_DIR + self.I2C_DEV_MAPPING[self.index - 1][0]
|
i2c_path = self.I2C_DIR + self.I2C_DEV_MAPPING[self.index - 1][0]
|
||||||
@ -54,10 +62,6 @@ class Thermal(ThermalBase):
|
|||||||
|
|
||||||
if self.index == 4:
|
if self.index == 4:
|
||||||
hwmon_temp_suffix = "crit"
|
hwmon_temp_suffix = "crit"
|
||||||
|
|
||||||
if self.index > 4:
|
|
||||||
self.is_psu_thermal = True
|
|
||||||
self.dependency = Psu(self.index / 7)
|
|
||||||
else:
|
else:
|
||||||
dev_path = "/sys/devices/platform/coretemp.0/hwmon/"
|
dev_path = "/sys/devices/platform/coretemp.0/hwmon/"
|
||||||
hwmon_temp_index = self.index - 7
|
hwmon_temp_index = self.index - 7
|
||||||
@ -168,6 +172,23 @@ class Thermal(ThermalBase):
|
|||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
Returns:
|
||||||
|
integer: The 1-based relative physical position in parent
|
||||||
|
device or -1 if cannot determine the position
|
||||||
|
"""
|
||||||
|
return self.index
|
||||||
|
|
||||||
|
def is_replaceable(self):
|
||||||
|
"""
|
||||||
|
Indicate whether Thermal is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
def get_temperature(self):
|
def get_temperature(self):
|
||||||
"""
|
"""
|
||||||
Retrieves current temperature reading from thermal
|
Retrieves current temperature reading from thermal
|
||||||
|
@ -54,9 +54,21 @@ class Chassis(ChassisBase):
|
|||||||
power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
|
power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
|
||||||
power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED
|
power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED
|
||||||
|
|
||||||
|
status_led_reg_to_color = {
|
||||||
|
0x00: 'green', 0x01: 'blinking green', 0x02: 'amber',
|
||||||
|
0x04: 'amber', 0x08: 'blinking amber', 0x10: 'blinking amber'
|
||||||
|
}
|
||||||
|
|
||||||
|
color_to_status_led_reg = {
|
||||||
|
'green': 0x00, 'blinking green': 0x01,
|
||||||
|
'amber': 0x02, 'blinking amber': 0x08
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
ChassisBase.__init__(self)
|
ChassisBase.__init__(self)
|
||||||
|
self.status_led_reg = "sys_status_led"
|
||||||
|
self.supported_led_color = ['green', 'blinking green', 'amber', 'blinking amber']
|
||||||
# Initialize EEPROM
|
# Initialize EEPROM
|
||||||
self._eeprom = Eeprom()
|
self._eeprom = Eeprom()
|
||||||
for i in range(MAX_S6100_MODULE):
|
for i in range(MAX_S6100_MODULE):
|
||||||
@ -113,6 +125,23 @@ class Chassis(ChassisBase):
|
|||||||
rv = rv.lstrip(" ")
|
rv = rv.lstrip(" ")
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
def _set_pmc_register(self, reg_name, value):
|
||||||
|
# On successful write, returns the length of value written on
|
||||||
|
# reg_name and on failure returns 'ERR'
|
||||||
|
rv = 'ERR'
|
||||||
|
mb_reg_file = self.MAILBOX_DIR + '/' + reg_name
|
||||||
|
|
||||||
|
if (not os.path.isfile(mb_reg_file)):
|
||||||
|
return rv
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(mb_reg_file, 'w') as fd:
|
||||||
|
rv = fd.write(str(value))
|
||||||
|
except IOError:
|
||||||
|
rv = 'ERR'
|
||||||
|
|
||||||
|
return rv
|
||||||
|
|
||||||
def _get_register(self, reg_file):
|
def _get_register(self, reg_file):
|
||||||
# On successful read, returns the value read from given
|
# On successful read, returns the value read from given
|
||||||
# reg_name and on failure returns 'ERR'
|
# reg_name and on failure returns 'ERR'
|
||||||
@ -172,6 +201,23 @@ class Chassis(ChassisBase):
|
|||||||
"""
|
"""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
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 Chassis is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
def get_base_mac(self):
|
def get_base_mac(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the base MAC address for the chassis
|
Retrieves the base MAC address for the chassis
|
||||||
@ -325,3 +371,38 @@ class Chassis(ChassisBase):
|
|||||||
break
|
break
|
||||||
|
|
||||||
return True, ret_dict
|
return True, ret_dict
|
||||||
|
|
||||||
|
def set_status_led(self, color):
|
||||||
|
"""
|
||||||
|
Sets the state of the system LED
|
||||||
|
|
||||||
|
Args:
|
||||||
|
color: A string representing the color with which to set the
|
||||||
|
system LED
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if system LED state is set successfully, False if not
|
||||||
|
"""
|
||||||
|
if color not in self.supported_led_color:
|
||||||
|
return False
|
||||||
|
|
||||||
|
value = self.color_to_status_led_reg[color]
|
||||||
|
rv = self._set_pmc_register(self.status_led_reg, value)
|
||||||
|
if (rv != 'ERR'):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_status_led(self):
|
||||||
|
"""
|
||||||
|
Gets the state of the system LED
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string, one of the valid LED color strings which could be
|
||||||
|
vendor specified.
|
||||||
|
"""
|
||||||
|
reg_val = self._get_pmc_register(self.status_led_reg)
|
||||||
|
if (reg_val != 'ERR'):
|
||||||
|
return self.status_led_reg_to_color.get(int(reg_val, 16), None)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
@ -39,9 +39,10 @@ class Component(ComponentBase):
|
|||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, component_index=0,
|
def __init__(self, component_index=0,
|
||||||
is_module=False, iom_index=0, i2c_line=0):
|
is_module=False, iom_index=0, i2c_line=0, dependency=None):
|
||||||
|
|
||||||
self.is_module_component = is_module
|
self.is_module_component = is_module
|
||||||
|
self.dependency = dependency
|
||||||
|
|
||||||
if self.is_module_component:
|
if self.is_module_component:
|
||||||
self.index = iom_index
|
self.index = iom_index
|
||||||
@ -132,6 +133,61 @@ class Component(ComponentBase):
|
|||||||
"""
|
"""
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
"""
|
||||||
|
Retrieves the part number of the component
|
||||||
|
Returns:
|
||||||
|
string: Part number of component
|
||||||
|
"""
|
||||||
|
return 'NA'
|
||||||
|
|
||||||
|
def get_serial(self):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the component
|
||||||
|
Returns:
|
||||||
|
string: Serial number of component
|
||||||
|
"""
|
||||||
|
return 'NA'
|
||||||
|
|
||||||
|
def get_presence(self):
|
||||||
|
"""
|
||||||
|
Retrieves the presence of the component
|
||||||
|
Returns:
|
||||||
|
bool: True if present, False if not
|
||||||
|
"""
|
||||||
|
if self.is_module_component:
|
||||||
|
return self.dependency.get_presence()
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_status(self):
|
||||||
|
"""
|
||||||
|
Retrieves the operational status of the component
|
||||||
|
Returns:
|
||||||
|
bool: True if component is operating properly, False if not
|
||||||
|
"""
|
||||||
|
if self.is_module_component:
|
||||||
|
return self.dependency.get_status()
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
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 component is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
def get_description(self):
|
def get_description(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the description of the component
|
Retrieves the description of the component
|
||||||
|
@ -26,30 +26,23 @@ class Fan(FanBase):
|
|||||||
HWMON_NODE = os.listdir(HWMON_DIR)[0]
|
HWMON_NODE = os.listdir(HWMON_DIR)[0]
|
||||||
MAILBOX_DIR = HWMON_DIR + HWMON_NODE
|
MAILBOX_DIR = HWMON_DIR + HWMON_NODE
|
||||||
|
|
||||||
def __init__(self, fantray_index=1, fan_index=1, psu_fan=False):
|
def __init__(self, fantray_index=1, psu_index=1, psu_fan=False, dependency=None):
|
||||||
self.is_psu_fan = psu_fan
|
self.is_psu_fan = psu_fan
|
||||||
if not self.is_psu_fan:
|
if not self.is_psu_fan:
|
||||||
# API index is starting from 0, DellEMC platform index is starting
|
self.fantrayindex = fantray_index
|
||||||
# from 1
|
self.dependency = dependency
|
||||||
self.fantrayindex = fantray_index + 1
|
|
||||||
self.fanindex = fan_index + 1
|
|
||||||
self.fan_presence_reg = "fan{}_fault".format(
|
|
||||||
2 * self.fantrayindex - 1)
|
|
||||||
self.fan_status_reg = "fan{}_alarm".format(
|
self.fan_status_reg = "fan{}_alarm".format(
|
||||||
2 * self.fantrayindex - 1)
|
2 * self.fantrayindex - 1)
|
||||||
self.get_fan_speed_reg = "fan{}_input".format(
|
self.get_fan_speed_reg = "fan{}_input".format(
|
||||||
2 * self.fantrayindex - 1)
|
2 * self.fantrayindex - 1)
|
||||||
self.get_fan_dir_reg = "fan{}_airflow".format(
|
self.get_fan_dir_reg = "fan{}_airflow".format(
|
||||||
2 * self.fantrayindex - 1)
|
2 * self.fantrayindex - 1)
|
||||||
self.fan_serialno_reg = "fan{}_serialno".format(
|
|
||||||
2 * self.fantrayindex - 1)
|
|
||||||
self.max_fan_speed = MAX_S6100_FAN_SPEED
|
self.max_fan_speed = MAX_S6100_FAN_SPEED
|
||||||
else:
|
else:
|
||||||
# PSU Fan index starts from 11
|
self.psuindex = psu_index
|
||||||
self.fanindex = fan_index + 10
|
self.fan_presence_reg = "fan{}_fault".format(self.psuindex + 10)
|
||||||
self.fan_presence_reg = "fan{}_fault".format(self.fanindex)
|
self.get_fan_speed_reg = "fan{}_input".format(self.psuindex + 10)
|
||||||
self.get_fan_speed_reg = "fan{}_input".format(self.fanindex)
|
self.get_fan_dir_reg = "fan{}_airflow".format(self.psuindex + 10)
|
||||||
self.get_fan_dir_reg = "fan{}_airflow".format(self.fanindex)
|
|
||||||
self.max_fan_speed = MAX_S6100_PSU_FAN_SPEED
|
self.max_fan_speed = MAX_S6100_PSU_FAN_SPEED
|
||||||
|
|
||||||
def _get_pmc_register(self, reg_name):
|
def _get_pmc_register(self, reg_name):
|
||||||
@ -77,10 +70,9 @@ class Fan(FanBase):
|
|||||||
string: The name of the device
|
string: The name of the device
|
||||||
"""
|
"""
|
||||||
if not self.is_psu_fan:
|
if not self.is_psu_fan:
|
||||||
return "FanTray{}-Fan{}".format(
|
return "FanTray{}-Fan1".format(self.fantrayindex)
|
||||||
self.fantrayindex, self.fanindex - 1)
|
|
||||||
else:
|
else:
|
||||||
return "PSU{} Fan".format(self.fanindex - 10)
|
return "PSU{} Fan".format(self.psuindex)
|
||||||
|
|
||||||
def get_model(self):
|
def get_model(self):
|
||||||
"""
|
"""
|
||||||
@ -88,21 +80,7 @@ class Fan(FanBase):
|
|||||||
Returns:
|
Returns:
|
||||||
string: Part number of FAN
|
string: Part number of FAN
|
||||||
"""
|
"""
|
||||||
# For Serial number "US-01234D-54321-25A-0123-A00", the part
|
return 'NA'
|
||||||
# number is "01234D"
|
|
||||||
if self.is_psu_fan:
|
|
||||||
return 'NA'
|
|
||||||
|
|
||||||
fan_serialno = self._get_pmc_register(self.fan_serialno_reg)
|
|
||||||
if (fan_serialno != 'ERR') and self.get_presence():
|
|
||||||
if (len(fan_serialno.split('-')) > 1):
|
|
||||||
fan_partno = fan_serialno.split('-')[1]
|
|
||||||
else:
|
|
||||||
fan_partno = 'NA'
|
|
||||||
else:
|
|
||||||
fan_partno = 'NA'
|
|
||||||
|
|
||||||
return fan_partno
|
|
||||||
|
|
||||||
def get_serial(self):
|
def get_serial(self):
|
||||||
"""
|
"""
|
||||||
@ -110,15 +88,7 @@ class Fan(FanBase):
|
|||||||
Returns:
|
Returns:
|
||||||
string: Serial number of FAN
|
string: Serial number of FAN
|
||||||
"""
|
"""
|
||||||
# Sample Serial number format "US-01234D-54321-25A-0123-A00"
|
return 'NA'
|
||||||
if self.is_psu_fan:
|
|
||||||
return 'NA'
|
|
||||||
|
|
||||||
fan_serialno = self._get_pmc_register(self.fan_serialno_reg)
|
|
||||||
if (fan_serialno == 'ERR') or not self.get_presence():
|
|
||||||
fan_serialno = 'NA'
|
|
||||||
|
|
||||||
return fan_serialno
|
|
||||||
|
|
||||||
def get_presence(self):
|
def get_presence(self):
|
||||||
"""
|
"""
|
||||||
@ -126,14 +96,17 @@ class Fan(FanBase):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: True if fan is present, False if not
|
bool: True if fan is present, False if not
|
||||||
"""
|
"""
|
||||||
status = False
|
if not self.is_psu_fan:
|
||||||
fantray_presence = self._get_pmc_register(self.fan_presence_reg)
|
return self.dependency.get_presence()
|
||||||
if (fantray_presence != 'ERR'):
|
|
||||||
fantray_presence = int(fantray_presence, 10)
|
|
||||||
if (~fantray_presence & 0b1):
|
|
||||||
status = True
|
|
||||||
|
|
||||||
return status
|
presence = False
|
||||||
|
fan_presence = self._get_pmc_register(self.fan_presence_reg)
|
||||||
|
if (fan_presence != 'ERR'):
|
||||||
|
fan_presence = int(fan_presence, 10)
|
||||||
|
if (~fan_presence & 0b1):
|
||||||
|
presence = True
|
||||||
|
|
||||||
|
return presence
|
||||||
|
|
||||||
def get_status(self):
|
def get_status(self):
|
||||||
"""
|
"""
|
||||||
@ -157,6 +130,23 @@ class Fan(FanBase):
|
|||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
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 Fan is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
def get_direction(self):
|
def get_direction(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the fan airflow direction
|
Retrieves the fan airflow direction
|
||||||
@ -216,7 +206,6 @@ class Fan(FanBase):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: True if set success, False if fail.
|
bool: True if set success, False if fail.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Fan speeds are controlled by Smart-fussion FPGA.
|
# Fan speeds are controlled by Smart-fussion FPGA.
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -229,7 +218,7 @@ class Fan(FanBase):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: True if set success, False if fail.
|
bool: True if set success, False if fail.
|
||||||
"""
|
"""
|
||||||
# Leds are controlled by Smart-fussion FPGA.
|
# No LED available for FanTray and PSU Fan
|
||||||
# Return True to avoid thermalctld alarm.
|
# Return True to avoid thermalctld alarm.
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -240,17 +229,8 @@ class Fan(FanBase):
|
|||||||
Returns:
|
Returns:
|
||||||
A string, one of the predefined STATUS_LED_COLOR_* strings.
|
A string, one of the predefined STATUS_LED_COLOR_* strings.
|
||||||
"""
|
"""
|
||||||
if self.is_psu_fan:
|
# No LED available for FanTray and PSU Fan
|
||||||
# No LED available for PSU Fan
|
return None
|
||||||
return None
|
|
||||||
else:
|
|
||||||
if self.get_presence():
|
|
||||||
if self.get_status():
|
|
||||||
return self.STATUS_LED_COLOR_GREEN
|
|
||||||
else:
|
|
||||||
return self.STATUS_LED_COLOR_AMBER
|
|
||||||
else:
|
|
||||||
return self.STATUS_LED_COLOR_OFF
|
|
||||||
|
|
||||||
def get_target_speed(self):
|
def get_target_speed(self):
|
||||||
"""
|
"""
|
||||||
@ -262,5 +242,3 @@ class Fan(FanBase):
|
|||||||
# Fan speeds are controlled by Smart-fussion FPGA.
|
# Fan speeds are controlled by Smart-fussion FPGA.
|
||||||
# Return current speed to avoid false thermalctld alarm.
|
# Return current speed to avoid false thermalctld alarm.
|
||||||
return self.get_speed()
|
return self.get_speed()
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
import os
|
||||||
|
|
||||||
from sonic_platform_base.fan_drawer_base import FanDrawerBase
|
from sonic_platform_base.fan_drawer_base import FanDrawerBase
|
||||||
from sonic_platform.fan import Fan
|
from sonic_platform.fan import Fan
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
@ -16,14 +18,38 @@ except ImportError as e:
|
|||||||
|
|
||||||
|
|
||||||
class FanDrawer(FanDrawerBase):
|
class FanDrawer(FanDrawerBase):
|
||||||
"""DellEMC Platform-specific Fan class"""
|
"""DellEMC Platform-specific Fan Drawer class"""
|
||||||
|
|
||||||
|
HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/"
|
||||||
|
HWMON_NODE = os.listdir(HWMON_DIR)[0]
|
||||||
|
MAILBOX_DIR = HWMON_DIR + HWMON_NODE
|
||||||
|
|
||||||
def __init__(self, fantray_index):
|
def __init__(self, fantray_index):
|
||||||
|
|
||||||
FanDrawerBase.__init__(self)
|
FanDrawerBase.__init__(self)
|
||||||
# FanTray is 1-based in DellEMC platforms
|
# FanTray is 1-based in DellEMC platforms
|
||||||
self.fantrayindex = fantray_index + 1
|
self.index = fantray_index + 1
|
||||||
self._fan_list.append(Fan(fantray_index))
|
self.presence_reg = "fan{}_fault".format(2 * self.index - 1)
|
||||||
|
self.serialno_reg = "fan{}_serialno".format(2 * self.index - 1)
|
||||||
|
|
||||||
|
self._fan_list.append(Fan(self.index, dependency=self))
|
||||||
|
|
||||||
|
def _get_pmc_register(self, reg_name):
|
||||||
|
# On successful read, returns the value read from given
|
||||||
|
# reg_name and on failure returns 'ERR'
|
||||||
|
rv = 'ERR'
|
||||||
|
mb_reg_file = self.MAILBOX_DIR+'/'+reg_name
|
||||||
|
|
||||||
|
if (not os.path.isfile(mb_reg_file)):
|
||||||
|
return rv
|
||||||
|
try:
|
||||||
|
with open(mb_reg_file, 'r') as fd:
|
||||||
|
rv = fd.read()
|
||||||
|
except Exception as error:
|
||||||
|
rv = 'ERR'
|
||||||
|
|
||||||
|
rv = rv.rstrip('\r\n')
|
||||||
|
rv = rv.lstrip(" ")
|
||||||
|
return rv
|
||||||
|
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
"""
|
"""
|
||||||
@ -31,4 +57,105 @@ class FanDrawer(FanDrawerBase):
|
|||||||
Returns:
|
Returns:
|
||||||
string: The name of the device
|
string: The name of the device
|
||||||
"""
|
"""
|
||||||
return "FanTray{}".format(self.fantrayindex)
|
return "FanTray{}".format(self.index)
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
"""
|
||||||
|
Retrieves the part number of Fandrawer
|
||||||
|
Returns:
|
||||||
|
string: Part number of Fandrawer
|
||||||
|
"""
|
||||||
|
# For Serial number "US-01234D-54321-25A-0123-A00", the part
|
||||||
|
# number is "01234D"
|
||||||
|
fantray_serialno = self._get_pmc_register(self.serialno_reg)
|
||||||
|
if (fantray_serialno != 'ERR') and self.get_presence():
|
||||||
|
if (len(fantray_serialno.split('-')) > 1):
|
||||||
|
fantray_partno = fantray_serialno.split('-')[1]
|
||||||
|
else:
|
||||||
|
fantray_partno = 'NA'
|
||||||
|
else:
|
||||||
|
fantray_partno = 'NA'
|
||||||
|
|
||||||
|
return fantray_partno
|
||||||
|
|
||||||
|
def get_serial(self):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of Fandrawer
|
||||||
|
Returns:
|
||||||
|
string: Serial number of Fandrawer
|
||||||
|
"""
|
||||||
|
# Sample Serial number format "US-01234D-54321-25A-0123-A00"
|
||||||
|
fantray_serialno = self._get_pmc_register(self.serialno_reg)
|
||||||
|
if (fantray_serialno == 'ERR') or not self.get_presence():
|
||||||
|
fantray_serialno = 'NA'
|
||||||
|
|
||||||
|
return fantray_serialno
|
||||||
|
|
||||||
|
def get_presence(self):
|
||||||
|
"""
|
||||||
|
Retrieves the presence of the Fandrawer
|
||||||
|
Returns:
|
||||||
|
bool: True if fan is present, False if not
|
||||||
|
"""
|
||||||
|
presence = False
|
||||||
|
fantray_presence = self._get_pmc_register(self.presence_reg)
|
||||||
|
if (fantray_presence != 'ERR'):
|
||||||
|
fantray_presence = int(fantray_presence, 10)
|
||||||
|
if (~fantray_presence & 0b1):
|
||||||
|
presence = True
|
||||||
|
|
||||||
|
return presence
|
||||||
|
|
||||||
|
def get_status(self):
|
||||||
|
"""
|
||||||
|
Retrieves the operational status of the Fandrawer
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if Fandrawer is operating properly, False if not
|
||||||
|
"""
|
||||||
|
return self.get_fan(0).get_status()
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
Returns:
|
||||||
|
integer: The 1-based relative physical position in parent
|
||||||
|
device or -1 if cannot determine the position
|
||||||
|
"""
|
||||||
|
return self.index
|
||||||
|
|
||||||
|
def is_replaceable(self):
|
||||||
|
"""
|
||||||
|
Indicate whether this Fandrawer is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def set_status_led(self, color):
|
||||||
|
"""
|
||||||
|
Set led to expected color
|
||||||
|
Args:
|
||||||
|
color: A string representing the color with which to set the
|
||||||
|
fan module status LED
|
||||||
|
Returns:
|
||||||
|
bool: True if set success, False if fail.
|
||||||
|
"""
|
||||||
|
# Leds are controlled by Smart-fussion FPGA.
|
||||||
|
# Return True to avoid thermalctld alarm.
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_status_led(self):
|
||||||
|
"""
|
||||||
|
Gets the state of the Fan status LED
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string, one of the predefined STATUS_LED_COLOR_* strings.
|
||||||
|
"""
|
||||||
|
if self.get_presence():
|
||||||
|
if self.get_fan(0).get_status():
|
||||||
|
return self.STATUS_LED_COLOR_GREEN
|
||||||
|
else:
|
||||||
|
return self.STATUS_LED_COLOR_AMBER
|
||||||
|
else:
|
||||||
|
return self.STATUS_LED_COLOR_OFF
|
||||||
|
@ -63,7 +63,7 @@ class Module(ModuleBase):
|
|||||||
self.iom_presence_reg = "iom_presence"
|
self.iom_presence_reg = "iom_presence"
|
||||||
|
|
||||||
component = Component(is_module=True, iom_index=self.index,
|
component = Component(is_module=True, iom_index=self.index,
|
||||||
i2c_line=self.port_i2c_line)
|
i2c_line=self.port_i2c_line, dependency=self)
|
||||||
self._component_list.append(component)
|
self._component_list.append(component)
|
||||||
|
|
||||||
eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom"
|
eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom"
|
||||||
@ -157,6 +157,23 @@ class Module(ModuleBase):
|
|||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
Returns:
|
||||||
|
integer: The 1-based relative physical position in parent
|
||||||
|
device or -1 if cannot determine the position
|
||||||
|
"""
|
||||||
|
return self.index
|
||||||
|
|
||||||
|
def is_replaceable(self):
|
||||||
|
"""
|
||||||
|
Indicate whether Module is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
def get_base_mac(self):
|
def get_base_mac(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the base MAC address for the module
|
Retrieves the base MAC address for the module
|
||||||
|
@ -34,13 +34,15 @@ class Psu(PsuBase):
|
|||||||
self.psu_voltage_reg = "in30_input"
|
self.psu_voltage_reg = "in30_input"
|
||||||
self.psu_current_reg = "curr602_input"
|
self.psu_current_reg = "curr602_input"
|
||||||
self.psu_power_reg = "power2_input"
|
self.psu_power_reg = "power2_input"
|
||||||
|
self.psu_temperature_reg = "temp14_input"
|
||||||
elif self.index == 2:
|
elif self.index == 2:
|
||||||
self.psu_voltage_reg = "in32_input"
|
self.psu_voltage_reg = "in32_input"
|
||||||
self.psu_current_reg = "curr702_input"
|
self.psu_current_reg = "curr702_input"
|
||||||
self.psu_power_reg = "power4_input"
|
self.psu_power_reg = "power4_input"
|
||||||
|
self.psu_temperature_reg = "temp15_input"
|
||||||
|
|
||||||
# Passing True to specify it is a PSU fan
|
# Passing True to specify it is a PSU fan
|
||||||
psu_fan = Fan(fan_index=self.index, psu_fan=True)
|
psu_fan = Fan(psu_index=self.index, psu_fan=True)
|
||||||
self._fan_list.append(psu_fan)
|
self._fan_list.append(psu_fan)
|
||||||
|
|
||||||
def _get_pmc_register(self, reg_name):
|
def _get_pmc_register(self, reg_name):
|
||||||
@ -232,3 +234,87 @@ class Psu(PsuBase):
|
|||||||
# In S6100, SmartFusion FPGA controls the PSU LED and the PSU
|
# In S6100, SmartFusion FPGA controls the PSU LED and the PSU
|
||||||
# LED state cannot be changed from CPU.
|
# LED state cannot be changed from CPU.
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
Returns:
|
||||||
|
integer: The 1-based relative physical position in parent
|
||||||
|
device or -1 if cannot determine the position
|
||||||
|
"""
|
||||||
|
return self.index
|
||||||
|
|
||||||
|
def is_replaceable(self):
|
||||||
|
"""
|
||||||
|
Indicate whether this PSU is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_temperature(self):
|
||||||
|
"""
|
||||||
|
Retrieves current temperature reading from PSU
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A float number of current temperature in Celsius up to
|
||||||
|
nearest thousandth of one degree Celsius, e.g. 30.125
|
||||||
|
"""
|
||||||
|
temperature = 0.0
|
||||||
|
if self.get_presence():
|
||||||
|
psu_temperature = self._get_pmc_register(self.psu_temperature_reg)
|
||||||
|
if (psu_temperature != 'ERR'):
|
||||||
|
temperature = float(psu_temperature) / 1000
|
||||||
|
|
||||||
|
return temperature
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
return 90.0
|
||||||
|
|
||||||
|
def get_voltage_high_threshold(self):
|
||||||
|
"""
|
||||||
|
Retrieves the high threshold PSU voltage output
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A float number, the high threshold output voltage in volts,
|
||||||
|
e.g. 12.1
|
||||||
|
"""
|
||||||
|
voltage_high_threshold = 0.0
|
||||||
|
if self.get_presence():
|
||||||
|
psu_type = self._get_pmc_register(self.psu_presence_reg)
|
||||||
|
if (psu_type != 'ERR'):
|
||||||
|
psu_type = int(psu_type, 16)
|
||||||
|
if (psu_type & 0b10):
|
||||||
|
voltage_high_threshold = 12.6
|
||||||
|
else:
|
||||||
|
voltage_high_threshold = 12.8
|
||||||
|
|
||||||
|
return voltage_high_threshold
|
||||||
|
|
||||||
|
def get_voltage_low_threshold(self):
|
||||||
|
"""
|
||||||
|
Retrieves the low threshold PSU voltage output
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A float number, the low threshold output voltage in volts,
|
||||||
|
e.g. 12.1
|
||||||
|
"""
|
||||||
|
voltage_low_threshold = 0.0
|
||||||
|
if self.get_presence():
|
||||||
|
psu_type = self._get_pmc_register(self.psu_presence_reg)
|
||||||
|
if (psu_type != 'ERR'):
|
||||||
|
psu_type = int(psu_type, 16)
|
||||||
|
if (psu_type & 0b10):
|
||||||
|
voltage_low_threshold = 11.4
|
||||||
|
else:
|
||||||
|
voltage_low_threshold = 11.6
|
||||||
|
|
||||||
|
return voltage_low_threshold
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import re
|
import re
|
||||||
|
import struct
|
||||||
import time
|
import time
|
||||||
from sonic_platform_base.sfp_base import SfpBase
|
from sonic_platform_base.sfp_base import SfpBase
|
||||||
from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId
|
from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId
|
||||||
@ -27,6 +28,9 @@ INFO_OFFSET = 128
|
|||||||
DOM_OFFSET = 0
|
DOM_OFFSET = 0
|
||||||
DOM_OFFSET1 = 384
|
DOM_OFFSET1 = 384
|
||||||
|
|
||||||
|
QSFP_CONTROL_OFFSET = 86
|
||||||
|
QSFP_POWEROVERRIDE_OFFSET = 93
|
||||||
|
|
||||||
cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)',
|
cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)',
|
||||||
'Length OM1(m)', 'Length Cable Assembly(m)')
|
'Length OM1(m)', 'Length Cable Assembly(m)')
|
||||||
|
|
||||||
@ -107,7 +111,7 @@ class Sfp(SfpBase):
|
|||||||
sfp_control, sfp_ctrl_idx):
|
sfp_control, sfp_ctrl_idx):
|
||||||
SfpBase.__init__(self)
|
SfpBase.__init__(self)
|
||||||
self.sfp_type = sfp_type
|
self.sfp_type = sfp_type
|
||||||
self.index = index
|
self.index = index + 1
|
||||||
self.eeprom_path = eeprom_path
|
self.eeprom_path = eeprom_path
|
||||||
self.sfp_control = sfp_control
|
self.sfp_control = sfp_control
|
||||||
self.sfp_ctrl_idx = sfp_ctrl_idx
|
self.sfp_ctrl_idx = sfp_ctrl_idx
|
||||||
@ -131,9 +135,10 @@ class Sfp(SfpBase):
|
|||||||
eeprom.close()
|
eeprom.close()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
raw = bytearray(raw)
|
||||||
try:
|
try:
|
||||||
for n in range(0, num_bytes):
|
for n in range(0, num_bytes):
|
||||||
eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2)
|
eeprom_raw[n] = hex(raw[n])[2:].zfill(2)
|
||||||
except BaseException:
|
except BaseException:
|
||||||
eeprom.close()
|
eeprom.close()
|
||||||
return None
|
return None
|
||||||
@ -594,40 +599,14 @@ class Sfp(SfpBase):
|
|||||||
"""
|
"""
|
||||||
Retrieves the TX disabled channels in this SFP
|
Retrieves the TX disabled channels in this SFP
|
||||||
"""
|
"""
|
||||||
tx_disable = None
|
tx_disable_channel = 0
|
||||||
tx_disable_list = []
|
|
||||||
|
|
||||||
tx_disable_data = self._get_eeprom_data('tx_disable')
|
tx_disable = self.get_tx_disable()
|
||||||
if (tx_disable_data is not None):
|
for channel, disable in enumerate(tx_disable):
|
||||||
tx_disable = tx_disable_data['data']['Tx1Disable']['value']
|
if disable:
|
||||||
if (tx_disable == 'On'):
|
tx_disable_channel |= 1 << channel
|
||||||
tx_disable_list.append(1)
|
|
||||||
else:
|
|
||||||
tx_disable_list.append(0)
|
|
||||||
tx_disable = tx_disable_data['data']['Tx2Disable']['value']
|
|
||||||
if (tx_disable == 'On'):
|
|
||||||
tx_disable_list.append(1)
|
|
||||||
else:
|
|
||||||
tx_disable_list.append(0)
|
|
||||||
tx_disable = tx_disable_data['data']['Tx3Disable']['value']
|
|
||||||
if (tx_disable == 'On'):
|
|
||||||
tx_disable_list.append(1)
|
|
||||||
else:
|
|
||||||
tx_disable_list.append(0)
|
|
||||||
tx_disable = tx_disable_data['data']['Tx4Disable']['value']
|
|
||||||
if (tx_disable == 'On'):
|
|
||||||
tx_disable_list.append(1)
|
|
||||||
else:
|
|
||||||
tx_disable_list.append(0)
|
|
||||||
|
|
||||||
bit4 = int(tx_disable_list[3]) * 8
|
return tx_disable_channel
|
||||||
bit3 = int(tx_disable_list[2]) * 4
|
|
||||||
bit2 = int(tx_disable_list[1]) * 2
|
|
||||||
bit1 = int(tx_disable_list[0]) * 1
|
|
||||||
|
|
||||||
tx_disable_channel = hex(bit4 + bit3 + bit2 + bit1)
|
|
||||||
|
|
||||||
return tx_disable_channel
|
|
||||||
|
|
||||||
def get_lpmode(self):
|
def get_lpmode(self):
|
||||||
"""
|
"""
|
||||||
@ -836,19 +815,68 @@ class Sfp(SfpBase):
|
|||||||
"""
|
"""
|
||||||
Disable SFP TX for all channels
|
Disable SFP TX for all channels
|
||||||
"""
|
"""
|
||||||
return False
|
eeprom = None
|
||||||
|
tx_disable_value = 0xf if tx_disable else 0x0
|
||||||
|
|
||||||
|
try:
|
||||||
|
eeprom = open(self.eeprom_path, "r+b")
|
||||||
|
eeprom.seek(QSFP_CONTROL_OFFSET)
|
||||||
|
eeprom.write(struct.pack('B', tx_disable_value))
|
||||||
|
except IOError:
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
if eeprom is not None:
|
||||||
|
eeprom.close()
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def tx_disable_channel(self, channel, disable):
|
def tx_disable_channel(self, channel, disable):
|
||||||
"""
|
"""
|
||||||
Sets the tx_disable for specified SFP channels
|
Sets the tx_disable for specified SFP channels
|
||||||
"""
|
"""
|
||||||
return False
|
eeprom = None
|
||||||
|
current_state = self.get_tx_disable_channel()
|
||||||
|
|
||||||
|
if disable:
|
||||||
|
tx_disable_value = current_state | channel
|
||||||
|
else:
|
||||||
|
tx_disable_value = current_state & (~channel)
|
||||||
|
|
||||||
|
try:
|
||||||
|
eeprom = open(self.eeprom_path, "r+b")
|
||||||
|
eeprom.seek(QSFP_CONTROL_OFFSET)
|
||||||
|
eeprom.write(struct.pack('B', tx_disable_value))
|
||||||
|
except IOError:
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
if eeprom is not None:
|
||||||
|
eeprom.close()
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def set_power_override(self, power_override, power_set):
|
def set_power_override(self, power_override, power_set):
|
||||||
"""
|
"""
|
||||||
Sets SFP power level using power_override and power_set
|
Sets SFP power level using power_override and power_set
|
||||||
"""
|
"""
|
||||||
return False
|
eeprom = None
|
||||||
|
power_override_bit = 0x1 if power_override else 0
|
||||||
|
power_set_bit = 0x2 if power_set else 0
|
||||||
|
value = power_override_bit | power_set_bit
|
||||||
|
|
||||||
|
try:
|
||||||
|
eeprom = open(self.eeprom_path, "r+b")
|
||||||
|
eeprom.seek(QSFP_POWEROVERRIDE_OFFSET)
|
||||||
|
eeprom.write(struct.pack('B', value))
|
||||||
|
except IOError:
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
if eeprom is not None:
|
||||||
|
eeprom.close()
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def get_status(self):
|
def get_status(self):
|
||||||
"""
|
"""
|
||||||
@ -862,3 +890,20 @@ class Sfp(SfpBase):
|
|||||||
status = True
|
status = True
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
Returns:
|
||||||
|
integer: The 1-based relative physical position in parent
|
||||||
|
device or -1 if cannot determine the position
|
||||||
|
"""
|
||||||
|
return self.index
|
||||||
|
|
||||||
|
def is_replaceable(self):
|
||||||
|
"""
|
||||||
|
Indicate whether this device is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
@ -131,6 +131,23 @@ class Thermal(ThermalBase):
|
|||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
def get_position_in_parent(self):
|
||||||
|
"""
|
||||||
|
Retrieves 1-based relative physical position in parent device.
|
||||||
|
Returns:
|
||||||
|
integer: The 1-based relative physical position in parent
|
||||||
|
device or -1 if cannot determine the position
|
||||||
|
"""
|
||||||
|
return self.index
|
||||||
|
|
||||||
|
def is_replaceable(self):
|
||||||
|
"""
|
||||||
|
Indicate whether this Thermal is replaceable.
|
||||||
|
Returns:
|
||||||
|
bool: True if it is replaceable.
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
def get_temperature(self):
|
def get_temperature(self):
|
||||||
"""
|
"""
|
||||||
Retrieves current temperature reading from thermal
|
Retrieves current temperature reading from thermal
|
||||||
|
Loading…
Reference in New Issue
Block a user