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

[201911] Dell S6000 I2C not responding to certain optics - porting #8855

Merged
merged 1 commit into from
Oct 25, 2021
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
103 changes: 102 additions & 1 deletion device/dell/x86_64-dell_s6000_s1220-r0/plugins/sfputil.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

try:
import time
import fcntl
import datetime
from sonic_sfp.sfputilbase import SfpUtilBase
except ImportError as e:
Expand All @@ -19,6 +20,7 @@ class SfpUtil(SfpUtilBase):
PORTS_IN_BLOCK = 32

EEPROM_OFFSET = 20
SFP_LOCK_FILE="/etc/sonic/sfp_lock"

_port_to_eeprom_mapping = {}
port_dict = {}
Expand Down Expand Up @@ -73,10 +75,19 @@ def get_presence(self, port_num):
if port_num < self.port_start or port_num > self.port_end:
return False

try:
fd = open(self.SFP_LOCK_FILE, "r")
except IOError as e:
print("Error: unable to open file: "+ str(e))
return False
fcntl.flock(fd, fcntl.LOCK_EX)
self.set_modsel(port_num)

try:
reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_modprs")
except IOError as e:
print "Error: unable to open file: %s" % str(e)
fcntl.flock(fd, fcntl.LOCK_UN)
return False

content = reg_file.readline().rstrip()
Expand All @@ -86,13 +97,103 @@ def get_presence(self, port_num):

# Mask off the bit corresponding to our port
mask = (1 << port_num)

fcntl.flock(fd, fcntl.LOCK_UN)
# ModPrsL is active low
if reg_value & mask == 0:
return True

return False

def get_modsel(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
return False

try:
reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_modsel")
except IOError as e:
print("Error: unable to open file: %s" % str(e))
return False

content = reg_file.readline().rstrip()

# content is a string containing the hex representation of the register
reg_value = int(content, 16)

# Mask off the bit corresponding to our port
mask = (1 << port_num)

if reg_value & mask == 1:
return False

return True

def set_modsel(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
return False

try:
reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_modsel", "r+")
except IOError as e:
print("Error: unable to open file: %s" % str(e))
return False

content = reg_file.readline().rstrip()

# content is a string containing the hex representation of the register
reg_value = int(content, 16)

# Mask off the bit corresponding to our port
mask = (1 << port_num)
reg_value = reg_value | int("0xffffffff", 16)
reg_value = reg_value & ~mask

# Convert our register value back to a hex string and write back
content = hex(reg_value)

reg_file.seek(0)
reg_file.write(content)
reg_file.close()

return True

def get_eeprom_raw(self, port_num, num_bytes=256):
# Read interface id EEPROM at addr 0x50
try:
fd = open(self.SFP_LOCK_FILE, "r")
except IOError as e:
print("Error: unable to open file: %s" % str(e))
return None
fcntl.flock(fd, fcntl.LOCK_EX)
self.set_modsel(port_num)
eeprom_bytes = self._read_eeprom_devid(port_num, self.IDENTITY_EEPROM_ADDR, 0, num_bytes)
fcntl.flock(fd, fcntl.LOCK_UN)
return eeprom_bytes

def get_eeprom_dom_raw(self, port_num):
if port_num in self.osfp_ports:
return None
if port_num in self.qsfp_ports:
# QSFP DOM EEPROM is also at addr 0x50 and thus also stored in eeprom_ifraw
return None
else:
# Read dom eeprom at addr 0x51
if not self.get_modsel(port_num):
try:
fd = open(self.SFP_LOCK_FILE, "r")
except IOError as e:
print("Error: unable to open file: %s" % str(e))
return None
fcntl.flock(fd, fcntl.LOCK_EX)
self.set_modsel(port_num)
eeprom_bytes = self._read_eeprom_devid(port_num, self.DOM_EEPROM_ADDR, 0)
fcntl.flock(fd, fcntl.LOCK_UN)
return eeprom_bytes
else:
return self._read_eeprom_devid(port_num, self.DOM_EEPROM_ADDR, 0)


def get_low_power_mode(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,25 @@ static ssize_t get_modsel(struct device *dev, struct device_attribute *devattr,
return sprintf(buf, "0x%08x\n", data);
}

static ssize_t set_modsel(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count)
{
int err;
unsigned long data = 0;
struct cpld_platform_data *pdata = dev->platform_data;

err = kstrtoul(buf, 16, &data);
if (err)
return err;

dell_i2c_smbus_write_byte_data(pdata[slave_cpld].client, 0x0, (u8)(data & 0xff));
dell_i2c_smbus_write_byte_data(pdata[slave_cpld].client, 0x1, (u8)((data >> 8) & 0xff));
dell_i2c_smbus_write_byte_data(pdata[master_cpld].client, 0xa, (u8)((data >> 16) & 0xff));
dell_i2c_smbus_write_byte_data(pdata[master_cpld].client, 0xb, (u8)((data >> 24) & 0xff));

msleep(2); // As per HW spec
return count;
}

static ssize_t get_lpmode(struct device *dev, struct device_attribute *devattr, char *buf)
{
int ret;
Expand Down Expand Up @@ -1128,7 +1147,7 @@ static ssize_t get_reboot_reason(struct device *dev,
return sprintf(buf, "0x%x\n", data);
}

static DEVICE_ATTR(qsfp_modsel, S_IRUGO, get_modsel, NULL);
static DEVICE_ATTR(qsfp_modsel, S_IRUGO | S_IWUSR, get_modsel, set_modsel);
static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL);
static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode);
static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ remove_python_api_package() {
# read SONiC immutable variables
[ -f /etc/sonic/sonic-environment ] && . /etc/sonic/sonic-environment

if [ ! -e /etc/sonic/sfp_lock ]; then
touch /etc/sonic/sfp_lock
fi

if [[ "$1" == "init" ]]; then
depmod -a
modprobe nvram
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

try:
import os
import fcntl
import time
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform_base.sfp_base import SfpBase
Expand Down Expand Up @@ -149,6 +150,15 @@ def _get_eeprom_data(self, eeprom_key):
if (self.sfpInfo is None):
return None

SFP_LOCK_FILE="/etc/sonic/sfp_lock"
try:
fd = open(SFP_LOCK_FILE, "r")
except IOError as e:
print("Error: unable to open file: %s" % str(e))
return None
fcntl.flock(fd, fcntl.LOCK_EX)
self.set_modsel()

page_offset = sff8436_parser[eeprom_key][PAGE_OFFSET]
eeprom_data_raw = self._read_eeprom_bytes(
self.eeprom_path,
Expand All @@ -167,6 +177,7 @@ def _get_eeprom_data(self, eeprom_key):
self.sfpDomInfo, sff8436_parser[eeprom_key][FUNC_NAME])(
eeprom_data_raw, 0)

fcntl.flock(fd, fcntl.LOCK_UN)
return eeprom_data


Expand Down Expand Up @@ -410,6 +421,16 @@ def get_presence(self):
Retrieves the presence of the sfp
"""
presence_ctrl = self.sfp_control + 'qsfp_modprs'
SFP_LOCK_FILE="/etc/sonic/sfp_lock"

try:
fd = open(SFP_LOCK_FILE, "r")
except IOError as e:
print("Error: unable to open file: %s" % str(e))
return False
fcntl.flock(fd, fcntl.LOCK_EX)
self.set_modsel()

try:
reg_file = open(presence_ctrl)
except IOError as e:
Expand All @@ -424,12 +445,69 @@ def get_presence(self):
# Mask off the bit corresponding to our port
mask = (1 << self.sfp_ctrl_idx)

fcntl.flock(fd, fcntl.LOCK_UN)

# ModPrsL is active low
if ((reg_value & mask) == 0):
return True

return False

def get_modsel(self):
modsel_ctrl = self.sfp_control + 'qsfp_modsel'
try:
reg_file = open(modsel_ctrl, "r+")
except IOError as e:
return False

reg_hex = reg_file.readline().rstrip()

# content is a string containing the hex
# representation of the register
reg_value = int(reg_hex, 16)

# Mask off the bit corresponding to our port
index = self.sfp_ctrl_idx

mask = (1 << index)

if ((reg_value & mask) == 1):
modsel_state = False
else:
modsel_state = True

return modsel_state

def set_modsel(self):
modsel_ctrl = self.sfp_control + 'qsfp_modsel'
try:
reg_file = open(modsel_ctrl, "r+")
except IOError as e:
return False

reg_hex = reg_file.readline().rstrip()

# content is a string containing the hex
# representation of the register
reg_value = int(reg_hex, 16)

# Mask off the bit corresponding to our port
index = self.sfp_ctrl_idx

reg_value = reg_value | int("0xffffffff", 16)
mask = (1 << index)

reg_value = (reg_value & ~mask)

# Convert our register value back to a hex string and write back
content = hex(reg_value)

reg_file.seek(0)
reg_file.write(content)
reg_file.close()

return True

def get_model(self):
"""
Retrieves the model number (or part number) of the sfp
Expand Down