diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/port_config.ini b/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/port_config.ini index 20d1b84edc..da3321b556 100644 --- a/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/port_config.ini +++ b/device/juniper/x86_64-juniper_qfx5210-r0/Juniper-QFX5210-64C/port_config.ini @@ -1,65 +1,65 @@ -# name lanes alias -Ethernet0 73,74,75,76 hundredGigE1 -Ethernet4 65,66,67,68 hundredGigE2 -Ethernet8 81,82,83,84 hundredGigE3 -Ethernet12 89,90,91,92 hundredGigE4 -Ethernet16 105,106,107,108 hundredGigE5 -Ethernet20 97,98,99,100 hundredGigE6 -Ethernet24 113,114,115,116 hundredGigE7 -Ethernet28 121,122,123,124 hundredGigE8 -Ethernet32 41,42,43,44 hundredGigE9 -Ethernet36 33,34,35,36 hundredGigE10 -Ethernet40 49,50,51,52 hundredGigE11 -Ethernet44 57,58,59,60 hundredGigE12 -Ethernet48 137,138,139,140 hundredGigE13 -Ethernet52 129,130,131,132 hundredGigE14 -Ethernet56 145,146,147,148 hundredGigE15 -Ethernet60 153,154,155,156 hundredGigE16 -Ethernet64 173,174,175,176 hundredGigE17 -Ethernet68 165,166,167,168 hundredGigE18 -Ethernet72 181,182,183,184 hundredGigE19 -Ethernet76 189,190,191,192 hundredGigE20 -Ethernet80 13,14,15,16 hundredGigE21 -Ethernet84 5,6,7,8 hundredGigE22 -Ethernet88 29,30,31,32 hundredGigE23 -Ethernet92 21,22,23,24 hundredGigE24 -Ethernet96 205,206,207,208 hundredGigE25 -Ethernet100 197,198,199,200 hundredGigE26 -Ethernet104 213,214,215,216 hundredGigE27 -Ethernet108 221,222,223,224 hundredGigE28 -Ethernet112 229,230,231,232 hundredGigE29 -Ethernet116 237,238,239,240 hundredGigE30 -Ethernet120 245,246,247,248 hundredGigE31 -Ethernet124 253,254,255,256 hundredGigE32 -Ethernet128 69,70,71,72 hundredGigE33 -Ethernet132 77,78,79,80 hundredGigE34 -Ethernet136 93,94,95,96 hundredGigE35 -Ethernet140 85,86,87,88 hundredGigE36 -Ethernet144 101,102,103,104 hundredGigE37 -Ethernet148 109,110,111,112 hundredGigE38 -Ethernet152 125,126,127,128 hundredGigE39 -Ethernet156 117,118,119,120 hundredGigE40 -Ethernet160 37,38,39,40 hundredGigE41 -Ethernet164 45,46,47,48 hundredGigE42 -Ethernet168 61,62,63,64 hundredGigE43 -Ethernet172 53,54,55,56 hundredGigE44 -Ethernet176 133,134,135,136 hundredGigE45 -Ethernet180 141,142,143,144 hundredGigE46 -Ethernet184 157,158,159,160 hundredGigE47 -Ethernet188 149,150,151,152 hundredGigE48 -Ethernet192 161,162,163,164 hundredGigE49 -Ethernet196 169,170,171,172 hundredGigE50 -Ethernet200 185,186,187,188 hundredGigE51 -Ethernet204 177,178,179,180 hundredGigE52 -Ethernet208 1,2,3,4 hundredGigE53 -Ethernet212 9,10,11,12 hundredGigE54 -Ethernet216 25,26,27,28 hundredGigE55 -Ethernet220 17,18,19,20 hundredGigE56 -Ethernet224 193,194,195,196 hundredGigE57 -Ethernet228 201,202,203,204 hundredGigE58 -Ethernet232 217,218,219,220 hundredGigE59 -Ethernet236 209,210,211,212 hundredGigE60 -Ethernet240 225,226,227,228 hundredGigE61 -Ethernet244 233,234,235,236 hundredGigE62 -Ethernet248 249,250,251,252 hundredGigE63 -Ethernet252 241,242,243,244 hundredGigE64 +# name lanes alias index speed +Ethernet0 73,74,75,76 hundredGigE1 0 100000 +Ethernet4 65,66,67,68 hundredGigE2 1 100000 +Ethernet8 81,82,83,84 hundredGigE3 2 100000 +Ethernet12 89,90,91,92 hundredGigE4 3 100000 +Ethernet16 105,106,107,108 hundredGigE5 4 100000 +Ethernet20 97,98,99,100 hundredGigE6 5 100000 +Ethernet24 113,114,115,116 hundredGigE7 6 100000 +Ethernet28 121,122,123,124 hundredGigE8 7 100000 +Ethernet32 41,42,43,44 hundredGigE9 8 100000 +Ethernet36 33,34,35,36 hundredGigE10 9 100000 +Ethernet40 49,50,51,52 hundredGigE11 10 100000 +Ethernet44 57,58,59,60 hundredGigE12 11 100000 +Ethernet48 137,138,139,140 hundredGigE13 12 100000 +Ethernet52 129,130,131,132 hundredGigE14 13 100000 +Ethernet56 145,146,147,148 hundredGigE15 14 100000 +Ethernet60 153,154,155,156 hundredGigE16 15 100000 +Ethernet64 173,174,175,176 hundredGigE17 16 100000 +Ethernet68 165,166,167,168 hundredGigE18 17 100000 +Ethernet72 181,182,183,184 hundredGigE19 18 100000 +Ethernet76 189,190,191,192 hundredGigE20 19 100000 +Ethernet80 13,14,15,16 hundredGigE21 20 100000 +Ethernet84 5,6,7,8 hundredGigE22 21 100000 +Ethernet88 29,30,31,32 hundredGigE23 22 100000 +Ethernet92 21,22,23,24 hundredGigE24 23 100000 +Ethernet96 205,206,207,208 hundredGigE25 24 100000 +Ethernet100 197,198,199,200 hundredGigE26 25 100000 +Ethernet104 213,214,215,216 hundredGigE27 26 100000 +Ethernet108 221,222,223,224 hundredGigE28 27 100000 +Ethernet112 229,230,231,232 hundredGigE29 28 100000 +Ethernet116 237,238,239,240 hundredGigE30 29 100000 +Ethernet120 245,246,247,248 hundredGigE31 30 100000 +Ethernet124 253,254,255,256 hundredGigE32 31 100000 +Ethernet128 69,70,71,72 hundredGigE33 32 100000 +Ethernet132 77,78,79,80 hundredGigE34 33 100000 +Ethernet136 93,94,95,96 hundredGigE35 34 100000 +Ethernet140 85,86,87,88 hundredGigE36 35 100000 +Ethernet144 101,102,103,104 hundredGigE37 36 100000 +Ethernet148 109,110,111,112 hundredGigE38 37 100000 +Ethernet152 125,126,127,128 hundredGigE39 38 100000 +Ethernet156 117,118,119,120 hundredGigE40 39 100000 +Ethernet160 37,38,39,40 hundredGigE41 40 100000 +Ethernet164 45,46,47,48 hundredGigE42 41 100000 +Ethernet168 61,62,63,64 hundredGigE43 42 100000 +Ethernet172 53,54,55,56 hundredGigE44 43 100000 +Ethernet176 133,134,135,136 hundredGigE45 44 100000 +Ethernet180 141,142,143,144 hundredGigE46 45 100000 +Ethernet184 157,158,159,160 hundredGigE47 46 100000 +Ethernet188 149,150,151,152 hundredGigE48 47 100000 +Ethernet192 161,162,163,164 hundredGigE49 48 100000 +Ethernet196 169,170,171,172 hundredGigE50 49 100000 +Ethernet200 185,186,187,188 hundredGigE51 50 100000 +Ethernet204 177,178,179,180 hundredGigE52 51 100000 +Ethernet208 1,2,3,4 hundredGigE53 52 100000 +Ethernet212 9,10,11,12 hundredGigE54 53 100000 +Ethernet216 25,26,27,28 hundredGigE55 54 100000 +Ethernet220 17,18,19,20 hundredGigE56 55 100000 +Ethernet224 193,194,195,196 hundredGigE57 56 100000 +Ethernet228 201,202,203,204 hundredGigE58 57 100000 +Ethernet232 217,218,219,220 hundredGigE59 58 100000 +Ethernet236 209,210,211,212 hundredGigE60 59 100000 +Ethernet240 225,226,227,228 hundredGigE61 60 100000 +Ethernet244 233,234,235,236 hundredGigE62 61 100000 +Ethernet248 249,250,251,252 hundredGigE63 62 100000 +Ethernet252 241,242,243,244 hundredGigE64 63 100000 diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/plugins/sfputil.py b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/sfputil.py index fb5d57a609..59b1dfdb58 100644 --- a/device/juniper/x86_64-juniper_qfx5210-r0/plugins/sfputil.py +++ b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/sfputil.py @@ -43,146 +43,79 @@ class SfpUtil(SfpUtilBase): cmd = '/var/run/sfppresence' _port_to_eeprom_mapping = {} port_to_i2c_mapping = { - 61 : 25, - 62 : 26, - 63 : 27, - 64 : 28, - 55 : 29, - 56 : 30, - 53 : 31, - 54 : 32, - 9 : 33, - 10 : 34, - 11 : 35, - 12 : 36, - 1 : 37, - 2 : 38, - 3 : 39, - 4 : 40, - 6 : 41, - 5 : 42, - 8 : 43, - 7 : 44, - 13 : 45, - 14 : 46, - 15 : 47, - 16 : 48, - 17 : 49, - 18 : 50, - 19 : 51, - 20 : 52, - 25 : 53, - 26 : 54, - 27 : 55, - 28 : 56, - 29 : 57, - 30 : 58, - 31 : 59, - 32 : 60, - 21 : 61, - 22 : 62, - 23 : 63, - 24 : 64, - 41 : 65, - 42 : 66, - 43 : 67, - 44 : 68, - 33 : 69, - 34 : 70, - 35 : 71, - 36 : 72, - 45 : 73, - 46 : 74, - 47 : 75, - 48 : 76, - 37 : 77, - 38 : 78, - 39 : 79, - 40 : 80, - 57 : 81, - 58 : 82, - 59 : 83, - 60 : 84, - 49 : 85, - 50 : 86, - 51 : 87, - 52 : 88,} + 60 : 25, + 61 : 26, + 62 : 27, + 63 : 28, + 54 : 29, + 55 : 30, + 52 : 31, + 53 : 32, + 8 : 33, + 9 : 34, + 10 : 35, + 11 : 36, + 0 : 37, + 1 : 38, + 2 : 39, + 3 : 40, + 5 : 41, + 4 : 42, + 7 : 43, + 6 : 44, + 12 : 45, + 13 : 46, + 14 : 47, + 15 : 48, + 16 : 49, + 17 : 50, + 18 : 51, + 19 : 52, + 24 : 53, + 25 : 54, + 26 : 55, + 27 : 56, + 28 : 57, + 29 : 58, + 30 : 59, + 31 : 60, + 20 : 61, + 21 : 62, + 22 : 63, + 23 : 64, + 40 : 65, + 41 : 66, + 42 : 67, + 43 : 68, + 32 : 69, + 33 : 70, + 34 : 71, + 35 : 72, + 44 : 73, + 45 : 74, + 46 : 75, + 47 : 76, + 36 : 77, + 37 : 78, + 38 : 79, + 39 : 80, + 56 : 81, + 57 : 82, + 58 : 83, + 59 : 84, + 48 : 85, + 49 : 86, + 50 : 87, + 51 : 88,} - port_to_sysfs_map = [ - '/sys/bus/i2c/devices/37-0050/sfp_is_present', - '/sys/bus/i2c/devices/38-0050/sfp_is_present', - '/sys/bus/i2c/devices/39-0050/sfp_is_present', - '/sys/bus/i2c/devices/40-0050/sfp_is_present', - '/sys/bus/i2c/devices/42-0050/sfp_is_present', - '/sys/bus/i2c/devices/41-0050/sfp_is_present', - '/sys/bus/i2c/devices/44-0050/sfp_is_present', - '/sys/bus/i2c/devices/43-0050/sfp_is_present', - '/sys/bus/i2c/devices/33-0050/sfp_is_present', - '/sys/bus/i2c/devices/34-0050/sfp_is_present', - '/sys/bus/i2c/devices/35-0050/sfp_is_present', - '/sys/bus/i2c/devices/36-0050/sfp_is_present', - '/sys/bus/i2c/devices/45-0050/sfp_is_present', - '/sys/bus/i2c/devices/46-0050/sfp_is_present', - '/sys/bus/i2c/devices/47-0050/sfp_is_present', - '/sys/bus/i2c/devices/48-0050/sfp_is_present', - '/sys/bus/i2c/devices/49-0050/sfp_is_present', - '/sys/bus/i2c/devices/50-0050/sfp_is_present', - '/sys/bus/i2c/devices/51-0050/sfp_is_present', - '/sys/bus/i2c/devices/52-0050/sfp_is_present', - '/sys/bus/i2c/devices/61-0050/sfp_is_present', - '/sys/bus/i2c/devices/62-0050/sfp_is_present', - '/sys/bus/i2c/devices/63-0050/sfp_is_present', - '/sys/bus/i2c/devices/64-0050/sfp_is_present', - '/sys/bus/i2c/devices/53-0050/sfp_is_present', - '/sys/bus/i2c/devices/54-0050/sfp_is_present', - '/sys/bus/i2c/devices/55-0050/sfp_is_present', - '/sys/bus/i2c/devices/56-0050/sfp_is_present', - '/sys/bus/i2c/devices/57-0050/sfp_is_present', - '/sys/bus/i2c/devices/58-0050/sfp_is_present', - '/sys/bus/i2c/devices/59-0050/sfp_is_present', - '/sys/bus/i2c/devices/60-0050/sfp_is_present', - '/sys/bus/i2c/devices/69-0050/sfp_is_present', - '/sys/bus/i2c/devices/70-0050/sfp_is_present', - '/sys/bus/i2c/devices/71-0050/sfp_is_present', - '/sys/bus/i2c/devices/72-0050/sfp_is_present', - '/sys/bus/i2c/devices/77-0050/sfp_is_present', - '/sys/bus/i2c/devices/78-0050/sfp_is_present', - '/sys/bus/i2c/devices/79-0050/sfp_is_present', - '/sys/bus/i2c/devices/80-0050/sfp_is_present', - '/sys/bus/i2c/devices/65-0050/sfp_is_present', - '/sys/bus/i2c/devices/66-0050/sfp_is_present', - '/sys/bus/i2c/devices/67-0050/sfp_is_present', - '/sys/bus/i2c/devices/68-0050/sfp_is_present', - '/sys/bus/i2c/devices/73-0050/sfp_is_present', - '/sys/bus/i2c/devices/74-0050/sfp_is_present', - '/sys/bus/i2c/devices/75-0050/sfp_is_present', - '/sys/bus/i2c/devices/76-0050/sfp_is_present', - '/sys/bus/i2c/devices/85-0050/sfp_is_present', - '/sys/bus/i2c/devices/86-0050/sfp_is_present', - '/sys/bus/i2c/devices/87-0050/sfp_is_present', - '/sys/bus/i2c/devices/88-0050/sfp_is_present', - '/sys/bus/i2c/devices/31-0050/sfp_is_present', - '/sys/bus/i2c/devices/32-0050/sfp_is_present', - '/sys/bus/i2c/devices/29-0050/sfp_is_present', - '/sys/bus/i2c/devices/30-0050/sfp_is_present', - '/sys/bus/i2c/devices/81-0050/sfp_is_present', - '/sys/bus/i2c/devices/82-0050/sfp_is_present', - '/sys/bus/i2c/devices/83-0050/sfp_is_present', - '/sys/bus/i2c/devices/84-0050/sfp_is_present', - '/sys/bus/i2c/devices/25-0050/sfp_is_present', - '/sys/bus/i2c/devices/26-0050/sfp_is_present', - '/sys/bus/i2c/devices/27-0050/sfp_is_present', - '/sys/bus/i2c/devices/28-0050/sfp_is_present' - - ] # sys.path.append('/usr/local/bin') _qsfp_ports = range(0, ports_in_block + 1) def __init__(self): - eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom' - for x in range(0, self._port_end + 1): - port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x+1]) + eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' + for x in range(self._port_start, self._port_end + 1): + port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x]) self._port_to_eeprom_mapping[x] = port_eeprom_path SfpUtilBase.__init__(self) @@ -210,10 +143,9 @@ class SfpUtil(SfpUtilBase): if port_num < self._port_start or port_num > self._port_end: return False - path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present" - port_ps = path.format(self.port_to_i2c_mapping[port_num+1]) + path = "/sys/bus/i2c/devices/19-0060/module_present_{0}" + port_ps = path.format(port_num + 1) - try: reg_file = open(port_ps) except IOError as e: @@ -278,6 +210,8 @@ class SfpUtil(SfpUtilBase): current_sfp_values = [0] * 64 previous_sfp_values = [0] * 64 + path = "/sys/bus/i2c/devices/19-0060/module_present_{0}" + if not os.path.isfile(self.cmd): pass else: @@ -287,9 +221,10 @@ class SfpUtil(SfpUtilBase): previous_sfp_values = self.read_from_file(self.cmd) # Read the current values from sysfs - for x in range(len(self.port_to_sysfs_map)): + for x in range(self._port_start , self._port_end + 1): try: - reg_file = open(self.port_to_sysfs_map[x], 'r') + new_path = path.format(x + 1) + reg_file = open(new_path, 'r') except IOError as e: print "Error: unable to open file: %s" % str(e) return False, defl_dict @@ -305,7 +240,7 @@ class SfpUtil(SfpUtilBase): else: return False, defl_dict - def get_transceiver_change_event(self): + def get_transceiver_change_event(self, timeout=2000): time.sleep(3) return self.sfp_detect() diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/Makefile b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/Makefile index 85f96f1dd8..2218af494d 100644 --- a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/Makefile +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/Makefile @@ -1,2 +1,2 @@ -obj-m:=x86-64-juniper-qfx5210-64x-fan.o x86-64-juniper-qfx5210-64x-sfp.o x86-64-juniper-qfx5210-64x-leds.o \ +obj-m:=x86-64-juniper-qfx5210-64x-fan.o x86-64-juniper-qfx5210-64x-leds.o \ x86-64-juniper-qfx5210-64x-psu.o juniper_i2c_cpld.o ym2651y.o diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-psu.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-psu.c index 526e46433c..d42e61b3c5 100644 --- a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-psu.c +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-psu.c @@ -1,7 +1,7 @@ /* * An hwmon driver for juniper qfx5210_64x Power Module * - * Tested and validated on Juniper QFX5210 + * Modified and tested on Juniper QFX5210 * Ciju Rajan K * * Copyright (C) 2014 Accton Technology Corporation. @@ -103,6 +103,30 @@ static const struct attribute_group qfx5210_64x_psu_group = { .attrs = qfx5210_64x_psu_attributes, }; +/* + * This function is defined in juniper_i2c_cpld.c + */ +extern int juniper_i2c_cpld_write(unsigned short, u8, u8); + +/* + * QFX5210 power off sequence + */ +static void qfx5210_cpld_power_off(void) +{ + printk(KERN_ALERT "pm_power_off: qfx5210_cpld_power_off\n"); + (void) juniper_i2c_cpld_write(0x65, 0x14, 0x00); + msleep(100); + (void) juniper_i2c_cpld_write(0x77, 0x00, 0x01); + msleep(100); + (void) juniper_i2c_cpld_write(0x76, 0x00, 0x04); +} + +/* + * Default platform pm_power_off handler + */ +static void (*default_pm_power_off)(void); + + static int qfx5210_64x_psu_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) { @@ -141,7 +165,12 @@ static int qfx5210_64x_psu_probe(struct i2c_client *client, dev_info(&client->dev, "%s: psu '%s'\n", dev_name(data->hwmon_dev), client->name); - + /* + * Store the default poweroff handler for later usage + */ + default_pm_power_off = pm_power_off; + pm_power_off = qfx5210_cpld_power_off; + return 0; exit_remove: @@ -161,6 +190,11 @@ static int qfx5210_64x_psu_remove(struct i2c_client *client) sysfs_remove_group(&client->dev.kobj, &qfx5210_64x_psu_group); kfree(data); + /* + * Restore the poweroff handler + */ + pm_power_off = default_pm_power_off; + return 0; } diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-sfp.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-sfp.c deleted file mode 100644 index 0a173965fd..0000000000 --- a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/x86-64-juniper-qfx5210-64x-sfp.c +++ /dev/null @@ -1,1579 +0,0 @@ -/* - * SFP driver for juniper qfx5210_64x sfp - * - * Tested and validated on Juniper QFX5210 - * Ciju Rajan K - * - * Copyright (C) Brandon Chuang - * - * Based on ad7414.c - * Copyright 2006 Stefan Roese , DENX Software Engineering - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "qfx5210_64x_sfp" /* Platform dependent */ - -#define DEBUG_MODE 0 - -#if (DEBUG_MODE == 1) - #define DEBUG_PRINT(fmt, args...) \ - printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) -#else - #define DEBUG_PRINT(fmt, args...) -#endif - -#define NUM_OF_SFP_PORT 24 -#define EEPROM_NAME "sfp_eeprom" -#define EEPROM_SIZE 256 /* 256 byte eeprom */ -#define BIT_INDEX(i) (1ULL << (i)) -#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ -#define I2C_RW_RETRY_COUNT 10 -#define I2C_RW_RETRY_INTERVAL 60 /* ms */ - -#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) - -#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 -#define SFF8024_DEVICE_ID_SFP 0x3 -#define SFF8024_DEVICE_ID_QSFP 0xC -#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD -#define SFF8024_DEVICE_ID_QSFP28 0x11 - -#define SFF8436_RX_LOS_ADDR 3 -#define SFF8436_TX_FAULT_ADDR 4 -#define SFF8436_TX_DISABLE_ADDR 86 - -#define MULTIPAGE_SUPPORT 1 - -#if (MULTIPAGE_SUPPORT == 1) -/* fundamental unit of addressing for SFF_8472/SFF_8436 */ -#define SFF_8436_PAGE_SIZE 128 -/* - * The current 8436 (QSFP) spec provides for only 4 supported - * pages (pages 0-3). - * This driver is prepared to support more, but needs a register in the - * EEPROM to indicate how many pages are supported before it is safe - * to implement more pages in the driver. - */ -#define SFF_8436_SPECED_PAGES 4 -#define SFF_8436_EEPROM_SIZE ((1 + SFF_8436_SPECED_PAGES) * SFF_8436_PAGE_SIZE) -#define SFF_8436_EEPROM_UNPAGED_SIZE (2 * SFF_8436_PAGE_SIZE) -/* - * The current 8472 (SFP) spec provides for only 3 supported - * pages (pages 0-2). - * This driver is prepared to support more, but needs a register in the - * EEPROM to indicate how many pages are supported before it is safe - * to implement more pages in the driver. - */ -#define SFF_8472_SPECED_PAGES 3 -#define SFF_8472_EEPROM_SIZE ((3 + SFF_8472_SPECED_PAGES) * SFF_8436_PAGE_SIZE) -#define SFF_8472_EEPROM_UNPAGED_SIZE (4 * SFF_8436_PAGE_SIZE) - -/* a few constants to find our way around the EEPROM */ -#define SFF_8436_PAGE_SELECT_REG 0x7F -#define SFF_8436_PAGEABLE_REG 0x02 -#define SFF_8436_NOT_PAGEABLE (1<<2) -#define SFF_8472_PAGEABLE_REG 0x40 -#define SFF_8472_PAGEABLE (1<<4) - -/* - * This parameter is to help this driver avoid blocking other drivers out - * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C - * clock, one 256 byte read takes about 1/43 second which is excessive; - * but the 1/170 second it takes at 400 kHz may be quite reasonable; and - * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. - * - * This value is forced to be a power of two so that writes align on pages. - */ -static unsigned io_limit = SFF_8436_PAGE_SIZE; - -/* - * specs often allow 5 msec for a page write, sometimes 20 msec; - * it's important to recover from write timeouts. - */ -static unsigned write_timeout = 25; - -typedef enum qsfp_opcode { - QSFP_READ_OP = 0, - QSFP_WRITE_OP = 1 -} qsfp_opcode_e; -#endif - -static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; -static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); -static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); -extern int juniper_i2c_cpld_read (u8 cpld_addr, u8 reg); - -enum sfp_sysfs_attributes { - PRESENT, - PRESENT_ALL, - PORT_NUMBER, - PORT_TYPE, - DDM_IMPLEMENTED, - TX_FAULT, - TX_FAULT1, - TX_FAULT2, - TX_FAULT3, - TX_FAULT4, - TX_DISABLE, - TX_DISABLE1, - TX_DISABLE2, - TX_DISABLE3, - TX_DISABLE4, - RX_LOS, - RX_LOS1, - RX_LOS2, - RX_LOS3, - RX_LOS4, - RX_LOS_ALL -}; - -/* SFP/QSFP common attributes for sysfs */ -static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); -static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); -static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); -static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE); -static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT); - -/* QSFP attributes for sysfs */ -static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS); -static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); -static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); -static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); -static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); -static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); -static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); -static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); -static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); -static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); -static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); -static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); -static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); -static struct attribute *qsfp_attributes[] = { - &sensor_dev_attr_sfp_port_number.dev_attr.attr, - &sensor_dev_attr_sfp_is_present.dev_attr.attr, - &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, - NULL -}; - -/* Platform dependent +++ */ -#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) - -enum port_numbers { -qfx5210_64x_port1, qfx5210_64x_port2, qfx5210_64x_port3, qfx5210_64x_port4, -qfx5210_64x_port5, qfx5210_64x_port6, qfx5210_64x_port7, qfx5210_64x_port8, -qfx5210_64x_port9, qfx5210_64x_port10, qfx5210_64x_port11, qfx5210_64x_port12, -qfx5210_64x_port13, qfx5210_64x_port14, qfx5210_64x_port15, qfx5210_64x_port16, -qfx5210_64x_port17, qfx5210_64x_port18, qfx5210_64x_port19, qfx5210_64x_port20, -qfx5210_64x_port21, qfx5210_64x_port22, qfx5210_64x_port23, qfx5210_64x_port24, -qfx5210_64x_port25, qfx5210_64x_port26, qfx5210_64x_port27, qfx5210_64x_port28, -qfx5210_64x_port29, qfx5210_64x_port30, qfx5210_64x_port31, qfx5210_64x_port32, -qfx5210_64x_port33, qfx5210_64x_port34, qfx5210_64x_port35, qfx5210_64x_port36, -qfx5210_64x_port37, qfx5210_64x_port38, qfx5210_64x_port39, qfx5210_64x_port40, -qfx5210_64x_port41, qfx5210_64x_port42, qfx5210_64x_port43, qfx5210_64x_port44, -qfx5210_64x_port45, qfx5210_64x_port46, qfx5210_64x_port47, qfx5210_64x_port48, -qfx5210_64x_port49, qfx5210_64x_port50, qfx5210_64x_port51, qfx5210_64x_port52, -qfx5210_64x_port53, qfx5210_64x_port54, qfx5210_64x_port55, qfx5210_64x_port56, -qfx5210_64x_port57, qfx5210_64x_port58, qfx5210_64x_port59, qfx5210_64x_port60, -qfx5210_64x_port61, qfx5210_64x_port62, qfx5210_64x_port63, qfx5210_64x_port64 -}; - -#define I2C_DEV_ID(x) { #x, x} - -static const struct i2c_device_id sfp_device_id[] = { -I2C_DEV_ID(qfx5210_64x_port1), -I2C_DEV_ID(qfx5210_64x_port2), -I2C_DEV_ID(qfx5210_64x_port3), -I2C_DEV_ID(qfx5210_64x_port4), -I2C_DEV_ID(qfx5210_64x_port5), -I2C_DEV_ID(qfx5210_64x_port6), -I2C_DEV_ID(qfx5210_64x_port7), -I2C_DEV_ID(qfx5210_64x_port8), -I2C_DEV_ID(qfx5210_64x_port9), -I2C_DEV_ID(qfx5210_64x_port10), -I2C_DEV_ID(qfx5210_64x_port11), -I2C_DEV_ID(qfx5210_64x_port12), -I2C_DEV_ID(qfx5210_64x_port13), -I2C_DEV_ID(qfx5210_64x_port14), -I2C_DEV_ID(qfx5210_64x_port15), -I2C_DEV_ID(qfx5210_64x_port16), -I2C_DEV_ID(qfx5210_64x_port17), -I2C_DEV_ID(qfx5210_64x_port18), -I2C_DEV_ID(qfx5210_64x_port19), -I2C_DEV_ID(qfx5210_64x_port20), -I2C_DEV_ID(qfx5210_64x_port21), -I2C_DEV_ID(qfx5210_64x_port22), -I2C_DEV_ID(qfx5210_64x_port23), -I2C_DEV_ID(qfx5210_64x_port24), -I2C_DEV_ID(qfx5210_64x_port25), -I2C_DEV_ID(qfx5210_64x_port26), -I2C_DEV_ID(qfx5210_64x_port27), -I2C_DEV_ID(qfx5210_64x_port28), -I2C_DEV_ID(qfx5210_64x_port29), -I2C_DEV_ID(qfx5210_64x_port30), -I2C_DEV_ID(qfx5210_64x_port31), -I2C_DEV_ID(qfx5210_64x_port32), -I2C_DEV_ID(qfx5210_64x_port33), -I2C_DEV_ID(qfx5210_64x_port34), -I2C_DEV_ID(qfx5210_64x_port35), -I2C_DEV_ID(qfx5210_64x_port36), -I2C_DEV_ID(qfx5210_64x_port37), -I2C_DEV_ID(qfx5210_64x_port38), -I2C_DEV_ID(qfx5210_64x_port39), -I2C_DEV_ID(qfx5210_64x_port40), -I2C_DEV_ID(qfx5210_64x_port41), -I2C_DEV_ID(qfx5210_64x_port42), -I2C_DEV_ID(qfx5210_64x_port43), -I2C_DEV_ID(qfx5210_64x_port44), -I2C_DEV_ID(qfx5210_64x_port45), -I2C_DEV_ID(qfx5210_64x_port46), -I2C_DEV_ID(qfx5210_64x_port47), -I2C_DEV_ID(qfx5210_64x_port48), -I2C_DEV_ID(qfx5210_64x_port49), -I2C_DEV_ID(qfx5210_64x_port50), -I2C_DEV_ID(qfx5210_64x_port51), -I2C_DEV_ID(qfx5210_64x_port52), -I2C_DEV_ID(qfx5210_64x_port53), -I2C_DEV_ID(qfx5210_64x_port54), -I2C_DEV_ID(qfx5210_64x_port55), -I2C_DEV_ID(qfx5210_64x_port56), -I2C_DEV_ID(qfx5210_64x_port57), -I2C_DEV_ID(qfx5210_64x_port58), -I2C_DEV_ID(qfx5210_64x_port59), -I2C_DEV_ID(qfx5210_64x_port60), -I2C_DEV_ID(qfx5210_64x_port61), -I2C_DEV_ID(qfx5210_64x_port62), -I2C_DEV_ID(qfx5210_64x_port63), -I2C_DEV_ID(qfx5210_64x_port64), -{ /* LIST END */ } -}; -MODULE_DEVICE_TABLE(i2c, sfp_device_id); -/* Platform dependent --- */ - -enum driver_type_e { - DRIVER_TYPE_SFP_MSA, - DRIVER_TYPE_SFP_DDM, - DRIVER_TYPE_QSFP, - DRIVER_TYPE_XFP -}; - -/* Each client has this additional data - */ -struct eeprom_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - struct bin_attribute bin; /* eeprom data */ -}; - -struct qsfp_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u8 status[3]; /* bit0:port0, bit1:port1 and so on */ - /* index 0 => tx_fail - 1 => tx_disable - 2 => rx_loss */ - u8 device_id; - struct eeprom_data eeprom; -}; - -struct sfp_port_data { - struct mutex update_lock; - enum driver_type_e driver_type; - int port; /* CPLD port index */ - u64 present; /* present status, bit0:port0, bit1:port1 and so on */ - - struct qsfp_data *qsfp; - - struct i2c_client *client; -#if (MULTIPAGE_SUPPORT == 1) - int use_smbus; - u8 *writebuf; - unsigned write_max; -#endif -}; - -#if (MULTIPAGE_SUPPORT == 1) -static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, - char *buf, loff_t off, size_t len, qsfp_opcode_e opcode); -#endif -static ssize_t show_port_number(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); -} - -/* Platform dependent +++ */ -static struct sfp_port_data *sfp_update_present(struct i2c_client *client) -{ - struct sfp_port_data *data = i2c_get_clientdata(client); - int i = 0; - int status = -1; - u8 regs[] = {0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77}; - - DEBUG_PRINT("Starting sfp present status update"); - mutex_lock(&data->update_lock); - - /* Read present status of port 1~64 */ - data->present = 0; - - for (i = 0; i < ARRAY_SIZE(regs); i++) { - status = juniper_i2c_cpld_read(0x60, regs[i]); - - if (status < 0) { - DEBUG_PRINT("cpld(0x60) reg(0x%x) err %d", regs[i], status); - goto exit; - } - - DEBUG_PRINT("Present status = 0x%lx", data->present); - data->present |= (u64)status << (i*8); - } - - DEBUG_PRINT("Present status = 0x%lx", data->present); -exit: - mutex_unlock(&data->update_lock); - return (status < 0) ? ERR_PTR(status) : data; -} - -/* Platform dependent --- */ - -static int sfp_is_port_present(struct i2c_client *client, int port) -{ - struct sfp_port_data *data = i2c_get_clientdata(client); - - data = sfp_update_present(client); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - return (data->present & BIT_INDEX(data->port)) ? 0 : 1; /* Platform dependent */ -} - -/* Platform dependent +++ */ -static ssize_t show_present(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); - - if (PRESENT_ALL == attr->index) { - int i; - u8 values[8] = {0}; - struct sfp_port_data *data = sfp_update_present(client); - - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - for (i = 0; i < ARRAY_SIZE(values); i++) { - values[i] = ~(u8)(data->present >> (i * 8)); - } - - /* Return values 1 -> 64 in order */ - return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", - values[0], values[1], values[2], values[3], - values[4], values[5], values[6], values[7]); - } - else { - struct sfp_port_data *data = i2c_get_clientdata(client); - int present = sfp_is_port_present(client, data->port); - - if (IS_ERR_VALUE(present)) { - return present; - } - - /* PRESENT */ - return sprintf(buf, "%d\n", present); - } -} -/* Platform dependent --- */ - -static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - int i, status = -1; - u8 buf = 0; - u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; - - if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { - return data; - } - - DEBUG_PRINT("Starting sfp tx rx status update"); - mutex_lock(&data->update_lock); - data->qsfp->valid = 0; - memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); - - /* Notify device to update tx fault/ tx disable/ rx los status */ - for (i = 0; i < ARRAY_SIZE(reg); i++) { - status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); - if (unlikely(status < 0)) { - goto exit; - } - } - msleep(200); - - /* Read actual tx fault/ tx disable/ rx los status */ - for (i = 0; i < ARRAY_SIZE(reg); i++) { - status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); - if (unlikely(status < 0)) { - goto exit; - } - - DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); - data->qsfp->status[i] = (buf & 0xF); - } - - data->qsfp->valid = 1; - data->qsfp->last_updated = jiffies; - -exit: - mutex_unlock(&data->update_lock); - return (status < 0) ? ERR_PTR(status) : data; -} - -static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, - char *buf) -{ - int present; - u8 val = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - present = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENXIO; - } - - data = qsfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - switch (attr->index) { - case TX_FAULT: - val = !!(data->qsfp->status[2] & 0xF); - break; - case TX_FAULT1: - case TX_FAULT2: - case TX_FAULT3: - case TX_FAULT4: - val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); - break; - case TX_DISABLE: - val = data->qsfp->status[1] & 0xF; - break; - case TX_DISABLE1: - case TX_DISABLE2: - case TX_DISABLE3: - case TX_DISABLE4: - val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); - break; - case RX_LOS: - val = !!(data->qsfp->status[0] & 0xF); - break; - case RX_LOS1: - case RX_LOS2: - case RX_LOS3: - case RX_LOS4: - val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); - break; - default: - break; - } - - return sprintf(buf, "%d\n", val); -} - -static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - long disable; - int status; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - status = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(status)) { - return status; - } - - if (!status) { - /* port is not present */ - return -ENXIO; - } - - status = kstrtol(buf, 10, &disable); - if (status) { - return status; - } - - data = qsfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - mutex_lock(&data->update_lock); - - if (attr->index == TX_DISABLE) { - if (disable) { - data->qsfp->status[1] |= 0xF; - } - else { - data->qsfp->status[1] &= ~0xF; - } - } - else {/* TX_DISABLE1 ~ TX_DISABLE4*/ - if (disable) { - data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); - } - else { - data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); - } - } - - DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); - status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); - if (unlikely(status < 0)) { - count = status; - } - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, - int data_len) -{ -#if USE_I2C_BLOCK_READ - int status, retry = I2C_RW_RETRY_COUNT; - - if (data_len > I2C_SMBUS_BLOCK_MAX) { - data_len = I2C_SMBUS_BLOCK_MAX; - } - - while (retry) { - status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - return status; - } - - return data_len; -#else - int status, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_write_byte_data(client, command, *data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - return status; - } - - return 1; -#endif - - -} - -#if (MULTIPAGE_SUPPORT == 0) -static ssize_t sfp_port_write(struct sfp_port_data *data, - const char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) { - return count; - } - - /* - * Write data to chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&data->update_lock); - - while (count) { - ssize_t status; - - status = sfp_eeprom_write(data->client, off, buf, count); - if (status <= 0) { - if (retval == 0) { - retval = status; - } - break; - } - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&data->update_lock); - return retval; -} -#endif - -static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - int present; - struct sfp_port_data *data; - DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); - data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - - present = sfp_is_port_present(data->client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENODEV; - } - -#if (MULTIPAGE_SUPPORT == 1) - return sfp_port_read_write(data, buf, off, count, QSFP_WRITE_OP); -#else - return sfp_port_write(data, buf, off, count); -#endif -} - -static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, - int data_len) -{ -#if USE_I2C_BLOCK_READ - int status, retry = I2C_RW_RETRY_COUNT; - - if (data_len > I2C_SMBUS_BLOCK_MAX) { - data_len = I2C_SMBUS_BLOCK_MAX; - } - - while (retry) { - status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - goto abort; - } - if (unlikely(status != data_len)) { - status = -EIO; - goto abort; - } - - //result = data_len; - -abort: - return status; -#else - int status, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_read_byte_data(client, command); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); - goto abort; - } - - *data = (u8)status; - status = 1; - -abort: - return status; -#endif -} - -#if (MULTIPAGE_SUPPORT == 1) -/*-------------------------------------------------------------------------*/ -/* - * This routine computes the addressing information to be used for - * a given r/w request. - * - * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), - * the page, and the offset. - * - * Handles both SFP and QSFP. - * For SFP, offset 0-255 are on client[0], >255 is on client[1] - * Offset 256-383 are on the lower half of client[1] - * Pages are accessible on the upper half of client[1]. - * Offset >383 are in 128 byte pages mapped into the upper half - * - * For QSFP, all offsets are on client[0] - * offset 0-127 are on the lower half of client[0] (no paging) - * Pages are accessible on the upper half of client[1]. - * Offset >127 are in 128 byte pages mapped into the upper half - * - * Callers must not read/write beyond the end of a client or a page - * without recomputing the client/page. Hence offset (within page) - * plus length must be less than or equal to 128. (Note that this - * routine does not have access to the length of the call, hence - * cannot do the validity check.) - * - * Offset within Lower Page 00h and Upper Page 00h are not recomputed - */ -static uint8_t sff_8436_translate_offset(struct sfp_port_data *port_data, - loff_t *offset, struct i2c_client **client) -{ - unsigned page = 0; - - *client = port_data->client; - - /* - * if offset is in the range 0-128... - * page doesn't matter (using lower half), return 0. - * offset is already correct (don't add 128 to get to paged area) - */ - if (*offset < SFF_8436_PAGE_SIZE) - return page; - - /* note, page will always be positive since *offset >= 128 */ - page = (*offset >> 7)-1; - /* 0x80 places the offset in the top half, offset is last 7 bits */ - *offset = SFF_8436_PAGE_SIZE + (*offset & 0x7f); - - return page; /* note also returning client and offset */ -} - -static ssize_t sff_8436_eeprom_read(struct sfp_port_data *port_data, - struct i2c_client *client, - char *buf, unsigned offset, size_t count) -{ - struct i2c_msg msg[2]; - u8 msgbuf[2]; - unsigned long timeout, read_time; - int status, i; - - memset(msg, 0, sizeof(msg)); - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /*smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* - * When we have a better choice than SMBus calls, use a - * combined I2C message. Write address; then read up to - * io_limit data bytes. msgbuf is u8 and will cast to our - * needs. - */ - i = 0; - msgbuf[i++] = offset; - - msg[0].addr = client->addr; - msg[0].buf = msgbuf; - msg[0].len = i; - - msg[1].addr = client->addr; - msg[1].flags = I2C_M_RD; - msg[1].buf = buf; - msg[1].len = count; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - read_time = jiffies; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_read_i2c_block_data(client, offset, - count, buf); - break; - case I2C_SMBUS_WORD_DATA: - status = i2c_smbus_read_word_data(client, offset); - if (status >= 0) { - buf[0] = status & 0xff; - if (count == 2) - buf[1] = status >> 8; - status = count; - } - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_read_byte_data(client, offset); - if (status >= 0) { - buf[0] = status; - status = count; - } - break; - default: - status = i2c_transfer(client->adapter, msg, 2); - if (status == 2) - status = count; - } - - dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", - count, offset, status, jiffies); - - if (status == count) /* happy path */ - return count; - - if (status == -ENXIO) /* no module present */ - return status; - - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); - } while (time_before(read_time, timeout)); - - return -ETIMEDOUT; -} - -static ssize_t sff_8436_eeprom_write(struct sfp_port_data *port_data, - struct i2c_client *client, - const char *buf, - unsigned offset, size_t count) -{ - struct i2c_msg msg; - ssize_t status; - unsigned long timeout, write_time; - unsigned next_page_start; - int i = 0; - - /* write max is at most a page - * (In this driver, write_max is actually one byte!) - */ - if (count > port_data->write_max) - count = port_data->write_max; - - /* shorten count if necessary to avoid crossing page boundary */ - next_page_start = roundup(offset + 1, SFF_8436_PAGE_SIZE); - if (offset + count > next_page_start) - count = next_page_start - offset; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /*smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* If we'll use I2C calls for I/O, set up the message */ - msg.addr = client->addr; - msg.flags = 0; - - /* msg.buf is u8 and casts will mask the values */ - msg.buf = port_data->writebuf; - - msg.buf[i++] = offset; - memcpy(&msg.buf[i], buf, count); - msg.len = i + count; - break; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - write_time = jiffies; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_write_i2c_block_data(client, - offset, count, buf); - if (status == 0) - status = count; - break; - case I2C_SMBUS_WORD_DATA: - if (count == 2) { - status = i2c_smbus_write_word_data(client, - offset, (u16)((buf[0])|(buf[1] << 8))); - } else { - /* count = 1 */ - status = i2c_smbus_write_byte_data(client, - offset, buf[0]); - } - if (status == 0) - status = count; - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_write_byte_data(client, offset, - buf[0]); - if (status == 0) - status = count; - break; - default: - status = i2c_transfer(client->adapter, &msg, 1); - if (status == 1) - status = count; - break; - } - - dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", - count, offset, (long int) status, jiffies); - - if (status == count) - return count; - - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); - } while (time_before(write_time, timeout)); - - return -ETIMEDOUT; -} - - -static ssize_t sff_8436_eeprom_update_client(struct sfp_port_data *port_data, - char *buf, loff_t off, - size_t count, qsfp_opcode_e opcode) -{ - struct i2c_client *client; - ssize_t retval = 0; - u8 page = 0; - loff_t phy_offset = off; - int ret = 0; - - page = sff_8436_translate_offset(port_data, &phy_offset, &client); - - dev_dbg(&client->dev, - "sff_8436_eeprom_update_client off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", - off, page, phy_offset, (long int) count, opcode); - if (page > 0) { - ret = sff_8436_eeprom_write(port_data, client, &page, - SFF_8436_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_dbg(&client->dev, - "Write page register for page %d failed ret:%d!\n", - page, ret); - return ret; - } - } - - while (count) { - ssize_t status; - - if (opcode == QSFP_READ_OP) { - status = sff_8436_eeprom_read(port_data, client, - buf, phy_offset, count); - } else { - status = sff_8436_eeprom_write(port_data, client, - buf, phy_offset, count); - } - if (status <= 0) { - if (retval == 0) - retval = status; - break; - } - buf += status; - phy_offset += status; - count -= status; - retval += status; - } - - - if (page > 0) { - /* return the page register to page 0 (why?) */ - page = 0; - ret = sff_8436_eeprom_write(port_data, client, &page, - SFF_8436_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_err(&client->dev, - "Restore page register to page %d failed ret:%d!\n", - page, ret); - return ret; - } - } - return retval; -} - - -/* - * Figure out if this access is within the range of supported pages. - * Note this is called on every access because we don't know if the - * module has been replaced since the last call. - * If/when modules support more pages, this is the routine to update - * to validate and allow access to additional pages. - * - * Returns updated len for this access: - * - entire access is legal, original len is returned. - * - access begins legal but is too long, len is truncated to fit. - * - initial offset exceeds supported pages, return -EINVAL - */ -static ssize_t sff_8436_page_legal(struct sfp_port_data *port_data, - loff_t off, size_t len) -{ - struct i2c_client *client = port_data->client; - u8 regval; - int status; - size_t maxlen; - - if (off < 0) return -EINVAL; - if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { - /* SFP case */ - /* if no pages needed, we're good */ - if ((off + len) <= SFF_8472_EEPROM_UNPAGED_SIZE) return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= SFF_8472_EEPROM_SIZE) return -EINVAL; - /* in between, are pages supported? */ - status = sff_8436_eeprom_read(port_data, client, ®val, - SFF_8472_PAGEABLE_REG, 1); - if (status < 0) return status; /* error out (no module?) */ - if (regval & SFF_8472_PAGEABLE) { - /* Pages supported, trim len to the end of pages */ - maxlen = SFF_8472_EEPROM_SIZE - off; - } else { - /* pages not supported, trim len to unpaged size */ - maxlen = SFF_8472_EEPROM_UNPAGED_SIZE - off; - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, SFP, off %lld len %ld\n", - off, (long int) len); - } - else if (port_data->driver_type == DRIVER_TYPE_QSFP || - port_data->driver_type == DRIVER_TYPE_XFP) { - /* QSFP case */ - /* if no pages needed, we're good */ - if ((off + len) <= SFF_8436_EEPROM_UNPAGED_SIZE) return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= SFF_8436_EEPROM_SIZE) return -EINVAL; - /* in between, are pages supported? */ - status = sff_8436_eeprom_read(port_data, client, ®val, - SFF_8436_PAGEABLE_REG, 1); - if (status < 0) return status; /* error out (no module?) */ - if (regval & SFF_8436_NOT_PAGEABLE) { - /* pages not supported, trim len to unpaged size */ - maxlen = SFF_8436_EEPROM_UNPAGED_SIZE - off; - } else { - /* Pages supported, trim len to the end of pages */ - maxlen = SFF_8436_EEPROM_SIZE - off; - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, QSFP, off %lld len %ld\n", - off, (long int) len); - } - else { - return -EINVAL; - } - return len; -} - - -static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, - char *buf, loff_t off, size_t len, qsfp_opcode_e opcode) -{ - struct i2c_client *client = port_data->client; - int chunk; - int status = 0; - ssize_t retval; - size_t pending_len = 0, chunk_len = 0; - loff_t chunk_offset = 0, chunk_start_offset = 0; - - if (unlikely(!len)) - return len; - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&port_data->update_lock); - - /* - * Confirm this access fits within the device suppored addr range - */ - len = sff_8436_page_legal(port_data, off, len); - if (len < 0) { - status = len; - goto err; - } - - /* - * For each (128 byte) chunk involved in this request, issue a - * separate call to sff_eeprom_update_client(), to - * ensure that each access recalculates the client/page - * and writes the page register as needed. - * Note that chunk to page mapping is confusing, is different for - * QSFP and SFP, and never needs to be done. Don't try! - */ - pending_len = len; /* amount remaining to transfer */ - retval = 0; /* amount transferred */ - for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { - - /* - * Compute the offset and number of bytes to be read/write - * - * 1. start at offset 0 (within the chunk), and read/write - * the entire chunk - * 2. start at offset 0 (within the chunk) and read/write less - * than entire chunk - * 3. start at an offset not equal to 0 and read/write the rest - * of the chunk - * 4. start at an offset not equal to 0 and read/write less than - * (end of chunk - offset) - */ - chunk_start_offset = chunk * SFF_8436_PAGE_SIZE; - - if (chunk_start_offset < off) { - chunk_offset = off; - if ((off + pending_len) < (chunk_start_offset + - SFF_8436_PAGE_SIZE)) - chunk_len = pending_len; - else - chunk_len = (chunk+1)*SFF_8436_PAGE_SIZE - off;/*SFF_8436_PAGE_SIZE - off;*/ - } else { - chunk_offset = chunk_start_offset; - if (pending_len > SFF_8436_PAGE_SIZE) - chunk_len = SFF_8436_PAGE_SIZE; - else - chunk_len = pending_len; - } - - dev_dbg(&client->dev, - "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", - off, (long int) len, chunk_start_offset, chunk_offset, - (long int) chunk_len, (long int) pending_len); - - /* - * note: chunk_offset is from the start of the EEPROM, - * not the start of the chunk - */ - status = sff_8436_eeprom_update_client(port_data, buf, - chunk_offset, chunk_len, opcode); - if (status != chunk_len) { - /* This is another 'no device present' path */ - dev_dbg(&client->dev, - "sff_8436_update_client for chunk %d chunk_offset %lld chunk_len %ld failed %d!\n", - chunk, chunk_offset, (long int) chunk_len, status); - goto err; - } - buf += status; - pending_len -= status; - retval += status; - } - mutex_unlock(&port_data->update_lock); - - return retval; - -err: - mutex_unlock(&port_data->update_lock); - - return status; -} - -#else -static ssize_t sfp_port_read(struct sfp_port_data *data, - char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) { - DEBUG_PRINT("Count = 0, return"); - return count; - } - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&data->update_lock); - - while (count) { - ssize_t status; - - status = sfp_eeprom_read(data->client, off, buf, count); - if (status <= 0) { - if (retval == 0) { - retval = status; - } - break; - } - - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&data->update_lock); - return retval; - -} -#endif - -static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - int present; - struct sfp_port_data *data; - DEBUG_PRINT("offset = (%d), count = (%d)", off, count); - - data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - present = sfp_is_port_present(data->client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENODEV; - } - -#if (MULTIPAGE_SUPPORT == 1) - return sfp_port_read_write(data, buf, off, count, QSFP_READ_OP); -#else - return sfp_port_read(data, buf, off, count); -#endif -} - -#if (MULTIPAGE_SUPPORT == 1) -static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom, size_t size) -#else -static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) -#endif -{ - int err; - - sysfs_bin_attr_init(eeprom); - eeprom->attr.name = EEPROM_NAME; - eeprom->attr.mode = S_IWUSR | S_IRUGO; - eeprom->read = sfp_bin_read; - eeprom->write = sfp_bin_write; -#if (MULTIPAGE_SUPPORT == 1) - eeprom->size = size; -#else - eeprom->size = EEPROM_SIZE; -#endif - - /* Create eeprom file */ - err = sysfs_create_bin_file(kobj, eeprom); - if (err) { - return err; - } - - return 0; -} - -static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) -{ - sysfs_remove_bin_file(kobj, eeprom); - return 0; -} - - -#if (MULTIPAGE_SUPPORT == 0) -static int sfp_i2c_check_functionality(struct i2c_client *client) -{ -#if USE_I2C_BLOCK_READ - return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); -#else - return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); -#endif -} -#endif - - -static const struct attribute_group qsfp_group = { - .attrs = qsfp_attributes, -}; - -static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, - struct qsfp_data **data) -{ - int status; - struct qsfp_data *qsfp; - -#if (MULTIPAGE_SUPPORT == 0) - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } -#endif - - qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); - if (!qsfp) { - status = -ENOMEM; - goto exit; - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &qsfp_group); - if (status) { - goto exit_free; - } - - /* init eeprom */ -#if (MULTIPAGE_SUPPORT == 1) - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin, SFF_8436_EEPROM_SIZE); -#else - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); -#endif - if (status) { - goto exit_remove; - } - - *data = qsfp; - dev_info(&client->dev, "qsfp '%s'\n", client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &qsfp_group); -exit_free: - kfree(qsfp); -exit: - - return status; -} - -/* Platform dependent +++ */ -static int sfp_device_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - int ret = 0; - struct sfp_port_data *data = NULL; - - if (client->addr != SFP_EEPROM_A0_I2C_ADDR) { - return -ENODEV; - } - - if (dev_id->driver_data < qfx5210_64x_port1 || dev_id->driver_data > qfx5210_64x_port64) { - return -ENXIO; - } - - data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); - if (!data) { - return -ENOMEM; - } - -#if (MULTIPAGE_SUPPORT == 1) - data->use_smbus = 0; - - /* Use I2C operations unless we're stuck with SMBus extensions. */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { - data->use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_WORD_DATA)) { - data->use_smbus = I2C_SMBUS_WORD_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE_DATA)) { - data->use_smbus = I2C_SMBUS_BYTE_DATA; - } else { - ret = -EPFNOSUPPORT; - goto exit_kfree; - } - } - - if (!data->use_smbus || - (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || - i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_WORD_DATA) || - i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { - /* - * NOTE: AN-2079 - * Finisar recommends that the host implement 1 byte writes - * only since this module only supports 32 byte page boundaries. - * 2 byte writes are acceptable for PE and Vout changes per - * Application Note AN-2071. - */ - unsigned write_max = 1; - - if (write_max > io_limit) - write_max = io_limit; - if (data->use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) - write_max = I2C_SMBUS_BLOCK_MAX; - data->write_max = write_max; - - /* buffer (data + address at the beginning) */ - data->writebuf = kmalloc(write_max + 2, GFP_KERNEL); - if (!data->writebuf) { - ret = -ENOMEM; - goto exit_kfree; - } - } else { - dev_warn(&client->dev, - "cannot write due to controller restrictions."); - } - - if (data->use_smbus == I2C_SMBUS_WORD_DATA || - data->use_smbus == I2C_SMBUS_BYTE_DATA) { - dev_notice(&client->dev, "Falling back to %s reads, " - "performance will suffer\n", data->use_smbus == - I2C_SMBUS_WORD_DATA ? "word" : "byte"); - } -#endif - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - data->port = dev_id->driver_data; - data->client = client; - data->driver_type = DRIVER_TYPE_QSFP; - - ret = qsfp_probe(client, dev_id, &data->qsfp); - if (ret < 0) { - goto exit_kfree_buf; - } - - return ret; - -exit_kfree_buf: -#if (MULTIPAGE_SUPPORT == 1) - if (data->writebuf) kfree(data->writebuf); -#endif - -exit_kfree: - kfree(data); - return ret; -} -/* Platform dependent --- */ - -static int qsfp_remove(struct i2c_client *client, struct qsfp_data *data) -{ - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); - sysfs_remove_group(&client->dev.kobj, &qsfp_group); - kfree(data); - return 0; -} - -static int sfp_device_remove(struct i2c_client *client) -{ - int ret = 0; - struct sfp_port_data *data = i2c_get_clientdata(client); - - if (data->driver_type == DRIVER_TYPE_QSFP) { - ret = qsfp_remove(client, data->qsfp); - } - - kfree(data); - return ret; -} - -/* Addresses scanned - */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; - -static struct i2c_driver sfp_driver = { - .driver = { - .name = DRIVER_NAME, - }, - .probe = sfp_device_probe, - .remove = sfp_device_remove, - .id_table = sfp_device_id, - .address_list = normal_i2c, -}; - -static int __init sfp_init(void) -{ - return i2c_add_driver(&sfp_driver); -} - -static void __exit sfp_exit(void) -{ - i2c_del_driver(&sfp_driver); -} - -MODULE_AUTHOR("Brandon Chuang "); -MODULE_DESCRIPTION("juniper qfx5210_64x_sfp driver"); -MODULE_LICENSE("GPL"); - -module_init(sfp_init); -module_exit(sfp_exit); - diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_util.py b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_util.py index 2e65b76148..ccb32a3a89 100755 --- a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_util.py +++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_util.py @@ -56,8 +56,6 @@ args = [] ALL_DEVICE = {} DEVICE_NO = {'led':4, 'fan':4,'thermal':6, 'psu':2, 'sfp':64} FORCE = 0 -#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG) -#logging.basicConfig(level=logging.INFO) if DEBUG == True: @@ -124,6 +122,7 @@ def main(): print 'Error: Execution of "%s" failed', DisableWatchDogCmd return False + CPUeepromFileCmd = 'cat /sys/devices/pci0000:00/0000:00:1f.3/i2c-0/0-0056/eeprom > /etc/init.d/eeprom_qfx5210_ascii' # Write the contents of CPU EEPROM to file try: @@ -178,11 +177,11 @@ def driver_check(): kos = [ 'modprobe i2c_dev', -'modprobe i2c_mux_pca954x', +'modprobe i2c_mux_pca954x force_deselect_on_exit=1', +'modprobe optoe', 'modprobe juniper_i2c_cpld' , 'modprobe ym2651y' , 'modprobe x86-64-juniper-qfx5210-64x-fan' , -'modprobe x86-64-juniper-qfx5210-64x-sfp' , 'modprobe x86-64-juniper-qfx5210-64x-leds' , 'modprobe x86-64-juniper-qfx5210-64x-psu' ] @@ -220,7 +219,7 @@ i2c_bus = {'fan': ['17-0068'] , i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] , 'thermal': ['hwmon/hwmon*/temp1_input'] , 'psu': ['psu_present ', 'psu_power_good'] , - 'sfp': ['sfp_is_present ', 'sfp_tx_disable']} + 'sfp': ['sfp_is_present ', 'module_present']} sfp_map = [37,38,39,40,42,41,44,43,33,34,35,36,45,46,47,48,49,50,51,52, 61,62,63,64,53,54,55,56,57,58,59,60,69,70,71,72,77,78,79,80,65, @@ -274,11 +273,17 @@ def device_install(): return status for i in range(0,len(sfp_map)): - status, output =log_os_system("echo qfx5210_64x_port"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1) + path = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device" + status, output =log_os_system("echo optoe1 0x50 > " + path, 1) if status: print output if FORCE == 0: - return status + return status + status, output =log_os_system("echo Port"+str(i)+" > /sys/bus/i2c/devices/"+str(sfp_map[i])+"-0050/port_name", 1) + if status: + print output + if FORCE == 0: + return status return def device_uninstall(): @@ -381,7 +386,8 @@ def devices_info(): elif 'sfp' == key: for k in range(0,DEVICE_NO[key]): node = key+str(k+1) - path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j] + fmt = i2c_prefix+"19-0060/{0}_{1}" + path = fmt.format(nodes[j], k+1) my_log(node+": "+ path) ALL_DEVICE[key][node].append(path) else: @@ -416,10 +422,8 @@ def show_eeprom(index): print("Please install first!") return - if len(ALL_DEVICE)==0: - devices_info() - node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0] - node = node.replace(node.split("/")[-1], 'sfp_eeprom') + i = int(index)-1 + node = i2c_prefix+ str(sfp_map[i])+ i2c_bus['sfp'][0]+"/"+ 'eeprom' # check if got hexdump command in current environment ret, log = log_os_system("which hexdump", 0) ret, log2 = log_os_system("which busybox hexdump", 0) @@ -434,7 +438,7 @@ def show_eeprom(index): return 1 print node + ":" - ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1) + ret, log = log_os_system(hex_cmd +" -C "+node, 1) if ret==0: print log else: