Commit 4cee2700 authored by Adam Wujek's avatar Adam Wujek

[FEATURE: #251] userspace/tools: Add disabling SFP's TX

Disabling of SFP's TX is possible only via HAL.
Disabling it I2C directly is a risky, it can corrupt SFP's EEPROM if
HAL is running.
Signed-off-by: 's avatarAdam Wujek <dev_public@wujek.eu>
parent b2bec831
Pipeline #3267 failed with stage
in 0 seconds
...@@ -49,6 +49,10 @@ ...@@ -49,6 +49,10 @@
#define HEXP_FREQ 0 #define HEXP_FREQ 0
#define HEXP_PHASE 1 #define HEXP_PHASE 1
#define HEXP_SFP_TX_CMD_ENABLE_TX 1
#define HEXP_SFP_TX_CMD_DISABLE_TX 2
#define HEXP_SFP_TX_CMD_STATUS 3
/////////////////added by ML////////// /////////////////added by ML//////////
#define HEXP_EXTSRC_CMD_CHECK 0 #define HEXP_EXTSRC_CMD_CHECK 0
...@@ -116,9 +120,11 @@ typedef struct { ...@@ -116,9 +120,11 @@ typedef struct {
extern struct minipc_pd __rpcdef_lock_cmd; extern struct minipc_pd __rpcdef_lock_cmd;
extern struct minipc_pd __rpcdef_pps_cmd; extern struct minipc_pd __rpcdef_pps_cmd;
extern struct minipc_pd __rpcdef_port_info_cmd; extern struct minipc_pd __rpcdef_port_info_cmd;
extern struct minipc_pd __rpcdef_sfp_tx_cmd;
/* Prototypes of functions that call on rpc */ /* Prototypes of functions that call on rpc */
extern int halexp_lock_cmd(const char *port_name, int command, int priority); extern int halexp_lock_cmd(const char *port_name, int command, int priority);
extern int halexp_pps_cmd(int cmd, hexp_pps_params_t *params); extern int halexp_pps_cmd(int cmd, hexp_pps_params_t *params);
extern int halexp_sfp_tx_cmd(int cmd, int port);
#endif #endif
...@@ -31,6 +31,17 @@ int halexp_pps_cmd(int cmd, hexp_pps_params_t * params) ...@@ -31,6 +31,17 @@ int halexp_pps_cmd(int cmd, hexp_pps_params_t * params)
return rval; return rval;
} }
int halexp_sfp_tx_cmd(int cmd, int port)
{
int ret, rval;
ret = minipc_call(hal_ch, DEFAULT_TO, &__rpcdef_sfp_tx_cmd,
&rval, cmd, port);
if (ret < 0)
return ret;
return rval;
}
/* Some clients call this, some call the client_init() defined later */ /* Some clients call this, some call the client_init() defined later */
int halexp_client_try_connect(int retries, int timeout) int halexp_client_try_connect(int retries, int timeout)
{ {
......
...@@ -36,3 +36,14 @@ struct minipc_pd __rpcdef_port_info_cmd = { ...@@ -36,3 +36,14 @@ struct minipc_pd __rpcdef_port_info_cmd = {
MINIPC_ARG_END, MINIPC_ARG_END,
}, },
}; };
//int halexp_sfp_tx_cmd(int cmd, int port);
struct minipc_pd __rpcdef_sfp_tx_cmd = {
.name = "sfp_tx_cmd",
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
.args = {
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
MINIPC_ARG_END,
},
};
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "../libwr/i2c_sfp.h" #include "../libwr/i2c_sfp.h"
#include <libwr/shmem.h> #include <libwr/shmem.h>
#include <libwr/hal_shmem.h> #include <libwr/hal_shmem.h>
#include <libwr/hal_client.h>
#define SFP_EEPROM_READ 1 #define SFP_EEPROM_READ 1
...@@ -19,6 +20,10 @@ ...@@ -19,6 +20,10 @@
#define READ_HAL 1 #define READ_HAL 1
#define READ_I2C 2 #define READ_I2C 2
#define HAL_CONNECT_RETRIES 5
#define HAL_CONNECT_TIMEOUT 2000000 /* us */
static struct wrs_shm_head *hal_head; static struct wrs_shm_head *hal_head;
static struct hal_port_state *hal_ports; static struct hal_port_state *hal_ports;
static int hal_nports_local; static int hal_nports_local;
...@@ -28,21 +33,23 @@ void print_info(char *prgname) ...@@ -28,21 +33,23 @@ void print_info(char *prgname)
printf("usage: %s <-I|-L> [parameters]\n", prgname); printf("usage: %s <-I|-L> [parameters]\n", prgname);
printf("" printf(""
"Select the source of SFP eeprom data:\n" "Select the source of SFP eeprom data:\n"
" -L Use eeprom data read by HAL at SFP insertion time\n" " -L Use eeprom data read by HAL at SFP insertion time\n"
" -I Use read eeprom data directly from SFP via I2C\n" " -I Use read eeprom data directly from SFP via I2C\n"
" (Use with caution! May corrupt SFPs EEPROM if HAL is running!)\n"
"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"
" -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" " -d Dump sfp DOM data page\n"
" -x Dump sfp/DOM header also in hex\n" " -x Dump sfp/DOM header also in hex\n"
" -q Decrease verbosity\n" " -t <on|off|0|1|s> Enable(1), disable(1) or check status of SFP's TX pin; Use with -L or -I\n"
" -v Increase verbosity\n" " -q Decrease verbosity\n"
" -V Print version\n" " -v Increase verbosity\n"
" -h Show this message\n" " -V Print version\n"
" -h Show this message\n"
"\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"
); );
...@@ -298,6 +305,8 @@ int main(int argc, char **argv) ...@@ -298,6 +305,8 @@ int main(int argc, char **argv)
int operation = 0; int operation = 0;
char *eeprom_file = NULL; char *eeprom_file = NULL;
int sfp_data_source = 0; int sfp_data_source = 0;
int sfp_tx_update = 0;
int sfp_tx_enable = 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]; struct shw_sfp_dom hal_sfp_raw_dom_lc[HAL_MAX_PORTS];
...@@ -307,7 +316,7 @@ int main(int argc, char **argv) ...@@ -307,7 +316,7 @@ int main(int argc, char **argv)
nports = 18; nports = 18;
dump_port = 1; dump_port = 1;
while ((c = getopt(argc, argv, "a:hqvp:xVf:LIdH:")) != -1) { while ((c = getopt(argc, argv, "a:hqvp:xVf:LIdH:t:")) != -1) {
switch (c) { switch (c) {
case 'p': case 'p':
dump_port = atoi(optarg); dump_port = atoi(optarg);
...@@ -360,6 +369,21 @@ int main(int argc, char **argv) ...@@ -360,6 +369,21 @@ int main(int argc, char **argv)
/* Set path for shmem files */ /* Set path for shmem files */
wrs_shm_set_path(optarg); wrs_shm_set_path(optarg);
break; break;
case 't':
/* Handle enable/disable/status of SFP's TX */
if (!strcmp(optarg, "on") || !strcmp(optarg, "1")) {
sfp_tx_update = 1;
sfp_tx_enable = HEXP_SFP_TX_CMD_ENABLE_TX;
}
if (!strcmp(optarg, "off") || !strcmp(optarg, "0")) {
sfp_tx_update = 1;
sfp_tx_enable = HEXP_SFP_TX_CMD_DISABLE_TX;
}
if (!strcmp(optarg, "status") || !strcmp(optarg, "s")) {
sfp_tx_update = 1;
sfp_tx_enable = HEXP_SFP_TX_CMD_STATUS;
}
break;
case 'h': case 'h':
default: default:
print_info(argv[0]); print_info(argv[0]);
...@@ -369,18 +393,71 @@ int main(int argc, char **argv) ...@@ -369,18 +393,71 @@ int main(int argc, char **argv)
} }
if (sfp_data_source != READ_HAL && sfp_data_source != READ_I2C) { if (sfp_data_source != READ_HAL && sfp_data_source != READ_I2C) {
pr_error("Please specify the source of SFP eeprom data.\n" pr_error("Please specify the communication way with SFP:\n"
" -L for saved data in HAL at SFP plugin\n" " -L for saved data in HAL at SFP insertion\n"
" or TX pin enable/disable\n"
" -I for direct access to SFPs via i2c\n"); " -I for direct access to SFPs via i2c\n");
exit(1); exit(1);
} }
if (sfp_tx_update && sfp_data_source == READ_HAL) {
char *msg;
int ret;
switch(sfp_tx_enable) {
case HEXP_SFP_TX_CMD_ENABLE_TX:
msg = "Enable";
break;
case HEXP_SFP_TX_CMD_DISABLE_TX:
msg = "Disable";
break;
case HEXP_SFP_TX_CMD_STATUS:
msg = "Check status of";
break;
default:
printf("%s BUG: line %d, wrong value %d of "
"sfp_tx_enable\n",
__func__, __LINE__, sfp_tx_enable);
}
if (sfp_data_source == READ_HAL) { printf("%s TX via HAL for port %d\n", msg, dump_port);
ret = halexp_client_try_connect(HAL_CONNECT_RETRIES,
HAL_CONNECT_TIMEOUT);
if (ret < 0) {
pr_error("Can't establish WRIPC connection to the HAL "
"daemon!\n");
exit(1);
}
ret = halexp_sfp_tx_cmd(sfp_tx_enable, dump_port);
if (sfp_tx_enable == HEXP_SFP_TX_CMD_STATUS) {
switch(ret) {
case HEXP_SFP_TX_CMD_ENABLE_TX:
msg = "enabled";
break;
case HEXP_SFP_TX_CMD_DISABLE_TX:
msg = "disabled";
break;
default:
msg = "Error (unable to read)";
break;
}
printf("SFP's TX for port %d %s\n",
dump_port, msg);
}
exit(0);
}
else if (sfp_data_source == READ_HAL) {
hal_init_shm(); hal_init_shm();
hal_read(hal_sfp_raw_header_lc, hal_sfp_raw_dom_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");
} }
if (sfp_tx_update && sfp_data_source == READ_I2C) {
printf("Setting TX pin of SFP via I2C is not supported!\n"
"Use -L parameter to set it via HAL\n");
exit(1);
}
if (sfp_data_source == READ_I2C) { if (sfp_data_source == READ_I2C) {
/* init i2c, be carefull all i2c transfers are in race with /* init i2c, be carefull all i2c transfers are in race with
* hal! */ * hal! */
......
...@@ -170,6 +170,38 @@ int halexp_port_info_cmd(hexp_port_info_params_t * params) ...@@ -170,6 +170,38 @@ int halexp_port_info_cmd(hexp_port_info_params_t * params)
return 1; return 1;
} }
/* Phase/Clock adjutsment call. Called by the PTPd servo. Controls
* both the PLLs and the PPS Generator. */
int halexp_sfp_tx_cmd(int cmd, int port)
{
int new_status = 0;
int ret;
if (port < 1 || port > halPorts.numberOfPorts) {
pr_debug("%s: wrong port number %d\n", __func__, port);
return -EINVAL;
}
switch (cmd) {
case HEXP_SFP_TX_CMD_ENABLE_TX:
new_status = 0;
break;
case HEXP_SFP_TX_CMD_DISABLE_TX:
new_status = 1;
break;
case HEXP_SFP_TX_CMD_STATUS:
ret = shw_sfp_gpio_get(port - 1);
ret = (ret & SFP_TX_DISABLE) ? HEXP_SFP_TX_CMD_DISABLE_TX : HEXP_SFP_TX_CMD_ENABLE_TX;
return ret;
default:
return -EINVAL;
}
shw_sfp_set_tx_disable(port - 1, new_status);
return 0;
}
static void hal_cleanup_wripc(void) static void hal_cleanup_wripc(void)
{ {
minipc_close(hal_ch); minipc_close(hal_ch);
...@@ -212,6 +244,15 @@ static int export_port_info_cmd(const struct minipc_pd *pd, ...@@ -212,6 +244,15 @@ static int export_port_info_cmd(const struct minipc_pd *pd,
return 0; return 0;
} }
static int export_sfp_tx_cmd(const struct minipc_pd *pd,
uint32_t * args, void *ret)
{
int rval;
rval = halexp_sfp_tx_cmd(args[0] /* cmd */, args[1] /* port */);
*(int *)ret = rval;
return 0;
}
/* Creates a wripc server and exports all public API functions */ /* Creates a wripc server and exports all public API functions */
int hal_wripc_init(struct hal_port_state *hal_ports, char *logfilename) int hal_wripc_init(struct hal_port_state *hal_ports, char *logfilename)
...@@ -241,10 +282,12 @@ int hal_wripc_init(struct hal_port_state *hal_ports, char *logfilename) ...@@ -241,10 +282,12 @@ int hal_wripc_init(struct hal_port_state *hal_ports, char *logfilename)
__rpcdef_pps_cmd.f = export_pps_cmd; __rpcdef_pps_cmd.f = export_pps_cmd;
__rpcdef_lock_cmd.f = export_lock_cmd; __rpcdef_lock_cmd.f = export_lock_cmd;
__rpcdef_port_info_cmd.f = export_port_info_cmd; __rpcdef_port_info_cmd.f = export_port_info_cmd;
__rpcdef_sfp_tx_cmd.f = export_sfp_tx_cmd;
minipc_export(hal_ch, &__rpcdef_pps_cmd); minipc_export(hal_ch, &__rpcdef_pps_cmd);
minipc_export(hal_ch, &__rpcdef_lock_cmd); minipc_export(hal_ch, &__rpcdef_lock_cmd);
minipc_export(hal_ch, &__rpcdef_port_info_cmd); minipc_export(hal_ch, &__rpcdef_port_info_cmd);
minipc_export(hal_ch, &__rpcdef_sfp_tx_cmd);
/* FIXME: pll_cmd is empty anyways???? */ /* FIXME: pll_cmd is empty anyways???? */
......
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