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,cmd: event) ;
148 event = 0 ;
149 } while (state != smc->mib.m[MAC0].fddiMACRMTState) ;
150 rmt_state_change(smc,r_state: (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,i: 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,value: 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,i: 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,i: 1) ;
245 smt_stat_counter(smc,stat: 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,value: smc->s.mac_d_max*2,RM_TIMEOUT_D_MAX) ;
275 start_rmt_timer1(smc,value: smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
276 start_rmt_timer2(smc,value: 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,value: 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 value: 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,value: 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,value: smc->s.rmt_t_announce,RM_TIMEOUT_ANNOUNCE);
367 start_rmt_timer1(smc,value: smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
368 start_rmt_timer2(smc,value: 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,value: 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,value: 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,value: smc->s.rmt_t_direct,RM_TIMEOUT_T_DIRECT) ;
459 stop_rmt_timer1(smc) ;
460 start_rmt_timer2(smc,value: 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,value: 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,timer: &smc->r.rmt_timer0,time: 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,timer: &smc->r.rmt_timer1,time: 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,timer: &smc->r.rmt_timer2,time: 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,timer: &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,timer: &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,timer: &smc->r.rmt_timer2) ;
641}
642
643

source code of linux/drivers/net/fddi/skfp/rmt.c