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