[devices]: Address Dell issue#46 : Adding MUX reset logic to fix probe failures (#2356)

This commit is contained in:
padmanarayana 2019-01-08 15:27:16 -08:00 committed by lguohan
parent 1acb6717d9
commit 14a0297128
7 changed files with 157 additions and 18 deletions

View File

@ -18,7 +18,7 @@ i2c_config() {
done
if [[ "$count" -eq "$MAX_BUS_RETRY" ]]; then
echo "ERROR: $@ : i2c bus not created"
echo "dell_i2c_utils : ERROR: $@ : i2c bus not created"
return
fi
@ -31,7 +31,7 @@ i2c_config() {
done
if [[ "$count" -eq "$MAX_I2C_OP_RETRY" ]]; then
echo "ERROR: $@ : i2c operation failed"
echo "dell_i2c_utils : ERROR: $@ : i2c operation failed"
return
fi
}
@ -53,10 +53,75 @@ i2c_poll_bus_exists() {
done
if [[ "$count" -eq "$MAX_BUS_RETRY" ]]; then
echo "ERROR: $@ : i2c bus not created"
echo "dell_i2c_utils : ERROR: $@ : i2c bus not created"
return 1
else
return 0
fi
}
# Perform an i2c mux device create
# Input is of the form:
# i2c_mux_create mux_driver i2c_addr i2c_bus_num i2c_child_bus_num_start
# where i2c_bus_num is the bus number in which the mux is to be created and
# i2c_child_bus_num_start is the first of the 8 bus channels that this mux should create
i2c_mux_create() {
local MAX_MUX_CHANNEL_RETRY=3
local MAX_MUX_CHANNELS=8
local count=0
local i
local mux_driver=$1
local i2c_addr=$2
local i2c_bus_num=$3
local i2c_child_bus_num_start=$4
# Construct the i2c bus, the first and last bus channels that will be created under the MUX
i2c_bus=/sys/bus/i2c/devices/i2c-$i2c_bus_num
i2c_mux_channel_first=$i2c_bus/i2c-$i2c_child_bus_num_start
i2c_mux_channel_last=$i2c_bus/i2c-$(expr $i2c_child_bus_num_start + $MAX_MUX_CHANNELS - 1)
if i2c_poll_bus_exists $i2c_bus; then
while [[ "$count" -lt "$MAX_MUX_CHANNEL_RETRY" ]]; do
eval "echo $mux_driver $i2c_addr > /sys/bus/i2c/devices/i2c-$i2c_bus_num/new_device" > /dev/null 2>&1
ret=$?
# Give more time for the mux channels to get created based on retries
i=0
while [[ "$i" -lt "$count" ]]; do
sleep 1
i=$((i+1))
done
# Check if the (first and last) mux channels got created
if [[ $ret -eq "0" && -e $i2c_mux_channel_first && -e $i2c_mux_channel_last ]]; then
break;
else
# If the channel did not get created, remove the mux, reset the mux tree and retry
echo "dell_i2c_utils : ERROR: i2c mux channel not created for $mux_driver,$i2c_addr,$i2c_bus_num"
i2c_mux_delete $i2c_addr $i2c_bus_num
reset_muxes
fi
count=$((count+1))
done
fi
if [[ "$count" -eq "$MAX_MUX_CHANNEL_RETRY" ]]; then
echo "dell_i2c_utils : ERROR: $1,$2 : i2c mux channel not created"
return
fi
return
}
# Perform an i2c mux device delete
# Input is of the form:
# i2c_mux_delete i2c_addr i2c_bus_num
i2c_mux_delete() {
local i2c_addr
local i2c_bus_num
i2c_addr=$1
i2c_bus_num=$2
i2c_config "echo $i2c_addr > /sys/bus/i2c/devices/i2c-$i2c_bus_num/delete_device"
}

View File

@ -1,7 +1,7 @@
s6100/scripts/io_rd_wr.py usr/local/bin
s6100/scripts/iom_power_*.sh usr/local/bin
s6100/scripts/s6100_platform.sh usr/local/bin
common/dell_i2c_utils.sh usr/local/bin
common/io_rd_wr.py usr/local/bin
common/fstrim.timer etc/systemd/system
common/fstrim.service etc/systemd/system
common/platform_reboot usr/share/sonic/device/x86_64-dell_s6100_c2538-r0

View File

@ -1,6 +1,7 @@
z9100/scripts/check_qsfp.sh usr/local/bin
z9100/scripts/z9100_platform.sh usr/local/bin
common/dell_i2c_utils.sh usr/local/bin
common/io_rd_wr.py usr/local/bin
common/fstrim.timer etc/systemd/system
common/fstrim.service etc/systemd/system
common/platform_reboot usr/share/sonic/device/x86_64-dell_z9100_c2538-r0

View File

@ -11,6 +11,8 @@
//iom cpld slave address
#define IOM_CPLD_SLAVE_ADD 0x3e
#define CPLD_SEP_RST0 0x5
//iom cpld ver register
#define IOM_CPLD_SLAVE_VER 0x00
@ -384,6 +386,34 @@ static ssize_t set_abs_mask(struct device *dev, struct device_attribute *devattr
return count;
}
static ssize_t get_sep_reset(struct device *dev, struct device_attribute *devattr, char *buf)
{
int ret;
u8 devdata=0;
struct cpld_data *data = dev_get_drvdata(dev);
ret = dell_s6100_iom_cpld_read(data,IOM_CPLD_SLAVE_ADD,CPLD_SEP_RST0);
if(ret < 0)
return sprintf(buf, "read error");
devdata = (u8)ret & 0xff;
return sprintf(buf,"0x%02x\n",devdata);
}
static ssize_t set_sep_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count)
{
unsigned long devdata;
int err;
struct cpld_data *data = dev_get_drvdata(dev);
err = kstrtoul(buf, 16, &devdata);
if (err)
return err;
dell_s6100_iom_cpld_write(data,IOM_CPLD_SLAVE_ADD,CPLD_SEP_RST0,(u8)(devdata & 0xff));
return count;
}
static DEVICE_ATTR(iom_cpld_vers,S_IRUGO,get_cpldver, NULL);
static DEVICE_ATTR(qsfp_modprs, S_IRUGO,get_modprs, NULL);
static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR,get_lpmode,set_lpmode);
@ -396,6 +426,7 @@ static DEVICE_ATTR(qsfp_int, S_IRUGO, get_int, NULL);
static DEVICE_ATTR(qsfp_abs_int, S_IRUGO, get_abs_int, NULL);
static DEVICE_ATTR(qsfp_int_mask, S_IRUGO | S_IWUSR, get_int_mask, set_int_mask);
static DEVICE_ATTR(qsfp_abs_mask, S_IRUGO | S_IWUSR, get_abs_mask, set_abs_mask);
static DEVICE_ATTR(sep_reset, S_IRUGO | S_IWUSR, get_sep_reset, set_sep_reset);
static struct attribute *i2c_cpld_attrs[] = {
&dev_attr_qsfp_lpmode.attr,
@ -410,6 +441,7 @@ static struct attribute *i2c_cpld_attrs[] = {
&dev_attr_qsfp_abs_int.attr,
&dev_attr_qsfp_int_mask.attr,
&dev_attr_qsfp_abs_mask.attr,
&dev_attr_sep_reset.attr,
NULL,
};

View File

@ -21,9 +21,9 @@ init_devnum() {
# Attach/Detach CPU board mux @ 0x70
cpu_board_mux() {
case $1 in
"new_device") i2c_config "echo pca9547 0x70 > /sys/bus/i2c/devices/i2c-${devnum}/$1"
"new_device") i2c_mux_create pca9547 0x70 $devnum 2
;;
"delete_device") i2c_config "echo 0x70 > /sys/bus/i2c/devices/i2c-${devnum}/$1"
"delete_device") i2c_mux_delete 0x70 $devnum
;;
*) echo "s6100_platform: cpu_board_mux: invalid command !"
;;
@ -33,9 +33,9 @@ cpu_board_mux() {
# Attach/Detach Switchboard MUX @ 0x71
switch_board_mux() {
case $1 in
"new_device") i2c_config "echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-4/$1"
"new_device") i2c_mux_create pca9548 0x71 4 10
;;
"delete_device") i2c_config "echo 0x71 > /sys/bus/i2c/devices/i2c-4/$1"
"delete_device") i2c_mux_delete 0x71 4
;;
*) echo "s6100_platform: switch_board_mux : invalid command !"
;;
@ -78,13 +78,17 @@ switch_board_cpld() {
switch_board_qsfp_mux() {
case $1 in
"new_device")
# The mux for the QSFPs spawn {18..25}, {26..33}... {74..81}
# starting at chennel 18 and 16 channels per IOM.
channel_first=18
for ((i=9;i>=6;i--));
do
# 0x71 mux on the IOM 1
mux_index=$(expr $i - 5)
echo "Attaching PCA9548 $mux_index"
i2c_config "echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-$i/$1"
i2c_config "echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-$i/$1"
i2c_mux_create pca9548 0x71 $i $channel_first
i2c_mux_create pca9548 0x72 $i $(expr $channel_first + 8)
channel_first=$(expr $channel_first + 16)
done
;;
"delete_device")
@ -93,8 +97,8 @@ switch_board_qsfp_mux() {
# 0x71 mux on the IOM 1
mux_index=$(expr $i - 5)
echo "Detaching PCA9548 $mux_index"
i2c_config "echo 0x71 > /sys/bus/i2c/devices/i2c-$devnum/i2c-$i/$1"
i2c_config "echo 0x72 > /sys/bus/i2c/devices/i2c-$devnum/i2c-$i/$1"
i2c_mux_delete 0x71 $i
i2c_mux_delete 0x72 $i
done
;;
*) echo "s6100_platform: switch_board_qsfp_mux: invalid command !"
@ -191,6 +195,28 @@ xcvr_presence_interrupts() {
esac
}
# Reset the mux tree
reset_muxes() {
local i
# Reset the IOM muxes (if they have been already instantiated)
for ((i=14;i<=17;i++));
do
if [[ -e /sys/class/i2c-adapter/i2c-$i/$i-003e ]]; then
echo 0xfc > /sys/class/i2c-adapter/i2c-$i/$i-003e/sep_reset
echo 0xff > /sys/class/i2c-adapter/i2c-$i/$i-003e/sep_reset
fi
done
# Reset the switch card PCA9548A
io_rd_wr.py --set --val 0xef --offset 0x110
io_rd_wr.py --set --val 0xff --offset 0x110
# Reset the CPU Card PCA9547
io_rd_wr.py --set --val 0xfd --offset 0x20b
io_rd_wr.py --set --val 0xff --offset 0x20b
}
init_devnum
if [[ "$1" == "init" ]]; then

View File

@ -21,9 +21,9 @@ init_devnum() {
# Attach/Detach CPU board mux @ 0x70
cpu_board_mux() {
case $1 in
"new_device") i2c_config "echo pca9547 0x70 > /sys/bus/i2c/devices/i2c-${devnum}/$1"
"new_device") i2c_mux_create pca9547 0x70 $devnum 2
;;
"delete_device") i2c_config "echo 0x70 > /sys/bus/i2c/devices/i2c-${devnum}/$1"
"delete_device") i2c_mux_delete 0x70 $devnum
;;
*) echo "z9100_platform: cpu_board_mux: invalid command !"
;;
@ -33,9 +33,9 @@ cpu_board_mux() {
# Attach/Detach switch board MUX to IOM CPLDs @ 0x71
switch_board_mux() {
case $1 in
"new_device") i2c_config "echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-4/$1"
"new_device") i2c_mux_create pca9548 0x71 4 10
;;
"delete_device") i2c_config "echo 0x71 > /sys/bus/i2c/devices/i2c-4/$1"
"delete_device") i2c_mux_delete 0x71 4
;;
*) echo "z9100_platform: switch_board_mux : invalid command !"
;;
@ -78,12 +78,16 @@ switch_board_cpld() {
switch_board_qsfp_mux() {
case $1 in
"new_device")
# The mux for the QSFPs spawn {18..25}, {26..33}, {34..41} and {42..49}
# starting at chennel 18 and 8 channels per mux.
channel_first=18
for ((i=9;i>=6;i--));
do
# 0x71 mux on the IOM 1
mux_index=$(expr $i - 5)
echo "Attaching PCA9548 $mux_index"
i2c_config "echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-$i/$1"
i2c_mux_create pca9548 0x71 $i $channel_first
channel_first=$(expr $channel_first + 8)
done
;;
"delete_device")
@ -92,7 +96,7 @@ switch_board_qsfp_mux() {
# 0x71 mux on the IOM 1
mux_index=$(expr $i - 5)
echo "Detaching PCA9548 $mux_index"
i2c_config "echo 0x71 > /sys/bus/i2c/devices/i2c-$devnum/i2c-$i/$1"
i2c_mux_delete 0x71 $i
done
;;
*) echo "z9100_platform: switch_board_qsfp_mux: invalid command !"
@ -156,6 +160,17 @@ xcvr_presence_interrupts() {
esac
}
# Reset the mux tree
reset_muxes() {
# Reset the IOM muxes and the switch card mux
io_rd_wr.py --set --val 0xe0 --offset 0x110
io_rd_wr.py --set --val 0xff --offset 0x110
# Reset the CPU Card PCA9547
io_rd_wr.py --set --val 0xfd --offset 0x20b
io_rd_wr.py --set --val 0xff --offset 0x20b
}
init_devnum
if [[ "$1" == "init" ]]; then