xref: /openbmc/linux/drivers/net/fddi/skfp/srf.c (revision 76426e23)
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 7.2 Status Response Frame Implementation
15 	SRF state machine and frame generation
16 */
17 
18 #include "h/types.h"
19 #include "h/fddi.h"
20 #include "h/smc.h"
21 #include "h/smt_p.h"
22 
23 #define KERNEL
24 #include "h/smtstate.h"
25 
26 #ifndef	SLIM_SMT
27 #ifndef	BOOT
28 
29 #ifndef	lint
30 static const char ID_sccs[] = "@(#)srf.c	1.18 97/08/04 (C) SK " ;
31 #endif
32 
33 
34 /*
35  * function declarations
36  */
37 static void clear_all_rep(struct s_smc *smc);
38 static void clear_reported(struct s_smc *smc);
39 static void smt_send_srf(struct s_smc *smc);
40 static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index);
41 
42 #define MAX_EVCS	ARRAY_SIZE(smc->evcs)
43 
44 struct evc_init {
45 	u_char code ;
46 	u_char index ;
47 	u_char n ;
48 	u_short	para ;
49 }  ;
50 
51 static const struct evc_init evc_inits[] = {
52 	{ SMT_COND_SMT_PEER_WRAP,		0,1,SMT_P1048	} ,
53 
54 	{ SMT_COND_MAC_DUP_ADDR,		INDEX_MAC, NUMMACS,SMT_P208C } ,
55 	{ SMT_COND_MAC_FRAME_ERROR,		INDEX_MAC, NUMMACS,SMT_P208D } ,
56 	{ SMT_COND_MAC_NOT_COPIED,		INDEX_MAC, NUMMACS,SMT_P208E } ,
57 	{ SMT_EVENT_MAC_NEIGHBOR_CHANGE,	INDEX_MAC, NUMMACS,SMT_P208F } ,
58 	{ SMT_EVENT_MAC_PATH_CHANGE,		INDEX_MAC, NUMMACS,SMT_P2090 } ,
59 
60 	{ SMT_COND_PORT_LER,			INDEX_PORT,NUMPHYS,SMT_P4050 } ,
61 	{ SMT_COND_PORT_EB_ERROR,		INDEX_PORT,NUMPHYS,SMT_P4052 } ,
62 	{ SMT_EVENT_PORT_CONNECTION,		INDEX_PORT,NUMPHYS,SMT_P4051 } ,
63 	{ SMT_EVENT_PORT_PATH_CHANGE,		INDEX_PORT,NUMPHYS,SMT_P4053 } ,
64 } ;
65 
66 #define MAX_INIT_EVC	ARRAY_SIZE(evc_inits)
67 
68 void smt_init_evc(struct s_smc *smc)
69 {
70 	struct s_srf_evc	*evc ;
71 	const struct evc_init 	*init ;
72 	unsigned int		i ;
73 	int			index ;
74 	int			offset ;
75 
76 	static u_char		fail_safe = FALSE ;
77 
78 	memset((char *)smc->evcs,0,sizeof(smc->evcs)) ;
79 
80 	evc = smc->evcs ;
81 	init = evc_inits ;
82 
83 	for (i = 0 ; i < MAX_INIT_EVC ; i++) {
84 		for (index = 0 ; index < init->n ; index++) {
85 			evc->evc_code = init->code ;
86 			evc->evc_para = init->para ;
87 			evc->evc_index = init->index + index ;
88 #ifndef	DEBUG
89 			evc->evc_multiple = &fail_safe ;
90 			evc->evc_cond_state = &fail_safe ;
91 #endif
92 			evc++ ;
93 		}
94 		init++ ;
95 	}
96 
97 	if ((unsigned int) (evc - smc->evcs) > MAX_EVCS) {
98 		SMT_PANIC(smc,SMT_E0127, SMT_E0127_MSG) ;
99 	}
100 
101 	/*
102 	 * conditions
103 	 */
104 	smc->evcs[0].evc_cond_state = &smc->mib.fddiSMTPeerWrapFlag ;
105 	smc->evcs[1].evc_cond_state =
106 		&smc->mib.m[MAC0].fddiMACDuplicateAddressCond ;
107 	smc->evcs[2].evc_cond_state =
108 		&smc->mib.m[MAC0].fddiMACFrameErrorFlag ;
109 	smc->evcs[3].evc_cond_state =
110 		&smc->mib.m[MAC0].fddiMACNotCopiedFlag ;
111 
112 	/*
113 	 * events
114 	 */
115 	smc->evcs[4].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_N ;
116 	smc->evcs[5].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_P ;
117 
118 	offset = 6 ;
119 	for (i = 0 ; i < NUMPHYS ; i++) {
120 		/*
121 		 * conditions
122 		 */
123 		smc->evcs[offset + 0*NUMPHYS].evc_cond_state =
124 			&smc->mib.p[i].fddiPORTLerFlag ;
125 		smc->evcs[offset + 1*NUMPHYS].evc_cond_state =
126 			&smc->mib.p[i].fddiPORTEB_Condition ;
127 
128 		/*
129 		 * events
130 		 */
131 		smc->evcs[offset + 2*NUMPHYS].evc_multiple =
132 			&smc->mib.p[i].fddiPORTMultiple_U ;
133 		smc->evcs[offset + 3*NUMPHYS].evc_multiple =
134 			&smc->mib.p[i].fddiPORTMultiple_P ;
135 		offset++ ;
136 	}
137 #ifdef	DEBUG
138 	for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
139 		if (SMT_IS_CONDITION(evc->evc_code)) {
140 			if (!evc->evc_cond_state) {
141 				SMT_PANIC(smc,SMT_E0128, SMT_E0128_MSG) ;
142 			}
143 			evc->evc_multiple = &fail_safe ;
144 		}
145 		else {
146 			if (!evc->evc_multiple) {
147 				SMT_PANIC(smc,SMT_E0129, SMT_E0129_MSG) ;
148 			}
149 			evc->evc_cond_state = &fail_safe ;
150 		}
151 	}
152 #endif
153 	smc->srf.TSR = smt_get_time() ;
154 	smc->srf.sr_state = SR0_WAIT ;
155 }
156 
157 static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index)
158 {
159 	unsigned int		i ;
160 	struct s_srf_evc	*evc ;
161 
162 	for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
163 		if (evc->evc_code == code && evc->evc_index == index)
164 			return evc;
165 	}
166 	return NULL;
167 }
168 
169 #define THRESHOLD_2	(2*TICKS_PER_SECOND)
170 #define THRESHOLD_32	(32*TICKS_PER_SECOND)
171 
172 static const char * const srf_names[] = {
173 	"None","MACPathChangeEvent",	"MACNeighborChangeEvent",
174 	"PORTPathChangeEvent",		"PORTUndesiredConnectionAttemptEvent",
175 	"SMTPeerWrapCondition",		"SMTHoldCondition",
176 	"MACFrameErrorCondition",	"MACDuplicateAddressCondition",
177 	"MACNotCopiedCondition",	"PORTEBErrorCondition",
178 	"PORTLerCondition"
179 } ;
180 
181 void smt_srf_event(struct s_smc *smc, int code, int index, int cond)
182 {
183 	struct s_srf_evc	*evc ;
184 	int			cond_asserted = 0 ;
185 	int			cond_deasserted = 0 ;
186 	int			event_occurred = 0 ;
187 	int			tsr ;
188 	int			T_Limit = 2*TICKS_PER_SECOND ;
189 
190 	if (code == SMT_COND_MAC_DUP_ADDR && cond) {
191 		RS_SET(smc,RS_DUPADDR) ;
192 	}
193 
194 	if (code) {
195 		DB_SMT("SRF: %s index %d", srf_names[code], index);
196 
197 		if (!(evc = smt_get_evc(smc,code,index))) {
198 			DB_SMT("SRF : smt_get_evc() failed");
199 			return ;
200 		}
201 		/*
202 		 * ignore condition if no change
203 		 */
204 		if (SMT_IS_CONDITION(code)) {
205 			if (*evc->evc_cond_state == cond)
206 				return ;
207 		}
208 
209 		/*
210 		 * set transition time stamp
211 		 */
212 		smt_set_timestamp(smc,smc->mib.fddiSMTTransitionTimeStamp) ;
213 		if (SMT_IS_CONDITION(code)) {
214 			DB_SMT("SRF: condition is %s", cond ? "ON" : "OFF");
215 			if (cond) {
216 				*evc->evc_cond_state = TRUE ;
217 				evc->evc_rep_required = TRUE ;
218 				smc->srf.any_report = TRUE ;
219 				cond_asserted = TRUE ;
220 			}
221 			else {
222 				*evc->evc_cond_state = FALSE ;
223 				cond_deasserted = TRUE ;
224 			}
225 		}
226 		else {
227 			if (evc->evc_rep_required) {
228 				*evc->evc_multiple  = TRUE ;
229 			}
230 			else {
231 				evc->evc_rep_required = TRUE ;
232 				*evc->evc_multiple  = FALSE ;
233 			}
234 			smc->srf.any_report = TRUE ;
235 			event_occurred = TRUE ;
236 		}
237 #ifdef	FDDI_MIB
238 		snmp_srf_event(smc,evc) ;
239 #endif	/* FDDI_MIB */
240 	}
241 	tsr = smt_get_time() - smc->srf.TSR ;
242 
243 	switch (smc->srf.sr_state) {
244 	case SR0_WAIT :
245 		/* SR01a */
246 		if (cond_asserted && tsr < T_Limit) {
247 			smc->srf.SRThreshold = THRESHOLD_2 ;
248 			smc->srf.sr_state = SR1_HOLDOFF ;
249 			break ;
250 		}
251 		/* SR01b */
252 		if (cond_deasserted && tsr < T_Limit) {
253 			smc->srf.sr_state = SR1_HOLDOFF ;
254 			break ;
255 		}
256 		/* SR01c */
257 		if (event_occurred && tsr < T_Limit) {
258 			smc->srf.sr_state = SR1_HOLDOFF ;
259 			break ;
260 		}
261 		/* SR00b */
262 		if (cond_asserted && tsr >= T_Limit) {
263 			smc->srf.SRThreshold = THRESHOLD_2 ;
264 			smc->srf.TSR = smt_get_time() ;
265 			smt_send_srf(smc) ;
266 			break ;
267 		}
268 		/* SR00c */
269 		if (cond_deasserted && tsr >= T_Limit) {
270 			smc->srf.TSR = smt_get_time() ;
271 			smt_send_srf(smc) ;
272 			break ;
273 		}
274 		/* SR00d */
275 		if (event_occurred && tsr >= T_Limit) {
276 			smc->srf.TSR = smt_get_time() ;
277 			smt_send_srf(smc) ;
278 			break ;
279 		}
280 		/* SR00e */
281 		if (smc->srf.any_report && (u_long) tsr >=
282 			smc->srf.SRThreshold) {
283 			smc->srf.SRThreshold *= 2 ;
284 			if (smc->srf.SRThreshold > THRESHOLD_32)
285 				smc->srf.SRThreshold = THRESHOLD_32 ;
286 			smc->srf.TSR = smt_get_time() ;
287 			smt_send_srf(smc) ;
288 			break ;
289 		}
290 		/* SR02 */
291 		if (!smc->mib.fddiSMTStatRptPolicy) {
292 			smc->srf.sr_state = SR2_DISABLED ;
293 			break ;
294 		}
295 		break ;
296 	case SR1_HOLDOFF :
297 		/* SR10b */
298 		if (tsr >= T_Limit) {
299 			smc->srf.sr_state = SR0_WAIT ;
300 			smc->srf.TSR = smt_get_time() ;
301 			smt_send_srf(smc) ;
302 			break ;
303 		}
304 		/* SR11a */
305 		if (cond_asserted) {
306 			smc->srf.SRThreshold = THRESHOLD_2 ;
307 		}
308 		/* SR11b */
309 		/* SR11c */
310 		/* handled above */
311 		/* SR12 */
312 		if (!smc->mib.fddiSMTStatRptPolicy) {
313 			smc->srf.sr_state = SR2_DISABLED ;
314 			break ;
315 		}
316 		break ;
317 	case SR2_DISABLED :
318 		if (smc->mib.fddiSMTStatRptPolicy) {
319 			smc->srf.sr_state = SR0_WAIT ;
320 			smc->srf.TSR = smt_get_time() ;
321 			smc->srf.SRThreshold = THRESHOLD_2 ;
322 			clear_all_rep(smc) ;
323 			break ;
324 		}
325 		break ;
326 	}
327 }
328 
329 static void clear_all_rep(struct s_smc *smc)
330 {
331 	struct s_srf_evc	*evc ;
332 	unsigned int		i ;
333 
334 	for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
335 		evc->evc_rep_required = FALSE ;
336 		if (SMT_IS_CONDITION(evc->evc_code))
337 			*evc->evc_cond_state = FALSE ;
338 	}
339 	smc->srf.any_report = FALSE ;
340 }
341 
342 static void clear_reported(struct s_smc *smc)
343 {
344 	struct s_srf_evc	*evc ;
345 	unsigned int		i ;
346 
347 	smc->srf.any_report = FALSE ;
348 	for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
349 		if (SMT_IS_CONDITION(evc->evc_code)) {
350 			if (*evc->evc_cond_state == FALSE)
351 				evc->evc_rep_required = FALSE ;
352 			else
353 				smc->srf.any_report = TRUE ;
354 		}
355 		else {
356 			evc->evc_rep_required = FALSE ;
357 			*evc->evc_multiple = FALSE ;
358 		}
359 	}
360 }
361 
362 /*
363  * build and send SMT SRF frame
364  */
365 static void smt_send_srf(struct s_smc *smc)
366 {
367 
368 	struct smt_header	*smt ;
369 	struct s_srf_evc	*evc ;
370 	SK_LOC_DECL(struct s_pcon,pcon) ;
371 	SMbuf			*mb ;
372 	unsigned int		i ;
373 
374 	static const struct fddi_addr SMT_SRF_DA = {
375 		{ 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 }
376 	} ;
377 
378 	/*
379 	 * build SMT header
380 	 */
381 	if (!smc->r.sm_ma_avail)
382 		return ;
383 	if (!(mb = smt_build_frame(smc,SMT_SRF,SMT_ANNOUNCE,0)))
384 		return ;
385 
386 	RS_SET(smc,RS_SOFTERROR) ;
387 
388 	smt = smtod(mb, struct smt_header *) ;
389 	smt->smt_dest = SMT_SRF_DA ;		/* DA == SRF multicast */
390 
391 	/*
392 	 * setup parameter status
393 	 */
394 	pcon.pc_len = SMT_MAX_INFO_LEN ;	/* max para length */
395 	pcon.pc_err = 0 ;			/* no error */
396 	pcon.pc_badset = 0 ;			/* no bad set count */
397 	pcon.pc_p = (void *) (smt + 1) ;	/* paras start here */
398 
399 	smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
400 	smt_add_para(smc,&pcon,(u_short) SMT_P1034,0,0) ;
401 
402 	for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
403 		if (evc->evc_rep_required) {
404 			smt_add_para(smc,&pcon,evc->evc_para,
405 				(int)evc->evc_index,0) ;
406 		}
407 	}
408 	smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
409 	mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
410 
411 	DB_SMT("SRF: sending SRF at %p, len %d", smt, mb->sm_len);
412 	DB_SMT("SRF: state SR%d Threshold %lu",
413 	       smc->srf.sr_state, smc->srf.SRThreshold / TICKS_PER_SECOND);
414 #ifdef	DEBUG
415 	dump_smt(smc,smt,"SRF Send") ;
416 #endif
417 	smt_send_frame(smc,mb,FC_SMT_INFO,0) ;
418 	clear_reported(smc) ;
419 }
420 
421 #endif	/* no BOOT */
422 #endif	/* no SLIM_SMT */
423 
424