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 */ 68 static 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 */ 77 static 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 */ 95 static void rmt_fsm(struct s_smc *smc, int cmd); 96 static void start_rmt_timer0(struct s_smc *smc, u_long value, int event); 97 static void start_rmt_timer1(struct s_smc *smc, u_long value, int event); 98 static void start_rmt_timer2(struct s_smc *smc, u_long value, int event); 99 static void stop_rmt_timer0(struct s_smc *smc); 100 static void stop_rmt_timer1(struct s_smc *smc); 101 static void stop_rmt_timer2(struct s_smc *smc); 102 static void rmt_dup_actions(struct s_smc *smc); 103 static void rmt_reinsert_actions(struct s_smc *smc); 104 static void rmt_leave_actions(struct s_smc *smc); 105 static void rmt_new_dup_actions(struct s_smc *smc); 106 107 #ifndef SUPERNET_3 108 extern void restart_trt_for_dbcn() ; 109 #endif /*SUPERNET_3*/ 110 111 /* 112 init RMT state machine 113 clear all RMT vars and flags 114 */ 115 void 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 */ 137 void 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 */ 156 static 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 */ 521 static 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 */ 540 static 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 */ 549 static 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 */ 574 static 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 */ 587 static 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 */ 597 static 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 */ 607 static 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 */ 617 static 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 */ 627 static 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 */ 637 static 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