diff --git a/device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py index 851fb9ccc0..5e7d287ef5 100644 --- a/device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py +++ b/device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py @@ -14,58 +14,58 @@ class SfpUtil(SfpUtilBase): PORT_START = 1 PORT_END = 52 port_to_i2c_mapping = { - 1 : None, - 2 : None, - 3 : None, - 4 : None, - 5 : None, - 6 : None, - 7 : None, - 8 : None, - 9 : None, - 10 : None, - 11 : None, - 12 : None, - 13 : None, - 14 : None, - 15 : None, - 16 : None, - 17 : None, - 18 : None, - 19 : None, - 20 : None, - 21 : None, - 22 : None, - 23 : None, - 24 : None, - 25 : None, - 26 : None, - 27 : None, - 28 : None, - 29 : None, - 30 : None, - 31 : None, - 32 : None, - 33 : None, - 34 : None, - 35 : None, - 36 : None, - 37 : None, - 38 : None, - 39 : None, - 40 : None, - 41 : None, - 42 : None, - 43 : None, - 44 : None, - 45 : None, - 46 : None, - 47 : None, - 48 : None, - 49 : 15, - 50 : 14, - 51 : 17, - 52 : 16 + 1: None, + 2: None, + 3: None, + 4: None, + 5: None, + 6: None, + 7: None, + 8: None, + 9: None, + 10: None, + 11: None, + 12: None, + 13: None, + 14: None, + 15: None, + 16: None, + 17: None, + 18: None, + 19: None, + 20: None, + 21: None, + 22: None, + 23: None, + 24: None, + 25: None, + 26: None, + 27: None, + 28: None, + 29: None, + 30: None, + 31: None, + 32: None, + 33: None, + 34: None, + 35: None, + 36: None, + 37: None, + 38: None, + 39: None, + 40: None, + 41: None, + 42: None, + 43: None, + 44: None, + 45: None, + 46: None, + 47: None, + 48: None, + 49: 15, + 50: 14, + 51: 17, + 52: 16 } _port_to_eeprom_mapping = {} _sfp_port = range(49, PORT_END + 1) @@ -94,30 +94,42 @@ class SfpUtil(SfpUtilBase): self.port_to_eeprom_mapping[x] = port_eeprom_path SfpUtilBase.__init__(self) + 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: return False - + status = 1 try: - with open(sfp_modabs_path.format(port_num - 48), 'r') as port_status: - status = int(port_status.read()) - except IOError: + with open(sfp_modabs_path, 'r') as port_status: + status = int(port_status.read(), 16) + status = (status >> (port_num - 49)) & 1 + except IOError: return False return status == 0 - def get_low_power_mode(self, port_num): - raise NotImplementedError + raise NotImplementedError def set_low_power_mode(self, port_num, lpmode): - raise NotImplementedError + raise NotImplementedError def reset(self, port_num): - raise NotImplementedError - - def get_transceiver_change_event(self): 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 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init index 66f1ee5529..5192b202a3 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init @@ -60,6 +60,10 @@ start) echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-16/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." ;; diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/smc.c b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/smc.c index 82abc9e8ea..7b8d410cdd 100644 --- a/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/smc.c +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/smc.c @@ -116,6 +116,22 @@ enum MASTER_LED { #define FAN_2 1 #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 * [7:4] RESERVED * [3:0] TX_FAULT / MODABS / RXLOS @@ -124,6 +140,24 @@ enum MASTER_LED { #define SFP_MODABS 0x0243 #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 * [7:4] RATE SEL (RS0/RS1) * [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 devattr kernel device attribute * @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 devattr kernel device attribute * @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 devattr kernel device attribute * @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 devattr kernel device attribute * @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); int index = sa->index; unsigned char data = 0; - - // Use index to determind the status bit mutex_lock(&cpld_data->cpld_lock); data = inb(DEV_STAT); 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) { 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); data = inb(SFP_TXFAULT); + data = data & 0x0F; 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) { 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); data = inb(SFP_MODABS); + data = data & 0x0F; 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) { 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); data = inb(SFP_RXLOS); + data = data & 0x0F; 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) { 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); data = inb(SFP_TXCTRL); + data = data & 0x0F; 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) @@ -462,18 +487,13 @@ static ssize_t sfp_txdis_store(struct device *dev, struct device_attribute *attr long value; ssize_t status; 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); status = kstrtol(buf, 0, &value); if (status == 0) { - // check if value is 0, clear data = inb(SFP_TXCTRL); - if (!value) - data = data & ~( 1U << port_bit); - else - data = data | ( 1U << port_bit); + data = data & ~(0x0F); + data = data | (value & 0x0F); outb(data, SFP_TXCTRL); 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) { 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); - data = inb(SFP_TXCTRL); + data = inb(SFP_TXCTRL) >> 4; + data = data & 0x0F; 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) @@ -500,20 +516,14 @@ static ssize_t sfp_rs_store(struct device *dev, struct device_attribute *attr, c long value; ssize_t status; 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); status = kstrtol(buf, 0, &value); + value = (value & 0x0F) << 4; if (status == 0) { - // check if value is 0, clear data = inb(SFP_TXCTRL); - if (!value) - data = data & ~( 1U << port_bit); - else - data = data | ( 1U << port_bit); + data = data & ~(0xF0); + data = data | value; outb(data, SFP_TXCTRL); status = size; } @@ -521,6 +531,273 @@ static ssize_t sfp_rs_store(struct device *dev, struct device_attribute *attr, c 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, char *buf) { @@ -578,6 +855,15 @@ static DEVICE_ATTR_RO(sfp_modabs); static DEVICE_ATTR_RO(sfp_rxlos); static DEVICE_ATTR_RW(sfp_txdis); 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(fan2_dir, S_IRUGO, fan_dir_show, NULL, FAN_2); 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_txdis.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, }; @@ -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) { return; @@ -670,7 +945,7 @@ static struct platform_device cpld_dev = { static int cpld_drv_probe(struct platform_device *pdev) { struct resource *res; - int err, i = 0; + int err; cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct cpld_data), GFP_KERNEL); @@ -700,7 +975,8 @@ static int cpld_drv_probe(struct platform_device *pdev) 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)) { class_destroy(celplatform); sysfs_remove_group(&pdev->dev.kobj, &cpld_group); @@ -716,11 +992,6 @@ static int cpld_drv_probe(struct platform_device *pdev) return err; } - // Creae SFP devices - for ( i = 0; i < 4; i++) { - cpld_data->sfp_devices[i] = sfp_init(i); - } - // Clear all reset signals outb(0xFF, SPR_RESET); return 0; @@ -728,17 +999,8 @@ static int cpld_drv_probe(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); + put_device(cpld_data->fpp_node); sysfs_remove_group(&pdev->dev.kobj, &cpld_group); class_destroy(celplatform); return 0; @@ -773,5 +1035,5 @@ module_exit(cpld_exit); MODULE_AUTHOR("Celestica Inc."); MODULE_DESCRIPTION("Celestica E1031 SMC driver"); -MODULE_VERSION("0.0.3"); +MODULE_VERSION("1.0.0"); MODULE_LICENSE("GPL");