Commit ca58b912 authored by Jean-Claude BAU's avatar Jean-Claude BAU

Add new timer facility

New facility added to control a timer used to schedule the different
action in HAL. This facility is used to accelerate the processing of the
FSM during the TX and RX calibrations.
parent fabd2de5
......@@ -29,12 +29,6 @@
#define MAX_CLEANUP_CALLBACKS 16
typedef enum {
TMO_UPDATE_ALL=0,
TMO_UPDATE_FAN,
TMO_COUNT
}main_tmo_id_t;
static void cb_timer_update_fan(int timerId);
static void cb_timer_update_all(int timerId);
......@@ -42,7 +36,7 @@ static void cb_timer_update_all(int timerId);
static timer_parameter_t _timerParameters[] = {
{
.id=TMO_UPDATE_ALL,
.tmoMs=10, // 100ms
.tmoMs=100,
.repeat=1,
.cb=cb_timer_update_all
},
......@@ -52,11 +46,11 @@ static timer_parameter_t _timerParameters[] = {
.repeat=1,
.cb=cb_timer_update_fan
},
{
.id=TMO_END_BLOCK
}
};
#define MAIN_TIMER_COUNT (sizeof(_timerParameters)/sizeof(timer_parameter_t))
static int daemon_mode = 0;
static hal_cleanup_callback_t cleanup_cb[MAX_CLEANUP_CALLBACKS];
static char *logfilename;
......@@ -292,7 +286,7 @@ int main(int argc, char *argv[])
if (hal_init())
exit(1);
timer_init(_timerParameters,MAIN_TIMER_COUNT);
timer_init(_timerParameters);
/*
* Main loop update - polls for WRIPC requests and rolls the port
......@@ -309,7 +303,7 @@ int main(int argc, char *argv[])
hal_wripc_update(25 /* max ms delay */);
// Check main timers and call callback if timeout expires
timer_scan(_timerParameters,MAIN_TIMER_COUNT);
timer_scan(_timerParameters);
if ( hal_shmem->shmemState== HAL_SHMEM_STATE_INITITALIZING) {
// Check if all ports have been initialized
......
......@@ -19,6 +19,7 @@
#include <hal_exports.h>
#include "driver_stuff.h"
#include "hal_timer.h"
#include "hal_ports.h"
#include "hal_port_leds.h"
......@@ -107,7 +108,7 @@ static halPortFsmGen_t _portFsm = {
//TODO-ML: the below structure is redundant, consider reogranization to use
// hal_port_rts_state
static struct rts_pll_state _pll_state;
static uint32_t rxCalibInProgressMask=0;
static __inline__ void updatePllState(struct hal_port_state * ps) {
// update PLL state once for all ports
......@@ -138,12 +139,14 @@ static int _hal_port_rx_setup_state_start(void *vpfg, int eventMsk, int isNewSta
}
if ( ps->lpdc->isSupported ) {
/* Wait a bit to make sure early_link_up is resetted. This
/* Wait a bit to make sure early_link_up is reseted. This
timeout is initialized in hal_port_rx_setup_init_fsm(),
see detailed description there. */
if (! libwr_tmo_expired(&rxSetup->earlyup_timeout)) {
return 0;
}
// LPDC support
pcs_writel(ps, MDIO_LPC_CTRL_TX_ENABLE |
MDIO_LPC_CTRL_DMTD_SOURCE_RXRECCLK,
......@@ -167,6 +170,16 @@ static int _hal_port_rx_setup_state_start(void *vpfg, int eventMsk, int isNewSta
*/
static int _hal_port_rx_setup_state_reset_pcs(void *vpfg, int eventMsk, int isNewState) {
struct hal_port_state * ps=((halPortFsmGen_t *)vpfg)->ps;
uint32_t lastMask=rxCalibInProgressMask;
// Accelerate the treatment of the FSM engine if needed
rxCalibInProgressMask|=1<<ps->hw_index;
if ( lastMask!=rxCalibInProgressMask )
pr_info("%s: port=%s rxCalibInProgressMask=0x%x\n",__func__,ps->name,rxCalibInProgressMask);
if ( lastMask!=rxCalibInProgressMask && rxCalibInProgressMask) {
timer_update_tmo(TMO_UPDATE_ALL,99 /*10*/);
}
if( _isHalRxSetupEventEarlyLinkUp(eventMsk)) {
halPortLpdcRx_t *rxSetup=ps->lpdc->rxSetup;
......@@ -241,11 +254,12 @@ static int _hal_port_rx_setup_state_validate(void *vpfg, int eventMsk, int isNew
MDIO_LPC_CTRL_DMTD_SOURCE_RXRECCLK,
MDIO_LPC_CTRL);
pcs_writel(ps, BMCR_ANENABLE | BMCR_ANRESTART, MII_BMCR);
rts_enable_ptracker(ps->hw_index, 0);
pr_info("wri%d: RX calibration complete at phase %d "
"ps (after %d attempts).\n", ps->hw_index + 1,
phase, rxSetup->attempts);
rts_enable_ptracker(ps->hw_index, 0);
sleep(1); // fixme: really needed?
_fireState(vpfg, HAL_PORT_RX_SETUP_STATE_DONE);
}
......@@ -258,14 +272,24 @@ static int _hal_port_rx_setup_state_validate(void *vpfg, int eventMsk, int isNew
*
* if LPDC supported
* if early_link_down event then state=START
* if link up event then return final state machine reached
*
*/
static int _hal_port_rx_setup_state_done(void *vpfg, int eventMsk, int isNewState) {
struct hal_port_state * ps=((halPortFsmGen_t *)vpfg)->ps;
uint32_t lastMask=rxCalibInProgressMask;
// restore original speed for the treatment of the FSM engine
rxCalibInProgressMask&=~(1<<ps->hw_index);
if ( lastMask!=rxCalibInProgressMask )
pr_info("%s: port=%s rxCalibInProgressMask=0x%x\n",__func__,ps->name,rxCalibInProgressMask);
if ( lastMask!=rxCalibInProgressMask && !rxCalibInProgressMask) {
timer_restore_tmo(TMO_UPDATE_ALL);
}
/* earlyLinkUp detection only if LPDC support */
if ( ps->lpdc->isSupported ) {
if ( !_isHalRxSetupEventEarlyLinkUp(eventMsk)) {
// Port went done
pr_info("rxcal: early link flag lost on port wri%d\n",
......
......@@ -16,6 +16,7 @@
#include "hal_port_gen_fsm.h"
#include "driver_stuff.h"
#include "hal_port_leds.h"
#include "hal_timer.h"
#include "hal_main.h"
#include "hal_ports.h"
#include "hal_port_fsm_txP.h"
......@@ -90,6 +91,7 @@ static halPortFsmGen_t _portFsm = {
.pe=_fsmEvtTable
};
//TODO-ML: the below structure is redundant, consider reogranization to use
// hal_port_rts_state
static struct rts_pll_state _pll_state;
......@@ -97,6 +99,8 @@ static struct rts_pll_state _pll_state;
static char *_calibrationFileName = "/update/tx_phase_cal.conf";
struct config_file *_calibrationConfig; // Calibration config form file
static uint32_t txCalibInProgressMask=0;
static __inline__ void updatePllState(struct hal_port_state * ps) {
// update PLL state once for all ports
rts_get_state(&_pll_state);
......@@ -127,6 +131,17 @@ static int _within_range(int x, int minval, int maxval, int wrap);
*/
static int _hal_port_tx_setup_state_start(void *vpfg, int eventMsk, int isNewState) {
struct hal_port_state * ps=((halPortFsmGen_t *)vpfg)->ps;
uint32_t lastMask=txCalibInProgressMask;
// Accelerate the treatment of the FSM engine if needed
txCalibInProgressMask|=1<<ps->hw_index;
if ( lastMask!=txCalibInProgressMask )
pr_info("%s: port=%s txCalibInProgressMask=0x%x\n",__func__,ps->name,txCalibInProgressMask);
if ( lastMask!=txCalibInProgressMask && txCalibInProgressMask) {
timer_update_tmo(TMO_UPDATE_ALL,99 /*10*/);
}
if ( !ps->lpdc->isSupported ) {
// NO LPDC support
......@@ -306,6 +321,16 @@ static int _hal_port_tx_setup_state_validate(void *vpfg, int eventMsk, int isNew
static int _hal_port_tx_setup_state_wait_other_ports(void *vpfg, int eventMsk, int isNewState) {
struct hal_port_state * ps = ((halPortFsmGen_t *) vpfg)->ps;
uint32_t lastMask=txCalibInProgressMask;
// restore original speed for the treatment of the FSM engine
txCalibInProgressMask&=~(1<<ps->hw_index);
if ( lastMask!=txCalibInProgressMask )
pr_info("%s: port=%s txCalibInProgressMask=0x%x\n",__func__,ps->name,txCalibInProgressMask);
if ( lastMask!=txCalibInProgressMask && txCalibInProgressMask==0) {
timer_restore_tmo(TMO_UPDATE_ALL);
}
if (txSetupDoneOnAllPorts(ps) ) {
_write_tx_calibration_file(ps);
......
......@@ -41,19 +41,6 @@ extern struct wrs_shm_head *hal_shmem_hdr;
hal_ports_t halPorts;
/**
* End new stuff
*/
typedef enum {
TMO_PORT_TMO_RTS=0,
TMO_PORT_POLL_SFP,
TMO_PORT_SFP_DOM,
TMO_UPDATE_SYNC_LEDs,
TMO_UPDATE_LINK_LEDS,
TMO_COUNT
}port_tmo_id_t;
static void _cb_port_poll_rts_state(int timerId);
static void _cb_port_poll_sfp(int timerId);
static void _cb_port_poll_sfp_dom(int timerId);
......@@ -93,10 +80,11 @@ static timer_parameter_t _timerParameters[] = {
.repeat=1,
.cb=_cb_port_update_link_leds
},
{
.id=TMO_END_BLOCK
}
};
#define PORT_TIMER_COUNT (sizeof(_timerParameters)/sizeof(timer_parameter_t))
/* prototypes */
static int hal_port_check_lpdc_support(struct hal_port_state * ps);
......@@ -227,7 +215,7 @@ int hal_port_shmem_init(char *logfilename)
pr_info("Initializing switch ports...\n");
/* default timeouts */
timer_init(_timerParameters,PORT_TIMER_COUNT);
timer_init(_timerParameters);
/* Open a single raw socket for accessing the MAC addresses, etc. */
halPorts.hal_port_fd = socket(AF_PACKET, SOCK_DGRAM, 0);
......@@ -634,7 +622,7 @@ static void _cb_port_update_link_leds(int timerId){
/* Executes the port FSM for all ports. Called regularly by the main loop. */
void hal_port_update_all()
{
timer_scan(_timerParameters,PORT_TIMER_COUNT);
timer_scan(_timerParameters);
/* lock shmem */
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_BEGIN);
......
......@@ -61,5 +61,4 @@ extern int hal_add_cleanup_callback(hal_cleanup_callback_t cb);
extern int pcs_writel(struct hal_port_state *p, uint16_t value, int reg);
extern int pcs_readl(struct hal_port_state * p, int reg, uint32_t *value);
#endif
......@@ -6,27 +6,95 @@
*
*/
#include <time.h>
#include <libwr/wrs-msg.h>
#include "hal_timer.h"
void timer_init(timer_parameter_t *p,int nbTimers) {
int index;
#define TIMER_MAX_BLOCKS 5
for ( index=0; index < nbTimers; index++ ) {
static timer_parameter_t *blocks[TIMER_MAX_BLOCKS];
static time_t start, end;
static void _timer_register_block(timer_parameter_t *p) {
int i;
for (i=0; i<TIMER_MAX_BLOCKS; i++ ) {
if ( blocks[i]==p) {
// Already registered
return;
}
if ( blocks[i]==NULL) {
// Register the block
blocks[i]=p;
return;
}
}
}
void timer_init(timer_parameter_t *p) {
_timer_register_block(p);
while (p->id!=TMO_END_BLOCK) {
p->tmoMsRef=p->tmoMs; // Save the original value
libwr_tmo_init(&p->timer,p->tmoMs, p->repeat);
p++;
}
}
void timer_scan(timer_parameter_t *p,int nbTimers) {
int index;
void timer_scan(timer_parameter_t *p) {
for ( index=0; index < nbTimers; index++ ) {
while (p->id!=TMO_END_BLOCK) {
if (libwr_tmo_expired(&p->timer) && p->cb!=NULL) {
(*p->cb)(p->id);
}
p++;
}
}
void timer_update_tmo(tmo_id_t id,uint32_t tmoMs) {
int i;
for (i=0; i<TIMER_MAX_BLOCKS; i++ ) {
timer_parameter_t *p;
if ( (p=blocks[i])!=NULL ) {
while (p->id!=TMO_END_BLOCK) {
if (p->id==id) {
if ( p->tmoMs!=tmoMs ) {
p->tmoMs=tmoMs;
pr_info("%s: Timer %d set to %dms\n",__func__,id,p->tmoMs);
libwr_tmo_init(&p->timer,p->tmoMs, p->repeat);
time(&start);
}
}
p++;
}
}
}
}
void timer_restore_tmo(tmo_id_t id) {
int i;
for (i=0; i<TIMER_MAX_BLOCKS; i++ ) {
timer_parameter_t *p;
if ( (p=blocks[i])!=NULL ) {
while (p->id!=TMO_END_BLOCK) {
if (p->id==id) {
if ( p->tmoMs!=p->tmoMsRef) {
p->tmoMs=p->tmoMsRef;
pr_info("%s: Timer %d restored to %dms\n",__func__,id,p->tmoMs);
libwr_tmo_init(&p->timer,p->tmoMs, p->repeat);
time(&end);
pr_info("%s: Execution time %f seconds\n",__func__,difftime(end, start));
}
}
p++;
}
}
}
}
......@@ -11,16 +11,34 @@
#include <libwr/timeout.h>
// List of all timer
typedef enum {
// RESERVED
TMO_END_BLOCK,
// MAIN
TMO_UPDATE_ALL=1,
TMO_UPDATE_FAN,
// PORTS
TMO_PORT_TMO_RTS,
TMO_PORT_POLL_SFP,
TMO_PORT_SFP_DOM,
TMO_UPDATE_SYNC_LEDs,
TMO_UPDATE_LINK_LEDS,
}tmo_id_t;
typedef struct {
int id;
tmo_id_t id;
uint32_t tmoMs; // Time out value in ms
uint32_t tmoMsRef; // Time out reference value in ms
int repeat; // restart timeout automatically
timeout_t timer;
void (*cb)(int timerId);
}timer_parameter_t;
extern void timer_init(timer_parameter_t *p,int nbTimers);
extern void timer_scan(timer_parameter_t *p,int nbTimers);
extern void timer_update_tmo(tmo_id_t id,uint32_t tmoMs);
extern void timer_restore_tmo(tmo_id_t id);
extern void timer_init(timer_parameter_t *p);
extern void timer_scan(timer_parameter_t *p);
#endif
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