Commit dfcea15f authored by Adam Wujek's avatar Adam Wujek 💬

Merge branch 'sfp_diag'

--Read DOM (Diagnostic Monitoring data) data from SFPs
--Fix the write to SFPs eeprom
--store DOM data in the HAL's shmem
Signed-off-by: Adam Wujek's avatarAdam Wujek <adam.wujek@cern.ch>
parents 79f88bdf 579646e4
...@@ -860,7 +860,11 @@ config FAN_HYSTERESIS_PWM_VAL ...@@ -860,7 +860,11 @@ config FAN_HYSTERESIS_PWM_VAL
PWM value used to drive fans. Range from 4 to 1000. PWM value used to drive fans. Range from 4 to 1000.
endmenu endmenu
config READ_SFP_DIAG_ENABLE
bool "Read SFPs Diagnostic Monitoring"
default n
help
Let HAL to read Diagnostic Monitoring from SFP's eeprom.
endmenu endmenu
menu "RTU HP mask" menu "RTU HP mask"
......
...@@ -834,6 +834,11 @@ value is changed by the web interface, proper action is taken. ...@@ -834,6 +834,11 @@ value is changed by the web interface, proper action is taken.
below @t{CONFIG_FAN_HYSTERESIS_T_DISABLE}. These options are intended to below @t{CONFIG_FAN_HYSTERESIS_T_DISABLE}. These options are intended to
be used during development to reduce noise generated by switch. be used during development to reduce noise generated by switch.
@item CONFIG_READ_SFP_DIAG_ENABLE
Let HAL to read Diagnostic Monitoring from SFP's eeprom like
temperature, TX/RX power etc.
@item CONFIG_RTU_HP_MASK_ENABLE @item CONFIG_RTU_HP_MASK_ENABLE
@itemx CONFIG_RTU_HP_MASK_VAL @itemx CONFIG_RTU_HP_MASK_VAL
......
...@@ -47,6 +47,9 @@ ...@@ -47,6 +47,9 @@
#define SFP_LED_WRMODE_MASK(t) ((t) ? (1 << 5) : (1 << 3)) #define SFP_LED_WRMODE_MASK(t) ((t) ? (1 << 5) : (1 << 3))
#define SFP_TX_DISABLE_MASK(t) ((t) ? (1 << 7) : (1 << 2)) #define SFP_TX_DISABLE_MASK(t) ((t) ? (1 << 7) : (1 << 2))
/* Either 8 or 16 byte pages, so we use the smaller */
#define SFP_PAGE_SIZE 8
/* /*
* We need these tables because the schematics are messed up * We need these tables because the schematics are messed up
* The first one is for figuring out the masks in the pca9548's * The first one is for figuring out the masks in the pca9548's
...@@ -318,6 +321,15 @@ void shw_sfp_print_header(struct shw_sfp_header *head) ...@@ -318,6 +321,15 @@ void shw_sfp_print_header(struct shw_sfp_header *head)
printf("\n"); printf("\n");
} }
void shw_sfp_print_dom(struct shw_sfp_dom * dom)
{
printf("Temperature: %.3f C\n", (int8_t)dom->temp[0] + dom->temp[1]/(float)256);
printf("Voltage: %.3f V\n", (dom->vcc[0]*256 + dom->vcc[1])/(float)10000);
printf("Bias Current: %.3f uA\n", (dom->tx_bias[0]*256+dom->tx_bias[1])/(float)500000);
printf("TX power: %.3f mW\n", (dom->tx_pow[0]*256 + dom->tx_pow[1])/(float)100000);
printf("RX power: %.3f mW\n", (dom->rx_pow[0]*256 + dom->rx_pow[1])/(float)100000);
}
void shw_sfp_header_dump(struct shw_sfp_header *head) void shw_sfp_header_dump(struct shw_sfp_header *head)
{ {
int i; int i;
...@@ -332,6 +344,20 @@ void shw_sfp_header_dump(struct shw_sfp_header *head) ...@@ -332,6 +344,20 @@ void shw_sfp_header_dump(struct shw_sfp_header *head)
} }
void shw_sfp_dom_dump(struct shw_sfp_dom *dom)
{
int i;
uint8_t *dump = (uint8_t *) dom;
printf("Dom Dump:");
for (i = 0; i < sizeof(struct shw_sfp_dom); i++) {
if (i % 8 == 0)
printf("\n");
printf("%02X ", dump[i]);
}
printf("\n");
}
/* Get the SFP ID from the SFP number (0 to 17) */ /* Get the SFP ID from the SFP number (0 to 17) */
inline int shw_sfp_id(int num) inline int shw_sfp_id(int num)
{ {
...@@ -369,15 +395,26 @@ int32_t shw_sfp_read(int num, uint32_t addr, int off, int len, uint8_t * buf) ...@@ -369,15 +395,26 @@ int32_t shw_sfp_read(int num, uint32_t addr, int off, int len, uint8_t * buf)
return i2c_transfer(bus, addr, 0, len, buf); return i2c_transfer(bus, addr, 0, len, buf);
} }
int32_t shw_sfp_write(int num, uint32_t addr, int off, int len, uint8_t * buf) int32_t shw_sfp_write(int num, uint32_t addr, int off, int len, uint8_t * buf)
{ {
int id; int id;
uint8_t byte1, byte2; uint8_t byte1, byte2;
int32_t counter = 0;
struct i2c_bus *bus; struct i2c_bus *bus;
int i = 0;
uint8_t page[SFP_PAGE_SIZE + 1];
int ret;
/* The SFP eeprom only supports 8 bit addresses */
if (len < 1 || len > 256 || off < 0 || off > 256 || off + len < 0
|| off + len > 256)
return -1;
id = shw_sfp_id(num); id = shw_sfp_id(num);
if (id < 0) if (id < 0)
return -1; return -1;
bus = &i2c_buses[WR_MUX_BUS]; bus = &i2c_buses[WR_MUX_BUS];
if (id == 0 || id == 1) if (id == 0 || id == 1)
bus = &i2c_buses[WR_SFP0_BUS + id]; bus = &i2c_buses[WR_SFP0_BUS + id];
...@@ -390,11 +427,44 @@ int32_t shw_sfp_write(int num, uint32_t addr, int off, int len, uint8_t * buf) ...@@ -390,11 +427,44 @@ int32_t shw_sfp_write(int num, uint32_t addr, int off, int len, uint8_t * buf)
i2c_transfer(bus, 0x71, 1, 0, &byte2); i2c_transfer(bus, 0x71, 1, 0, &byte2);
} }
/* Send the offset we want to write to if requested */ /* Write in a paged mode, 1 byte address */
if (off >= 0) page[0] = (counter + off) & 0xff;
i2c_transfer(bus, addr, 1, 0, (uint8_t *) & off); while (counter < len)
/* Do the read */ {
return i2c_transfer(bus, addr, len, 0, buf); page[i + 1] = buf[counter++];
i++;
/* When we hit a page boundary then perform a write */
if ((off + counter) % SFP_PAGE_SIZE == 0)
{
pr_debug("Writing %d bytes to EEPROM address %02x\n",
i, page[0]);
ret = i2c_transfer(bus, addr, i + 1, 0, page);
if (ret < 0) {
pr_error("i2c_transfer error code 0x%x\n",
ret);
return -1;
}
i = 0;
page[0] = (counter + off) & 0xff;
/* Sleep 10ms for eeprom to finish writing the page */
/* XXX this should actually be done by polling the */
/* EEPROM and seeing if it is ready */
usleep(10000);
}
}
/* Write the last page, if not already done */
if (i != 0)
{
pr_debug("Writing last %d bytes to EEPROM address %02x\n",
i, page[0]);
ret = i2c_transfer(bus, addr, i + 1, 0, page);
if (ret < 0) {
pr_error("i2c_transfer error code 0x%x\n", ret);
return -1;
}
usleep(10000);
}
return counter;
} }
uint32_t shw_sfp_module_scan(void) uint32_t shw_sfp_module_scan(void)
...@@ -559,6 +629,39 @@ int shw_sfp_read_header(int num, struct shw_sfp_header *head) ...@@ -559,6 +629,39 @@ int shw_sfp_read_header(int num, struct shw_sfp_header *head)
return 0; return 0;
} }
int shw_sfp_read_dom(int num, struct shw_sfp_dom *dom)
{
int ret;
if (shw_sfp_id(num) < 0) {
pr_error("shw_sfp_read_header: wrong SFP num %d\n", num + 1);
return -1;
}
ret = shw_sfp_module_scan();
if (!(ret & (1 << num))) {
pr_error("shw_sfp_read_header: SFP not present %d\n", num + 1);
return -2;
}
ret =
shw_sfp_read(num, I2C_SFP_DOM_ADDRESS, 0x0,
sizeof(struct shw_sfp_dom), (uint8_t *) dom);
if (ret == I2C_DEV_NOT_FOUND) {
pr_error("shw_sfp_read_header: I2C_DEV_NOT_FOUND\n");
return -ENODEV;
}
return 0;
}
/* Function to update SFP's Diagnostic Monitoring data from SFP's eeprom */
int shw_sfp_update_dom(int num, struct shw_sfp_dom *dom)
{
/* For now copy entire eeprom */
return shw_sfp_read_dom(num, dom);
}
int shw_sfp_read_verify_header(int num, struct shw_sfp_header *head) int shw_sfp_read_verify_header(int num, struct shw_sfp_header *head)
{ {
int ret; int ret;
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
//address from AT24C01 datasheet (1k, all address lines shorted to the ground) //address from AT24C01 datasheet (1k, all address lines shorted to the ground)
#define I2C_SFP_ADDRESS 0x50 #define I2C_SFP_ADDRESS 0x50
// From SFF-8472, but right-shifted one bit as I2C addresses are only 7 bits.
#define I2C_SFP_DOM_ADDRESS 0x51
/* The two FPGA buses */ /* The two FPGA buses */
#define WR_FPGA_BUS0 0 #define WR_FPGA_BUS0 0
......
...@@ -12,6 +12,10 @@ ...@@ -12,6 +12,10 @@
#define HAL_PORT_STATE_CALIBRATION 3 #define HAL_PORT_STATE_CALIBRATION 3
#define HAL_PORT_STATE_LOCKING 4 #define HAL_PORT_STATE_LOCKING 4
/* Read temperature from SFPs */
#define READ_SFP_DIAG_ENABLE 1
#define READ_SFP_DIAG_DISABLE 0
#define DEFAULT_T2_PHASE_TRANS 0 #define DEFAULT_T2_PHASE_TRANS 0
#define DEFAULT_T4_PHASE_TRANS 0 #define DEFAULT_T4_PHASE_TRANS 0
...@@ -46,6 +50,7 @@ typedef struct hal_port_calibration { ...@@ -46,6 +50,7 @@ typedef struct hal_port_calibration {
struct shw_sfp_caldata sfp; struct shw_sfp_caldata sfp;
struct shw_sfp_header sfp_header_raw; struct shw_sfp_header sfp_header_raw;
struct shw_sfp_dom sfp_dom_raw;
} hal_port_calibration_t; } hal_port_calibration_t;
/* Internal port state structure */ /* Internal port state structure */
...@@ -100,6 +105,9 @@ struct hal_port_state { ...@@ -100,6 +105,9 @@ struct hal_port_state {
/* Endpoint's base address */ /* Endpoint's base address */
uint32_t ep_base; uint32_t ep_base;
/* whether SFP has diagnostic Monitoring capability */
int has_sfp_diag;
}; };
struct hal_temp_sensors { struct hal_temp_sensors {
...@@ -110,13 +118,15 @@ struct hal_temp_sensors { ...@@ -110,13 +118,15 @@ struct hal_temp_sensors {
}; };
/* This is the overall structure stored in shared memory */ /* This is the overall structure stored in shared memory */
#define HAL_SHMEM_VERSION 9 /* Version 9 because of adding sfp_header_raw */ #define HAL_SHMEM_VERSION 10 /* Version 10 because of adding sfp_dom_raw
has_sfp_diag and read_sfp_diag */
struct hal_shmem_header { struct hal_shmem_header {
int nports; int nports;
int hal_mode; int hal_mode;
struct hal_port_state *ports; struct hal_port_state *ports;
struct hal_temp_sensors temp; struct hal_temp_sensors temp;
int read_sfp_diag;
}; };
static inline int state_up(int state) static inline int state_up(int state)
......
...@@ -30,6 +30,16 @@ ...@@ -30,6 +30,16 @@
#define SFP_SPEED_1Gb_10 0x0A /* Unfortunatelly the above is not always true, #define SFP_SPEED_1Gb_10 0x0A /* Unfortunatelly the above is not always true,
* e.g. Cisco copper SFP (MGBT1) says simply 10 and not 13.*/ * e.g. Cisco copper SFP (MGBT1) says simply 10 and not 13.*/
#define SFP_DIAGNOSTIC_IMPLEMENTED (1 << 6) /* Digital diagnostic monitoring
implemented. "1" for compliance
with SFF-8472 */
#define SFP_ADDR_CHANGE_REQ (1 << 2) /* Bit 2 indicates whether or not it is
necessary for the host to perform an
address change sequence before
accessing information at 2-wire serial
address A2h. */
struct shw_sfp_caldata { struct shw_sfp_caldata {
uint32_t flags; uint32_t flags;
/* /*
...@@ -64,9 +74,9 @@ struct shw_sfp_header { ...@@ -64,9 +74,9 @@ struct shw_sfp_header {
uint8_t length3; /* Link length supported for 50/125 mm fiber (10m) */ uint8_t length3; /* Link length supported for 50/125 mm fiber (10m) */
uint8_t length4; /* Link length supported for 62.5/125 mm fiber (10m) */ uint8_t length4; /* Link length supported for 62.5/125 mm fiber (10m) */
uint8_t length5; /* Link length supported for copper (1m) */ uint8_t length5; /* Link length supported for copper (1m) */
uint8_t reserved2; uint8_t length6; /* Link length supported on OM3 (1m) */
uint8_t vendor_name[16]; uint8_t vendor_name[16];
uint8_t reserved3; uint8_t reserved3; /* This is now a field named transceiver */
uint8_t vendor_oui[3]; uint8_t vendor_oui[3];
uint8_t vendor_pn[16]; uint8_t vendor_pn[16];
uint8_t vendor_rev[4]; uint8_t vendor_rev[4];
...@@ -80,10 +90,73 @@ struct shw_sfp_header { ...@@ -80,10 +90,73 @@ struct shw_sfp_header {
uint8_t br_min; uint8_t br_min;
uint8_t vendor_serial[16]; uint8_t vendor_serial[16];
uint8_t date_code[8]; uint8_t date_code[8];
uint8_t reserved[3]; uint8_t diagnostic_monitoring_type;
uint8_t enhanced_options;
uint8_t sff_8472_compliance;
uint8_t cc_ext; uint8_t cc_ext;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct shw_sfp_dom {
/* Treshold values, 0 - 55 */
uint8_t temp_high_alarm[2];
uint8_t temp_low_alarm[2];
uint8_t temp_high_warn[2];
uint8_t temp_low_warn[2];
uint8_t volt_high_alarm[2];
uint8_t volt_low_alarm[2];
uint8_t volt_high_warn[2];
uint8_t volt_low_warn[2];
uint8_t bias_high_alarm[2];
uint8_t bias_low_alarm[2];
uint8_t bias_high_warn[2];
uint8_t bias_low_warn[2];
uint8_t tx_pow_high_alarm[2];
uint8_t tx_pow_low_alarm[2];
uint8_t tx_pow_high_warn[2];
uint8_t tx_pow_low_warn[2];
uint8_t rx_pow_high_alarm[2];
uint8_t rx_pow_log_alarm[2];
uint8_t rx_power_high_warn[2];
uint8_t rx_power_low_warn[2];
uint8_t unalloc0[16];
/* Calibration data, 56-91 */
uint8_t cal_rx_pwr4[4];
uint8_t cal_rx_pwr3[4];
uint8_t cal_rx_pwr2[4];
uint8_t cal_rx_pwr1[4];
uint8_t cal_rx_pwr0[4];
uint8_t cal_tx_i_slope[2];
uint8_t cal_tx_i_offset[2];
uint8_t cal_tx_pow_slope[2];
uint8_t cal_tx_pow_offset[2];
uint8_t cal_T_slope[2];
uint8_t cal_T_offset[2];
uint8_t cal_V_slope[2];
uint8_t cal_V_offset[2];
/* Unallocated and checksum, 92-95 */
uint8_t cal_unalloc[3];
uint8_t CC_DMI;
/* Real Time Diagnostics, 96-111 */
uint8_t temp[2];
uint8_t vcc[2];
uint8_t tx_bias[2];
uint8_t tx_pow[2];
uint8_t rx_pow[2];
uint8_t rtd_unalloc0[4];
uint8_t OSCB;
uint8_t rtd_unalloc1;
/* Alarms and Warnings, 112 - 117 */
uint8_t alw[6];
/* Extended Module Control/Status bytes 118 - 119 */
uint8_t emcsb[2];
/* Vendor locations 120 - 127 */
uint8_t vendor_locations[8];
/* User data 128 - 247 */
uint8_t dom_user[120];
/* Vendor specific control function locations 248 - 255 */
uint8_t vendor_functions[8];
} __attribute__ ((packed));
/* Public API */ /* Public API */
/* /*
...@@ -113,6 +186,18 @@ int shw_sfp_read_db(void); ...@@ -113,6 +186,18 @@ int shw_sfp_read_db(void);
/* Read and verify the header all at once. returns -1 on failure */ /* Read and verify the header all at once. returns -1 on failure */
int shw_sfp_read_verify_header(int num, struct shw_sfp_header *head); int shw_sfp_read_verify_header(int num, struct shw_sfp_header *head);
/* Read the SFP diagnostics page */
int shw_sfp_read_dom(int num, struct shw_sfp_dom *dom);
/* Update the SFP diagnostics page */
int shw_sfp_update_dom(int num, struct shw_sfp_dom *dom);
/* Decode and print the SFP real time diagnostics */
void shw_sfp_print_dom(struct shw_sfp_dom * dom);
/* Dump the SFP diagnostics page in hex */
void shw_sfp_dom_dump(struct shw_sfp_dom * dom);
/* return NULL if no data found */ /* return NULL if no data found */
struct shw_sfp_caldata *shw_sfp_get_cal_data(int num, struct shw_sfp_caldata *shw_sfp_get_cal_data(int num,
struct shw_sfp_header *head); struct shw_sfp_header *head);
......
ppsi @ 6f9508cf
Subproject commit 3ece12b3824d42910145fe0fa622d00cac1597ef Subproject commit 6f9508cfb22a78f00fab8db6ff2e6c84441dcb3a
...@@ -382,6 +382,7 @@ void dump_many_fields(void *addr, struct dump_info *info, int ninfo) ...@@ -382,6 +382,7 @@ void dump_many_fields(void *addr, struct dump_info *info, int ninfo)
struct dump_info hal_shmem_info [] = { struct dump_info hal_shmem_info [] = {
DUMP_FIELD(int, nports), DUMP_FIELD(int, nports),
DUMP_FIELD(int, hal_mode), DUMP_FIELD(int, hal_mode),
DUMP_FIELD(int, read_sfp_diag),
DUMP_FIELD(sensor_temp, temp.fpga), DUMP_FIELD(sensor_temp, temp.fpga),
DUMP_FIELD(sensor_temp, temp.pll), DUMP_FIELD(sensor_temp, temp.pll),
DUMP_FIELD(sensor_temp, temp.psl), DUMP_FIELD(sensor_temp, temp.psl),
...@@ -433,6 +434,7 @@ struct dump_info hal_port_info [] = { ...@@ -433,6 +434,7 @@ struct dump_info hal_port_info [] = {
DUMP_FIELD(uint32_t, t2_phase_transition), DUMP_FIELD(uint32_t, t2_phase_transition),
DUMP_FIELD(uint32_t, t4_phase_transition), DUMP_FIELD(uint32_t, t4_phase_transition),
DUMP_FIELD(uint32_t, ep_base), DUMP_FIELD(uint32_t, ep_base),
DUMP_FIELD(int, has_sfp_diag),
}; };
int dump_hal_mem(struct wrs_shm_head *head) int dump_hal_mem(struct wrs_shm_head *head)
......
...@@ -33,11 +33,12 @@ void print_info(char *prgname) ...@@ -33,11 +33,12 @@ void print_info(char *prgname)
"Optional parameters:\n" "Optional parameters:\n"
" -p <num> Dump sfp header for specific port (1-18); dump sfp header info for all\n" " -p <num> Dump sfp header for specific port (1-18); dump sfp header info for all\n"
" ports if no <-p> specified\n" " ports if no <-p> specified\n"
" -x Dump sfp header also in hex\n"
" -a <READ|WRITE> Read/write SFP's eeprom; works only with <-I>;\n" " -a <READ|WRITE> Read/write SFP's eeprom; works only with <-I>;\n"
" before READs/WRITEs disable HAL and monit!\n" " before READs/WRITEs disable HAL and monit!\n"
" -f <file> File to READ/WRITE SFP's eeprom\n" " -f <file> File to READ/WRITE SFP's eeprom\n"
" -H <dir> Open shmem dumps from the given directory; works only with <-L>\n" " -H <dir> Open shmem dumps from the given directory; works only with <-L>\n"
" -d Dump sfp DOM data page\n"
" -x Dump sfp/DOM header also in hex\n"
" -q Decrease verbosity\n" " -q Decrease verbosity\n"
" -v Increase verbosity\n" " -v Increase verbosity\n"
" -V Print version\n" " -V Print version\n"
...@@ -201,7 +202,8 @@ void print_version(char *prgname) ...@@ -201,7 +202,8 @@ void print_version(char *prgname)
__GIT_USR__); __GIT_USR__);
} }
int hal_read(struct shw_sfp_header *sfp_header_local_copy) { int hal_read(struct shw_sfp_header *sfp_header_local_copy,
struct shw_sfp_dom *sfp_dom) {
unsigned ii; unsigned ii;
unsigned retries = 0; unsigned retries = 0;
int port; int port;
...@@ -214,7 +216,12 @@ int hal_read(struct shw_sfp_header *sfp_header_local_copy) { ...@@ -214,7 +216,12 @@ int hal_read(struct shw_sfp_header *sfp_header_local_copy) {
&hal_ports[port].calib.sfp_header_raw, &hal_ports[port].calib.sfp_header_raw,
sizeof(struct shw_sfp_header)); sizeof(struct shw_sfp_header));
} }
if (sfp_dom)
for (port = 0; port < hal_nports_local; port++) {
memcpy(&sfp_dom[port],
&hal_ports[port].calib.sfp_dom_raw,
sizeof(struct shw_sfp_dom));
}
retries++; retries++;
if (retries > 100) if (retries > 100)
return -1; return -1;
...@@ -280,23 +287,27 @@ int main(int argc, char **argv) ...@@ -280,23 +287,27 @@ int main(int argc, char **argv)
int c; int c;
struct shw_sfp_header sfp_hdr; struct shw_sfp_header sfp_hdr;
struct shw_sfp_header *sfp_hdr_p; struct shw_sfp_header *sfp_hdr_p;
struct shw_sfp_dom sfp_dom;
struct shw_sfp_dom *sfp_dom_p;
int err; int err;
int nports; int nports;
int dump_port; int dump_port;
int i; int i;
int dump_hex_header = 0; int dump_hex_header = 0;
int dump_sfp_dom = 0;
int operation = 0; int operation = 0;
char *eeprom_file = NULL; char *eeprom_file = NULL;
int sfp_data_source = 0; int sfp_data_source = 0;
/* local copy of sfp eeprom */ /* local copy of sfp eeprom */
struct shw_sfp_header hal_sfp_raw_header_lc[HAL_MAX_PORTS]; struct shw_sfp_header hal_sfp_raw_header_lc[HAL_MAX_PORTS];
struct shw_sfp_dom hal_sfp_raw_dom_lc[HAL_MAX_PORTS];
wrs_msg_init(argc, argv); wrs_msg_init(argc, argv);
nports = 18; nports = 18;
dump_port = 1; dump_port = 1;
while ((c = getopt(argc, argv, "a:hqvp:xVf:LIH:")) != -1) { while ((c = getopt(argc, argv, "a:hqvp:xVf:LIdH:")) != -1) {
switch (c) { switch (c) {
case 'p': case 'p':
dump_port = atoi(optarg); dump_port = atoi(optarg);
...@@ -311,6 +322,9 @@ int main(int argc, char **argv) ...@@ -311,6 +322,9 @@ int main(int argc, char **argv)
case 'x': case 'x':
dump_hex_header = 1; dump_hex_header = 1;
break; break;
case 'd':
dump_sfp_dom = 1;
break;
case 'V': case 'V':
print_version(argv[0]); print_version(argv[0]);
exit(0); exit(0);
...@@ -363,7 +377,7 @@ int main(int argc, char **argv) ...@@ -363,7 +377,7 @@ int main(int argc, char **argv)
if (sfp_data_source == READ_HAL) { if (sfp_data_source == READ_HAL) {
hal_init_shm(); hal_init_shm();
hal_read(hal_sfp_raw_header_lc); hal_read(hal_sfp_raw_header_lc, hal_sfp_raw_dom_lc);
printf("Reading SFP eeprom from HAL\n"); printf("Reading SFP eeprom from HAL\n");
} }
...@@ -392,9 +406,13 @@ int main(int argc, char **argv) ...@@ -392,9 +406,13 @@ int main(int argc, char **argv)
memset(&sfp_hdr, 0, sizeof(sfp_hdr)); memset(&sfp_hdr, 0, sizeof(sfp_hdr));
sfp_hdr_p = &sfp_hdr; sfp_hdr_p = &sfp_hdr;
err = shw_sfp_read_header(i - 1, sfp_hdr_p); err = shw_sfp_read_header(i - 1, sfp_hdr_p);
memset(&sfp_dom, 0, sizeof(sfp_dom));
sfp_dom_p = &sfp_dom;
shw_sfp_read_dom(i - 1, sfp_dom_p);
} }
if (sfp_data_source == READ_HAL) { if (sfp_data_source == READ_HAL) {
sfp_hdr_p = &hal_sfp_raw_header_lc[i - 1]; sfp_hdr_p = &hal_sfp_raw_header_lc[i - 1];
sfp_dom_p = &hal_sfp_raw_dom_lc[i - 1];
} }
err = shw_sfp_header_verify(sfp_hdr_p); err = shw_sfp_header_verify(sfp_hdr_p);
if (err == -2) { if (err == -2) {
...@@ -408,6 +426,12 @@ int main(int argc, char **argv) ...@@ -408,6 +426,12 @@ int main(int argc, char **argv)
if (dump_hex_header) { if (dump_hex_header) {
shw_sfp_header_dump(sfp_hdr_p); shw_sfp_header_dump(sfp_hdr_p);
} }
if(dump_sfp_dom) {
shw_sfp_print_dom(sfp_dom_p);
if(dump_hex_header) {
shw_sfp_dom_dump(sfp_dom_p);
}
}
} }
} }
return 0; return 0;
......
...@@ -211,6 +211,7 @@ static int hal_port_init(int index) ...@@ -211,6 +211,7 @@ static int hal_port_init(int index)
int hal_port_init_shmem(char *logfilename) int hal_port_init_shmem(char *logfilename)
{ {
int index; int index;
char *ret;
pr_info("Initializing switch ports...\n"); pr_info("Initializing switch ports...\n");
/* default timeouts */ /* default timeouts */
...@@ -255,6 +256,14 @@ int hal_port_init_shmem(char *logfilename) ...@@ -255,6 +256,14 @@ int hal_port_init_shmem(char *logfilename)
hal_shmem->nports = hal_port_nports; hal_shmem->nports = hal_port_nports;
hal_shmem_hdr->version = HAL_SHMEM_VERSION; hal_shmem_hdr->version = HAL_SHMEM_VERSION;
hal_shmem->hal_mode = hal_get_timing_mode(); hal_shmem->hal_mode = hal_get_timing_mode();
ret = libwr_cfg_get("READ_SFP_DIAG_ENABLE");
if (ret && !strcmp(ret, "y")) {
pr_info("Read SFP Diagnostic Monitoring enabled\n");
hal_shmem->read_sfp_diag = READ_SFP_DIAG_ENABLE;
} else
hal_shmem->read_sfp_diag = READ_SFP_DIAG_DISABLE;
/* Release processes waiting for HAL's to fill shm with correct data /* Release processes waiting for HAL's to fill shm with correct data
When shm is opened successfully data in shm is still not populated! When shm is opened successfully data in shm is still not populated!
Read data with wrs_shm_seqbegin and wrs_shm_seqend! Read data with wrs_shm_seqbegin and wrs_shm_seqend!
...@@ -478,6 +487,7 @@ static void hal_port_insert_sfp(struct hal_port_state * p) ...@@ -478,6 +487,7 @@ static void hal_port_insert_sfp(struct hal_port_state * p)
int err; int err;
memset(&shdr, 0, sizeof(struct shw_sfp_header)); memset(&shdr, 0, sizeof(struct shw_sfp_header));
memset(&p->calib.sfp_dom_raw, 0, sizeof(struct shw_sfp_dom));
err = shw_sfp_read_verify_header(p->hw_index, &shdr); err = shw_sfp_read_verify_header(p->hw_index, &shdr);
memcpy(&p->calib.sfp_header_raw, &shdr, sizeof(struct shw_sfp_header)); memcpy(&p->calib.sfp_header_raw, &shdr, sizeof(struct shw_sfp_header));
if (err == -2) { if (err == -2) {
...@@ -489,7 +499,27 @@ static void hal_port_insert_sfp(struct hal_port_state * p) ...@@ -489,7 +499,27 @@ static void hal_port_insert_sfp(struct hal_port_state * p)
p->name); p->name);
return; return;
} }
if (hal_shmem->read_sfp_diag == READ_SFP_DIAG_ENABLE
&& shdr.diagnostic_monitoring_type & SFP_DIAGNOSTIC_IMPLEMENTED) {
pr_info("SFP Diagnostic Monitoring implemented in SFP plugged"
" to port %d (%s)\n", p->hw_index + 1, p->name);
if (shdr.diagnostic_monitoring_type & SFP_ADDR_CHANGE_REQ) {
pr_warning("SFP in port %d (%s) requires special "
"address change before accessing Diagnostic"
" Monitoring, which is not implemented "
"right now\n", p->hw_index + 1, p->name);
} else {
/* copy coontent of SFP's Diagnostic Monitoring */
shw_sfp_read_dom(p->hw_index, &p->calib.sfp_dom_raw);
if (err < 0) {
pr_error("Failed to read SFP Diagnostic "
"Monitoring for port %d (%s)\n",
p->hw_index + 1, p->name);
}
p->has_sfp_diag = 1;
}
}
pr_info("SFP Info: Manufacturer: %.16s P/N: %.16s, S/N: %.16s\n", pr_info("SFP Info: Manufacturer: %.16s P/N: %.16s, S/N: %.16s\n",
shdr.vendor_name, shdr.vendor_pn, shdr.vendor_serial); shdr.vendor_name, shdr.vendor_pn, shdr.vendor_serial);
cdata = shw_sfp_get_cal_data(p->hw_index, &shdr); cdata = shw_sfp_get_cal_data(p->hw_index, &shdr);
...@@ -570,6 +600,8 @@ static void hal_port_remove_sfp(struct hal_port_state * p) ...@@ -570,6 +600,8 @@ static void hal_port_remove_sfp(struct hal_port_state * p)
/* clean SFP's details when removing SFP */ /* clean SFP's details when removing SFP */
memset(&p->calib.sfp, 0, sizeof(p->calib.sfp)); memset(&p->calib.sfp, 0, sizeof(p->calib.sfp));
memset(&p->calib.sfp_header_raw, 0, sizeof(struct shw_sfp_header)); memset(&p->calib.sfp_header_raw, 0, sizeof(struct shw_sfp_header));
memset(&p->calib.sfp_dom_raw, 0, sizeof(struct shw_sfp_dom));
p->has_sfp_diag = 0;
} }
/* detects insertion/removal of SFP transceivers */ /* detects insertion/removal of SFP transceivers */
...@@ -615,10 +647,20 @@ void hal_port_update_all() ...@@ -615,10 +647,20 @@ void hal_port_update_all()
hal_port_poll_sfp(); hal_port_poll_sfp();
for (i = 0; i < HAL_MAX_PORTS; i++) for (i = 0; i < HAL_MAX_PORTS; i++)
if (ports[i].in_use) if (ports[i].in_use) {
hal_port_fsm(&ports[i]); hal_port_fsm(&ports[i]);
/* update DOM only for plugged ports with DOM
* capabilities */
if (ports[i].state != HAL_PORT_STATE_DISABLED
&& hal_shmem->read_sfp_diag == READ_SFP_DIAG_ENABLE
&& (ports[i].has_sfp_diag)) {
shw_sfp_update_dom(ports[i].hw_index,
&ports[i].calib.sfp_dom_raw);
}
}
/* unlock shmem */ /* unlock shmem */
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_END); wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_END);
} }
int hal_port_enable_tracking(const char *port_name) int hal_port_enable_tracking(const char *port_name)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment