[platform-device/haliburton] Support xcvr and sensor monitoring (#1998)

* [platform/haliburton] Fix kernel panic when remove smc module.

* [platform/haliburton] Chanage sysfs to support module interrupt

* [device/haliburton] Update sfputil to use new sysfs.

* [device/haliburton] sfputil to support xcvrd monitoring.
This commit is contained in:
Pradchaya P 2018-08-29 22:50:29 +07:00 committed by lguohan
parent 929ef530ce
commit e8db1846ad
3 changed files with 423 additions and 145 deletions

View File

@ -14,58 +14,58 @@ class SfpUtil(SfpUtilBase):
PORT_START = 1 PORT_START = 1
PORT_END = 52 PORT_END = 52
port_to_i2c_mapping = { port_to_i2c_mapping = {
1 : None, 1: None,
2 : None, 2: None,
3 : None, 3: None,
4 : None, 4: None,
5 : None, 5: None,
6 : None, 6: None,
7 : None, 7: None,
8 : None, 8: None,
9 : None, 9: None,
10 : None, 10: None,
11 : None, 11: None,
12 : None, 12: None,
13 : None, 13: None,
14 : None, 14: None,
15 : None, 15: None,
16 : None, 16: None,
17 : None, 17: None,
18 : None, 18: None,
19 : None, 19: None,
20 : None, 20: None,
21 : None, 21: None,
22 : None, 22: None,
23 : None, 23: None,
24 : None, 24: None,
25 : None, 25: None,
26 : None, 26: None,
27 : None, 27: None,
28 : None, 28: None,
29 : None, 29: None,
30 : None, 30: None,
31 : None, 31: None,
32 : None, 32: None,
33 : None, 33: None,
34 : None, 34: None,
35 : None, 35: None,
36 : None, 36: None,
37 : None, 37: None,
38 : None, 38: None,
39 : None, 39: None,
40 : None, 40: None,
41 : None, 41: None,
42 : None, 42: None,
43 : None, 43: None,
44 : None, 44: None,
45 : None, 45: None,
46 : None, 46: None,
47 : None, 47: None,
48 : None, 48: None,
49 : 15, 49: 15,
50 : 14, 50: 14,
51 : 17, 51: 17,
52 : 16 52: 16
} }
_port_to_eeprom_mapping = {} _port_to_eeprom_mapping = {}
_sfp_port = range(49, PORT_END + 1) _sfp_port = range(49, PORT_END + 1)
@ -94,30 +94,42 @@ class SfpUtil(SfpUtilBase):
self.port_to_eeprom_mapping[x] = port_eeprom_path self.port_to_eeprom_mapping[x] = port_eeprom_path
SfpUtilBase.__init__(self) SfpUtilBase.__init__(self)
def get_presence(self, port_num): def get_presence(self, port_num):
sfp_modabs_path = '/sys/devices/platform/e1031.smc/SFP/SFP{0}/sfp_modabs' sfp_modabs_path = '/sys/devices/platform/e1031.smc/SFP/sfp_modabs'
if port_num not in self._sfp_port: if port_num not in self._sfp_port:
return False return False
status = 1 status = 1
try: try:
with open(sfp_modabs_path.format(port_num - 48), 'r') as port_status: with open(sfp_modabs_path, 'r') as port_status:
status = int(port_status.read()) status = int(port_status.read(), 16)
except IOError: status = (status >> (port_num - 49)) & 1
except IOError:
return False return False
return status == 0 return status == 0
def get_low_power_mode(self, port_num): def get_low_power_mode(self, port_num):
raise NotImplementedError raise NotImplementedError
def set_low_power_mode(self, port_num, lpmode): def set_low_power_mode(self, port_num, lpmode):
raise NotImplementedError raise NotImplementedError
def reset(self, port_num): def reset(self, port_num):
raise NotImplementedError
def get_transceiver_change_event(self):
raise NotImplementedError raise NotImplementedError
def get_transceiver_change_event(self, timeout=0):
modabs_interrupt_path = '/sys/devices/platform/e1031.smc/SFP/modabs_int'
ports_evt = {}
try:
with open(modabs_interrupt_path, 'r') as port_changes:
changes = int(port_changes.read(), 16)
for port_num in self._sfp_port:
change = (changes >> ( port_num - 49)) & 1
if change == 1:
ports_evt[str(port_num)] = str(self.get_presence(port_num))
except IOError:
return False, {}
return True, ports_evt

View File

@ -60,6 +60,10 @@ start)
echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-16/new_device echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-16/new_device
echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-17/new_device echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-17/new_device
# Enable SFP module presence interrupt
echo "both" > /sys/devices/platform/e1031.smc/SFP/modabs_trig
echo 0 > /sys/devices/platform/e1031.smc/SFP/modabs_mask
echo "done." echo "done."
;; ;;

View File

@ -116,6 +116,22 @@ enum MASTER_LED {
#define FAN_2 1 #define FAN_2 1
#define FAN_1 0 #define FAN_1 0
/* SFP PORT INT TRIGGER MODE
* [7:6] RESERVED
* [5:4] RXLOS
* [3:2] MODABS
* [1:0] TXFAULT
* 00: falling edge,
* 01: rising edge,
* 10: Both edges,
* 11: low level detect
*/
#define TRIG_MODE 0x0240
#define TXFAULT_TRIG 0
#define MODABS_TRIG 2
#define RXLOS_TRIG 4
/* SFP PORT STATUS /* SFP PORT STATUS
* [7:4] RESERVED * [7:4] RESERVED
* [3:0] TX_FAULT / MODABS / RXLOS * [3:0] TX_FAULT / MODABS / RXLOS
@ -124,6 +140,24 @@ enum MASTER_LED {
#define SFP_MODABS 0x0243 #define SFP_MODABS 0x0243
#define SFP_RXLOS 0x0244 #define SFP_RXLOS 0x0244
/* SFP PORT INTERRUPT
* [7:4] RESERVED
* [3:0] TX_FAULT / MODABS / RXLOS
* 1: int, 0: no int
*/
#define TXFAULT_INT 0x0246
#define MODABS_INT 0x0247
#define RXLOS_INT 0x0248
/* INTERRUPT MASK REGISTER
* [7:4] RESERVED
* [3:0] TX_FAULT / MODABS / RXLOS
* 1: mask, 0: not mask
*/
#define TXFAULT_MSK 0x024A
#define MODABS_MSK 0x024B
#define RXLOS_MSK 0x024C
/* SFP PORT CTRL /* SFP PORT CTRL
* [7:4] RATE SEL (RS0/RS1) * [7:4] RATE SEL (RS0/RS1)
* [3:0] TX_DIS * [3:0] TX_DIS
@ -250,7 +284,7 @@ static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr
} }
/** /**
* Show status led * @brief Show status led
* @param dev kernel device * @param dev kernel device
* @param devattr kernel device attribute * @param devattr kernel device attribute
* @param buf buffer for get value * @param buf buffer for get value
@ -269,7 +303,7 @@ static ssize_t status_led_show(struct device *dev, struct device_attribute *deva
} }
/** /**
* Set the status led * @brief Set the status led
* @param dev kernel device * @param dev kernel device
* @param devattr kernel device attribute * @param devattr kernel device attribute
* @param buf buffer of set value - off/on/blink * @param buf buffer of set value - off/on/blink
@ -301,7 +335,7 @@ static ssize_t status_led_store(struct device *dev, struct device_attribute *dev
} }
/** /**
* Show master led * @brief Show master led
* @param dev kernel device * @param dev kernel device
* @param devattr kernel device attribute * @param devattr kernel device attribute
* @param buf buffer for get value * @param buf buffer for get value
@ -320,7 +354,7 @@ static ssize_t master_led_show(struct device *dev, struct device_attribute *deva
} }
/** /**
* Set the master led * @brief Set the master led
* @param dev kernel device * @param dev kernel device
* @param devattr kernel device attribute * @param devattr kernel device attribute
* @param buf buffer of set value - off/green/amber * @param buf buffer of set value - off/green/amber
@ -401,8 +435,6 @@ static ssize_t fan_dir_show(struct device *dev, struct device_attribute *devattr
struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr); struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr);
int index = sa->index; int index = sa->index;
unsigned char data = 0; unsigned char data = 0;
// Use index to determind the status bit
mutex_lock(&cpld_data->cpld_lock); mutex_lock(&cpld_data->cpld_lock);
data = inb(DEV_STAT); data = inb(DEV_STAT);
mutex_unlock(&cpld_data->cpld_lock); mutex_unlock(&cpld_data->cpld_lock);
@ -413,48 +445,41 @@ static ssize_t fan_dir_show(struct device *dev, struct device_attribute *devattr
static ssize_t sfp_txfault_show(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t sfp_txfault_show(struct device *dev, struct device_attribute *attr, char *buf)
{ {
unsigned char data; unsigned char data;
struct sfp_device_data *dev_data = dev_get_drvdata(dev);
unsigned int port_bit = dev_data->portid - 1;
mutex_lock(&cpld_data->cpld_lock); mutex_lock(&cpld_data->cpld_lock);
data = inb(SFP_TXFAULT); data = inb(SFP_TXFAULT);
data = data & 0x0F;
mutex_unlock(&cpld_data->cpld_lock); mutex_unlock(&cpld_data->cpld_lock);
return sprintf(buf, "%d\n", (data >> port_bit ) & 1U); return sprintf(buf, "0x%x\n", data);
} }
static ssize_t sfp_modabs_show(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t sfp_modabs_show(struct device *dev, struct device_attribute *attr, char *buf)
{ {
unsigned char data; unsigned char data;
struct sfp_device_data *dev_data = dev_get_drvdata(dev);
unsigned int port_bit = dev_data->portid - 1;
mutex_lock(&cpld_data->cpld_lock); mutex_lock(&cpld_data->cpld_lock);
data = inb(SFP_MODABS); data = inb(SFP_MODABS);
data = data & 0x0F;
mutex_unlock(&cpld_data->cpld_lock); mutex_unlock(&cpld_data->cpld_lock);
return sprintf(buf, "%d\n", (data >> port_bit ) & 1U); return sprintf(buf, "0x%x\n", data);
} }
static ssize_t sfp_rxlos_show(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t sfp_rxlos_show(struct device *dev, struct device_attribute *attr, char *buf)
{ {
unsigned char data; unsigned char data;
struct sfp_device_data *dev_data = dev_get_drvdata(dev);
unsigned int port_bit = dev_data->portid - 1;
mutex_lock(&cpld_data->cpld_lock); mutex_lock(&cpld_data->cpld_lock);
data = inb(SFP_RXLOS); data = inb(SFP_RXLOS);
data = data & 0x0F;
mutex_unlock(&cpld_data->cpld_lock); mutex_unlock(&cpld_data->cpld_lock);
return sprintf(buf, "%d\n", (data >> port_bit ) & 1U); return sprintf(buf, "0x%x\n", data);
} }
static ssize_t sfp_txdis_show(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t sfp_txdis_show(struct device *dev, struct device_attribute *attr, char *buf)
{ {
unsigned char data; unsigned char data;
struct sfp_device_data *dev_data = dev_get_drvdata(dev);
unsigned int port_bit = dev_data->portid - 1;
mutex_lock(&cpld_data->cpld_lock); mutex_lock(&cpld_data->cpld_lock);
data = inb(SFP_TXCTRL); data = inb(SFP_TXCTRL);
data = data & 0x0F;
mutex_unlock(&cpld_data->cpld_lock); mutex_unlock(&cpld_data->cpld_lock);
return sprintf(buf, "%d\n", (data >> port_bit ) & 1U); return sprintf(buf, "0x%x\n", data);
} }
static ssize_t sfp_txdis_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) static ssize_t sfp_txdis_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
@ -462,18 +487,13 @@ static ssize_t sfp_txdis_store(struct device *dev, struct device_attribute *attr
long value; long value;
ssize_t status; ssize_t status;
unsigned char data; unsigned char data;
struct sfp_device_data *dev_data = dev_get_drvdata(dev);
unsigned int port_bit = dev_data->portid - 1;
mutex_lock(&cpld_data->cpld_lock); mutex_lock(&cpld_data->cpld_lock);
status = kstrtol(buf, 0, &value); status = kstrtol(buf, 0, &value);
if (status == 0) { if (status == 0) {
// check if value is 0, clear
data = inb(SFP_TXCTRL); data = inb(SFP_TXCTRL);
if (!value) data = data & ~(0x0F);
data = data & ~( 1U << port_bit); data = data | (value & 0x0F);
else
data = data | ( 1U << port_bit);
outb(data, SFP_TXCTRL); outb(data, SFP_TXCTRL);
status = size; status = size;
} }
@ -484,15 +504,11 @@ static ssize_t sfp_txdis_store(struct device *dev, struct device_attribute *attr
static ssize_t sfp_rs_show(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t sfp_rs_show(struct device *dev, struct device_attribute *attr, char *buf)
{ {
unsigned char data; unsigned char data;
struct sfp_device_data *dev_data = dev_get_drvdata(dev);
unsigned int port_bit = dev_data->portid - 1;
// High nibble
port_bit = port_bit + 4;
mutex_lock(&cpld_data->cpld_lock); mutex_lock(&cpld_data->cpld_lock);
data = inb(SFP_TXCTRL); data = inb(SFP_TXCTRL) >> 4;
data = data & 0x0F;
mutex_unlock(&cpld_data->cpld_lock); mutex_unlock(&cpld_data->cpld_lock);
return sprintf(buf, "%d\n", (data >> port_bit ) & 1U); return sprintf(buf, "0x%x\n", data);
} }
static ssize_t sfp_rs_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) static ssize_t sfp_rs_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
@ -500,20 +516,14 @@ static ssize_t sfp_rs_store(struct device *dev, struct device_attribute *attr, c
long value; long value;
ssize_t status; ssize_t status;
unsigned char data; unsigned char data;
struct sfp_device_data *dev_data = dev_get_drvdata(dev);
unsigned int port_bit = dev_data->portid - 1;
// High nibble
port_bit = port_bit + 4;
mutex_lock(&cpld_data->cpld_lock); mutex_lock(&cpld_data->cpld_lock);
status = kstrtol(buf, 0, &value); status = kstrtol(buf, 0, &value);
value = (value & 0x0F) << 4;
if (status == 0) { if (status == 0) {
// check if value is 0, clear
data = inb(SFP_TXCTRL); data = inb(SFP_TXCTRL);
if (!value) data = data & ~(0xF0);
data = data & ~( 1U << port_bit); data = data | value;
else
data = data | ( 1U << port_bit);
outb(data, SFP_TXCTRL); outb(data, SFP_TXCTRL);
status = size; status = size;
} }
@ -521,6 +531,273 @@ static ssize_t sfp_rs_store(struct device *dev, struct device_attribute *attr, c
return status; return status;
} }
/**
* @brief Show the avaliable interrupt trigger mode.
* "none" means the interrupt is masked.
*
* @return Current trigger mode.
*/
static ssize_t txfault_trig_show(struct device *dev, struct device_attribute *attr, char *buf)
{
unsigned char mode;
char *mode_str[5] = {"falling", "rising", "both", "low"};
mutex_lock(&cpld_data->cpld_lock);
mode = inb(TRIG_MODE) >> TXFAULT_TRIG;
mode = mode & 0x3;
mutex_unlock(&cpld_data->cpld_lock);
return sprintf(buf, "%s\n", mode_str[mode]);
}
/**
* @brief Set the trigger mode of each interrupt type.
* Only one trigger mode allow in a type.
*
* @param buf The trigger mode of follwings
* "falling", "rising", "both"
*/
static ssize_t txfault_trig_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
ssize_t status;
unsigned char data, trig_mode;
if (sysfs_streq(buf, "falling")) {
trig_mode = 0;
} else if (sysfs_streq(buf, "rising")) {
trig_mode = 1;
} else if (sysfs_streq(buf, "both")) {
trig_mode = 2;
} else if (sysfs_streq(buf, "low")) {
trig_mode = 3;
} else {
status = -EINVAL;
return status;
}
mutex_lock(&cpld_data->cpld_lock);
data = inb(TRIG_MODE);
data = data & ~(0x03 << TXFAULT_TRIG);
data = data | trig_mode << TXFAULT_TRIG;
outb(data, TRIG_MODE);
mutex_unlock(&cpld_data->cpld_lock);
status = size;
return status;
}
/**
* @brief Show the avaliable interrupt trigger mode.
* "none" means the interrupt is masked.
*
* @return Current trigger mode.
*/
static ssize_t modabs_trig_show(struct device *dev, struct device_attribute *attr, char *buf)
{
unsigned char mode;
char *mode_str[5] = {"falling", "rising", "both", "low"};
mutex_lock(&cpld_data->cpld_lock);
mode = inb(TRIG_MODE) >> MODABS_TRIG;
mode = mode & 0x3;
mutex_unlock(&cpld_data->cpld_lock);
return sprintf(buf, "%s\n", mode_str[mode]);
}
/**
* @brief Set the trigger mode of each interrupt type.
* Only one trigger mode allow in a type.
*
* @param buf The trigger mode of follwings
* "falling", "rising", "both", "low"
*/
static ssize_t modabs_trig_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
ssize_t status;
unsigned char data, trig_mode;
if (sysfs_streq(buf, "falling")) {
trig_mode = 0;
} else if (sysfs_streq(buf, "rising")) {
trig_mode = 1;
} else if (sysfs_streq(buf, "both")) {
trig_mode = 2;
} else if (sysfs_streq(buf, "low")) {
trig_mode = 3;
} else {
status = -EINVAL;
return status;
}
mutex_lock(&cpld_data->cpld_lock);
data = inb(TRIG_MODE);
data = data & ~(0x03 << MODABS_TRIG);
data = data | trig_mode << MODABS_TRIG;
outb(data, TRIG_MODE);
mutex_unlock(&cpld_data->cpld_lock);
status = size;
return status;
}
/**
* @brief Show the avaliable interrupt trigger mode.
* "none" means the interrupt is masked.
*
* @return Current trigger mode.
*/
static ssize_t rxlos_trig_show(struct device *dev, struct device_attribute *attr, char *buf)
{
unsigned char mode;
char *mode_str[5] = {"falling", "rising", "both", "low"};
mutex_lock(&cpld_data->cpld_lock);
mode = inb(TRIG_MODE) >> RXLOS_TRIG;
mode = mode & 0x3;
mutex_unlock(&cpld_data->cpld_lock);
return sprintf(buf, "%s\n", mode_str[mode]);
}
/**
* @brief Set the trigger mode of each interrupt type.
* Only one trigger mode allow in a type.
*
* @param buf The trigger mode of follwings
* "falling", "rising", "both", "low"
*/
static ssize_t rxlos_trig_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
ssize_t status;
unsigned char data, trig_mode;
if (sysfs_streq(buf, "falling")) {
trig_mode = 0;
} else if (sysfs_streq(buf, "rising")) {
trig_mode = 1;
} else if (sysfs_streq(buf, "both")) {
trig_mode = 2;
} else if (sysfs_streq(buf, "low")) {
trig_mode = 3;
} else {
status = -EINVAL;
return status;
}
mutex_lock(&cpld_data->cpld_lock);
data = inb(TRIG_MODE);
data = data & ~(0x03 << RXLOS_TRIG);
data = data | trig_mode << RXLOS_TRIG;
outb(data, TRIG_MODE);
mutex_unlock(&cpld_data->cpld_lock);
status = size;
return status;
}
static ssize_t txfault_int_show(struct device *dev, struct device_attribute *attr, char *buf)
{
unsigned char data;
mutex_lock(&cpld_data->cpld_lock);
data = inb(TXFAULT_INT);
data = data & 0x0F;
mutex_unlock(&cpld_data->cpld_lock);
return sprintf(buf, "0x%x\n", data);
}
static ssize_t modabs_int_show(struct device *dev, struct device_attribute *attr, char *buf)
{
unsigned char data;
mutex_lock(&cpld_data->cpld_lock);
data = inb(MODABS_INT);
data = data & 0x0F;
mutex_unlock(&cpld_data->cpld_lock);
return sprintf(buf, "0x%x\n", data);
}
static ssize_t rxlos_int_show(struct device *dev, struct device_attribute *attr, char *buf)
{
unsigned char data;
mutex_lock(&cpld_data->cpld_lock);
data = inb(RXLOS_INT);
data = data & 0x0F;
mutex_unlock(&cpld_data->cpld_lock);
return sprintf(buf, "0x%x\n", data);
}
static ssize_t txfault_mask_show(struct device *dev, struct device_attribute *attr, char *buf)
{
unsigned char data;
mutex_lock(&cpld_data->cpld_lock);
data = inb(TXFAULT_MSK);
data = data & 0x0F;
mutex_unlock(&cpld_data->cpld_lock);
return sprintf(buf, "0x%x\n", data);
}
static ssize_t txfault_mask_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
long value;
ssize_t status;
status = kstrtol(buf, 0, &value);
value = value & 0x0F;
if (status == 0) {
mutex_lock(&cpld_data->cpld_lock);
outb(value, TXFAULT_MSK);
mutex_unlock(&cpld_data->cpld_lock);
status = size;
}
return status;
}
static ssize_t modabs_mask_show(struct device *dev, struct device_attribute *attr, char *buf)
{
unsigned char data;
mutex_lock(&cpld_data->cpld_lock);
data = inb(MODABS_MSK);
data = data & 0x0F;
mutex_unlock(&cpld_data->cpld_lock);
return sprintf(buf, "0x%x\n", data);
}
static ssize_t modabs_mask_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
long value;
ssize_t status;
status = kstrtol(buf, 0, &value);
value = value & 0x0F;
if (status == 0) {
mutex_lock(&cpld_data->cpld_lock);
outb(value, MODABS_MSK);
mutex_unlock(&cpld_data->cpld_lock);
status = size;
}
return status;
}
static ssize_t rxlos_mask_show(struct device *dev, struct device_attribute *attr, char *buf)
{
unsigned char data;
mutex_lock(&cpld_data->cpld_lock);
data = inb(RXLOS_MSK);
data = data & 0x0F;
mutex_unlock(&cpld_data->cpld_lock);
return sprintf(buf, "0x%x\n", data);
}
static ssize_t rxlos_mask_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
{
long value;
ssize_t status;
status = kstrtol(buf, 0, &value);
value = value & 0x0F;
if (status == 0) {
mutex_lock(&cpld_data->cpld_lock);
outb(value, RXLOS_MSK);
mutex_unlock(&cpld_data->cpld_lock);
status = size;
}
return status;
}
static ssize_t fan_led_show(struct device *dev, struct device_attribute *devattr, static ssize_t fan_led_show(struct device *dev, struct device_attribute *devattr,
char *buf) char *buf)
{ {
@ -578,6 +855,15 @@ static DEVICE_ATTR_RO(sfp_modabs);
static DEVICE_ATTR_RO(sfp_rxlos); static DEVICE_ATTR_RO(sfp_rxlos);
static DEVICE_ATTR_RW(sfp_txdis); static DEVICE_ATTR_RW(sfp_txdis);
static DEVICE_ATTR_RW(sfp_rs); static DEVICE_ATTR_RW(sfp_rs);
static DEVICE_ATTR_RW(txfault_trig);
static DEVICE_ATTR_RW(modabs_trig);
static DEVICE_ATTR_RW(rxlos_trig);
static DEVICE_ATTR_RO(txfault_int);
static DEVICE_ATTR_RO(modabs_int);
static DEVICE_ATTR_RO(rxlos_int);
static DEVICE_ATTR_RW(txfault_mask);
static DEVICE_ATTR_RW(modabs_mask);
static DEVICE_ATTR_RW(rxlos_mask);
static SENSOR_DEVICE_ATTR(fan1_dir, S_IRUGO, fan_dir_show, NULL, FAN_1); static SENSOR_DEVICE_ATTR(fan1_dir, S_IRUGO, fan_dir_show, NULL, FAN_1);
static SENSOR_DEVICE_ATTR(fan2_dir, S_IRUGO, fan_dir_show, NULL, FAN_2); static SENSOR_DEVICE_ATTR(fan2_dir, S_IRUGO, fan_dir_show, NULL, FAN_2);
static SENSOR_DEVICE_ATTR(fan3_dir, S_IRUGO, fan_dir_show, NULL, FAN_3); static SENSOR_DEVICE_ATTR(fan3_dir, S_IRUGO, fan_dir_show, NULL, FAN_3);
@ -619,6 +905,15 @@ static struct attribute *sfp_attrs[] = {
&dev_attr_sfp_rxlos.attr, &dev_attr_sfp_rxlos.attr,
&dev_attr_sfp_txdis.attr, &dev_attr_sfp_txdis.attr,
&dev_attr_sfp_rs.attr, &dev_attr_sfp_rs.attr,
&dev_attr_txfault_trig.attr,
&dev_attr_modabs_trig.attr,
&dev_attr_rxlos_trig.attr,
&dev_attr_txfault_int.attr,
&dev_attr_modabs_int.attr,
&dev_attr_rxlos_int.attr,
&dev_attr_txfault_mask.attr,
&dev_attr_modabs_mask.attr,
&dev_attr_rxlos_mask.attr,
NULL, NULL,
}; };
@ -632,26 +927,6 @@ static struct resource cpld_resources[] = {
}, },
}; };
static struct device * sfp_init(int portid) {
struct sfp_device_data *new_data;
struct device *new_device;
new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
if (!new_data) {
printk(KERN_ALERT "Cannot alloc sff device data @port%d", portid);
return NULL;
}
/* Front panel port ID start from 1 */
new_data->portid = portid + 1;
new_device = device_create_with_groups(celplatform, cpld_data->fpp_node, MKDEV(0, 0), new_data, sfp_groups, "SFP%d", new_data->portid);
if (IS_ERR(new_device)) {
printk(KERN_ALERT "Cannot create sff device @port%d", portid);
kfree(new_data);
return NULL;
}
return new_device;
}
static void cpld_dev_release( struct device * dev) static void cpld_dev_release( struct device * dev)
{ {
return; return;
@ -670,7 +945,7 @@ static struct platform_device cpld_dev = {
static int cpld_drv_probe(struct platform_device *pdev) static int cpld_drv_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
int err, i = 0; int err;
cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct cpld_data), cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct cpld_data),
GFP_KERNEL); GFP_KERNEL);
@ -700,7 +975,8 @@ static int cpld_drv_probe(struct platform_device *pdev)
return PTR_ERR(celplatform); return PTR_ERR(celplatform);
} }
cpld_data->fpp_node = device_create(celplatform, NULL, MKDEV(0, 0), NULL, "optical_ports"); cpld_data->fpp_node = device_create_with_groups(celplatform, NULL, MKDEV(0, 0), NULL, sfp_groups, "optical_ports");
if (IS_ERR(cpld_data->fpp_node)) { if (IS_ERR(cpld_data->fpp_node)) {
class_destroy(celplatform); class_destroy(celplatform);
sysfs_remove_group(&pdev->dev.kobj, &cpld_group); sysfs_remove_group(&pdev->dev.kobj, &cpld_group);
@ -716,11 +992,6 @@ static int cpld_drv_probe(struct platform_device *pdev)
return err; return err;
} }
// Creae SFP devices
for ( i = 0; i < 4; i++) {
cpld_data->sfp_devices[i] = sfp_init(i);
}
// Clear all reset signals // Clear all reset signals
outb(0xFF, SPR_RESET); outb(0xFF, SPR_RESET);
return 0; return 0;
@ -728,17 +999,8 @@ static int cpld_drv_probe(struct platform_device *pdev)
static int cpld_drv_remove(struct platform_device *pdev) static int cpld_drv_remove(struct platform_device *pdev)
{ {
struct sfp_device_data *rem_data;
int i;
for ( i = 0; i < 4; i++ ) {
rem_data = dev_get_drvdata(cpld_data->sfp_devices[i]);
put_device(cpld_data->sfp_devices[i]);
device_unregister(cpld_data->sfp_devices[i]);
kzfree(rem_data);
}
put_device(cpld_data->fpp_node);
device_unregister(cpld_data->fpp_node); device_unregister(cpld_data->fpp_node);
put_device(cpld_data->fpp_node);
sysfs_remove_group(&pdev->dev.kobj, &cpld_group); sysfs_remove_group(&pdev->dev.kobj, &cpld_group);
class_destroy(celplatform); class_destroy(celplatform);
return 0; return 0;
@ -773,5 +1035,5 @@ module_exit(cpld_exit);
MODULE_AUTHOR("Celestica Inc."); MODULE_AUTHOR("Celestica Inc.");
MODULE_DESCRIPTION("Celestica E1031 SMC driver"); MODULE_DESCRIPTION("Celestica E1031 SMC driver");
MODULE_VERSION("0.0.3"); MODULE_VERSION("1.0.0");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");