DellEmc: Platform 2.0 Api(chassis,fan,eeprom) for S6100 and Z9100 (#3234)
This commit is contained in:
parent
6f40933d3d
commit
a99a37dbef
@ -70,7 +70,7 @@
|
|||||||
#define FAN_TRAY_AIRFLOW 0x0116
|
#define FAN_TRAY_AIRFLOW 0x0116
|
||||||
|
|
||||||
|
|
||||||
/* FAN Z9100 */
|
/* FAN */
|
||||||
#define SMF_FAN_SPEED_ADDR 0x00F3
|
#define SMF_FAN_SPEED_ADDR 0x00F3
|
||||||
#define FAN_TRAY_1_SPEED 0x00F3
|
#define FAN_TRAY_1_SPEED 0x00F3
|
||||||
#define FAN_TRAY_1_FAN_2_SPEED 0x00F5
|
#define FAN_TRAY_1_FAN_2_SPEED 0x00F5
|
||||||
@ -83,6 +83,11 @@
|
|||||||
#define FAN_TRAY_5_FAN_1_SPEED 0x0103
|
#define FAN_TRAY_5_FAN_1_SPEED 0x0103
|
||||||
#define FAN_TRAY_5_FAN_2_SPEED 0x0105
|
#define FAN_TRAY_5_FAN_2_SPEED 0x0105
|
||||||
#define FAN_TRAY_5 4
|
#define FAN_TRAY_5 4
|
||||||
|
#define FAN_1_SERIAL_CODE 0x0117
|
||||||
|
#define FAN_2_SERIAL_CODE 0x013A
|
||||||
|
#define FAN_3_SERIAL_CODE 0x015D
|
||||||
|
#define FAN_4_SERIAL_CODE 0x0180
|
||||||
|
#define FAN_5_SERIAL_CODE 0x01A3
|
||||||
#define FAN_601_FAULT (2 + 1)
|
#define FAN_601_FAULT (2 + 1)
|
||||||
#define IN28_INPUT (27 + 1)
|
#define IN28_INPUT (27 + 1)
|
||||||
#define IN404_INPUT (43 + 1)
|
#define IN404_INPUT (43 + 1)
|
||||||
@ -1738,12 +1743,12 @@ static ssize_t show_psu(struct device *dev,
|
|||||||
|
|
||||||
/* FAN and PSU EEPROM PPID format is:
|
/* FAN and PSU EEPROM PPID format is:
|
||||||
COUNTRY_CODE-PART_NO-MFG_ID-MFG_DATE_CODE-SERIAL_NO-LABEL_REV */
|
COUNTRY_CODE-PART_NO-MFG_ID-MFG_DATE_CODE-SERIAL_NO-LABEL_REV */
|
||||||
static ssize_t show_psu_ppid(struct device *dev,
|
static ssize_t show_ppid(struct device *dev,
|
||||||
struct device_attribute *devattr, char *buf)
|
struct device_attribute *devattr, char *buf)
|
||||||
{
|
{
|
||||||
int index = to_sensor_dev_attr(devattr)->index;
|
int index = to_sensor_dev_attr(devattr)->index;
|
||||||
struct smf_data *data = dev_get_drvdata(dev);
|
struct smf_data *data = dev_get_drvdata(dev);
|
||||||
char psu_ppid[EEPROM_PPID_SIZE + 1] = {0};
|
char ppid[EEPROM_PPID_SIZE + 1] = {0};
|
||||||
char psu_mfg_date[EEPROM_MFG_DATE_SIZE + 1] = {0};
|
char psu_mfg_date[EEPROM_MFG_DATE_SIZE + 1] = {0};
|
||||||
char psu_mfg_date_code[EEPROM_DATE_CODE_SIZE + 1] = {0};
|
char psu_mfg_date_code[EEPROM_DATE_CODE_SIZE + 1] = {0};
|
||||||
char temp;
|
char temp;
|
||||||
@ -1751,102 +1756,128 @@ static ssize_t show_psu_ppid(struct device *dev,
|
|||||||
|
|
||||||
switch(index) {
|
switch(index) {
|
||||||
|
|
||||||
case 1:
|
/* PPID starts from Country Code*/
|
||||||
// PPID starts from Country Code
|
case 0:
|
||||||
reg = PSU_1_COUNTRY_CODE;
|
reg = FAN_1_SERIAL_CODE;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 1:
|
||||||
reg = PSU_2_COUNTRY_CODE;
|
reg = FAN_2_SERIAL_CODE;
|
||||||
break;
|
break;
|
||||||
default:
|
case 2:
|
||||||
return ret;
|
reg = FAN_3_SERIAL_CODE;
|
||||||
}
|
break;
|
||||||
|
case 3:
|
||||||
|
reg = FAN_4_SERIAL_CODE;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
reg = FAN_5_SERIAL_CODE;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
reg = PSU_1_COUNTRY_CODE;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
reg = PSU_2_COUNTRY_CODE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// Get Country Code
|
// Get Country Code
|
||||||
for( i = 0; i < EEPROM_COUNTRY_CODE_SIZE; i++) {
|
for( i = 0; i < EEPROM_COUNTRY_CODE_SIZE; i++) {
|
||||||
psu_ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
|
ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
|
||||||
}
|
}
|
||||||
psu_ppid[ppid_pos++] = '-';
|
ppid[ppid_pos++] = '-';
|
||||||
|
|
||||||
// Get Part Number
|
// Get Part Number
|
||||||
for( i = 0; i < EEPROM_PART_NO_SIZE; i++) {
|
for( i = 0; i < EEPROM_PART_NO_SIZE; i++) {
|
||||||
psu_ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
|
ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
|
||||||
}
|
}
|
||||||
psu_ppid[ppid_pos++] = '-';
|
ppid[ppid_pos++] = '-';
|
||||||
|
|
||||||
// Get Manufacture ID
|
// Get Manufacture ID
|
||||||
for( i = 0; i < EEPROM_MFG_ID_SIZE; i++) {
|
for( i = 0; i < EEPROM_MFG_ID_SIZE; i++) {
|
||||||
psu_ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
|
ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
|
||||||
}
|
}
|
||||||
psu_ppid[ppid_pos++] = '-';
|
ppid[ppid_pos++] = '-';
|
||||||
|
if(index > 9){ //Applicable only for PSU
|
||||||
|
// Get Manufacture date
|
||||||
|
for( i = 0; i < EEPROM_MFG_DATE_SIZE; i++) {
|
||||||
|
psu_mfg_date[i] = (char)smf_read_reg(data,reg++);
|
||||||
|
}
|
||||||
|
|
||||||
// Get Manufacture date
|
/* Converting 6 digit date code [yymmdd] to 3 digit[ymd]
|
||||||
for( i = 0; i < EEPROM_MFG_DATE_SIZE; i++) {
|
Year Starting from 2010 [0-9] , Day : 1-9 and A-V , Month : 1-9 and A-C */
|
||||||
psu_mfg_date[i] = (char)smf_read_reg(data,reg++);
|
// Year Validation and Conversion
|
||||||
|
if( ( psu_mfg_date[0] == '1' ) && ( psu_mfg_date[1] >= '0' ) && ( psu_mfg_date[1] <= '9') )
|
||||||
|
{
|
||||||
|
psu_mfg_date_code[0] = psu_mfg_date[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
psu_mfg_date_code[0] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Month Validation and Conversion
|
||||||
|
temp = ( ( psu_mfg_date[2] - 0x30 ) * 10 ) + ( psu_mfg_date[3] - 0x30 );
|
||||||
|
if( ( temp >= 1) && ( temp < 10) )
|
||||||
|
{
|
||||||
|
psu_mfg_date_code[1] = temp + 0x30; // 0- 9
|
||||||
|
}
|
||||||
|
else if ( ( temp >= 10) && ( temp <= 12) )
|
||||||
|
{
|
||||||
|
psu_mfg_date_code[1] = temp + 0x37; // A-C
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
psu_mfg_date_code[1]= ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Date Validation and Conversion
|
||||||
|
temp = ( ( psu_mfg_date[4] - 0x30 ) * 10 ) + ( psu_mfg_date[5] - 0x30 );
|
||||||
|
if( ( temp >= 1) && ( temp < 10) )
|
||||||
|
{
|
||||||
|
psu_mfg_date_code[2] = temp + 0x30; // 0- 9
|
||||||
|
}
|
||||||
|
else if( ( temp >= 10) && ( temp <= 31) )
|
||||||
|
{
|
||||||
|
psu_mfg_date_code[2] = temp + 0x37; // A-V
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
psu_mfg_date_code[2] = ' ';
|
||||||
|
}
|
||||||
|
for( i = 0; i < EEPROM_DATE_CODE_SIZE; i++) {
|
||||||
|
ppid[ppid_pos++] = psu_mfg_date_code[i];
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
for( i = 0; i < EEPROM_DATE_CODE_SIZE; i++) {
|
||||||
|
ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Converting 6 digit date code [yymmdd] to 3 digit[ymd]
|
ppid[ppid_pos++] = '-';
|
||||||
Year Starting from 2010 [0-9] , Day : 1-9 and A-V , Month : 1-9 and A-C */
|
|
||||||
// Year Validation and Conversion
|
|
||||||
if( ( psu_mfg_date[0] == '1' ) && ( psu_mfg_date[1] >= '0' ) && ( psu_mfg_date[1] <= '9') )
|
|
||||||
{
|
|
||||||
psu_mfg_date_code[0] = psu_mfg_date[1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
psu_mfg_date_code[0] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Month Validation and Conversion
|
|
||||||
temp = ( ( psu_mfg_date[2] - 0x30 ) * 10 ) + ( psu_mfg_date[3] - 0x30 );
|
|
||||||
if( ( temp >= 1) && ( temp < 10) )
|
|
||||||
{
|
|
||||||
psu_mfg_date_code[1] = temp + 0x30; // 0- 9
|
|
||||||
}
|
|
||||||
else if ( ( temp >= 10) && ( temp <= 12) )
|
|
||||||
{
|
|
||||||
psu_mfg_date_code[1] = temp + 0x37; // A-C
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
psu_mfg_date_code[1]= ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Date Validation and Conversion
|
|
||||||
temp = ( ( psu_mfg_date[4] - 0x30 ) * 10 ) + ( psu_mfg_date[5] - 0x30 );
|
|
||||||
if( ( temp >= 1) && ( temp < 10) )
|
|
||||||
{
|
|
||||||
psu_mfg_date_code[2] = temp + 0x30; // 0- 9
|
|
||||||
}
|
|
||||||
else if( ( temp >= 10) && ( temp <= 31) )
|
|
||||||
{
|
|
||||||
psu_mfg_date_code[2] = temp + 0x37; // A-V
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
psu_mfg_date_code[2] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
for( i = 0; i < EEPROM_DATE_CODE_SIZE; i++) {
|
|
||||||
psu_ppid[ppid_pos++] = psu_mfg_date_code[i];
|
|
||||||
}
|
|
||||||
psu_ppid[ppid_pos++] = '-';
|
|
||||||
|
|
||||||
// Get Serial Number
|
// Get Serial Number
|
||||||
for( i = 0; i < EEPROM_SERIAL_NO_SIZE; i++) {
|
for( i = 0; i < EEPROM_SERIAL_NO_SIZE; i++) {
|
||||||
psu_ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
|
ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
|
||||||
}
|
}
|
||||||
psu_ppid[ppid_pos++] = '-';
|
ppid[ppid_pos++] = '-';
|
||||||
|
|
||||||
// Skipping service tag in PPID
|
if(index > 9){
|
||||||
reg += EEPROM_SERVICE_TAG_SIZE;
|
// Skipping PSU service tag in PPID
|
||||||
|
reg += EEPROM_SERVICE_TAG_SIZE;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// Skipping FAN partno tag in PPID
|
||||||
|
reg += EEPROM_PART_NO_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
// Get Label Revision
|
// Get Label Revision
|
||||||
for( i = 0; i < EEPROM_LABEL_REV_SIZE; i++) {
|
for( i = 0; i < EEPROM_LABEL_REV_SIZE; i++) {
|
||||||
psu_ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
|
ppid[ppid_pos++] = (char)smf_read_reg(data,reg++);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sprintf(buf, "%s\n",psu_ppid);
|
return sprintf(buf, "%s\n",ppid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static umode_t smf_psu_is_visible(struct kobject *kobj,
|
static umode_t smf_psu_is_visible(struct kobject *kobj,
|
||||||
@ -1924,14 +1955,19 @@ static SENSOR_DEVICE_ATTR(fan7_airflow, S_IRUGO, show_fan_airflow, NULL, 3);
|
|||||||
static SENSOR_DEVICE_ATTR(fan9_airflow, S_IRUGO, show_fan_airflow, NULL, 4);
|
static SENSOR_DEVICE_ATTR(fan9_airflow, S_IRUGO, show_fan_airflow, NULL, 4);
|
||||||
static SENSOR_DEVICE_ATTR(fan11_airflow, S_IRUGO, show_psu_fan, NULL, 0);
|
static SENSOR_DEVICE_ATTR(fan11_airflow, S_IRUGO, show_psu_fan, NULL, 0);
|
||||||
static SENSOR_DEVICE_ATTR(fan12_airflow, S_IRUGO, show_psu_fan, NULL, 3);
|
static SENSOR_DEVICE_ATTR(fan12_airflow, S_IRUGO, show_psu_fan, NULL, 3);
|
||||||
|
static SENSOR_DEVICE_ATTR(fan1_serialno, S_IRUGO, show_ppid, NULL, 0);
|
||||||
|
static SENSOR_DEVICE_ATTR(fan3_serialno, S_IRUGO, show_ppid, NULL, 1);
|
||||||
|
static SENSOR_DEVICE_ATTR(fan5_serialno, S_IRUGO, show_ppid, NULL, 2);
|
||||||
|
static SENSOR_DEVICE_ATTR(fan7_serialno, S_IRUGO, show_ppid, NULL, 3);
|
||||||
|
static SENSOR_DEVICE_ATTR(fan9_serialno, S_IRUGO, show_ppid, NULL, 4);
|
||||||
/* IOM status */
|
/* IOM status */
|
||||||
static SENSOR_DEVICE_ATTR(iom_status, S_IRUGO, show_voltage, NULL, 44);
|
static SENSOR_DEVICE_ATTR(iom_status, S_IRUGO, show_voltage, NULL, 44);
|
||||||
static SENSOR_DEVICE_ATTR(iom_presence, S_IRUGO, show_voltage, NULL, 45);
|
static SENSOR_DEVICE_ATTR(iom_presence, S_IRUGO, show_voltage, NULL, 45);
|
||||||
|
|
||||||
static SENSOR_DEVICE_ATTR(psu1_presence, S_IRUGO, show_psu, NULL, 1);
|
static SENSOR_DEVICE_ATTR(psu1_presence, S_IRUGO, show_psu, NULL, 1);
|
||||||
static SENSOR_DEVICE_ATTR(psu2_presence, S_IRUGO, show_psu, NULL, 6);
|
static SENSOR_DEVICE_ATTR(psu2_presence, S_IRUGO, show_psu, NULL, 6);
|
||||||
static SENSOR_DEVICE_ATTR(psu1_serialno, S_IRUGO, show_psu_ppid, NULL, 1);
|
static SENSOR_DEVICE_ATTR(psu1_serialno, S_IRUGO, show_ppid, NULL, 10);
|
||||||
static SENSOR_DEVICE_ATTR(psu2_serialno, S_IRUGO, show_psu_ppid, NULL, 2);
|
static SENSOR_DEVICE_ATTR(psu2_serialno, S_IRUGO, show_ppid, NULL, 11);
|
||||||
static SENSOR_DEVICE_ATTR(current_total_power, S_IRUGO, show_psu, NULL, 10);
|
static SENSOR_DEVICE_ATTR(current_total_power, S_IRUGO, show_psu, NULL, 10);
|
||||||
|
|
||||||
/* SMF Version */
|
/* SMF Version */
|
||||||
@ -1964,6 +2000,11 @@ static struct attribute *smf_dell_attrs[] = {
|
|||||||
&sensor_dev_attr_psu2_presence.dev_attr.attr,
|
&sensor_dev_attr_psu2_presence.dev_attr.attr,
|
||||||
&sensor_dev_attr_psu1_serialno.dev_attr.attr,
|
&sensor_dev_attr_psu1_serialno.dev_attr.attr,
|
||||||
&sensor_dev_attr_psu2_serialno.dev_attr.attr,
|
&sensor_dev_attr_psu2_serialno.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_fan1_serialno.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_fan3_serialno.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_fan5_serialno.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_fan7_serialno.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_fan9_serialno.dev_attr.attr,
|
||||||
&sensor_dev_attr_current_total_power.dev_attr.attr,
|
&sensor_dev_attr_current_total_power.dev_attr.attr,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
@ -1980,7 +2021,7 @@ static const struct attribute_group *smf_groups[] = {
|
|||||||
&smf_vsen_group,
|
&smf_vsen_group,
|
||||||
&smf_curr_group,
|
&smf_curr_group,
|
||||||
&smf_tcpu_group,
|
&smf_tcpu_group,
|
||||||
&smf_dell_group,
|
&smf_dell_group,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
# DELLEMC
|
# DELLEMC S6100
|
||||||
#
|
#
|
||||||
# Module contains an implementation of SONiC Platform Base API and
|
# Module contains an implementation of SONiC Platform Base API and
|
||||||
# provides the platform information
|
# provides the platform information
|
||||||
@ -13,6 +13,7 @@ try:
|
|||||||
from sonic_platform_base.chassis_base import ChassisBase
|
from sonic_platform_base.chassis_base import ChassisBase
|
||||||
from sonic_platform.psu import Psu
|
from sonic_platform.psu import Psu
|
||||||
from sonic_platform.fan import Fan
|
from sonic_platform.fan import Fan
|
||||||
|
from 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")
|
||||||
|
|
||||||
@ -42,8 +43,10 @@ class Chassis(ChassisBase):
|
|||||||
power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED
|
power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ChassisBase.__init__(self)
|
|
||||||
|
|
||||||
|
ChassisBase.__init__(self)
|
||||||
|
# Initialize EEPROM
|
||||||
|
self.sys_eeprom = Eeprom()
|
||||||
for i in range(MAX_S6100_FAN):
|
for i in range(MAX_S6100_FAN):
|
||||||
fan = Fan(i)
|
fan = Fan(i)
|
||||||
self._fan_list.append(fan)
|
self._fan_list.append(fan)
|
||||||
@ -52,7 +55,7 @@ class Chassis(ChassisBase):
|
|||||||
psu = Psu(i)
|
psu = Psu(i)
|
||||||
self._psu_list.append(psu)
|
self._psu_list.append(psu)
|
||||||
|
|
||||||
def get_pmc_register(self, reg_name):
|
def _get_pmc_register(self, reg_name):
|
||||||
# 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'
|
||||||
rv = 'ERR'
|
rv = 'ERR'
|
||||||
@ -71,12 +74,79 @@ class Chassis(ChassisBase):
|
|||||||
rv = rv.lstrip(" ")
|
rv = rv.lstrip(" ")
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
"""
|
||||||
|
Retrieves the name of the device
|
||||||
|
Returns:
|
||||||
|
string: The name of the device
|
||||||
|
"""
|
||||||
|
return self.sys_eeprom.modelstr()
|
||||||
|
|
||||||
|
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 self.sys_eeprom.part_number_str()
|
||||||
|
|
||||||
|
def get_serial(self):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the device (Service tag)
|
||||||
|
Returns:
|
||||||
|
string: Serial number of device
|
||||||
|
"""
|
||||||
|
return self.sys_eeprom.serial_str()
|
||||||
|
|
||||||
|
def get_base_mac(self):
|
||||||
|
"""
|
||||||
|
Retrieves the base MAC address for the chassis
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string containing the MAC address in the format
|
||||||
|
'XX:XX:XX:XX:XX:XX'
|
||||||
|
"""
|
||||||
|
return self.sys_eeprom.base_mac_addr()
|
||||||
|
|
||||||
|
def get_serial_number(self):
|
||||||
|
"""
|
||||||
|
Retrieves the hardware serial number for the chassis
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string containing the hardware serial number for this chassis.
|
||||||
|
"""
|
||||||
|
return self.sys_eeprom.serial_number_str()
|
||||||
|
|
||||||
|
def get_system_eeprom_info(self):
|
||||||
|
"""
|
||||||
|
Retrieves the full content of system EEPROM information for the chassis
|
||||||
|
Returns:
|
||||||
|
A dictionary where keys are the type code defined in
|
||||||
|
OCP ONIE TlvInfo EEPROM format and values are their corresponding
|
||||||
|
values.
|
||||||
|
"""
|
||||||
|
|
||||||
def get_reboot_cause(self):
|
def get_reboot_cause(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the cause of the previous reboot
|
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.
|
||||||
"""
|
"""
|
||||||
reset_reason = int(self.get_pmc_register('smf_reset_reason'))
|
|
||||||
power_reason = int(self.get_pmc_register('smf_poweron_reason'))
|
reset_reason = int(self._get_pmc_register('smf_reset_reason'))
|
||||||
|
power_reason = int(self._get_pmc_register('smf_poweron_reason'))
|
||||||
|
|
||||||
# Reset_Reason = 11 ==> PowerLoss
|
# Reset_Reason = 11 ==> PowerLoss
|
||||||
# So return the reboot reason from Last Power_Reason Dictionary
|
# So return the reboot reason from Last Power_Reason Dictionary
|
||||||
@ -93,4 +163,3 @@ class Chassis(ChassisBase):
|
|||||||
return (self.reset_reason_dict[reset_reason], None)
|
return (self.reset_reason_dict[reset_reason], None)
|
||||||
|
|
||||||
return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")
|
return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")
|
||||||
|
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# DellEmc S6100
|
||||||
|
#
|
||||||
|
# Platform and model specific eeprom subclass, inherits from the base class,
|
||||||
|
# and provides the followings:
|
||||||
|
# - the eeprom format definition
|
||||||
|
# - specific encoder/decoder if there is special need
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
try:
|
||||||
|
from sonic_eeprom import eeprom_tlvinfo
|
||||||
|
import binascii
|
||||||
|
except ImportError, e:
|
||||||
|
raise ImportError (str(e) + "- required module not found")
|
||||||
|
|
||||||
|
|
||||||
|
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0050/eeprom"
|
||||||
|
super(Eeprom, self).__init__(self.eeprom_path, 0, '', True)
|
||||||
|
try:
|
||||||
|
self.eeprom_data = self.read_eeprom()
|
||||||
|
except:
|
||||||
|
self.eeprom_data = "N/A"
|
||||||
|
raise RuntimeError("Eeprom is not Programmed")
|
||||||
|
|
||||||
|
|
||||||
|
def serial_number_str(self):
|
||||||
|
(is_valid, results) = self.get_tlv_field(
|
||||||
|
self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER)
|
||||||
|
if not is_valid:
|
||||||
|
return "N/A"
|
||||||
|
|
||||||
|
return results[2]
|
||||||
|
|
||||||
|
def base_mac_addr(self):
|
||||||
|
(is_valid, results) = self.get_tlv_field(
|
||||||
|
self.eeprom_data, self._TLV_CODE_MAC_BASE)
|
||||||
|
if not is_valid or results[1] != 6:
|
||||||
|
return super(TlvInfoDecoder, self).switchaddrstr(e)
|
||||||
|
|
||||||
|
return ":".join([binascii.b2a_hex(T) for T in results[2]])
|
||||||
|
|
||||||
|
def modelstr(self):
|
||||||
|
(is_valid, results) = self.get_tlv_field(
|
||||||
|
self.eeprom_data, self._TLV_CODE_PRODUCT_NAME)
|
||||||
|
if not is_valid:
|
||||||
|
return "N/A"
|
||||||
|
|
||||||
|
return results[2]
|
||||||
|
|
||||||
|
def part_number_str(self):
|
||||||
|
(is_valid, results) = self.get_tlv_field(
|
||||||
|
self.eeprom_data, self._TLV_CODE_PART_NUMBER)
|
||||||
|
if not is_valid:
|
||||||
|
return "N/A"
|
||||||
|
|
||||||
|
return results[2]
|
||||||
|
|
||||||
|
def serial_str(self):
|
||||||
|
(is_valid, results) = self.get_tlv_field(
|
||||||
|
self.eeprom_data, self._TLV_CODE_SERVICE_TAG)
|
||||||
|
if not is_valid:
|
||||||
|
return "N/A"
|
||||||
|
|
||||||
|
return results[2]
|
||||||
|
|
||||||
|
def revision_str(self):
|
||||||
|
(is_valid, results) = self.get_tlv_field(
|
||||||
|
self.eeprom_data, self._TLV_CODE_DEVICE_VERSION)
|
||||||
|
if not is_valid:
|
||||||
|
return "N/A"
|
||||||
|
|
||||||
|
return results[2]
|
||||||
|
|
@ -1,42 +1,221 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# DellEMC
|
# DellEMC S6100
|
||||||
#
|
#
|
||||||
# Module contains an implementation of SONiC Platform Base API and
|
# Module contains an implementation of SONiC Platform Base API and
|
||||||
# provides the Fans' information which are available in the platform
|
# provides the Fans' information which are available in the platform.
|
||||||
#
|
#
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import os
|
|
||||||
from sonic_platform_base.fan_base import FanBase
|
from sonic_platform_base.fan_base import FanBase
|
||||||
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_S6100_PSU_FAN_SPEED = 18000
|
MAX_S6100_PSU_FAN_SPEED = 18000
|
||||||
MAX_S6100_FAN_SPEED = 16000
|
MAX_S6100_FAN_SPEED = 16000
|
||||||
|
|
||||||
|
|
||||||
class Fan(FanBase):
|
class Fan(FanBase):
|
||||||
"""DellEMC Platform-specific FAN class"""
|
"""DellEMC Platform-specific Fan class"""
|
||||||
|
|
||||||
HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/"
|
HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/"
|
||||||
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, fan_index, psu_fan=False):
|
def __init__(self, fantray_index, fan_index=1, psu_fan=False):
|
||||||
self.is_psu_fan = psu_fan
|
self.is_psu_fan = psu_fan
|
||||||
if not self.is_psu_fan:
|
if not self.is_psu_fan:
|
||||||
# Fan is 1-based in DellEMC platforms
|
# API index is starting from 0, DellEMC platform index is starting
|
||||||
self.index = fan_index + 1
|
# from 1
|
||||||
self.get_fan_speed_reg = "fan{}_input".format(2*self.index - 1)
|
self.fantrayindex = fantray_index + 1
|
||||||
|
self.fanindex = fan_index + 1
|
||||||
|
self.get_fan_speed_reg = "fan{}_input".format(
|
||||||
|
2 * self.fantrayindex - 1)
|
||||||
|
self.get_fan_dir_reg = "fan{}_airflow".format(
|
||||||
|
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
|
# PSU Fan index starts from 11
|
||||||
self.index = fan_index + 10
|
self.fanindex = fan_index + 10
|
||||||
self.get_fan_speed_reg = "fan{}_input".format(self.index)
|
self.get_fan_speed_reg = "fan{}_input".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):
|
||||||
|
# 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):
|
||||||
|
"""
|
||||||
|
Retrieves the fan name
|
||||||
|
Returns:
|
||||||
|
string: The name of the device
|
||||||
|
"""
|
||||||
|
if not self.is_psu_fan:
|
||||||
|
return "FanTray{}-Fan{}".format(
|
||||||
|
self.fantrayindex, self.fanindex - 1)
|
||||||
|
else:
|
||||||
|
return "PSU{} Fan".format(self.index - 10)
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
"""
|
||||||
|
Retrieves the part number of the FAN
|
||||||
|
Returns:
|
||||||
|
string: Part number of FAN
|
||||||
|
"""
|
||||||
|
# For Serial number "US-01234D-54321-25A-0123-A00", the part
|
||||||
|
# number is "01234D"
|
||||||
|
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):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the FAN
|
||||||
|
Returns:
|
||||||
|
string: Serial number of FAN
|
||||||
|
"""
|
||||||
|
# Sample Serial number format "US-01234D-54321-25A-0123-A00"
|
||||||
|
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):
|
||||||
|
"""
|
||||||
|
Retrieves the presence of the FAN
|
||||||
|
Returns:
|
||||||
|
bool: True if fan is present, False if not
|
||||||
|
"""
|
||||||
|
status = False
|
||||||
|
fantray_presence = self._get_pmc_register(self.get_fan_speed_reg)
|
||||||
|
if (fantray_presence != 'ERR'):
|
||||||
|
fantray_presence = int(fantray_presence, 10)
|
||||||
|
if (fantray_presence > 0):
|
||||||
|
status = True
|
||||||
|
|
||||||
|
return status
|
||||||
|
|
||||||
|
def get_status(self):
|
||||||
|
"""
|
||||||
|
Retrieves the operational status of the FAN
|
||||||
|
Returns:
|
||||||
|
bool: True if FAN is operating properly, False if not
|
||||||
|
"""
|
||||||
|
status = False
|
||||||
|
fantray_status = self._get_pmc_register(self.get_fan_speed_reg)
|
||||||
|
if (fantray_status != 'ERR'):
|
||||||
|
fantray_status = int(fantray_status, 10)
|
||||||
|
if (fantray_status > 5000):
|
||||||
|
status = True
|
||||||
|
|
||||||
|
return status
|
||||||
|
|
||||||
|
def get_direction(self):
|
||||||
|
"""
|
||||||
|
Retrieves the fan airflow direction
|
||||||
|
Returns:
|
||||||
|
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
|
||||||
|
depending on fan direction
|
||||||
|
"""
|
||||||
|
direction = ['FAN_DIRECTION_INTAKE', 'FAN_DIRECTION_EXHAUST']
|
||||||
|
fan_direction = self._get_pmc_register(self.get_fan_dir_reg)
|
||||||
|
if (fan_direction != 'ERR') and self.get_presence():
|
||||||
|
fan_direction = int(fan_direction, 10)
|
||||||
|
else:
|
||||||
|
return 'N/A'
|
||||||
|
return direction[fan_direction]
|
||||||
|
|
||||||
|
def get_speed(self):
|
||||||
|
"""
|
||||||
|
Retrieves the speed of fan
|
||||||
|
Returns:
|
||||||
|
int: percentage of the max fan speed
|
||||||
|
"""
|
||||||
|
fan_speed = self._get_pmc_register(self.get_fan_speed_reg)
|
||||||
|
if (fan_speed != 'ERR') and self.get_presence():
|
||||||
|
speed_in_rpm = int(fan_speed, 10)
|
||||||
|
speed = (100 * speed_in_rpm)/self.max_fan_speed
|
||||||
|
else:
|
||||||
|
speed = 0
|
||||||
|
|
||||||
|
return speed
|
||||||
|
|
||||||
|
def get_speed_tolerance(self):
|
||||||
|
"""
|
||||||
|
Retrieves the speed tolerance of the fan
|
||||||
|
Returns:
|
||||||
|
An integer, the percentage of variance from target speed which is
|
||||||
|
considered tolerable
|
||||||
|
"""
|
||||||
|
if self.get_presence():
|
||||||
|
# The tolerance value is fixed as 20% for all the DellEmc platform
|
||||||
|
tolerance = 20
|
||||||
|
else:
|
||||||
|
tolerance = 0
|
||||||
|
|
||||||
|
return tolerance
|
||||||
|
|
||||||
|
def set_speed(self, speed):
|
||||||
|
"""
|
||||||
|
Set fan speed to expected value
|
||||||
|
Args:
|
||||||
|
speed: An integer, the percentage of full fan speed to set fan to,
|
||||||
|
in the range 0 (off) to 100 (full speed)
|
||||||
|
Returns:
|
||||||
|
bool: True if set success, False if fail.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Fan speeds are controlled by Smart-fussion FPGA.
|
||||||
|
return False
|
||||||
|
|
||||||
|
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.
|
||||||
|
status = False
|
||||||
|
return status
|
||||||
|
|
||||||
|
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)
|
||||||
|
"""
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
# DELLEMC
|
# DELLEMC Z9100
|
||||||
#
|
#
|
||||||
# Module contains an implementation of SONiC Platform Base API and
|
# Module contains an implementation of SONiC Platform Base API and
|
||||||
# provides the platform information
|
# provides the platform information
|
||||||
@ -11,9 +11,15 @@
|
|||||||
try:
|
try:
|
||||||
import os
|
import os
|
||||||
from sonic_platform_base.chassis_base import ChassisBase
|
from sonic_platform_base.chassis_base import ChassisBase
|
||||||
|
from sonic_platform.fan import Fan
|
||||||
|
from 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")
|
||||||
|
|
||||||
|
MAX_Z9100_FANTRAY = 5
|
||||||
|
MAX_Z9100_FAN = 2
|
||||||
|
MAX_Z9100_PSU = 2
|
||||||
|
|
||||||
|
|
||||||
class Chassis(ChassisBase):
|
class Chassis(ChassisBase):
|
||||||
"""
|
"""
|
||||||
@ -37,9 +43,16 @@ class Chassis(ChassisBase):
|
|||||||
power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED
|
power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ChassisBase.__init__(self)
|
|
||||||
|
|
||||||
def get_pmc_register(self, reg_name):
|
ChassisBase.__init__(self)
|
||||||
|
# Initialize EEPROM
|
||||||
|
self.sys_eeprom = Eeprom()
|
||||||
|
for i in range(MAX_Z9100_FANTRAY):
|
||||||
|
for j in range(MAX_Z9100_FAN):
|
||||||
|
fan = Fan(i, j)
|
||||||
|
self._fan_list.append(fan)
|
||||||
|
|
||||||
|
def _get_pmc_register(self, reg_name):
|
||||||
# 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'
|
||||||
rv = 'ERR'
|
rv = 'ERR'
|
||||||
@ -58,12 +71,70 @@ class Chassis(ChassisBase):
|
|||||||
rv = rv.lstrip(" ")
|
rv = rv.lstrip(" ")
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
"""
|
||||||
|
Retrieves the name of the device
|
||||||
|
Returns:
|
||||||
|
string: The name of the device
|
||||||
|
"""
|
||||||
|
return self.sys_eeprom.modelstr()
|
||||||
|
|
||||||
|
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 self.sys_eeprom.part_number_str()
|
||||||
|
|
||||||
|
def get_serial(self):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the device (Service tag)
|
||||||
|
Returns:
|
||||||
|
string: Serial number of device
|
||||||
|
"""
|
||||||
|
return self.sys_eeprom.serial_str()
|
||||||
|
|
||||||
|
def get_base_mac(self):
|
||||||
|
"""
|
||||||
|
Retrieves the base MAC address for the chassis
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string containing the MAC address in the format
|
||||||
|
'XX:XX:XX:XX:XX:XX'
|
||||||
|
"""
|
||||||
|
return self.sys_eeprom.base_mac_addr()
|
||||||
|
|
||||||
|
def get_serial_number(self):
|
||||||
|
"""
|
||||||
|
Retrieves the hardware serial number for the chassis
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string containing the hardware serial number for this chassis.
|
||||||
|
"""
|
||||||
|
return self.sys_eeprom.serial_number_str()
|
||||||
|
|
||||||
def get_reboot_cause(self):
|
def get_reboot_cause(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the cause of the previous reboot
|
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.
|
||||||
"""
|
"""
|
||||||
reset_reason = int(self.get_pmc_register('smf_reset_reason'))
|
|
||||||
power_reason = int(self.get_pmc_register('smf_poweron_reason'))
|
reset_reason = int(self._get_pmc_register('smf_reset_reason'))
|
||||||
|
power_reason = int(self._get_pmc_register('smf_poweron_reason'))
|
||||||
|
|
||||||
# Reset_Reason = 11 ==> PowerLoss
|
# Reset_Reason = 11 ==> PowerLoss
|
||||||
# So return the reboot reason from Last Power_Reason Dictionary
|
# So return the reboot reason from Last Power_Reason Dictionary
|
||||||
@ -81,3 +152,4 @@ class Chassis(ChassisBase):
|
|||||||
|
|
||||||
return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")
|
return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# DellEmc Z9100
|
||||||
|
#
|
||||||
|
# Platform and model specific eeprom subclass, inherits from the base class,
|
||||||
|
# and provides the followings:
|
||||||
|
# - the eeprom format definition
|
||||||
|
# - specific encoder/decoder if there is special need
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
try:
|
||||||
|
from sonic_eeprom import eeprom_tlvinfo
|
||||||
|
import binascii
|
||||||
|
except ImportError, e:
|
||||||
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
|
||||||
|
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0050/eeprom"
|
||||||
|
super(Eeprom, self).__init__(self.eeprom_path, 0, '', True)
|
||||||
|
try:
|
||||||
|
self.eeprom_data = self.read_eeprom()
|
||||||
|
except:
|
||||||
|
self.eeprom_data = "N/A"
|
||||||
|
raise RuntimeError("Eeprom is not Programmed")
|
||||||
|
|
||||||
|
def serial_number_str(self):
|
||||||
|
(is_valid, results) = self.get_tlv_field(
|
||||||
|
self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER)
|
||||||
|
if not is_valid:
|
||||||
|
return "N/A"
|
||||||
|
return results[2]
|
||||||
|
|
||||||
|
def base_mac_addr(self):
|
||||||
|
(is_valid, t) = self.get_tlv_field(
|
||||||
|
self.eeprom_data, self._TLV_CODE_MAC_BASE)
|
||||||
|
if not is_valid or t[1] != 6:
|
||||||
|
return super(TlvInfoDecoder, self).switchaddrstr(e)
|
||||||
|
|
||||||
|
return ":".join([binascii.b2a_hex(T) for T in t[2]])
|
||||||
|
|
||||||
|
def modelstr(self):
|
||||||
|
(is_valid, results) = self.get_tlv_field(
|
||||||
|
self.eeprom_data, self._TLV_CODE_PRODUCT_NAME)
|
||||||
|
if not is_valid:
|
||||||
|
return "N/A"
|
||||||
|
|
||||||
|
return results[2]
|
||||||
|
|
||||||
|
def part_number_str(self):
|
||||||
|
(is_valid, results) = self.get_tlv_field(
|
||||||
|
self.eeprom_data, self._TLV_CODE_PART_NUMBER)
|
||||||
|
if not is_valid:
|
||||||
|
return "N/A"
|
||||||
|
|
||||||
|
return results[2]
|
||||||
|
|
||||||
|
def serial_str(self):
|
||||||
|
(is_valid, results) = self.get_tlv_field(
|
||||||
|
self.eeprom_data, self._TLV_CODE_SERVICE_TAG)
|
||||||
|
if not is_valid:
|
||||||
|
return "N/A"
|
||||||
|
|
||||||
|
return results[2]
|
||||||
|
|
||||||
|
def revision_str(self):
|
||||||
|
(is_valid, results) = self.get_tlv_field(
|
||||||
|
self.eeprom_data, self._TLV_CODE_DEVICE_VERSION)
|
||||||
|
if not is_valid:
|
||||||
|
return "N/A"
|
||||||
|
|
||||||
|
return results[2]
|
||||||
|
|
222
platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/fan.py
Executable file
222
platform/broadcom/sonic-platform-modules-dell/z9100/sonic_platform/fan.py
Executable file
@ -0,0 +1,222 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# DellEMC Z9100
|
||||||
|
#
|
||||||
|
# Module contains an implementation of SONiC Platform Base API and
|
||||||
|
# provides the Fans' information which are available in the platform.
|
||||||
|
#
|
||||||
|
########################################################################
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
try:
|
||||||
|
from sonic_platform_base.fan_base import FanBase
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
MAX_Z9100_PSU_FAN_SPEED = 18000
|
||||||
|
MAX_Z9100_FAN_SPEED = 16000
|
||||||
|
|
||||||
|
|
||||||
|
class Fan(FanBase):
|
||||||
|
"""DellEMC Platform-specific Fan 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, fan_index=1, psu_fan=False):
|
||||||
|
self.is_psu_fan = psu_fan
|
||||||
|
if not self.is_psu_fan:
|
||||||
|
# API index is starting from 0, DellEMC platform index is starting
|
||||||
|
# from 1
|
||||||
|
self.fantrayindex = fantray_index + 1
|
||||||
|
self.fanindex = fan_index + 1
|
||||||
|
self.get_fan_speed_reg = "fan{}_input".format(
|
||||||
|
2 * (self.fantrayindex - 1) + (self.fanindex - 1) + 1 )
|
||||||
|
self.get_fan_dir_reg = "fan{}_airflow".format(
|
||||||
|
2 * self.fantrayindex - 1)
|
||||||
|
self.fan_serialno_reg = "fan{}_serialno".format(
|
||||||
|
2 * self.fantrayindex - 1)
|
||||||
|
self.max_fan_speed = MAX_Z9100_FAN_SPEED
|
||||||
|
else:
|
||||||
|
# PSU Fan index starts from 11
|
||||||
|
self.fanindex = fan_index + 10
|
||||||
|
self.get_fan_speed_reg = "fan{}_input".format(self.fanindex)
|
||||||
|
self.max_fan_speed = MAX_Z9100_PSU_FAN_SPEED
|
||||||
|
|
||||||
|
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):
|
||||||
|
"""
|
||||||
|
Retrieves the fan name
|
||||||
|
Returns:
|
||||||
|
string: The name of the device
|
||||||
|
"""
|
||||||
|
if not self.is_psu_fan:
|
||||||
|
return "FanTray{}-Fan{}".format(self.fantrayindex, self.fanindex)
|
||||||
|
else:
|
||||||
|
return "PSU{} Fan".format(self.index - 10)
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
"""
|
||||||
|
Retrieves the part number of the FAN
|
||||||
|
Returns:
|
||||||
|
string: Part number of FAN
|
||||||
|
"""
|
||||||
|
# For Serial number "US-01234D-54321-25A-0123-A00", the part
|
||||||
|
# number is "01234D"
|
||||||
|
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):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the FAN
|
||||||
|
Returns:
|
||||||
|
string: Serial number of FAN
|
||||||
|
"""
|
||||||
|
# Sample Serial number format "US-01234D-54321-25A-0123-A00"
|
||||||
|
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):
|
||||||
|
"""
|
||||||
|
Retrieves the presence of the FAN
|
||||||
|
Returns:
|
||||||
|
bool: True if fan is present, False if not
|
||||||
|
"""
|
||||||
|
status = False
|
||||||
|
fantray_presence = self._get_pmc_register(self.get_fan_speed_reg)
|
||||||
|
if (fantray_presence != 'ERR'):
|
||||||
|
fantray_presence = int(fantray_presence, 10)
|
||||||
|
if (fantray_presence > 0):
|
||||||
|
status = True
|
||||||
|
|
||||||
|
return status
|
||||||
|
|
||||||
|
def get_status(self):
|
||||||
|
"""
|
||||||
|
Retrieves the operational status of the FAN
|
||||||
|
Returns:
|
||||||
|
bool: True if FAN is operating properly, False if not
|
||||||
|
"""
|
||||||
|
status = False
|
||||||
|
fantray_status = self._get_pmc_register(self.get_fan_speed_reg)
|
||||||
|
if (fantray_status != 'ERR'):
|
||||||
|
fantray_status = int(fantray_status, 10)
|
||||||
|
if (fantray_status > 5000):
|
||||||
|
status = True
|
||||||
|
|
||||||
|
return status
|
||||||
|
|
||||||
|
def get_direction(self):
|
||||||
|
"""
|
||||||
|
Retrieves the fan airflow direction
|
||||||
|
Returns:
|
||||||
|
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
|
||||||
|
depending on fan direction
|
||||||
|
"""
|
||||||
|
direction = ['FAN_DIRECTION_INTAKE', 'FAN_DIRECTION_EXHAUST']
|
||||||
|
fan_direction = self._get_pmc_register(self.get_fan_dir_reg)
|
||||||
|
if (fan_direction != 'ERR') and self.get_presence():
|
||||||
|
fan_direction = int(fan_direction, 10)
|
||||||
|
else:
|
||||||
|
return 'N/A'
|
||||||
|
return direction[fan_direction]
|
||||||
|
|
||||||
|
def get_speed(self):
|
||||||
|
"""
|
||||||
|
Retrieves the speed of fan
|
||||||
|
Returns:
|
||||||
|
int: percentage of the max fan speed
|
||||||
|
"""
|
||||||
|
fan_speed = self._get_pmc_register(self.get_fan_speed_reg)
|
||||||
|
if (fan_speed != 'ERR') and self.get_presence():
|
||||||
|
speed_in_rpm = int(fan_speed, 10)
|
||||||
|
speed = (100 * speed_in_rpm)/self.max_fan_speed
|
||||||
|
else:
|
||||||
|
speed = 0
|
||||||
|
|
||||||
|
return speed
|
||||||
|
|
||||||
|
def get_speed_tolerance(self):
|
||||||
|
"""
|
||||||
|
Retrieves the speed tolerance of the fan
|
||||||
|
Returns:
|
||||||
|
An integer, the percentage of variance from target speed which is
|
||||||
|
considered tolerable
|
||||||
|
"""
|
||||||
|
if self.get_presence():
|
||||||
|
# The tolerance value is fixed as 20% for all the DellEmc platform
|
||||||
|
tolerance = 20
|
||||||
|
else:
|
||||||
|
tolerance = 0
|
||||||
|
|
||||||
|
return tolerance
|
||||||
|
|
||||||
|
def set_speed(self, speed):
|
||||||
|
"""
|
||||||
|
Set fan speed to expected value
|
||||||
|
Args:
|
||||||
|
speed: An integer, the percentage of full fan speed to set fan to,
|
||||||
|
in the range 0 (off) to 100 (full speed)
|
||||||
|
Returns:
|
||||||
|
bool: True if set success, False if fail.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Fan speeds are controlled by Smart-fussion FPGA.
|
||||||
|
return False
|
||||||
|
|
||||||
|
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.
|
||||||
|
status = False
|
||||||
|
return status
|
||||||
|
|
||||||
|
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)
|
||||||
|
"""
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user