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
643