Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DellEMC: Platform 2.0 Api - Fan for z9264f #4191

Merged
merged 4 commits into from
Mar 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ z9264f/scripts/check_qsfp.sh usr/local/bin
z9264f/scripts/platform_sensors.py usr/local/bin
z9264f/scripts/sensors usr/bin
z9264f/scripts/pcisysfs.py usr/bin
z9264f/scripts/qsfp_irq_enable.py usr/bin
z9264f/scripts/port_irq_enable.py usr/bin
z9264f/cfg/z9264f-modules.conf etc/modules-load.d
z9264f/systemd/platform-modules-z9264f.service etc/systemd/system
z9264f/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-dellemc_z9264f_c3538-r0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,10 @@ if [ "$1" == "init" ]; then
switch_board_modsel
init_switch_port_led
install_python_api_package
python /usr/bin/qsfp_irq_enable.py
python /usr/bin/port_irq_enable.py
platform_firmware_versions


elif [ "$1" == "deinit" ]; then
sys_eeprom "delete_device"
switch_board_qsfp "delete_device"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
__all__ = ["platform", "chassis", "sfp", "eeprom", "component", "psu", "thermal"]
from sonic_platform import *

__all__ = ["platform", "chassis", "sfp", "eeprom", "component", "psu", "thermal", "fan"]
from sonic_platform import *
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@
from sonic_platform.eeprom import Eeprom
from sonic_platform.component import Component
from sonic_platform.psu import Psu
from sonic_platform.fan import Fan
from sonic_platform.thermal import Thermal
except ImportError as e:
raise ImportError(str(e) + "- required module not found")

MAX_Z9264F_FANTRAY =4
MAX_Z9264F_FAN = 2
MAX_Z9264F_COMPONENT = 8 # BIOS,BMC,FPGA,SYSTEM CPLD,4 SLAVE CPLDs
MAX_Z9264F_PSU = 2
MAX_Z9264F_THERMAL = 8
Expand Down Expand Up @@ -66,7 +69,12 @@ def __init__(self):
for i in range(MAX_Z9264F_PSU):
psu = Psu(i)
self._psu_list.append(psu)


for i in range(MAX_Z9264F_FANTRAY):
for j in range(MAX_Z9264F_FAN):
fan = Fan(i,j)
self._fan_list.append(fan)

for i in range(MAX_Z9264F_THERMAL):
thermal = Thermal(i)
self._thermal_list.append(thermal)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
#!/usr/bin/env python

########################################################################
# DellEMC Z9264F
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Fans' information which are available in the platform.
#
########################################################################

try:
from sonic_platform_base.fan_base import FanBase
from sonic_platform.ipmihelper import IpmiSensor, IpmiFru
except ImportError as e:
raise ImportError(str(e) + "- required module not found")

#Derived the offset from BMC management information
FAN1_MAX_SPEED_OFFSET = 71
FAN2_MAX_SPEED_OFFSET = 73
PSU_FAN_MAX_SPEED_OFFSET = 50
FAN_DIRECTION_OFFSET = 69
PSU_FAN_DIRECTION_OFFSET = 47


class Fan(FanBase):
"""DellEMC Platform-specific Fan class"""
#Derived the sensor IDs from BMC
# { FAN-ID: { Sensor-Name: Sensor-ID } }
FAN_SENSOR_MAPPING = { 1: {"Prsnt": 0x51, "State": 0x64, "Speed": 0x24},
2: {"Prsnt": 0x51, "State": 0x60, "Speed": 0x20},
3: {"Prsnt": 0x52, "State": 0x65, "Speed": 0x25},
4: {"Prsnt": 0x52, "State": 0x61, "Speed": 0x21},
5: {"Prsnt": 0x53, "State": 0x66, "Speed": 0x26},
6: {"Prsnt": 0x53, "State": 0x62, "Speed": 0x22},
7: {"Prsnt": 0x54, "State": 0x67, "Speed": 0x27},
8: {"Prsnt": 0x54, "State": 0x63, "Speed": 0x23} }
PSU_FAN_SENSOR_MAPPING = { 1: {"State": 0x46, "Speed": 0x2e},
2: {"State": 0x47, "Speed": 0x2f} }

# { FANTRAY-ID: FRU-ID }
FAN_FRU_MAPPING = { 1: 1, 2: 2, 3: 3, 4: 4 }
PSU_FRU_MAPPING = { 1: 6, 2: 7 }

def __init__(self, fantray_index=1, fan_index=1, psu_fan=False,
dependency=None):
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
if (self.fanindex == 1):
self.max_speed_offset = FAN1_MAX_SPEED_OFFSET
else:
self.max_speed_offset = FAN2_MAX_SPEED_OFFSET
self.fan_direction_offset = FAN_DIRECTION_OFFSET
self.index = (self.fantrayindex - 1) * 2 + self.fanindex
self.prsnt_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["Prsnt"],
is_discrete=True)
self.state_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["State"],
is_discrete=True)
self.speed_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["Speed"])
self.fru = IpmiFru(self.FAN_FRU_MAPPING[self.fantrayindex])
else:
self.dependency = dependency
self.fanindex = fan_index
self.state_sensor = IpmiSensor(self.PSU_FAN_SENSOR_MAPPING[self.fanindex]["State"],
is_discrete=True)
self.speed_sensor = IpmiSensor(self.PSU_FAN_SENSOR_MAPPING[self.fanindex]["Speed"])
self.fru = IpmiFru(self.PSU_FRU_MAPPING[self.fanindex])
self.max_speed_offset = PSU_FAN_MAX_SPEED_OFFSET
self.fan_direction_offset = PSU_FAN_DIRECTION_OFFSET
self.max_speed = self.fru.get_fru_data(self.max_speed_offset,2)[1]
self.max_speed = self.max_speed[1] << 8 | self.max_speed[0]

def get_name(self):
"""
Retrieves the name of the device
Returns:
String: The name of the device
"""
if self.is_psu_fan:
return "PSU{} Fan".format(self.fanindex)
else:
return "FanTray{}-Fan{}".format(self.fantrayindex, self.fanindex)

def get_model(self):
"""
Retrieves the part number of the FAN
Returns:
String: Part number of FAN
"""
if self.is_psu_fan:
return 'NA'
else:
return self.fru.get_board_part_number()

def get_serial(self):
"""
Retrieves the serial number of the FAN
Returns:
String: Serial number of FAN
"""
if self.is_psu_fan:
return 'NA'
else:
return self.fru.get_board_serial()

def get_presence(self):
"""
Retrieves the presence of the FAN
Returns:
bool: True if fan is present, False if not
"""
presence = False
if self.is_psu_fan:
return self.dependency.get_presence()
else:
is_valid, state = self.prsnt_sensor.get_reading()
if is_valid:
if (state & 0b1):
presence = True
return presence

def get_status(self):
"""
Retrieves the operational status of the FAN
Returns:
bool: True if FAN is operating properly, False if not
"""
status = False
is_valid, state = self.state_sensor.get_reading()
if is_valid:
if (state == 0x00):
status = True
return status

def get_direction(self):
"""
Retrieves the fan airfow direction
Returns:
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
depending on fan direction

Notes:
In DellEMC platforms,
- Forward/Exhaust : Air flows from Port side to Fan side.
- Reverse/Intake : Air flows from Fan side to Port side.
"""
direction = [self.FAN_DIRECTION_EXHAUST, self.FAN_DIRECTION_INTAKE]
fan_status = self.get_status()
if not fan_status:
return 'NA'
is_valid, fan_direction = self.fru.get_fru_data(self.fan_direction_offset)
if is_valid:
return direction[fan_direction[0]]
else:
return 'NA'

def get_speed(self):
"""
Retrieves the speed of the fan
Returns:
int: percentage of the max fan speed
"""
if self.max_speed == 0:
self.max_speed = self.fru.get_fru_data(self.max_speed_offset,2)[1]
self.max_speed = self.max_speed[1] << 8 | self.max_speed[0]
is_valid, fan_speed = self.speed_sensor.get_reading()
if not is_valid or self.max_speed == 0:
speed = 0
else:
speed = (100 * fan_speed)/self.max_speed
return speed
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
try:
from sonic_platform_base.psu_base import PsuBase
from sonic_platform.ipmihelper import IpmiSensor, IpmiFru
from sonic_platform.fan import Fan
except ImportError as e:
raise ImportError(str(e) + "- required module not found")

Expand All @@ -38,6 +39,9 @@ def __init__(self, psu_index):
self.power_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Power"])
self.fru = IpmiFru(self.FRU_MAPPING[self.index])

self._fan_list.append(Fan(fan_index=self.index, psu_fan=True,
dependency=self))

def get_name(self):
"""
Retrieves the name of the device
Expand Down