[accton/as9716-32d] add support get_transceiver_change_event (#4105)

Co-authored-by: Jostar Yang <jostar_yang@accton.com.tw>
This commit is contained in:
jostar-yang 2020-04-23 13:54:48 +08:00 committed by GitHub
parent c52b8c4e75
commit 9129378097
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 164 additions and 7 deletions

View File

@ -5,6 +5,8 @@
try:
import time
import os
import sys, getopt
from sonic_sfp.sfputilbase import SfpUtilBase
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))
@ -141,10 +143,91 @@ class SfpUtil(SfpUtilBase):
return True
def get_transceiver_change_event(self):
"""
TODO: This function need to be implemented
when decide to support monitoring SFP(Xcvrd)
on this platform.
"""
raise NotImplementedError
def get_cpld_interrupt(self):
port_dict={}
for i in range(0,4):
if i==0 or i==1:
cpld_i2c_path = self.BASE_CPLD1_PATH + "cpld_intr_" + str(i+1)
else:
cpld_i2c_path = self.BASE_CPLD2_PATH + "cpld_intr_" +str(i+1)
start_i=(i*8)
end_i=(i*8+8)
try:
val_file = open(cpld_i2c_path)
except IOError as e:
print "Error: unable to open file: %s" % str(e)
for k in range (start_i, end_i):
port_dict[k]=0
return port_dict
status = val_file.readline().rstrip()
val_file.close()
status=status.strip()
status= int(status, 16)
interrupt_status = ~(status & 0xff)
if interrupt_status:
port_shift=0
for k in range (start_i, end_i):
if interrupt_status & (0x1<<port_shift):
port_dict[k]=1
else:
port_dict[k]=0
port_shift=port_shift+1
return port_dict
def get_transceiver_change_event(self, timeout=0):
start_time = time.time()
port_dict = {}
ori_present ={}
forever = False
if timeout == 0:
forever = True
elif timeout > 0:
timeout = timeout / float(1000) # Convert to secs
else:
print "get_transceiver_change_event:Invalid timeout value", timeout
return False, {}
end_time = start_time + timeout
if start_time > end_time:
print 'get_transceiver_change_event:' \
'time wrap / invalid timeout value', timeout
return False, {} # Time wrap or possibly incorrect timeout
#for i in range(self.port_start, self.port_end+1):
# ori_present[i]=self.get_presence(i)
while timeout >= 0:
change_status=0
port_dict = self.get_cpld_interrupt()
present=0
for key, value in port_dict.iteritems():
if value==1:
present=self.get_presence(key)
change_status=1
if present:
port_dict[key]='1'
else:
port_dict[key]='0'
if change_status:
return True, port_dict
if forever:
time.sleep(1)
else:
timeout = end_time - time.time()
if timeout >= 1:
time.sleep(1) # We poll at 1 second granularity
else:
if timeout > 0:
time.sleep(timeout)
return True, {}
print "get_evt_change_event: Should not reach here."
return False, {}

View File

@ -72,6 +72,7 @@ MODULE_DEVICE_TABLE(i2c, as9716_32d_cpld_id);
#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index
#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index
#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index
#define CPLD_INTR_ATTR_ID(index) CPLD_INTR_##index
enum as9716_32d_cpld_sysfs_attributes {
CPLD_VERSION,
@ -149,10 +150,17 @@ enum as9716_32d_cpld_sysfs_attributes {
TRANSCEIVER_RESET_ATTR_ID(30),
TRANSCEIVER_RESET_ATTR_ID(31),
TRANSCEIVER_RESET_ATTR_ID(32),
CPLD_INTR_ATTR_ID(1),
CPLD_INTR_ATTR_ID(2),
CPLD_INTR_ATTR_ID(3),
CPLD_INTR_ATTR_ID(4),
};
/* sysfs attributes for hwmon
*/
static ssize_t show_interrupt(struct device *dev, struct device_attribute *da,
char *buf);
static ssize_t show_status(struct device *dev, struct device_attribute *da,
char *buf);
static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da,
@ -188,6 +196,11 @@ static int as9716_32d_cpld_write_internal(struct i2c_client *client, u8 reg, u8
static SENSOR_DEVICE_ATTR(module_reset_##index, S_IWUSR | S_IRUGO, get_mode_reset, set_mode_reset, MODULE_RESET_##index)
#define DECLARE_TRANSCEIVER_RESET_ATTR(index) &sensor_dev_attr_module_reset_##index.dev_attr.attr
/*cpld interrupt*/
#define DECLARE_CPLD_DEVICE_INTR_ATTR(index) \
static SENSOR_DEVICE_ATTR(cpld_intr_##index, S_IRUGO, show_interrupt, NULL, CPLD_INTR_##index)
#define DECLARE_CPLD_INTR_ATTR(index) &sensor_dev_attr_cpld_intr_##index.dev_attr.attr
static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION);
@ -261,6 +274,10 @@ DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(29);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(30);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(31);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_RESET_ATTR(32);
DECLARE_CPLD_DEVICE_INTR_ATTR(1);
DECLARE_CPLD_DEVICE_INTR_ATTR(2);
DECLARE_CPLD_DEVICE_INTR_ATTR(3);
DECLARE_CPLD_DEVICE_INTR_ATTR(4);
@ -309,6 +326,8 @@ static struct attribute *as9716_32d_cpld1_attributes[] = {
DECLARE_TRANSCEIVER_RESET_ATTR(14),
DECLARE_TRANSCEIVER_RESET_ATTR(15),
DECLARE_TRANSCEIVER_RESET_ATTR(16),
DECLARE_CPLD_INTR_ATTR(1),
DECLARE_CPLD_INTR_ATTR(2),
NULL
};
@ -355,6 +374,8 @@ static struct attribute *as9716_32d_cpld2_attributes[] = {
DECLARE_TRANSCEIVER_RESET_ATTR(30),
DECLARE_TRANSCEIVER_RESET_ATTR(31),
DECLARE_TRANSCEIVER_RESET_ATTR(32),
DECLARE_CPLD_INTR_ATTR(3),
DECLARE_CPLD_INTR_ATTR(4),
NULL
};
@ -363,6 +384,47 @@ static const struct attribute_group as9716_32d_cpld2_group = {
};
static ssize_t show_interrupt(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct i2c_client *client = to_i2c_client(dev);
struct as9716_32d_cpld_data *data = i2c_get_clientdata(client);
int status = 0;
u8 reg = 0;
switch (attr->index)
{
case CPLD_INTR_1:
reg = 0x10;
break;
case CPLD_INTR_3:
reg = 0x10;
break;
case CPLD_INTR_2:
reg = 0x11;
break;
case CPLD_INTR_4:
reg = 0x11;
break;
default:
return -ENODEV;
}
mutex_lock(&data->update_lock);
status = as9716_32d_cpld_read_internal(client, reg);
if (unlikely(status < 0)) {
goto exit;
}
mutex_unlock(&data->update_lock);
return sprintf(buf, "0x%x\n", status);
exit:
mutex_unlock(&data->update_lock);
return status;
}
static ssize_t show_status(struct device *dev, struct device_attribute *da,
char *buf)
{
@ -723,9 +785,21 @@ static int as9716_32d_cpld_probe(struct i2c_client *client,
break;
case as9716_32d_cpld1:
group = &as9716_32d_cpld1_group;
/*Set interrupt mask to 0, and then can get intr from 0x8*/
status=as9716_32d_cpld_write_internal(client, 0x9, 0x0);
if (status < 0)
{
dev_dbg(&client->dev, "cpld1 reg 0x9 err %d\n", status);
}
break;
case as9716_32d_cpld2:
group = &as9716_32d_cpld2_group;
/*Set interrupt mask to 0, and then can get intr from 0x8*/
status=as9716_32d_cpld_write_internal(client, 0x9, 0x0);
if (status < 0)
{
dev_dbg(&client->dev, "cpld2 reg 0x65 err %d\n", status);
}
break;
case as9716_32d_cpld_cpu:
/* Disable CPLD reset to avoid DUT will be reset.