From c112bd11ef16b0999ad7c0be4efd4b94a2d3ac95 Mon Sep 17 00:00:00 2001 From: Adam Wujek <adam.wujek@cern.ch> Date: Fri, 26 Aug 2016 16:33:10 +0200 Subject: [PATCH] [Feature: 1364] userspace/wrsw_hal: store SFP's eeprom in shmem on SFP insert --add struct shw_sfp_header sfp_header_raw to the struct hal_port_calibration. --Increase HAL_SHMEM_VERSION to 9 due to the above --add a parameter to the wrs_sfp_dump to dump eeprom directly from the SFP or saved data from HAL Signed-off-by: Adam Wujek <adam.wujek@cern.ch> --- userspace/libwr/include/libwr/hal_shmem.h | 4 +- userspace/libwr/include/libwr/shmem.h | 1 + userspace/ppsi | 2 +- userspace/tools/wrs_sfp_dump.c | 190 +++++++++++++++++++--- userspace/wrsw_hal/hal_ports.c | 3 + 5 files changed, 170 insertions(+), 30 deletions(-) diff --git a/userspace/libwr/include/libwr/hal_shmem.h b/userspace/libwr/include/libwr/hal_shmem.h index c5da79eef..4fa23ef9f 100644 --- a/userspace/libwr/include/libwr/hal_shmem.h +++ b/userspace/libwr/include/libwr/hal_shmem.h @@ -45,7 +45,7 @@ typedef struct hal_port_calibration { int tx_calibrated; struct shw_sfp_caldata sfp; - + struct shw_sfp_header sfp_header_raw; } hal_port_calibration_t; /* Internal port state structure */ @@ -110,7 +110,7 @@ struct hal_temp_sensors { }; /* This is the overall structure stored in shared memory */ -#define HAL_SHMEM_VERSION 8 /* Version 8 because of adding HAL mode */ +#define HAL_SHMEM_VERSION 9 /* Version 9 because of adding sfp_header_raw */ struct hal_shmem_header { int nports; diff --git a/userspace/libwr/include/libwr/shmem.h b/userspace/libwr/include/libwr/shmem.h index fae34d253..9cb9cd721 100644 --- a/userspace/libwr/include/libwr/shmem.h +++ b/userspace/libwr/include/libwr/shmem.h @@ -5,6 +5,7 @@ #ifndef __WRS_SHM_H__ #define __WRS_SHM_H__ #include <stdint.h> +#include <stdio.h> #define WRS_SHM_DEFAULT_PATH "/dev/shm" #define WRS_SHM_FILE "wrs-shmem-%i" diff --git a/userspace/ppsi b/userspace/ppsi index d040a2070..ab7106d25 160000 --- a/userspace/ppsi +++ b/userspace/ppsi @@ -1 +1 @@ -Subproject commit d040a2070c57e7863ab528393667e3e5d8e3fd55 +Subproject commit ab7106d253d8d1a3651b8a5cb354a5dcd4ca1b63 diff --git a/userspace/tools/wrs_sfp_dump.c b/userspace/tools/wrs_sfp_dump.c index a0a331118..3da154704 100644 --- a/userspace/tools/wrs_sfp_dump.c +++ b/userspace/tools/wrs_sfp_dump.c @@ -5,6 +5,9 @@ #include <libwr/shw_io.h> /* for shw_sfp_buses_init and shw_sfp_print_header*/ #include "../libwr/i2c_sfp.h" +#include <libwr/shmem.h> +#include <libwr/hal_shmem.h> + #define SFP_EEPROM_READ 1 #define SFP_EEPROM_WRITE 2 @@ -13,21 +16,34 @@ #define MONIT_PROCESS_NAME "/usr/bin/monit" #define PROCESS_COMMAND_MONIT "/bin/ps axo stat o command" +#define READ_HAL 1 +#define READ_I2C 2 + +static struct wrs_shm_head *hal_head; +static struct hal_port_state *hal_ports; +static int hal_nports_local; + void print_info(char *prgname) { - printf("usage: %s [parameters]\n", prgname); + printf("usage: %s <-I|-L> [parameters]\n", prgname); printf("" - " Dump sfp header info for all ports\n" - " -p <num> Dump sfp header for specific port (1-18)\n" + "Select the source of SFP eeprom data:\n" + " -L Use eeprom data read by HAL at SFP insertion time\n" + " -I Use read eeprom data directly from SFP via I2C\n" + "Optional parameters:\n" + " -p <num> Dump sfp header for specific port (1-18); dump sfp header info for all\n" + " ports if no <-p> specified\n" " -x Dump sfp header also in hex\n" - " -h Show this message\n" + " -a <READ|WRITE> Read/write SFP's eeprom; works only with <-I>;\n" + " before READs/WRITEs disable HAL and monit!\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" " -q Decrease verbosity\n" " -v Increase verbosity\n" " -V Print version\n" - " -a <READ|WRITE> Read/write SFP's eeprom; before reads/writes disable HAL and monit!\n" - " -f <file> File to READ/WRITE SFP's eeprom\n" + " -h Show this message\n" "\n" - "NOTE: Be carefull! All reads (i2c transfers) are in race with hal!\n" + "NOTE: Be carefull! All reads (i2c transfers) are in race with HAL!\n" ); } @@ -95,6 +111,10 @@ static void sfp_eeprom_read(char *eeprom_file, int port) FILE *fp; int ret; + if (!eeprom_file) { + pr_error("Please specify file to READ!\n"); + exit(1); + } memset(&sfp_header, 0, sizeof(struct shw_sfp_header)); if (check_hal() > 0) { /* HAL may disturb sfp's eeprom read! */ @@ -132,14 +152,18 @@ static void sfp_eeprom_write(char *eeprom_file, int port) FILE *fp; int ret; + if (!eeprom_file) { + pr_error("Please specify file to WRITE!\n"); + exit(1); + } memset(&sfp_header, 0, sizeof(struct shw_sfp_header)); if (check_hal() > 0) { - /* HAL may disturb sfp's eeprom read! */ - pr_error("HAL is running! It may disturb SFP's eeprom read\n"); + /* HAL may disturb sfp's eeprom write! */ + pr_error("HAL is running! It may disturb SFP's eeprom write\n"); exit(1); } if (check_monit() > 0) { - /* Monit may restart, which may disturb sfp's eeprom read! */ + /* Monit may restart, which may disturb sfp's eeprom write! */ pr_error("Monit is running! It may restart HAL\n"); exit(1); } @@ -177,10 +201,81 @@ void print_version(char *prgname) __GIT_USR__); } +int hal_read(struct shw_sfp_header *sfp_header_local_copy) { + unsigned ii; + unsigned retries = 0; + int port; + + /* read data, with the sequential lock to have all data consistent */ + while (1) { + ii = wrs_shm_seqbegin(hal_head); + for (port = 0; port < hal_nports_local; port++) { + memcpy(&sfp_header_local_copy[port], + &hal_ports[port].calib.sfp_header_raw, + sizeof(struct shw_sfp_header)); + } + + retries++; + if (retries > 100) + return -1; + if (!wrs_shm_seqretry(hal_head, ii)) + break; /* consistent read */ + usleep(1000); + } + + return 0; +} + + +void hal_init_shm(void) +{ + struct hal_shmem_header *h; + int ret; + int n_wait = 0; + while ((ret = wrs_shm_get_and_check(wrs_shm_hal, &hal_head)) != 0) { + n_wait++; + if (ret == 1) { + pr_error("Unable to open HAL's shm !\n"); + } + if (ret == 2) { + pr_error("Unable to read HAL's version!\n"); + } + if (n_wait > 10) { + /* timeout! */ + exit(1); + } + sleep(1); + } + + if (hal_head->version != HAL_SHMEM_VERSION) { + pr_error("Unknown HAL's shm version %i (known is %i)\n", + hal_head->version, HAL_SHMEM_VERSION); + exit(1); + } + h = (void *)hal_head + hal_head->data_off; + /* Assume number of ports does not change in runtime */ + hal_nports_local = h->nports; + if (hal_nports_local > HAL_MAX_PORTS) { + pr_error("Too many ports reported by HAL. %d vs %d " + "supported\n", hal_nports_local, HAL_MAX_PORTS); + exit(1); + } + /* Even after HAL restart, HAL will place structures at the same + * addresses. No need to re-dereference pointer at each read. + */ + hal_ports = wrs_shm_follow(hal_head, h->ports); + if (!hal_ports) { + pr_error("Unable to follow hal_ports pointer in HAL's " + "shmem\n"); + exit(1); + } +} + int main(int argc, char **argv) { int c; - struct shw_sfp_header shdr; + struct shw_sfp_header sfp_hdr; + struct shw_sfp_header *sfp_hdr_p; int err; int nports; int dump_port; @@ -188,12 +283,16 @@ int main(int argc, char **argv) int dump_hex_header = 0; int operation = 0; char *eeprom_file = NULL; + int sfp_data_source = 0; + /* local copy of sfp eeprom */ + struct shw_sfp_header hal_sfp_raw_header_lc[HAL_MAX_PORTS]; + wrs_msg_init(argc, argv); nports = 18; dump_port = 1; - while ((c = getopt(argc, argv, "a:hqvp:xVf:")) != -1) { + while ((c = getopt(argc, argv, "a:hqvp:xVf:LIH:")) != -1) { switch (c) { case 'p': dump_port = atoi(optarg); @@ -210,7 +309,7 @@ int main(int argc, char **argv) break; case 'V': print_version(argv[0]); - break; + exit(0); case 'q': break; /* done in wrs_msg_init() */ case 'v': break; /* done in wrs_msg_init() */ case 'a': @@ -231,6 +330,18 @@ int main(int argc, char **argv) exit(1); } break; + case 'L': + /* HAL mode */ + sfp_data_source = READ_HAL; + break; + case 'I': + /* HAL mode */ + sfp_data_source = READ_I2C; + break; + case 'H': + /* HAL mode */ + wrs_shm_set_path(optarg); + break; case 'h': default: print_info(argv[0]); @@ -239,24 +350,49 @@ int main(int argc, char **argv) } } - /* init i2c, be carefull all i2c transfers are in race with hal! */ - assert_init(shw_io_init()); - assert_init(shw_fpga_mmap_init()); - assert_init(shw_sfp_buses_init()); + if (sfp_data_source != READ_HAL && sfp_data_source != READ_I2C) { + pr_error("Please specify the source of SFP eeprom data.\n" + " -L for saved data in HAL at SFP plugin\n" + " -I for direct access to SFPs via i2c\n"); + exit(1); + } - if (operation == SFP_EEPROM_READ) { - sfp_eeprom_read(eeprom_file, dump_port); - exit(0); + if (sfp_data_source == READ_HAL) { + hal_init_shm(); + hal_read(hal_sfp_raw_header_lc); + printf("Reading SFP eeprom from HAL\n"); } - if (operation == SFP_EEPROM_WRITE) { - sfp_eeprom_write(eeprom_file, dump_port); - exit(0); + + if (sfp_data_source == READ_I2C) { + /* init i2c, be carefull all i2c transfers are in race with + * hal! */ + assert_init(shw_io_init()); + assert_init(shw_fpga_mmap_init()); + assert_init(shw_sfp_buses_init()); + + if (operation == SFP_EEPROM_READ) { + sfp_eeprom_read(eeprom_file, dump_port); + exit(0); + } + if (operation == SFP_EEPROM_WRITE) { + sfp_eeprom_write(eeprom_file, dump_port); + exit(0); + } + printf("Reading SFP eeprom via I2C\n"); } + for (i = dump_port; i <= nports; i++) { - memset(&shdr, 0, sizeof(shdr)); printf("========= port %d =========\n", i); - err = shw_sfp_read_verify_header(i - 1, &shdr); + if (sfp_data_source == READ_I2C) { + memset(&sfp_hdr, 0, sizeof(sfp_hdr)); + sfp_hdr_p = &sfp_hdr; + err = shw_sfp_read_header(i - 1, sfp_hdr_p); + } + if (sfp_data_source == READ_HAL) { + sfp_hdr_p = &hal_sfp_raw_header_lc[i - 1]; + } + err = shw_sfp_header_verify(sfp_hdr_p); if (err == -2) { pr_error("SFP module not inserted in port %d. Failed " "to read SFP configuration header\n", i); @@ -264,9 +400,9 @@ int main(int argc, char **argv) pr_error("Failed to read SFP configuration header on " "port %d\n", i); } else { - shw_sfp_print_header(&shdr); + shw_sfp_print_header(sfp_hdr_p); if (dump_hex_header) { - shw_sfp_header_dump(&shdr); + shw_sfp_header_dump(sfp_hdr_p); } } } diff --git a/userspace/wrsw_hal/hal_ports.c b/userspace/wrsw_hal/hal_ports.c index eb63cedfc..287828bb8 100644 --- a/userspace/wrsw_hal/hal_ports.c +++ b/userspace/wrsw_hal/hal_ports.c @@ -478,7 +478,9 @@ static void hal_port_insert_sfp(struct hal_port_state * p) char subname[48]; int err; + memset(&shdr, 0, sizeof(struct shw_sfp_header)); 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) { pr_error("%s SFP module not inserted. Failed to read SFP " "configuration header\n", p->name); @@ -568,6 +570,7 @@ static void hal_port_remove_sfp(struct hal_port_state * p) p->state = HAL_PORT_STATE_DISABLED; /* 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)); } /* detects insertion/removal of SFP transceivers */ -- GitLab