cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rmt.c (16193B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/******************************************************************************
      3 *
      4 *	(C)Copyright 1998,1999 SysKonnect,
      5 *	a business unit of Schneider & Koch & Co. Datensysteme GmbH.
      6 *
      7 *	See the file "skfddi.c" for further information.
      8 *
      9 *	The information in this file is provided "AS IS" without warranty.
     10 *
     11 ******************************************************************************/
     12
     13/*
     14	SMT RMT
     15	Ring Management
     16*/
     17
     18/*
     19 * Hardware independent state machine implemantation
     20 * The following external SMT functions are referenced :
     21 *
     22 * 		queue_event()
     23 * 		smt_timer_start()
     24 * 		smt_timer_stop()
     25 *
     26 * 	The following external HW dependent functions are referenced :
     27 *		sm_ma_control()
     28 *		sm_mac_check_beacon_claim()
     29 *
     30 * 	The following HW dependent events are required :
     31 *		RM_RING_OP
     32 *		RM_RING_NON_OP
     33 *		RM_MY_BEACON
     34 *		RM_OTHER_BEACON
     35 *		RM_MY_CLAIM
     36 *		RM_TRT_EXP
     37 *		RM_VALID_CLAIM
     38 *
     39 */
     40
     41#include "h/types.h"
     42#include "h/fddi.h"
     43#include "h/smc.h"
     44
     45#define KERNEL
     46#include "h/smtstate.h"
     47
     48/*
     49 * FSM Macros
     50 */
     51#define AFLAG	0x10
     52#define GO_STATE(x)	(smc->mib.m[MAC0].fddiMACRMTState = (x)|AFLAG)
     53#define ACTIONS_DONE()	(smc->mib.m[MAC0].fddiMACRMTState &= ~AFLAG)
     54#define ACTIONS(x)	(x|AFLAG)
     55
     56#define RM0_ISOLATED	0
     57#define RM1_NON_OP	1		/* not operational */
     58#define RM2_RING_OP	2		/* ring operational */
     59#define RM3_DETECT	3		/* detect dupl addresses */
     60#define RM4_NON_OP_DUP	4		/* dupl. addr detected */
     61#define RM5_RING_OP_DUP	5		/* ring oper. with dupl. addr */
     62#define RM6_DIRECTED	6		/* sending directed beacons */
     63#define RM7_TRACE	7		/* trace initiated */
     64
     65/*
     66 * symbolic state names
     67 */
     68static const char * const rmt_states[] = {
     69	"RM0_ISOLATED","RM1_NON_OP","RM2_RING_OP","RM3_DETECT",
     70	"RM4_NON_OP_DUP","RM5_RING_OP_DUP","RM6_DIRECTED",
     71	"RM7_TRACE"
     72} ;
     73
     74/*
     75 * symbolic event names
     76 */
     77static const char * const rmt_events[] = {
     78	"NONE","RM_RING_OP","RM_RING_NON_OP","RM_MY_BEACON",
     79	"RM_OTHER_BEACON","RM_MY_CLAIM","RM_TRT_EXP","RM_VALID_CLAIM",
     80	"RM_JOIN","RM_LOOP","RM_DUP_ADDR","RM_ENABLE_FLAG",
     81	"RM_TIMEOUT_NON_OP","RM_TIMEOUT_T_STUCK",
     82	"RM_TIMEOUT_ANNOUNCE","RM_TIMEOUT_T_DIRECT",
     83	"RM_TIMEOUT_D_MAX","RM_TIMEOUT_POLL","RM_TX_STATE_CHANGE"
     84} ;
     85
     86/*
     87 * Globals
     88 * in struct s_rmt
     89 */
     90
     91
     92/*
     93 * function declarations
     94 */
     95static void rmt_fsm(struct s_smc *smc, int cmd);
     96static void start_rmt_timer0(struct s_smc *smc, u_long value, int event);
     97static void start_rmt_timer1(struct s_smc *smc, u_long value, int event);
     98static void start_rmt_timer2(struct s_smc *smc, u_long value, int event);
     99static void stop_rmt_timer0(struct s_smc *smc);
    100static void stop_rmt_timer1(struct s_smc *smc);
    101static void stop_rmt_timer2(struct s_smc *smc);
    102static void rmt_dup_actions(struct s_smc *smc);
    103static void rmt_reinsert_actions(struct s_smc *smc);
    104static void rmt_leave_actions(struct s_smc *smc);
    105static void rmt_new_dup_actions(struct s_smc *smc);
    106
    107#ifndef SUPERNET_3
    108extern void restart_trt_for_dbcn() ;
    109#endif /*SUPERNET_3*/
    110
    111/*
    112	init RMT state machine
    113	clear all RMT vars and flags
    114*/
    115void rmt_init(struct s_smc *smc)
    116{
    117	smc->mib.m[MAC0].fddiMACRMTState = ACTIONS(RM0_ISOLATED) ;
    118	smc->r.dup_addr_test = DA_NONE ;
    119	smc->r.da_flag = 0 ;
    120	smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
    121	smc->r.sm_ma_avail = FALSE ;
    122	smc->r.loop_avail = 0 ;
    123	smc->r.bn_flag = 0 ;
    124	smc->r.jm_flag = 0 ;
    125	smc->r.no_flag = TRUE ;
    126}
    127
    128/*
    129	RMT state machine
    130	called by dispatcher
    131
    132	do
    133		display state change
    134		process event
    135	until SM is stable
    136*/
    137void rmt(struct s_smc *smc, int event)
    138{
    139	int	state ;
    140
    141	do {
    142		DB_RMT("RMT : state %s%s event %s",
    143		       smc->mib.m[MAC0].fddiMACRMTState & AFLAG ? "ACTIONS " : "",
    144		       rmt_states[smc->mib.m[MAC0].fddiMACRMTState & ~AFLAG],
    145		       rmt_events[event]);
    146		state = smc->mib.m[MAC0].fddiMACRMTState ;
    147		rmt_fsm(smc,event) ;
    148		event = 0 ;
    149	} while (state != smc->mib.m[MAC0].fddiMACRMTState) ;
    150	rmt_state_change(smc,(int)smc->mib.m[MAC0].fddiMACRMTState) ;
    151}
    152
    153/*
    154	process RMT event
    155*/
    156static void rmt_fsm(struct s_smc *smc, int cmd)
    157{
    158	/*
    159	 * RM00-RM70 : from all states
    160	 */
    161	if (!smc->r.rm_join && !smc->r.rm_loop &&
    162		smc->mib.m[MAC0].fddiMACRMTState != ACTIONS(RM0_ISOLATED) &&
    163		smc->mib.m[MAC0].fddiMACRMTState != RM0_ISOLATED) {
    164		RS_SET(smc,RS_NORINGOP) ;
    165		rmt_indication(smc,0) ;
    166		GO_STATE(RM0_ISOLATED) ;
    167		return ;
    168	}
    169
    170	switch(smc->mib.m[MAC0].fddiMACRMTState) {
    171	case ACTIONS(RM0_ISOLATED) :
    172		stop_rmt_timer0(smc) ;
    173		stop_rmt_timer1(smc) ;
    174		stop_rmt_timer2(smc) ;
    175
    176		/*
    177		 * Disable MAC.
    178		 */
    179		sm_ma_control(smc,MA_OFFLINE) ;
    180		smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
    181		smc->r.loop_avail = FALSE ;
    182		smc->r.sm_ma_avail = FALSE ;
    183		smc->r.no_flag = TRUE ;
    184		DB_RMTN(1, "RMT : ISOLATED");
    185		ACTIONS_DONE() ;
    186		break ;
    187	case RM0_ISOLATED :
    188		/*RM01*/
    189		if (smc->r.rm_join || smc->r.rm_loop) {
    190			/*
    191			 * According to the standard the MAC must be reset
    192			 * here. The FORMAC will be initialized and Claim
    193			 * and Beacon Frames will be uploaded to the MAC.
    194			 * So any change of Treq will take effect NOW.
    195			 */
    196			sm_ma_control(smc,MA_RESET) ;
    197			GO_STATE(RM1_NON_OP) ;
    198			break ;
    199		}
    200		break ;
    201	case ACTIONS(RM1_NON_OP) :
    202		start_rmt_timer0(smc,smc->s.rmt_t_non_op,RM_TIMEOUT_NON_OP) ;
    203		stop_rmt_timer1(smc) ;
    204		stop_rmt_timer2(smc) ;
    205		sm_ma_control(smc,MA_BEACON) ;
    206		DB_RMTN(1, "RMT : RING DOWN");
    207		RS_SET(smc,RS_NORINGOP) ;
    208		smc->r.sm_ma_avail = FALSE ;
    209		rmt_indication(smc,0) ;
    210		ACTIONS_DONE() ;
    211		break ;
    212	case RM1_NON_OP :
    213		/*RM12*/
    214		if (cmd == RM_RING_OP) {
    215			RS_SET(smc,RS_RINGOPCHANGE) ;
    216			GO_STATE(RM2_RING_OP) ;
    217			break ;
    218		}
    219		/*RM13*/
    220		else if (cmd == RM_TIMEOUT_NON_OP) {
    221			smc->r.bn_flag = FALSE ;
    222			smc->r.no_flag = TRUE ;
    223			GO_STATE(RM3_DETECT) ;
    224			break ;
    225		}
    226		break ;
    227	case ACTIONS(RM2_RING_OP) :
    228		stop_rmt_timer0(smc) ;
    229		stop_rmt_timer1(smc) ;
    230		stop_rmt_timer2(smc) ;
    231		smc->r.no_flag = FALSE ;
    232		if (smc->r.rm_loop)
    233			smc->r.loop_avail = TRUE ;
    234		if (smc->r.rm_join) {
    235			smc->r.sm_ma_avail = TRUE ;
    236			if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable)
    237			smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ;
    238				else
    239			smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
    240		}
    241		DB_RMTN(1, "RMT : RING UP");
    242		RS_CLEAR(smc,RS_NORINGOP) ;
    243		RS_SET(smc,RS_RINGOPCHANGE) ;
    244		rmt_indication(smc,1) ;
    245		smt_stat_counter(smc,0) ;
    246		ACTIONS_DONE() ;
    247		break ;
    248	case RM2_RING_OP :
    249		/*RM21*/
    250		if (cmd == RM_RING_NON_OP) {
    251			smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
    252			smc->r.loop_avail = FALSE ;
    253			RS_SET(smc,RS_RINGOPCHANGE) ;
    254			GO_STATE(RM1_NON_OP) ;
    255			break ;
    256		}
    257		/*RM22a*/
    258		else if (cmd == RM_ENABLE_FLAG) {
    259			if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable)
    260			smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ;
    261				else
    262			smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
    263		}
    264		/*RM25*/
    265		else if (smc->r.dup_addr_test == DA_FAILED) {
    266			smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
    267			smc->r.loop_avail = FALSE ;
    268			smc->r.da_flag = TRUE ;
    269			GO_STATE(RM5_RING_OP_DUP) ;
    270			break ;
    271		}
    272		break ;
    273	case ACTIONS(RM3_DETECT) :
    274		start_rmt_timer0(smc,smc->s.mac_d_max*2,RM_TIMEOUT_D_MAX) ;
    275		start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
    276		start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
    277		sm_mac_check_beacon_claim(smc) ;
    278		DB_RMTN(1, "RMT : RM3_DETECT");
    279		ACTIONS_DONE() ;
    280		break ;
    281	case RM3_DETECT :
    282		if (cmd == RM_TIMEOUT_POLL) {
    283			start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
    284			sm_mac_check_beacon_claim(smc) ;
    285			break ;
    286		}
    287		if (cmd == RM_TIMEOUT_D_MAX) {
    288			smc->r.timer0_exp = TRUE ;
    289		}
    290		/*
    291		 *jd(22-Feb-1999)
    292		 * We need a time ">= 2*mac_d_max" since we had finished
    293		 * Claim or Beacon state. So we will restart timer0 at
    294		 * every state change.
    295		 */
    296		if (cmd == RM_TX_STATE_CHANGE) {
    297			start_rmt_timer0(smc,
    298					 smc->s.mac_d_max*2,
    299					 RM_TIMEOUT_D_MAX) ;
    300		}
    301		/*RM32*/
    302		if (cmd == RM_RING_OP) {
    303			GO_STATE(RM2_RING_OP) ;
    304			break ;
    305		}
    306		/*RM33a*/
    307		else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON)
    308			&& smc->r.bn_flag) {
    309			smc->r.bn_flag = FALSE ;
    310		}
    311		/*RM33b*/
    312		else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) {
    313			int	tx ;
    314			/*
    315			 * set bn_flag only if in state T4 or T5:
    316			 * only if we're the beaconer should we start the
    317			 * trace !
    318			 */
    319			if ((tx =  sm_mac_get_tx_state(smc)) == 4 || tx == 5) {
    320			DB_RMTN(2, "RMT : DETECT && TRT_EXPIRED && T4/T5");
    321				smc->r.bn_flag = TRUE ;
    322				/*
    323				 * If one of the upstream stations beaconed
    324				 * and the link to the upstream neighbor is
    325				 * lost we need to restart the stuck timer to
    326				 * check the "stuck beacon" condition.
    327				 */
    328				start_rmt_timer1(smc,smc->s.rmt_t_stuck,
    329					RM_TIMEOUT_T_STUCK) ;
    330			}
    331			/*
    332			 * We do NOT need to clear smc->r.bn_flag in case of
    333			 * not being in state T4 or T5, because the flag
    334			 * must be cleared in order to get in this condition.
    335			 */
    336
    337			DB_RMTN(2, "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)",
    338				tx, smc->r.bn_flag);
    339		}
    340		/*RM34a*/
    341		else if (cmd == RM_MY_CLAIM && smc->r.timer0_exp) {
    342			rmt_new_dup_actions(smc) ;
    343			GO_STATE(RM4_NON_OP_DUP) ;
    344			break ;
    345		}
    346		/*RM34b*/
    347		else if (cmd == RM_MY_BEACON && smc->r.timer0_exp) {
    348			rmt_new_dup_actions(smc) ;
    349			GO_STATE(RM4_NON_OP_DUP) ;
    350			break ;
    351		}
    352		/*RM34c*/
    353		else if (cmd == RM_VALID_CLAIM) {
    354			rmt_new_dup_actions(smc) ;
    355			GO_STATE(RM4_NON_OP_DUP) ;
    356			break ;
    357		}
    358		/*RM36*/
    359		else if (cmd == RM_TIMEOUT_T_STUCK &&
    360			smc->r.rm_join && smc->r.bn_flag) {
    361			GO_STATE(RM6_DIRECTED) ;
    362			break ;
    363		}
    364		break ;
    365	case ACTIONS(RM4_NON_OP_DUP) :
    366		start_rmt_timer0(smc,smc->s.rmt_t_announce,RM_TIMEOUT_ANNOUNCE);
    367		start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
    368		start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
    369		sm_mac_check_beacon_claim(smc) ;
    370		DB_RMTN(1, "RMT : RM4_NON_OP_DUP");
    371		ACTIONS_DONE() ;
    372		break ;
    373	case RM4_NON_OP_DUP :
    374		if (cmd == RM_TIMEOUT_POLL) {
    375			start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
    376			sm_mac_check_beacon_claim(smc) ;
    377			break ;
    378		}
    379		/*RM41*/
    380		if (!smc->r.da_flag) {
    381			GO_STATE(RM1_NON_OP) ;
    382			break ;
    383		}
    384		/*RM44a*/
    385		else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
    386			smc->r.bn_flag) {
    387			smc->r.bn_flag = FALSE ;
    388		}
    389		/*RM44b*/
    390		else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) {
    391			int	tx ;
    392			/*
    393			 * set bn_flag only if in state T4 or T5:
    394			 * only if we're the beaconer should we start the
    395			 * trace !
    396			 */
    397			if ((tx =  sm_mac_get_tx_state(smc)) == 4 || tx == 5) {
    398			DB_RMTN(2, "RMT : NOPDUP && TRT_EXPIRED && T4/T5");
    399				smc->r.bn_flag = TRUE ;
    400				/*
    401				 * If one of the upstream stations beaconed
    402				 * and the link to the upstream neighbor is
    403				 * lost we need to restart the stuck timer to
    404				 * check the "stuck beacon" condition.
    405				 */
    406				start_rmt_timer1(smc,smc->s.rmt_t_stuck,
    407					RM_TIMEOUT_T_STUCK) ;
    408			}
    409			/*
    410			 * We do NOT need to clear smc->r.bn_flag in case of
    411			 * not being in state T4 or T5, because the flag
    412			 * must be cleared in order to get in this condition.
    413			 */
    414
    415			DB_RMTN(2, "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)",
    416				tx, smc->r.bn_flag);
    417		}
    418		/*RM44c*/
    419		else if (cmd == RM_TIMEOUT_ANNOUNCE && !smc->r.bn_flag) {
    420			rmt_dup_actions(smc) ;
    421		}
    422		/*RM45*/
    423		else if (cmd == RM_RING_OP) {
    424			smc->r.no_flag = FALSE ;
    425			GO_STATE(RM5_RING_OP_DUP) ;
    426			break ;
    427		}
    428		/*RM46*/
    429		else if (cmd == RM_TIMEOUT_T_STUCK &&
    430			smc->r.rm_join && smc->r.bn_flag) {
    431			GO_STATE(RM6_DIRECTED) ;
    432			break ;
    433		}
    434		break ;
    435	case ACTIONS(RM5_RING_OP_DUP) :
    436		stop_rmt_timer0(smc) ;
    437		stop_rmt_timer1(smc) ;
    438		stop_rmt_timer2(smc) ;
    439		DB_RMTN(1, "RMT : RM5_RING_OP_DUP");
    440		ACTIONS_DONE() ;
    441		break;
    442	case RM5_RING_OP_DUP :
    443		/*RM52*/
    444		if (smc->r.dup_addr_test == DA_PASSED) {
    445			smc->r.da_flag = FALSE ;
    446			GO_STATE(RM2_RING_OP) ;
    447			break ;
    448		}
    449		/*RM54*/
    450		else if (cmd == RM_RING_NON_OP) {
    451			smc->r.jm_flag = FALSE ;
    452			smc->r.bn_flag = FALSE ;
    453			GO_STATE(RM4_NON_OP_DUP) ;
    454			break ;
    455		}
    456		break ;
    457	case ACTIONS(RM6_DIRECTED) :
    458		start_rmt_timer0(smc,smc->s.rmt_t_direct,RM_TIMEOUT_T_DIRECT) ;
    459		stop_rmt_timer1(smc) ;
    460		start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
    461		sm_ma_control(smc,MA_DIRECTED) ;
    462		RS_SET(smc,RS_BEACON) ;
    463		DB_RMTN(1, "RMT : RM6_DIRECTED");
    464		ACTIONS_DONE() ;
    465		break ;
    466	case RM6_DIRECTED :
    467		/*RM63*/
    468		if (cmd == RM_TIMEOUT_POLL) {
    469			start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
    470			sm_mac_check_beacon_claim(smc) ;
    471#ifndef SUPERNET_3
    472			/* Because of problems with the Supernet II chip set
    473			 * sending of Directed Beacon will stop after 165ms
    474			 * therefore restart_trt_for_dbcn(smc) will be called
    475			 * to prevent this.
    476			 */
    477			restart_trt_for_dbcn(smc) ;
    478#endif /*SUPERNET_3*/
    479			break ;
    480		}
    481		if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
    482			!smc->r.da_flag) {
    483			smc->r.bn_flag = FALSE ;
    484			GO_STATE(RM3_DETECT) ;
    485			break ;
    486		}
    487		/*RM64*/
    488		else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
    489			smc->r.da_flag) {
    490			smc->r.bn_flag = FALSE ;
    491			GO_STATE(RM4_NON_OP_DUP) ;
    492			break ;
    493		}
    494		/*RM67*/
    495		else if (cmd == RM_TIMEOUT_T_DIRECT) {
    496			GO_STATE(RM7_TRACE) ;
    497			break ;
    498		}
    499		break ;
    500	case ACTIONS(RM7_TRACE) :
    501		stop_rmt_timer0(smc) ;
    502		stop_rmt_timer1(smc) ;
    503		stop_rmt_timer2(smc) ;
    504		smc->e.trace_prop |= ENTITY_BIT(ENTITY_MAC) ;
    505		queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ;
    506		DB_RMTN(1, "RMT : RM7_TRACE");
    507		ACTIONS_DONE() ;
    508		break ;
    509	case RM7_TRACE :
    510		break ;
    511	default:
    512		SMT_PANIC(smc,SMT_E0122, SMT_E0122_MSG) ;
    513		break;
    514	}
    515}
    516
    517/*
    518 * (jd) RMT duplicate address actions
    519 * leave the ring or reinsert just as configured
    520 */
    521static void rmt_dup_actions(struct s_smc *smc)
    522{
    523	if (smc->r.jm_flag) {
    524	}
    525	else {
    526		if (smc->s.rmt_dup_mac_behavior) {
    527			SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ;
    528                        rmt_reinsert_actions(smc) ;
    529		}
    530		else {
    531			SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ;
    532			rmt_leave_actions(smc) ;
    533		}
    534	}
    535}
    536
    537/*
    538 * Reconnect to the Ring
    539 */
    540static void rmt_reinsert_actions(struct s_smc *smc)
    541{
    542	queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
    543	queue_event(smc,EVENT_ECM,EC_CONNECT) ;
    544}
    545
    546/*
    547 * duplicate address detected
    548 */
    549static void rmt_new_dup_actions(struct s_smc *smc)
    550{
    551	smc->r.da_flag = TRUE ;
    552	smc->r.bn_flag = FALSE ;
    553	smc->r.jm_flag = FALSE ;
    554	/*
    555	 * we have three options : change address, jam or leave
    556	 * we leave the ring as default 
    557	 * Optionally it's possible to reinsert after leaving the Ring
    558	 * but this will not conform with SMT Spec.
    559	 */
    560	if (smc->s.rmt_dup_mac_behavior) {
    561		SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ;
    562		rmt_reinsert_actions(smc) ;
    563	}
    564	else {
    565		SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ;
    566		rmt_leave_actions(smc) ;
    567	}
    568}
    569
    570
    571/*
    572 * leave the ring
    573 */
    574static void rmt_leave_actions(struct s_smc *smc)
    575{
    576	queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
    577	/*
    578	 * Note: Do NOT try again later. (with please reconnect)
    579	 * The station must be left from the ring!
    580	 */
    581}
    582
    583/*
    584 * SMT timer interface
    585 *	start RMT timer 0
    586 */
    587static void start_rmt_timer0(struct s_smc *smc, u_long value, int event)
    588{
    589	smc->r.timer0_exp = FALSE ;		/* clear timer event flag */
    590	smt_timer_start(smc,&smc->r.rmt_timer0,value,EV_TOKEN(EVENT_RMT,event));
    591}
    592
    593/*
    594 * SMT timer interface
    595 *	start RMT timer 1
    596 */
    597static void start_rmt_timer1(struct s_smc *smc, u_long value, int event)
    598{
    599	smc->r.timer1_exp = FALSE ;	/* clear timer event flag */
    600	smt_timer_start(smc,&smc->r.rmt_timer1,value,EV_TOKEN(EVENT_RMT,event));
    601}
    602
    603/*
    604 * SMT timer interface
    605 *	start RMT timer 2
    606 */
    607static void start_rmt_timer2(struct s_smc *smc, u_long value, int event)
    608{
    609	smc->r.timer2_exp = FALSE ;		/* clear timer event flag */
    610	smt_timer_start(smc,&smc->r.rmt_timer2,value,EV_TOKEN(EVENT_RMT,event));
    611}
    612
    613/*
    614 * SMT timer interface
    615 *	stop RMT timer 0
    616 */
    617static void stop_rmt_timer0(struct s_smc *smc)
    618{
    619	if (smc->r.rmt_timer0.tm_active)
    620		smt_timer_stop(smc,&smc->r.rmt_timer0) ;
    621}
    622
    623/*
    624 * SMT timer interface
    625 *	stop RMT timer 1
    626 */
    627static void stop_rmt_timer1(struct s_smc *smc)
    628{
    629	if (smc->r.rmt_timer1.tm_active)
    630		smt_timer_stop(smc,&smc->r.rmt_timer1) ;
    631}
    632
    633/*
    634 * SMT timer interface
    635 *	stop RMT timer 2
    636 */
    637static void stop_rmt_timer2(struct s_smc *smc)
    638{
    639	if (smc->r.rmt_timer2.tm_active)
    640		smt_timer_stop(smc,&smc->r.rmt_timer2) ;
    641}
    642