DellEMC: Fix z9332f low power mode issue (#8693)
This commit is contained in:
parent
800de696db
commit
77b6bc39be
@ -2,13 +2,12 @@
|
|||||||
#
|
#
|
||||||
# Platform-specific SFP transceiver interface for SONiC
|
# Platform-specific SFP transceiver interface for SONiC
|
||||||
#
|
#
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import struct
|
|
||||||
import sys
|
import sys
|
||||||
import getopt
|
import getopt
|
||||||
import time
|
import time
|
||||||
import select
|
import select
|
||||||
|
import io
|
||||||
from sonic_sfp.sfputilbase import SfpUtilBase
|
from sonic_sfp.sfputilbase import SfpUtilBase
|
||||||
from os import *
|
from os import *
|
||||||
from mmap import *
|
from mmap import *
|
||||||
@ -19,6 +18,25 @@ except ImportError as e:
|
|||||||
# from xcvrd
|
# from xcvrd
|
||||||
SFP_STATUS_REMOVED = '0'
|
SFP_STATUS_REMOVED = '0'
|
||||||
SFP_STATUS_INSERTED = '1'
|
SFP_STATUS_INSERTED = '1'
|
||||||
|
MEDIA_TYPE_OFFSET = 0
|
||||||
|
MEDIA_TYPE_WIDTH = 1
|
||||||
|
QSFP_DD_MODULE_ENC_OFFSET = 3
|
||||||
|
QSFP_DD_MODULE_ENC_WIDTH = 1
|
||||||
|
|
||||||
|
SFP_TYPE_LIST = [
|
||||||
|
'03' # SFP/SFP+/SFP28 and later
|
||||||
|
]
|
||||||
|
QSFP_TYPE_LIST = [
|
||||||
|
'0c', # QSFP
|
||||||
|
'0d', # QSFP+ or later
|
||||||
|
'11' # QSFP28 or later
|
||||||
|
]
|
||||||
|
QSFP_DD_TYPE_LIST = [
|
||||||
|
'18' #QSFP_DD Type
|
||||||
|
]
|
||||||
|
OSFP_TYPE_LIST=[
|
||||||
|
'19' # OSFP 8X Type
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class SfpUtil(SfpUtilBase):
|
class SfpUtil(SfpUtilBase):
|
||||||
@ -87,18 +105,77 @@ class SfpUtil(SfpUtilBase):
|
|||||||
def port_to_eeprom_mapping(self):
|
def port_to_eeprom_mapping(self):
|
||||||
return self._port_to_eeprom_mapping
|
return self._port_to_eeprom_mapping
|
||||||
|
|
||||||
|
def _read_eeprom_bytes(self, eeprom_path, offset, num_bytes):
|
||||||
|
eeprom_raw = []
|
||||||
|
try:
|
||||||
|
eeprom = io.open(eeprom_path, mode="rb", buffering=0)
|
||||||
|
except IOError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
for i in range(0, num_bytes):
|
||||||
|
eeprom_raw.append("0x00")
|
||||||
|
|
||||||
|
try:
|
||||||
|
eeprom.seek(offset)
|
||||||
|
raw = eeprom.read(num_bytes)
|
||||||
|
except IOError:
|
||||||
|
eeprom.close()
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
if isinstance(raw , str):
|
||||||
|
for n in range(0, num_bytes):
|
||||||
|
eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2)
|
||||||
|
else:
|
||||||
|
for n in range(0, num_bytes):
|
||||||
|
eeprom_raw[n] = hex(raw[n])[2:].zfill(2)
|
||||||
|
|
||||||
|
except (OSError, IOError):
|
||||||
|
eeprom.close()
|
||||||
|
return None
|
||||||
|
|
||||||
|
eeprom.close()
|
||||||
|
return eeprom_raw
|
||||||
|
|
||||||
|
def _write_eeprom_bytes(self, eeprom_path, offset, num_bytes, value):
|
||||||
|
try:
|
||||||
|
with io.open(eeprom_path, mode='r+b', buffering=0) as f:
|
||||||
|
f.seek(offset)
|
||||||
|
f.write(value[0:num_bytes])
|
||||||
|
except (OSError, IOError):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def get_media_type(self, port_num):
|
||||||
|
"""
|
||||||
|
Reads optic eeprom byte to determine media type inserted
|
||||||
|
"""
|
||||||
|
eeprom_raw = []
|
||||||
|
eeprom_raw = self._read_eeprom_bytes(self.port_to_eeprom_mapping[port_num], MEDIA_TYPE_OFFSET,
|
||||||
|
MEDIA_TYPE_WIDTH)
|
||||||
|
if eeprom_raw is not None:
|
||||||
|
if eeprom_raw[0] in SFP_TYPE_LIST:
|
||||||
|
sfp_type = 'SFP'
|
||||||
|
elif eeprom_raw[0] in QSFP_TYPE_LIST:
|
||||||
|
sfp_type = 'QSFP'
|
||||||
|
elif eeprom_raw[0] in QSFP_DD_TYPE_LIST:
|
||||||
|
sfp_type = 'QSFP_DD'
|
||||||
|
else:
|
||||||
|
#Set native port type if EEPROM type is not recognized/readable
|
||||||
|
sfp_type = 'QSFP_DD'
|
||||||
|
else:
|
||||||
|
sfp_type = 'QSFP_DD'
|
||||||
|
|
||||||
|
return sfp_type
|
||||||
|
|
||||||
def pci_mem_read(self, mm, offset):
|
def pci_mem_read(self, mm, offset):
|
||||||
mm.seek(offset)
|
mm.seek(offset)
|
||||||
read_data_stream = mm.read(4)
|
return mm.read_byte()
|
||||||
reg_val = struct.unpack('I', read_data_stream)
|
|
||||||
mem_val = str(reg_val)[1:-2]
|
|
||||||
# print "reg_val read:%x"%reg_val
|
|
||||||
return mem_val
|
|
||||||
|
|
||||||
def pci_mem_write(self, mm, offset, data):
|
def pci_mem_write(self, mm, offset, data):
|
||||||
mm.seek(offset)
|
mm.seek(offset)
|
||||||
# print "data to write:%x"%data
|
mm.write_byte(data)
|
||||||
mm.write(struct.pack('I', data))
|
|
||||||
|
|
||||||
def pci_set_value(self, resource, val, offset):
|
def pci_set_value(self, resource, val, offset):
|
||||||
fd = open(resource, O_RDWR)
|
fd = open(resource, O_RDWR)
|
||||||
@ -181,54 +258,70 @@ class SfpUtil(SfpUtilBase):
|
|||||||
# Check for invalid port_num
|
# Check for invalid port_num
|
||||||
if port_num < self.port_start or port_num > self.port_end:
|
if port_num < self.port_start or port_num > self.port_end:
|
||||||
return False
|
return False
|
||||||
|
if port_num > self.PORTS_IN_BLOCK:
|
||||||
# Port offset starts with 0x4000
|
|
||||||
port_offset = 16384 + ((port_num-1) * 16)
|
|
||||||
|
|
||||||
status = self.pci_get_value(self.BASE_RES_PATH, port_offset)
|
|
||||||
reg_value = int(status)
|
|
||||||
|
|
||||||
# Absence of status throws error
|
|
||||||
if (reg_value == ""):
|
|
||||||
return False
|
return False
|
||||||
|
if self.get_media_type(port_num) == 'QSFP_DD':
|
||||||
# Mask off 4th bit for presence
|
lpmode = self._read_eeprom_bytes(self.port_to_eeprom_mapping[port_num], QSFP_DD_MODULE_ENC_OFFSET,
|
||||||
mask = (1 << 6)
|
QSFP_DD_MODULE_ENC_WIDTH)
|
||||||
|
if lpmode is not None:
|
||||||
# LPMode is active high
|
if int(lpmode[0])>>1 == 1:
|
||||||
if reg_value & mask == 0:
|
return True
|
||||||
return False
|
return False
|
||||||
|
else:
|
||||||
|
# Port offset starts with 0x4000
|
||||||
|
port_offset = 16384 + ((port_num-1) * 16)
|
||||||
|
|
||||||
return True
|
status = self.pci_get_value(self.BASE_RES_PATH, port_offset)
|
||||||
|
# Absence of status throws error
|
||||||
|
if (status == ""):
|
||||||
|
return False
|
||||||
|
|
||||||
|
reg_value = int(status)
|
||||||
|
|
||||||
|
# Mask off 4th bit for presence
|
||||||
|
mask = (1 << 6)
|
||||||
|
|
||||||
|
# LPMode is active high
|
||||||
|
if reg_value & mask == 0:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def set_low_power_mode(self, port_num, lpmode):
|
def set_low_power_mode(self, port_num, lpmode):
|
||||||
|
|
||||||
# Check for invalid port_num
|
# Check for invalid port_num
|
||||||
if port_num < self.port_start or port_num > self.port_end:
|
if port_num < self.port_start or port_num > self.port_end:
|
||||||
return False
|
return False
|
||||||
|
if port_num > self.PORTS_IN_BLOCK:
|
||||||
# Port offset starts with 0x4000
|
|
||||||
port_offset = 16384 + ((port_num-1) * 16)
|
|
||||||
|
|
||||||
status = self.pci_get_value(self.BASE_RES_PATH, port_offset)
|
|
||||||
reg_value = int(status)
|
|
||||||
|
|
||||||
# Absence of status throws error
|
|
||||||
if (reg_value == ""):
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Mask off 4th bit for presence
|
if self.get_media_type(port_num) == 'QSFP_DD':
|
||||||
mask = (1 << 6)
|
if lpmode is True:
|
||||||
|
write_val = 0x10
|
||||||
|
else:
|
||||||
|
write_val = 0x0
|
||||||
|
|
||||||
# LPMode is active high; set or clear the bit accordingly
|
self._write_eeprom_bytes(self.port_to_eeprom_mapping[port_num], 26, 1, bytearray([write_val]))
|
||||||
if lpmode is True:
|
|
||||||
reg_value = reg_value | mask
|
|
||||||
else:
|
else:
|
||||||
reg_value = reg_value & ~mask
|
# Port offset starts with 0x4000
|
||||||
|
port_offset = 16384 + ((port_num-1) * 16)
|
||||||
|
status = self.pci_get_value(self.BASE_RES_PATH, port_offset)
|
||||||
|
reg_value = int(status)
|
||||||
|
|
||||||
# Convert our register value back to a hex string and write back
|
# Absence of status throws error
|
||||||
status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset)
|
if (reg_value == ""):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Mask off 4th bit for presence
|
||||||
|
mask = (1 << 6)
|
||||||
|
|
||||||
|
# LPMode is active high; set or clear the bit accordingly
|
||||||
|
if lpmode is True:
|
||||||
|
reg_value = reg_value | mask
|
||||||
|
else:
|
||||||
|
reg_value = reg_value & ~mask
|
||||||
|
|
||||||
|
# Convert our register value back to a hex string and write back
|
||||||
|
status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def reset(self, port_num):
|
def reset(self, port_num):
|
||||||
|
@ -13,7 +13,6 @@ try:
|
|||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import subprocess
|
import subprocess
|
||||||
import struct
|
|
||||||
import mmap
|
import mmap
|
||||||
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
|
||||||
@ -60,6 +59,8 @@ QSFP_DD_APP1_ADV_OFFSET = 86
|
|||||||
QSFP_DD_APP1_ADV_WIDTH = 32
|
QSFP_DD_APP1_ADV_WIDTH = 32
|
||||||
QSFP_DD_APP2_ADV_OFFSET = 351
|
QSFP_DD_APP2_ADV_OFFSET = 351
|
||||||
QSFP_DD_APP2_ADV_WIDTH = 28
|
QSFP_DD_APP2_ADV_WIDTH = 28
|
||||||
|
QSFP_DD_MODULE_ENC_OFFSET = 3
|
||||||
|
QSFP_DD_MODULE_ENC_WIDTH = 1
|
||||||
|
|
||||||
QSFP_INFO_OFFSET = 128
|
QSFP_INFO_OFFSET = 128
|
||||||
QSFP_DOM_OFFSET = 0
|
QSFP_DOM_OFFSET = 0
|
||||||
@ -311,16 +312,12 @@ class Sfp(SfpBase):
|
|||||||
|
|
||||||
def pci_mem_read(self, mm, offset):
|
def pci_mem_read(self, mm, offset):
|
||||||
mm.seek(offset)
|
mm.seek(offset)
|
||||||
read_data_stream = mm.read(4)
|
return mm.read_byte()
|
||||||
reg_val = struct.unpack('I', read_data_stream)
|
|
||||||
mem_val = str(reg_val)[1:-2]
|
|
||||||
# print "reg_val read:%x"%reg_val
|
|
||||||
return mem_val
|
|
||||||
|
|
||||||
def pci_mem_write(self, mm, offset, data):
|
def pci_mem_write(self, mm, offset, data):
|
||||||
mm.seek(offset)
|
mm.seek(offset)
|
||||||
# print "data to write:%x"%data
|
# print "data to write:%x"%data
|
||||||
mm.write(struct.pack('I', data))
|
mm.write_byte(data)
|
||||||
|
|
||||||
def pci_set_value(self, resource, val, offset):
|
def pci_set_value(self, resource, val, offset):
|
||||||
fd = os.open(resource, os.O_RDWR)
|
fd = os.open(resource, os.O_RDWR)
|
||||||
@ -338,6 +335,15 @@ class Sfp(SfpBase):
|
|||||||
os.close(fd)
|
os.close(fd)
|
||||||
return val
|
return val
|
||||||
|
|
||||||
|
def _write_eeprom_bytes(self, offset, num_bytes, value):
|
||||||
|
try:
|
||||||
|
with open(self.eeprom_path, mode='r+b', buffering=0) as f:
|
||||||
|
f.seek(offset)
|
||||||
|
f.write(value[0:num_bytes])
|
||||||
|
except (OSError, IOError):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def _read_eeprom_bytes(self, eeprom_path, offset, num_bytes):
|
def _read_eeprom_bytes(self, eeprom_path, offset, num_bytes):
|
||||||
eeprom_raw = []
|
eeprom_raw = []
|
||||||
try:
|
try:
|
||||||
@ -994,7 +1000,13 @@ class Sfp(SfpBase):
|
|||||||
"""
|
"""
|
||||||
lpmode_state = False
|
lpmode_state = False
|
||||||
try:
|
try:
|
||||||
if self.sfp_type.startswith('QSFP'):
|
if self.sfp_type == 'QSFP_DD':
|
||||||
|
lpmode = self._read_eeprom_bytes(self.eeprom_path, QSFP_DD_MODULE_ENC_OFFSET, QSFP_DD_MODULE_ENC_WIDTH)
|
||||||
|
if lpmode is not None:
|
||||||
|
if int(lpmode[0])>>1 == 1:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
else:
|
||||||
# Port offset starts with 0x4000
|
# Port offset starts with 0x4000
|
||||||
port_offset = 16384 + ((self.index-1) * 16)
|
port_offset = 16384 + ((self.index-1) * 16)
|
||||||
|
|
||||||
@ -1005,8 +1017,9 @@ class Sfp(SfpBase):
|
|||||||
mask = (1 << 6)
|
mask = (1 << 6)
|
||||||
|
|
||||||
lpmode_state = (reg_value & mask)
|
lpmode_state = (reg_value & mask)
|
||||||
except ValueError: pass
|
except ValueError:
|
||||||
return lpmode_state
|
pass
|
||||||
|
return bool(lpmode_state)
|
||||||
|
|
||||||
def get_power_override(self):
|
def get_power_override(self):
|
||||||
"""
|
"""
|
||||||
@ -1231,7 +1244,14 @@ class Sfp(SfpBase):
|
|||||||
Sets the lpmode(low power mode) of this SFP
|
Sets the lpmode(low power mode) of this SFP
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if self.port_type == 'QSFP_DD':
|
if self.sfp_type == 'QSFP_DD':
|
||||||
|
if lpmode is True:
|
||||||
|
write_val = 0x10
|
||||||
|
else:
|
||||||
|
write_val = 0x0
|
||||||
|
|
||||||
|
self._write_eeprom_bytes(26, 1, bytearray([write_val]))
|
||||||
|
else:
|
||||||
# Port offset starts with 0x4000
|
# Port offset starts with 0x4000
|
||||||
port_offset = 16384 + ((self.index-1) * 16)
|
port_offset = 16384 + ((self.index-1) * 16)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user