Commit 3f05b29c authored by Adam Wujek's avatar Adam Wujek 💬

userspace/wrsw_hal: save Diagnostic Monitoring data from SFP in HAL

Kconfig:
--add CONFIG_READ_SFP_DIAG_ENABLE
libwr:
--add the function shw_sfp_update_dom to update only needed values in the future
--increase HAL_SHMEM_VERSION due to the changes in structures
wrs_dump_shmem
--add new fields
HAL:
--read DOM (Diagnostic Monitoring data) from SFP's eeprom at plug and once
  per second
PPSI:
--uplift hal shmem header
wrs_sfp_dump:
--support reading SFP's DOM from HAL
Signed-off-by: Adam Wujek's avatarAdam Wujek <adam.wujek@cern.ch>
parent de57d4ae
......@@ -860,7 +860,11 @@ config FAN_HYSTERESIS_PWM_VAL
PWM value used to drive fans. Range from 4 to 1000.
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
menu "RTU HP mask"
......
......@@ -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
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
@itemx CONFIG_RTU_HP_MASK_VAL
......
......@@ -608,6 +608,13 @@ int shw_sfp_read_dom(int num, struct shw_sfp_dom *dom)
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 ret;
......
......@@ -12,6 +12,10 @@
#define HAL_PORT_STATE_CALIBRATION 3
#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_T4_PHASE_TRANS 0
......@@ -46,6 +50,7 @@ typedef struct hal_port_calibration {
struct shw_sfp_caldata sfp;
struct shw_sfp_header sfp_header_raw;
struct shw_sfp_dom sfp_dom_raw;
} hal_port_calibration_t;
/* Internal port state structure */
......@@ -100,6 +105,9 @@ struct hal_port_state {
/* Endpoint's base address */
uint32_t ep_base;
/* whether SFP has diagnostic Monitoring capability */
int has_sfp_diag;
};
struct hal_temp_sensors {
......@@ -110,13 +118,15 @@ struct hal_temp_sensors {
};
/* 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 {
int nports;
int hal_mode;
struct hal_port_state *ports;
struct hal_temp_sensors temp;
int read_sfp_diag;
};
static inline int state_up(int state)
......
......@@ -30,6 +30,16 @@
#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.*/
#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 {
uint32_t flags;
/*
......@@ -80,7 +90,9 @@ struct shw_sfp_header {
uint8_t br_min;
uint8_t vendor_serial[16];
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;
} __attribute__ ((packed));
......@@ -177,6 +189,9 @@ 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);
......
ppsi @ 6f9508cf
Subproject commit 3ece12b3824d42910145fe0fa622d00cac1597ef
Subproject commit 6f9508cfb22a78f00fab8db6ff2e6c84441dcb3a
......@@ -382,6 +382,7 @@ void dump_many_fields(void *addr, struct dump_info *info, int ninfo)
struct dump_info hal_shmem_info [] = {
DUMP_FIELD(int, nports),
DUMP_FIELD(int, hal_mode),
DUMP_FIELD(int, read_sfp_diag),
DUMP_FIELD(sensor_temp, temp.fpga),
DUMP_FIELD(sensor_temp, temp.pll),
DUMP_FIELD(sensor_temp, temp.psl),
......@@ -433,6 +434,7 @@ struct dump_info hal_port_info [] = {
DUMP_FIELD(uint32_t, t2_phase_transition),
DUMP_FIELD(uint32_t, t4_phase_transition),
DUMP_FIELD(uint32_t, ep_base),
DUMP_FIELD(int, has_sfp_diag),
};
int dump_hal_mem(struct wrs_shm_head *head)
......
......@@ -202,7 +202,8 @@ void print_version(char *prgname)
__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 retries = 0;
int port;
......@@ -215,7 +216,12 @@ int hal_read(struct shw_sfp_header *sfp_header_local_copy) {
&hal_ports[port].calib.sfp_header_raw,
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++;
if (retries > 100)
return -1;
......@@ -282,6 +288,7 @@ int main(int argc, char **argv)
struct shw_sfp_header sfp_hdr;
struct shw_sfp_header *sfp_hdr_p;
struct shw_sfp_dom sfp_dom;
struct shw_sfp_dom *sfp_dom_p;
int err;
int nports;
int dump_port;
......@@ -293,6 +300,7 @@ int main(int argc, char **argv)
int sfp_data_source = 0;
/* local copy of sfp eeprom */
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);
......@@ -369,7 +377,7 @@ int main(int argc, char **argv)
if (sfp_data_source == READ_HAL) {
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");
}
......@@ -398,9 +406,13 @@ int main(int argc, char **argv)
memset(&sfp_hdr, 0, sizeof(sfp_hdr));
sfp_hdr_p = &sfp_hdr;
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) {
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);
if (err == -2) {
......@@ -415,10 +427,9 @@ int main(int argc, char **argv)
shw_sfp_header_dump(sfp_hdr_p);
}
if(dump_sfp_dom) {
shw_sfp_read_dom(i - 1, &sfp_dom);
shw_sfp_print_dom(&sfp_dom);
shw_sfp_print_dom(sfp_dom_p);
if(dump_hex_header) {
shw_sfp_dom_dump(&sfp_dom);
shw_sfp_dom_dump(sfp_dom_p);
}
}
}
......
......@@ -211,6 +211,7 @@ static int hal_port_init(int index)
int hal_port_init_shmem(char *logfilename)
{
int index;
char *ret;
pr_info("Initializing switch ports...\n");
/* default timeouts */
......@@ -255,6 +256,14 @@ int hal_port_init_shmem(char *logfilename)
hal_shmem->nports = hal_port_nports;
hal_shmem_hdr->version = HAL_SHMEM_VERSION;
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
When shm is opened successfully data in shm is still not populated!
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)
int err;
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);
memcpy(&p->calib.sfp_header_raw, &shdr, sizeof(struct shw_sfp_header));
if (err == -2) {
......@@ -489,7 +499,27 @@ static void hal_port_insert_sfp(struct hal_port_state * p)
p->name);
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",
shdr.vendor_name, shdr.vendor_pn, shdr.vendor_serial);
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)
/* clean SFP's details when removing 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_dom_raw, 0, sizeof(struct shw_sfp_dom));
p->has_sfp_diag = 0;
}
/* detects insertion/removal of SFP transceivers */
......@@ -615,10 +647,20 @@ void hal_port_update_all()
hal_port_poll_sfp();
for (i = 0; i < HAL_MAX_PORTS; i++)
if (ports[i].in_use)
if (ports[i].in_use) {
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 */
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_END);
}
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