Skip to content

Commit ee9640e

Browse files
authored
Merge pull request sonic-net#194 from pphuchar/201911-q2bd-add-sfp-event
[device/platform] Implement xcvr insert/remove event on questone2bd
2 parents 61dce56 + 2983a23 commit ee9640e

File tree

2 files changed

+228
-5
lines changed
  • device/celestica/x86_64-cel_questone2bd-r0/sonic_platform
  • platform/broadcom/sonic-platform-modules-cel/questone2bd/modules

2 files changed

+228
-5
lines changed

device/celestica/x86_64-cel_questone2bd-r0/sonic_platform/chassis.py

+137-3
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@
99
#############################################################################
1010

1111
try:
12-
import sys
13-
import re
12+
import json
1413
import os
14+
import re
15+
import sys
1516
import subprocess
16-
import json
17+
import time
1718
from sonic_platform_base.chassis_base import ChassisBase
1819
from helper import APIHelper
1920
except ImportError as e:
@@ -25,13 +26,24 @@
2526
NUM_THERMAL = 11
2627
NUM_SFP = 56
2728
NUM_COMPONENT = 7
29+
30+
SFP_PORT_START = 1
31+
SFP_PORT_END = 48
32+
QSFP_PORT_START = 49
33+
QSFP_PORT_END = 56
34+
2835
REBOOT_CAUSE_REG = "0xA106"
2936
TLV_EEPROM_I2C_BUS = 0
3037
TLV_EEPROM_I2C_ADDR = 56
3138

3239
BASE_CPLD_PLATFORM = "questone2bd.cpldb"
3340
BASE_GETREG_PATH = "/sys/devices/platform/{}/getreg".format(BASE_CPLD_PLATFORM)
3441

42+
SWITCH_BRD_PLATFORM = "questone2bd.switchboard"
43+
PORT_INFO_PATH = "/sys/devices/platform/{}/SFF".format(SWITCH_BRD_PLATFORM)
44+
PATH_INT_SYSFS = "{0}/{port_name}/{type_prefix}_isr_flags"
45+
PATH_INTMASK_SYSFS = "{0}/{port_name}/{type_prefix}_isr_mask"
46+
PATH_PRS_SYSFS = "{0}/{port_name}/{prs_file_name}"
3547

3648
class Chassis(ChassisBase):
3749
"""Platform-specific Chassis class"""
@@ -40,12 +52,14 @@ def __init__(self):
4052
ChassisBase.__init__(self)
4153
self._api_helper = APIHelper()
4254
self.sfp_module_initialized = False
55+
self.POLL_INTERVAL = 1
4356

4457
if not self._api_helper.is_host():
4558
self.__initialize_fan()
4659
self.__initialize_psu()
4760
self.__initialize_eeprom()
4861
self.__initialize_thermals()
62+
self.__initialize_interrupts()
4963
else:
5064
self.__initialize_components()
5165

@@ -85,6 +99,46 @@ def __initialize_components(self):
8599
component = Component(index)
86100
self._component_list.append(component)
87101

102+
def __initialize_interrupts(self):
103+
# Initial Interrupt MASK for QSFP, SFP
104+
sfp_info_obj = {}
105+
106+
present_en = 0x10
107+
Rxlos_IntL_en = 0x01
108+
event_mask = present_en
109+
110+
for index in range(NUM_SFP):
111+
port_num = index + 1
112+
if port_num in range(SFP_PORT_START, SFP_PORT_END+1):
113+
port_name = "SFP{}".format(str(port_num - SFP_PORT_START + 1))
114+
port_type = "sfp"
115+
sysfs_prs_file = "{}_modabs".format(port_type)
116+
elif port_num in range(QSFP_PORT_START, QSFP_PORT_END+1):
117+
port_name = "QSFP{}".format(str(port_num - QSFP_PORT_START + 1))
118+
port_type = "qsfp"
119+
sysfs_prs_file = "{}_modprs".format(port_type)
120+
121+
sfp_info_obj[index] = {}
122+
sfp_info_obj[index]['intmask_sysfs'] = PATH_INTMASK_SYSFS.format(
123+
PORT_INFO_PATH,
124+
port_name = port_name,
125+
type_prefix = port_type)
126+
127+
sfp_info_obj[index]['int_sysfs'] = PATH_INT_SYSFS.format(
128+
PORT_INFO_PATH,
129+
port_name = port_name,
130+
type_prefix = port_type)
131+
132+
sfp_info_obj[index]['prs_sysfs'] = PATH_PRS_SYSFS.format(
133+
PORT_INFO_PATH,
134+
port_name = port_name,
135+
prs_file_name = sysfs_prs_file)
136+
137+
self._api_helper.write_file(
138+
sfp_info_obj[index]["intmask_sysfs"], hex(event_mask))
139+
140+
self.sfp_info_obj = sfp_info_obj
141+
88142
def get_base_mac(self):
89143
"""
90144
Retrieves the base MAC address for the chassis
@@ -260,3 +314,83 @@ def get_status(self):
260314
A boolean value, True if device is operating properly, False if not
261315
"""
262316
return True
317+
318+
##############################################################
319+
###################### Event methods #########################
320+
##############################################################
321+
322+
def __is_port_device_present(self, port_idx):
323+
prs_path = self.sfp_info_obj[port_idx]["prs_sysfs"]
324+
is_present = 1 - int(self._api_helper.read_txt_file(prs_path))
325+
return is_present
326+
327+
def __update_port_event_object(self, interrup_devices):
328+
port_dict = {}
329+
event_obj = {'sfp':port_dict}
330+
for port_idx in interrup_devices:
331+
device_id = str(port_idx + 1)
332+
port_dict[device_id] = str(self.__is_port_device_present(port_idx))
333+
334+
if len(port_dict):
335+
event_obj['sfp'] = port_dict
336+
337+
return event_obj
338+
339+
def __check_all_port_interrupt_event(self):
340+
interrupt_devices = {}
341+
for i in range(NUM_SFP):
342+
int_sysfs = self.sfp_info_obj[i]["int_sysfs"]
343+
interrupt_flags = self._api_helper.read_txt_file(int_sysfs)
344+
if interrupt_flags != '0x00':
345+
interrupt_devices[i] = 1
346+
return interrupt_devices
347+
348+
def get_change_event(self, timeout=0):
349+
"""
350+
Returns a nested dictionary containing all devices which have
351+
experienced a change at chassis level
352+
Args:
353+
timeout: Timeout in milliseconds (optional). If timeout == 0,
354+
this method will block until a change is detected.
355+
Returns:
356+
(bool, dict):
357+
- True if call successful, False if not;
358+
- A nested dictionary where key is a device type,
359+
value is a dictionary with key:value pairs in the
360+
format of {'device_id':'device_event'},
361+
where device_id is the device ID for this device and
362+
device_event,
363+
status='1' represents device inserted,
364+
status='0' represents device removed.
365+
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
366+
indicates that fan 0 has been removed, fan 2
367+
has been inserted and sfp 11 has been removed.
368+
"""
369+
if timeout == 0:
370+
timer = self.POLL_INTERVAL
371+
while True:
372+
interrupt_devices = self.__check_all_port_interrupt_event()
373+
if len(interrupt_devices):
374+
break
375+
else:
376+
time.sleep(timer)
377+
events_dict = self.__update_port_event_object(interrupt_devices)
378+
return (True, events_dict)
379+
else:
380+
timeout = timeout / float(1000)
381+
timer = min(timeout, self.POLL_INTERVAL)
382+
383+
while True:
384+
start_time = time.time()
385+
interrupt_devices = self.__check_all_port_interrupt_event()
386+
if len(interrupt_devices):
387+
break
388+
389+
if timeout <= 0:
390+
break
391+
else:
392+
time.sleep(timer)
393+
elasped_time = time.time() - start_time
394+
timeout = round(timeout - elasped_time, 3)
395+
events_dict = self.__update_port_event_object(interrupt_devices)
396+
return (True, events_dict)

platform/broadcom/sonic-platform-modules-cel/questone2bd/modules/switchboard_fpga.c

+91-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
*/
2626

2727
#ifndef TEST_MODE
28-
#define MOD_VERSION "0.5.4"
28+
#define MOD_VERSION "0.5.5"
2929
#else
3030
#define MOD_VERSION "TEST"
3131
#endif
@@ -867,6 +867,20 @@ static ssize_t qsfp_modprs_show(struct device *dev, struct device_attribute *att
867867
}
868868
DEVICE_ATTR_RO(qsfp_modprs);
869869

870+
static ssize_t qsfp_isr_flags_show(struct device *dev, struct device_attribute *attr, char *buf)
871+
{
872+
u8 data;
873+
int err;
874+
struct sff_device_data *dev_data = dev_get_drvdata(dev);
875+
unsigned int portid = dev_data->portid;
876+
err = i2c_xcvr_access(I2C_XCVR_INRT,portid,&data,I2C_SMBUS_READ);
877+
if(err < 0){
878+
return err;
879+
}
880+
return sprintf(buf, "0x%2.2x\n", data);
881+
}
882+
DEVICE_ATTR_RO(qsfp_isr_flags);
883+
870884
static ssize_t sfp_txfault_show(struct device *dev, struct device_attribute *attr, char *buf)
871885
{
872886
u8 data;
@@ -909,6 +923,20 @@ static ssize_t sfp_modabs_show(struct device *dev, struct device_attribute *attr
909923
}
910924
DEVICE_ATTR_RO(sfp_modabs);
911925

926+
static ssize_t sfp_isr_flags_show(struct device *dev, struct device_attribute *attr, char *buf)
927+
{
928+
u8 data;
929+
int err;
930+
struct sff_device_data *dev_data = dev_get_drvdata(dev);
931+
unsigned int portid = dev_data->portid;
932+
err = i2c_xcvr_access(I2C_XCVR_INRT,portid,&data,I2C_SMBUS_READ);
933+
if(err < 0){
934+
return err;
935+
}
936+
return sprintf(buf, "0x%2.2x\n", data);
937+
}
938+
DEVICE_ATTR_RO(sfp_isr_flags);
939+
912940
static ssize_t qsfp_modsel_show(struct device *dev, struct device_attribute *attr, char *buf)
913941
{
914942
u8 data;
@@ -980,6 +1008,35 @@ static ssize_t qsfp_reset_store(struct device *dev, struct device_attribute *att
9801008
}
9811009
DEVICE_ATTR_RW(qsfp_reset);
9821010

1011+
static ssize_t qsfp_isr_mask_show(struct device *dev, struct device_attribute *attr, char *buf)
1012+
{
1013+
u8 data;
1014+
int err;
1015+
struct sff_device_data *dev_data = dev_get_drvdata(dev);
1016+
unsigned int portid = dev_data->portid;
1017+
err = i2c_xcvr_access(I2C_XCVR_MASK,portid,&data,I2C_SMBUS_READ);
1018+
if(err < 0){
1019+
return err;
1020+
}
1021+
return sprintf(buf, "0x%2.2x\n", data);
1022+
}
1023+
1024+
static ssize_t qsfp_isr_mask_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
1025+
{
1026+
ssize_t status;
1027+
u8 data;
1028+
struct sff_device_data *dev_data = dev_get_drvdata(dev);
1029+
unsigned int portid = dev_data->portid;
1030+
1031+
status = kstrtou8(buf, 0, &data);
1032+
if (status == 0) {
1033+
i2c_xcvr_access(I2C_XCVR_MASK,portid,&data,I2C_SMBUS_WRITE);
1034+
status = size;
1035+
}
1036+
return status;
1037+
}
1038+
DEVICE_ATTR_RW(qsfp_isr_mask);
1039+
9831040
static ssize_t sfp_txdisable_show(struct device *dev, struct device_attribute *attr, char *buf)
9841041
{
9851042
u8 data;
@@ -1017,15 +1074,48 @@ static ssize_t sfp_txdisable_store(struct device *dev, struct device_attribute *
10171074
}
10181075
DEVICE_ATTR_RW(sfp_txdisable);
10191076

1077+
static ssize_t sfp_isr_mask_show(struct device *dev, struct device_attribute *attr, char *buf)
1078+
{
1079+
u8 data;
1080+
int err;
1081+
struct sff_device_data *dev_data = dev_get_drvdata(dev);
1082+
unsigned int portid = dev_data->portid;
1083+
err = i2c_xcvr_access(I2C_XCVR_MASK,portid,&data,I2C_SMBUS_READ);
1084+
if(err < 0){
1085+
return err;
1086+
}
1087+
return sprintf(buf, "0x%2.2x\n", data);
1088+
}
1089+
1090+
static ssize_t sfp_isr_mask_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
1091+
{
1092+
ssize_t status;
1093+
u8 data;
1094+
struct sff_device_data *dev_data = dev_get_drvdata(dev);
1095+
unsigned int portid = dev_data->portid;
1096+
1097+
status = kstrtou8(buf, 0, &data);
1098+
if (status == 0) {
1099+
i2c_xcvr_access(I2C_XCVR_MASK,portid,&data,I2C_SMBUS_WRITE);
1100+
status = size;
1101+
}
1102+
return status;
1103+
}
1104+
DEVICE_ATTR_RW(sfp_isr_mask);
1105+
10201106
static struct attribute *sff_attrs[] = {
10211107
&dev_attr_qsfp_modirq.attr,
10221108
&dev_attr_qsfp_modprs.attr,
10231109
&dev_attr_qsfp_modsel.attr,
10241110
&dev_attr_qsfp_reset.attr,
1111+
&dev_attr_qsfp_isr_flags.attr,
1112+
&dev_attr_qsfp_isr_mask.attr,
10251113
&dev_attr_sfp_txfault.attr,
10261114
&dev_attr_sfp_rxlos.attr,
10271115
&dev_attr_sfp_modabs.attr,
10281116
&dev_attr_sfp_txdisable.attr,
1117+
&dev_attr_sfp_isr_flags.attr,
1118+
&dev_attr_sfp_isr_mask.attr,
10291119
NULL,
10301120
};
10311121

@@ -2413,7 +2503,6 @@ static long fpgafw_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned
24132503
switch (status_reg) {
24142504
case 0x0000 : status_reg = 0x8000;
24152505
break;
2416-
24172506
case 0x8080 : status_reg = 0x80C0;
24182507
break;
24192508
case 0x80C0 : status_reg = 0x80F0;

0 commit comments

Comments
 (0)