-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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 S6000 : Platform2.0 API implementation [PSU, Thermal] #3357
Merged
sujinmkang
merged 7 commits into
sonic-net:master
from
ArunSaravananBalachandran:platfrom2.0_s6000
Sep 18, 2019
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
e5c74d1
DellEMC S6000 : Platform2.0 API implementation [PSU, Thermal]
ArunSaravananBalachandran e7a5443
Fix invalid number of arguments error
ArunSaravananBalachandran cd76ff1
DellEMC S6000 : Platform2.0 [ Thermal ]
ArunSaravananBalachandran 0ab4cff
DellEMC S6000 : Platform2.0 API [PSU, Thermal]
ArunSaravananBalachandran 1f5690e
Merge branch 'master' into platfrom2.0_s6000
ArunSaravananBalachandran 52839ce
Merge branch 'master' into platfrom2.0_s6000
ArunSaravananBalachandran 7f8a86e
Updated merge changes
ArunSaravananBalachandran File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
__all__ = ["platform", "chassis", "sfp"] | ||
__all__ = ["platform", "chassis", "sfp", "psu", "thermal"] | ||
from sonic_platform import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
240 changes: 240 additions & 0 deletions
240
platform/broadcom/sonic-platform-modules-dell/s6000/sonic_platform/psu.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,240 @@ | ||
#!/usr/bin/env python | ||
|
||
######################################################################## | ||
# DellEMC S6000 | ||
# | ||
# Module contains an implementation of SONiC Platform Base API and | ||
# provides the PSUs' information which are available in the platform | ||
# | ||
######################################################################## | ||
|
||
|
||
try: | ||
import os | ||
from sonic_platform_base.psu_base import PsuBase | ||
from sonic_platform.eeprom import Eeprom | ||
except ImportError as e: | ||
raise ImportError(str(e) + "- required module not found") | ||
|
||
|
||
class Psu(PsuBase): | ||
"""DellEMC Platform-specific PSU class""" | ||
|
||
CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0/" | ||
I2C_DIR = "/sys/class/i2c-adapter/" | ||
|
||
def __init__(self, psu_index): | ||
# PSU is 1-based in DellEMC platforms | ||
self.index = psu_index + 1 | ||
self.psu_presence_reg = "psu{}_prs".format(psu_index) | ||
self.psu_status_reg = "powersupply_status" | ||
|
||
if self.index == 1: | ||
ltc_dir = self.I2C_DIR + "i2c-11/11-0042/hwmon/" | ||
else: | ||
ltc_dir = self.I2C_DIR + "i2c-11/11-0040/hwmon/" | ||
hwmon_node = os.listdir(ltc_dir)[0] | ||
self.HWMON_DIR = ltc_dir + hwmon_node + '/' | ||
|
||
self.psu_voltage_reg = self.HWMON_DIR + "in1_input" | ||
self.psu_current_reg = self.HWMON_DIR + "curr1_input" | ||
self.psu_power_reg = self.HWMON_DIR + "power1_input" | ||
|
||
self.eeprom = Eeprom(is_psu=True, psu_index=self.index) | ||
|
||
# Overriding _fan_list class variable defined in PsuBase, to | ||
# make it unique per Psu object | ||
self._fan_list = [] | ||
|
||
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 _get_i2c_register(self, reg_file): | ||
# On successful read, returns the value read from given | ||
# reg_name and on failure returns 'ERR' | ||
rv = 'ERR' | ||
|
||
if (not os.path.isfile(reg_file)): | ||
return rv | ||
|
||
try: | ||
with open(reg_file, 'r') as fd: | ||
rv = fd.read() | ||
except: | ||
rv = 'ERR' | ||
|
||
rv = rv.rstrip('\r\n') | ||
rv = rv.lstrip(" ") | ||
return rv | ||
|
||
def get_name(self): | ||
""" | ||
Retrieves the name of the device | ||
|
||
Returns: | ||
string: The name of the device | ||
""" | ||
return "PSU{}".format(self.index) | ||
|
||
def get_presence(self): | ||
""" | ||
Retrieves the presence of the Power Supply Unit (PSU) | ||
|
||
Returns: | ||
bool: True if PSU is present, False if not | ||
""" | ||
status = False | ||
psu_presence = self._get_cpld_register(self.psu_presence_reg) | ||
if (psu_presence != 'ERR'): | ||
psu_presence = int(psu_presence) | ||
if psu_presence: | ||
status = True | ||
|
||
return status | ||
|
||
def get_model(self): | ||
""" | ||
Retrieves the part number of the PSU | ||
|
||
Returns: | ||
string: Part number of PSU | ||
""" | ||
return self.eeprom.part_number_str() | ||
|
||
def get_serial(self): | ||
""" | ||
Retrieves the serial number of the PSU | ||
|
||
Returns: | ||
string: Serial number of PSU | ||
""" | ||
# Sample Serial number format "US-01234D-54321-25A-0123-A00" | ||
return self.eeprom.serial_number_str() | ||
|
||
def get_status(self): | ||
""" | ||
Retrieves the operational status of the PSU | ||
|
||
Returns: | ||
bool: True if PSU is operating properly, False if not | ||
""" | ||
status = False | ||
psu_status = self._get_cpld_register(self.psu_status_reg) | ||
if (psu_status != 'ERR'): | ||
psu_status = (int(psu_status, 16) >> ((2 - self.index) * 4)) & 0xF | ||
if (~psu_status & 0b1000) and (~psu_status & 0b0100): | ||
status = True | ||
|
||
return status | ||
|
||
def get_voltage(self): | ||
""" | ||
Retrieves current PSU voltage output | ||
|
||
Returns: | ||
A float number, the output voltage in volts, | ||
e.g. 12.1 | ||
""" | ||
psu_voltage = self._get_i2c_register(self.psu_voltage_reg) | ||
if (psu_voltage != 'ERR') and self.get_status(): | ||
# Converting the value returned by driver which is in | ||
# millivolts to volts | ||
psu_voltage = float(psu_voltage) / 1000 | ||
else: | ||
psu_voltage = 0.0 | ||
|
||
return psu_voltage | ||
|
||
def get_current(self): | ||
""" | ||
Retrieves present electric current supplied by PSU | ||
|
||
Returns: | ||
A float number, electric current in amperes, | ||
e.g. 15.4 | ||
""" | ||
psu_current = self._get_i2c_register(self.psu_current_reg) | ||
if (psu_current != 'ERR') and self.get_status(): | ||
# Converting the value returned by driver which is in | ||
# milliamperes to amperes | ||
psu_current = float(psu_current) / 1000 | ||
else: | ||
psu_current = 0.0 | ||
|
||
return psu_current | ||
|
||
def get_power(self): | ||
""" | ||
Retrieves current energy supplied by PSU | ||
|
||
Returns: | ||
A float number, the power in watts, | ||
e.g. 302.6 | ||
""" | ||
psu_power = self._get_i2c_register(self.psu_power_reg) | ||
if (psu_power != 'ERR') and self.get_status(): | ||
# Converting the value returned by driver which is in | ||
# microwatts to watts | ||
psu_power = float(psu_power) / 1000000 | ||
else: | ||
psu_power = 0.0 | ||
|
||
return psu_power | ||
|
||
def get_powergood_status(self): | ||
""" | ||
Retrieves the powergood status of PSU | ||
Returns: | ||
A boolean, True if PSU has stablized its output voltages and | ||
passed all its internal self-tests, False if not. | ||
""" | ||
status = False | ||
psu_status = self._get_cpld_register(self.psu_status_reg) | ||
if (psu_status != 'ERR'): | ||
psu_status = (int(psu_status, 16) >> ((2 - self.index) * 4)) & 0xF | ||
if (psu_status == 0x2): | ||
status = True | ||
|
||
return status | ||
|
||
def get_status_led(self): | ||
""" | ||
Gets the state of the PSU status LED | ||
|
||
Returns: | ||
A string, one of the predefined STATUS_LED_COLOR_* strings. | ||
""" | ||
if self.get_powergood_status(): | ||
return self.STATUS_LED_COLOR_GREEN | ||
else: | ||
return self.STATUS_LED_COLOR_OFF | ||
|
||
def set_status_led(self, color): | ||
""" | ||
Sets the state of the PSU status LED | ||
Args: | ||
color: A string representing the color with which to set the | ||
PSU status LED | ||
Returns: | ||
bool: True if status LED state is set successfully, False if | ||
not | ||
""" | ||
# In S6000, the firmware running in the PSU controls the LED | ||
# and the PSU LED state cannot be changed from CPU. | ||
return False | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The S6000 has status LEDs on each PSU and also one power status LED on the front panel. How are these controlled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In S6000, the firmware running in the PSU controls the individual PSU's status LED.
The power status LED on the front panel is controlled via CPLD.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the CPLD will manage the power status LED on the front panel without software assistance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The front panel power status LED needs to be controlled by software via CPLD.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. Do you intend to control the power status LED somewhere other than here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, the front panel power status LED is not controlled here. If required we can take this as separate work-item.