xref: /OK3568_Linux_fs/kernel/drivers/isdn/mISDN/tei.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Author	Karsten Keil <kkeil@novell.com>
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright 2008  by Karsten Keil <kkeil@novell.com>
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun #include "layer2.h"
9*4882a593Smuzhiyun #include <linux/random.h>
10*4882a593Smuzhiyun #include <linux/slab.h>
11*4882a593Smuzhiyun #include "core.h"
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #define ID_REQUEST	1
14*4882a593Smuzhiyun #define ID_ASSIGNED	2
15*4882a593Smuzhiyun #define ID_DENIED	3
16*4882a593Smuzhiyun #define ID_CHK_REQ	4
17*4882a593Smuzhiyun #define ID_CHK_RES	5
18*4882a593Smuzhiyun #define ID_REMOVE	6
19*4882a593Smuzhiyun #define ID_VERIFY	7
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define TEI_ENTITY_ID	0xf
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define MGR_PH_ACTIVE	16
24*4882a593Smuzhiyun #define MGR_PH_NOTREADY	17
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define DATIMER_VAL	10000
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun static	u_int	*debug;
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun static struct Fsm deactfsm = {NULL, 0, 0, NULL, NULL};
31*4882a593Smuzhiyun static struct Fsm teifsmu = {NULL, 0, 0, NULL, NULL};
32*4882a593Smuzhiyun static struct Fsm teifsmn = {NULL, 0, 0, NULL, NULL};
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun enum {
35*4882a593Smuzhiyun 	ST_L1_DEACT,
36*4882a593Smuzhiyun 	ST_L1_DEACT_PENDING,
37*4882a593Smuzhiyun 	ST_L1_ACTIV,
38*4882a593Smuzhiyun };
39*4882a593Smuzhiyun #define DEACT_STATE_COUNT (ST_L1_ACTIV + 1)
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun static char *strDeactState[] =
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	"ST_L1_DEACT",
44*4882a593Smuzhiyun 	"ST_L1_DEACT_PENDING",
45*4882a593Smuzhiyun 	"ST_L1_ACTIV",
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun enum {
49*4882a593Smuzhiyun 	EV_ACTIVATE,
50*4882a593Smuzhiyun 	EV_ACTIVATE_IND,
51*4882a593Smuzhiyun 	EV_DEACTIVATE,
52*4882a593Smuzhiyun 	EV_DEACTIVATE_IND,
53*4882a593Smuzhiyun 	EV_UI,
54*4882a593Smuzhiyun 	EV_DATIMER,
55*4882a593Smuzhiyun };
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun #define DEACT_EVENT_COUNT (EV_DATIMER + 1)
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun static char *strDeactEvent[] =
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun 	"EV_ACTIVATE",
62*4882a593Smuzhiyun 	"EV_ACTIVATE_IND",
63*4882a593Smuzhiyun 	"EV_DEACTIVATE",
64*4882a593Smuzhiyun 	"EV_DEACTIVATE_IND",
65*4882a593Smuzhiyun 	"EV_UI",
66*4882a593Smuzhiyun 	"EV_DATIMER",
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun static void
da_debug(struct FsmInst * fi,char * fmt,...)70*4882a593Smuzhiyun da_debug(struct FsmInst *fi, char *fmt, ...)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun 	struct manager	*mgr = fi->userdata;
73*4882a593Smuzhiyun 	struct va_format vaf;
74*4882a593Smuzhiyun 	va_list va;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	if (!(*debug & DEBUG_L2_TEIFSM))
77*4882a593Smuzhiyun 		return;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	va_start(va, fmt);
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	vaf.fmt = fmt;
82*4882a593Smuzhiyun 	vaf.va = &va;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	printk(KERN_DEBUG "mgr(%d): %pV\n", mgr->ch.st->dev->id, &vaf);
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	va_end(va);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun static void
da_activate(struct FsmInst * fi,int event,void * arg)90*4882a593Smuzhiyun da_activate(struct FsmInst *fi, int event, void *arg)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	struct manager	*mgr = fi->userdata;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	if (fi->state == ST_L1_DEACT_PENDING)
95*4882a593Smuzhiyun 		mISDN_FsmDelTimer(&mgr->datimer, 1);
96*4882a593Smuzhiyun 	mISDN_FsmChangeState(fi, ST_L1_ACTIV);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun static void
da_deactivate_ind(struct FsmInst * fi,int event,void * arg)100*4882a593Smuzhiyun da_deactivate_ind(struct FsmInst *fi, int event, void *arg)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	mISDN_FsmChangeState(fi, ST_L1_DEACT);
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun static void
da_deactivate(struct FsmInst * fi,int event,void * arg)106*4882a593Smuzhiyun da_deactivate(struct FsmInst *fi, int event, void *arg)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun 	struct manager	*mgr = fi->userdata;
109*4882a593Smuzhiyun 	struct layer2	*l2;
110*4882a593Smuzhiyun 	u_long		flags;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	read_lock_irqsave(&mgr->lock, flags);
113*4882a593Smuzhiyun 	list_for_each_entry(l2, &mgr->layer2, list) {
114*4882a593Smuzhiyun 		if (l2->l2m.state > ST_L2_4) {
115*4882a593Smuzhiyun 			/* have still activ TEI */
116*4882a593Smuzhiyun 			read_unlock_irqrestore(&mgr->lock, flags);
117*4882a593Smuzhiyun 			return;
118*4882a593Smuzhiyun 		}
119*4882a593Smuzhiyun 	}
120*4882a593Smuzhiyun 	read_unlock_irqrestore(&mgr->lock, flags);
121*4882a593Smuzhiyun 	/* All TEI are inactiv */
122*4882a593Smuzhiyun 	if (!test_bit(OPTION_L1_HOLD, &mgr->options)) {
123*4882a593Smuzhiyun 		mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER,
124*4882a593Smuzhiyun 				  NULL, 1);
125*4882a593Smuzhiyun 		mISDN_FsmChangeState(fi, ST_L1_DEACT_PENDING);
126*4882a593Smuzhiyun 	}
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun static void
da_ui(struct FsmInst * fi,int event,void * arg)130*4882a593Smuzhiyun da_ui(struct FsmInst *fi, int event, void *arg)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun 	struct manager	*mgr = fi->userdata;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	/* restart da timer */
135*4882a593Smuzhiyun 	if (!test_bit(OPTION_L1_HOLD, &mgr->options)) {
136*4882a593Smuzhiyun 		mISDN_FsmDelTimer(&mgr->datimer, 2);
137*4882a593Smuzhiyun 		mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER,
138*4882a593Smuzhiyun 				  NULL, 2);
139*4882a593Smuzhiyun 	}
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun static void
da_timer(struct FsmInst * fi,int event,void * arg)143*4882a593Smuzhiyun da_timer(struct FsmInst *fi, int event, void *arg)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	struct manager	*mgr = fi->userdata;
146*4882a593Smuzhiyun 	struct layer2	*l2;
147*4882a593Smuzhiyun 	u_long		flags;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	/* check again */
150*4882a593Smuzhiyun 	read_lock_irqsave(&mgr->lock, flags);
151*4882a593Smuzhiyun 	list_for_each_entry(l2, &mgr->layer2, list) {
152*4882a593Smuzhiyun 		if (l2->l2m.state > ST_L2_4) {
153*4882a593Smuzhiyun 			/* have still activ TEI */
154*4882a593Smuzhiyun 			read_unlock_irqrestore(&mgr->lock, flags);
155*4882a593Smuzhiyun 			mISDN_FsmChangeState(fi, ST_L1_ACTIV);
156*4882a593Smuzhiyun 			return;
157*4882a593Smuzhiyun 		}
158*4882a593Smuzhiyun 	}
159*4882a593Smuzhiyun 	read_unlock_irqrestore(&mgr->lock, flags);
160*4882a593Smuzhiyun 	/* All TEI are inactiv */
161*4882a593Smuzhiyun 	mISDN_FsmChangeState(fi, ST_L1_DEACT);
162*4882a593Smuzhiyun 	_queue_data(&mgr->ch, PH_DEACTIVATE_REQ, MISDN_ID_ANY, 0, NULL,
163*4882a593Smuzhiyun 		    GFP_ATOMIC);
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun static struct FsmNode DeactFnList[] =
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun 	{ST_L1_DEACT, EV_ACTIVATE_IND, da_activate},
169*4882a593Smuzhiyun 	{ST_L1_ACTIV, EV_DEACTIVATE_IND, da_deactivate_ind},
170*4882a593Smuzhiyun 	{ST_L1_ACTIV, EV_DEACTIVATE, da_deactivate},
171*4882a593Smuzhiyun 	{ST_L1_DEACT_PENDING, EV_ACTIVATE, da_activate},
172*4882a593Smuzhiyun 	{ST_L1_DEACT_PENDING, EV_UI, da_ui},
173*4882a593Smuzhiyun 	{ST_L1_DEACT_PENDING, EV_DATIMER, da_timer},
174*4882a593Smuzhiyun };
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun enum {
177*4882a593Smuzhiyun 	ST_TEI_NOP,
178*4882a593Smuzhiyun 	ST_TEI_IDREQ,
179*4882a593Smuzhiyun 	ST_TEI_IDVERIFY,
180*4882a593Smuzhiyun };
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun #define TEI_STATE_COUNT (ST_TEI_IDVERIFY + 1)
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun static char *strTeiState[] =
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun 	"ST_TEI_NOP",
187*4882a593Smuzhiyun 	"ST_TEI_IDREQ",
188*4882a593Smuzhiyun 	"ST_TEI_IDVERIFY",
189*4882a593Smuzhiyun };
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun enum {
192*4882a593Smuzhiyun 	EV_IDREQ,
193*4882a593Smuzhiyun 	EV_ASSIGN,
194*4882a593Smuzhiyun 	EV_ASSIGN_REQ,
195*4882a593Smuzhiyun 	EV_DENIED,
196*4882a593Smuzhiyun 	EV_CHKREQ,
197*4882a593Smuzhiyun 	EV_CHKRESP,
198*4882a593Smuzhiyun 	EV_REMOVE,
199*4882a593Smuzhiyun 	EV_VERIFY,
200*4882a593Smuzhiyun 	EV_TIMER,
201*4882a593Smuzhiyun };
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun #define TEI_EVENT_COUNT (EV_TIMER + 1)
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun static char *strTeiEvent[] =
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	"EV_IDREQ",
208*4882a593Smuzhiyun 	"EV_ASSIGN",
209*4882a593Smuzhiyun 	"EV_ASSIGN_REQ",
210*4882a593Smuzhiyun 	"EV_DENIED",
211*4882a593Smuzhiyun 	"EV_CHKREQ",
212*4882a593Smuzhiyun 	"EV_CHKRESP",
213*4882a593Smuzhiyun 	"EV_REMOVE",
214*4882a593Smuzhiyun 	"EV_VERIFY",
215*4882a593Smuzhiyun 	"EV_TIMER",
216*4882a593Smuzhiyun };
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun static void
tei_debug(struct FsmInst * fi,char * fmt,...)219*4882a593Smuzhiyun tei_debug(struct FsmInst *fi, char *fmt, ...)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun 	struct teimgr	*tm = fi->userdata;
222*4882a593Smuzhiyun 	struct va_format vaf;
223*4882a593Smuzhiyun 	va_list va;
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	if (!(*debug & DEBUG_L2_TEIFSM))
226*4882a593Smuzhiyun 		return;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	va_start(va, fmt);
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	vaf.fmt = fmt;
231*4882a593Smuzhiyun 	vaf.va = &va;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	printk(KERN_DEBUG "sapi(%d) tei(%d): %pV\n",
234*4882a593Smuzhiyun 	       tm->l2->sapi, tm->l2->tei, &vaf);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	va_end(va);
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun static int
get_free_id(struct manager * mgr)242*4882a593Smuzhiyun get_free_id(struct manager *mgr)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun 	DECLARE_BITMAP(ids, 64) = { [0 ... BITS_TO_LONGS(64) - 1] = 0 };
245*4882a593Smuzhiyun 	int		i;
246*4882a593Smuzhiyun 	struct layer2	*l2;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	list_for_each_entry(l2, &mgr->layer2, list) {
249*4882a593Smuzhiyun 		if (l2->ch.nr > 63) {
250*4882a593Smuzhiyun 			printk(KERN_WARNING
251*4882a593Smuzhiyun 			       "%s: more as 63 layer2 for one device\n",
252*4882a593Smuzhiyun 			       __func__);
253*4882a593Smuzhiyun 			return -EBUSY;
254*4882a593Smuzhiyun 		}
255*4882a593Smuzhiyun 		__set_bit(l2->ch.nr, ids);
256*4882a593Smuzhiyun 	}
257*4882a593Smuzhiyun 	i = find_next_zero_bit(ids, 64, 1);
258*4882a593Smuzhiyun 	if (i < 64)
259*4882a593Smuzhiyun 		return i;
260*4882a593Smuzhiyun 	printk(KERN_WARNING "%s: more as 63 layer2 for one device\n",
261*4882a593Smuzhiyun 	       __func__);
262*4882a593Smuzhiyun 	return -EBUSY;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun static int
get_free_tei(struct manager * mgr)266*4882a593Smuzhiyun get_free_tei(struct manager *mgr)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun 	DECLARE_BITMAP(ids, 64) = { [0 ... BITS_TO_LONGS(64) - 1] = 0 };
269*4882a593Smuzhiyun 	int		i;
270*4882a593Smuzhiyun 	struct layer2	*l2;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	list_for_each_entry(l2, &mgr->layer2, list) {
273*4882a593Smuzhiyun 		if (l2->ch.nr == 0)
274*4882a593Smuzhiyun 			continue;
275*4882a593Smuzhiyun 		if ((l2->ch.addr & 0xff) != 0)
276*4882a593Smuzhiyun 			continue;
277*4882a593Smuzhiyun 		i = l2->ch.addr >> 8;
278*4882a593Smuzhiyun 		if (i < 64)
279*4882a593Smuzhiyun 			continue;
280*4882a593Smuzhiyun 		i -= 64;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 		__set_bit(i, ids);
283*4882a593Smuzhiyun 	}
284*4882a593Smuzhiyun 	i = find_first_zero_bit(ids, 64);
285*4882a593Smuzhiyun 	if (i < 64)
286*4882a593Smuzhiyun 		return i + 64;
287*4882a593Smuzhiyun 	printk(KERN_WARNING "%s: more as 63 dynamic tei for one device\n",
288*4882a593Smuzhiyun 	       __func__);
289*4882a593Smuzhiyun 	return -1;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun static void
teiup_create(struct manager * mgr,u_int prim,int len,void * arg)293*4882a593Smuzhiyun teiup_create(struct manager *mgr, u_int prim, int len, void *arg)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun 	struct sk_buff	*skb;
296*4882a593Smuzhiyun 	struct mISDNhead *hh;
297*4882a593Smuzhiyun 	int		err;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	skb = mI_alloc_skb(len, GFP_ATOMIC);
300*4882a593Smuzhiyun 	if (!skb)
301*4882a593Smuzhiyun 		return;
302*4882a593Smuzhiyun 	hh = mISDN_HEAD_P(skb);
303*4882a593Smuzhiyun 	hh->prim = prim;
304*4882a593Smuzhiyun 	hh->id = (mgr->ch.nr << 16) | mgr->ch.addr;
305*4882a593Smuzhiyun 	if (len)
306*4882a593Smuzhiyun 		skb_put_data(skb, arg, len);
307*4882a593Smuzhiyun 	err = mgr->up->send(mgr->up, skb);
308*4882a593Smuzhiyun 	if (err) {
309*4882a593Smuzhiyun 		printk(KERN_WARNING "%s: err=%d\n", __func__, err);
310*4882a593Smuzhiyun 		dev_kfree_skb(skb);
311*4882a593Smuzhiyun 	}
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun static u_int
new_id(struct manager * mgr)315*4882a593Smuzhiyun new_id(struct manager *mgr)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun 	u_int	id;
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	id = mgr->nextid++;
320*4882a593Smuzhiyun 	if (id == 0x7fff)
321*4882a593Smuzhiyun 		mgr->nextid = 1;
322*4882a593Smuzhiyun 	id <<= 16;
323*4882a593Smuzhiyun 	id |= GROUP_TEI << 8;
324*4882a593Smuzhiyun 	id |= TEI_SAPI;
325*4882a593Smuzhiyun 	return id;
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun static void
do_send(struct manager * mgr)329*4882a593Smuzhiyun do_send(struct manager *mgr)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun 	if (!test_bit(MGR_PH_ACTIVE, &mgr->options))
332*4882a593Smuzhiyun 		return;
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	if (!test_and_set_bit(MGR_PH_NOTREADY, &mgr->options)) {
335*4882a593Smuzhiyun 		struct sk_buff	*skb = skb_dequeue(&mgr->sendq);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 		if (!skb) {
338*4882a593Smuzhiyun 			test_and_clear_bit(MGR_PH_NOTREADY, &mgr->options);
339*4882a593Smuzhiyun 			return;
340*4882a593Smuzhiyun 		}
341*4882a593Smuzhiyun 		mgr->lastid = mISDN_HEAD_ID(skb);
342*4882a593Smuzhiyun 		mISDN_FsmEvent(&mgr->deact, EV_UI, NULL);
343*4882a593Smuzhiyun 		if (mgr->ch.recv(mgr->ch.peer, skb)) {
344*4882a593Smuzhiyun 			dev_kfree_skb(skb);
345*4882a593Smuzhiyun 			test_and_clear_bit(MGR_PH_NOTREADY, &mgr->options);
346*4882a593Smuzhiyun 			mgr->lastid = MISDN_ID_NONE;
347*4882a593Smuzhiyun 		}
348*4882a593Smuzhiyun 	}
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun static void
do_ack(struct manager * mgr,u_int id)352*4882a593Smuzhiyun do_ack(struct manager *mgr, u_int id)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun 	if (test_bit(MGR_PH_NOTREADY, &mgr->options)) {
355*4882a593Smuzhiyun 		if (id == mgr->lastid) {
356*4882a593Smuzhiyun 			if (test_bit(MGR_PH_ACTIVE, &mgr->options)) {
357*4882a593Smuzhiyun 				struct sk_buff	*skb;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 				skb = skb_dequeue(&mgr->sendq);
360*4882a593Smuzhiyun 				if (skb) {
361*4882a593Smuzhiyun 					mgr->lastid = mISDN_HEAD_ID(skb);
362*4882a593Smuzhiyun 					if (!mgr->ch.recv(mgr->ch.peer, skb))
363*4882a593Smuzhiyun 						return;
364*4882a593Smuzhiyun 					dev_kfree_skb(skb);
365*4882a593Smuzhiyun 				}
366*4882a593Smuzhiyun 			}
367*4882a593Smuzhiyun 			mgr->lastid = MISDN_ID_NONE;
368*4882a593Smuzhiyun 			test_and_clear_bit(MGR_PH_NOTREADY, &mgr->options);
369*4882a593Smuzhiyun 		}
370*4882a593Smuzhiyun 	}
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun static void
mgr_send_down(struct manager * mgr,struct sk_buff * skb)374*4882a593Smuzhiyun mgr_send_down(struct manager *mgr, struct sk_buff *skb)
375*4882a593Smuzhiyun {
376*4882a593Smuzhiyun 	skb_queue_tail(&mgr->sendq, skb);
377*4882a593Smuzhiyun 	if (!test_bit(MGR_PH_ACTIVE, &mgr->options)) {
378*4882a593Smuzhiyun 		_queue_data(&mgr->ch, PH_ACTIVATE_REQ, MISDN_ID_ANY, 0,
379*4882a593Smuzhiyun 			    NULL, GFP_KERNEL);
380*4882a593Smuzhiyun 	} else {
381*4882a593Smuzhiyun 		do_send(mgr);
382*4882a593Smuzhiyun 	}
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun static int
dl_unit_data(struct manager * mgr,struct sk_buff * skb)386*4882a593Smuzhiyun dl_unit_data(struct manager *mgr, struct sk_buff *skb)
387*4882a593Smuzhiyun {
388*4882a593Smuzhiyun 	if (!test_bit(MGR_OPT_NETWORK, &mgr->options)) /* only net send UI */
389*4882a593Smuzhiyun 		return -EINVAL;
390*4882a593Smuzhiyun 	if (!test_bit(MGR_PH_ACTIVE, &mgr->options))
391*4882a593Smuzhiyun 		_queue_data(&mgr->ch, PH_ACTIVATE_REQ, MISDN_ID_ANY, 0,
392*4882a593Smuzhiyun 			    NULL, GFP_KERNEL);
393*4882a593Smuzhiyun 	skb_push(skb, 3);
394*4882a593Smuzhiyun 	skb->data[0] = 0x02; /* SAPI 0 C/R = 1 */
395*4882a593Smuzhiyun 	skb->data[1] = 0xff; /* TEI 127 */
396*4882a593Smuzhiyun 	skb->data[2] = UI;   /* UI frame */
397*4882a593Smuzhiyun 	mISDN_HEAD_PRIM(skb) = PH_DATA_REQ;
398*4882a593Smuzhiyun 	mISDN_HEAD_ID(skb) = new_id(mgr);
399*4882a593Smuzhiyun 	skb_queue_tail(&mgr->sendq, skb);
400*4882a593Smuzhiyun 	do_send(mgr);
401*4882a593Smuzhiyun 	return 0;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun static unsigned int
random_ri(void)405*4882a593Smuzhiyun random_ri(void)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun 	u16 x;
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	get_random_bytes(&x, sizeof(x));
410*4882a593Smuzhiyun 	return x;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun static struct layer2 *
findtei(struct manager * mgr,int tei)414*4882a593Smuzhiyun findtei(struct manager *mgr, int tei)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun 	struct layer2	*l2;
417*4882a593Smuzhiyun 	u_long		flags;
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	read_lock_irqsave(&mgr->lock, flags);
420*4882a593Smuzhiyun 	list_for_each_entry(l2, &mgr->layer2, list) {
421*4882a593Smuzhiyun 		if ((l2->sapi == 0) && (l2->tei > 0) &&
422*4882a593Smuzhiyun 		    (l2->tei != GROUP_TEI) && (l2->tei == tei))
423*4882a593Smuzhiyun 			goto done;
424*4882a593Smuzhiyun 	}
425*4882a593Smuzhiyun 	l2 = NULL;
426*4882a593Smuzhiyun done:
427*4882a593Smuzhiyun 	read_unlock_irqrestore(&mgr->lock, flags);
428*4882a593Smuzhiyun 	return l2;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun static void
put_tei_msg(struct manager * mgr,u_char m_id,unsigned int ri,int tei)432*4882a593Smuzhiyun put_tei_msg(struct manager *mgr, u_char m_id, unsigned int ri, int tei)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun 	struct sk_buff *skb;
435*4882a593Smuzhiyun 	u_char bp[8];
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	bp[0] = (TEI_SAPI << 2);
438*4882a593Smuzhiyun 	if (test_bit(MGR_OPT_NETWORK, &mgr->options))
439*4882a593Smuzhiyun 		bp[0] |= 2; /* CR:=1 for net command */
440*4882a593Smuzhiyun 	bp[1] = (GROUP_TEI << 1) | 0x1;
441*4882a593Smuzhiyun 	bp[2] = UI;
442*4882a593Smuzhiyun 	bp[3] = TEI_ENTITY_ID;
443*4882a593Smuzhiyun 	bp[4] = ri >> 8;
444*4882a593Smuzhiyun 	bp[5] = ri & 0xff;
445*4882a593Smuzhiyun 	bp[6] = m_id;
446*4882a593Smuzhiyun 	bp[7] = ((tei << 1) & 0xff) | 1;
447*4882a593Smuzhiyun 	skb = _alloc_mISDN_skb(PH_DATA_REQ, new_id(mgr), 8, bp, GFP_ATOMIC);
448*4882a593Smuzhiyun 	if (!skb) {
449*4882a593Smuzhiyun 		printk(KERN_WARNING "%s: no skb for tei msg\n", __func__);
450*4882a593Smuzhiyun 		return;
451*4882a593Smuzhiyun 	}
452*4882a593Smuzhiyun 	mgr_send_down(mgr, skb);
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun static void
tei_id_request(struct FsmInst * fi,int event,void * arg)456*4882a593Smuzhiyun tei_id_request(struct FsmInst *fi, int event, void *arg)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun 	struct teimgr *tm = fi->userdata;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	if (tm->l2->tei != GROUP_TEI) {
461*4882a593Smuzhiyun 		tm->tei_m.printdebug(&tm->tei_m,
462*4882a593Smuzhiyun 				     "assign request for already assigned tei %d",
463*4882a593Smuzhiyun 				     tm->l2->tei);
464*4882a593Smuzhiyun 		return;
465*4882a593Smuzhiyun 	}
466*4882a593Smuzhiyun 	tm->ri = random_ri();
467*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_TEI)
468*4882a593Smuzhiyun 		tm->tei_m.printdebug(&tm->tei_m,
469*4882a593Smuzhiyun 				     "assign request ri %d", tm->ri);
470*4882a593Smuzhiyun 	put_tei_msg(tm->mgr, ID_REQUEST, tm->ri, GROUP_TEI);
471*4882a593Smuzhiyun 	mISDN_FsmChangeState(fi, ST_TEI_IDREQ);
472*4882a593Smuzhiyun 	mISDN_FsmAddTimer(&tm->timer, tm->tval, EV_TIMER, NULL, 1);
473*4882a593Smuzhiyun 	tm->nval = 3;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun static void
tei_id_assign(struct FsmInst * fi,int event,void * arg)477*4882a593Smuzhiyun tei_id_assign(struct FsmInst *fi, int event, void *arg)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun 	struct teimgr	*tm = fi->userdata;
480*4882a593Smuzhiyun 	struct layer2	*l2;
481*4882a593Smuzhiyun 	u_char *dp = arg;
482*4882a593Smuzhiyun 	int ri, tei;
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	ri = ((unsigned int) *dp++ << 8);
485*4882a593Smuzhiyun 	ri += *dp++;
486*4882a593Smuzhiyun 	dp++;
487*4882a593Smuzhiyun 	tei = *dp >> 1;
488*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_TEI)
489*4882a593Smuzhiyun 		tm->tei_m.printdebug(fi, "identity assign ri %d tei %d",
490*4882a593Smuzhiyun 				     ri, tei);
491*4882a593Smuzhiyun 	l2 = findtei(tm->mgr, tei);
492*4882a593Smuzhiyun 	if (l2) {	/* same tei is in use */
493*4882a593Smuzhiyun 		if (ri != l2->tm->ri) {
494*4882a593Smuzhiyun 			tm->tei_m.printdebug(fi,
495*4882a593Smuzhiyun 					     "possible duplicate assignment tei %d", tei);
496*4882a593Smuzhiyun 			tei_l2(l2, MDL_ERROR_RSP, 0);
497*4882a593Smuzhiyun 		}
498*4882a593Smuzhiyun 	} else if (ri == tm->ri) {
499*4882a593Smuzhiyun 		mISDN_FsmDelTimer(&tm->timer, 1);
500*4882a593Smuzhiyun 		mISDN_FsmChangeState(fi, ST_TEI_NOP);
501*4882a593Smuzhiyun 		tei_l2(tm->l2, MDL_ASSIGN_REQ, tei);
502*4882a593Smuzhiyun 	}
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun static void
tei_id_test_dup(struct FsmInst * fi,int event,void * arg)506*4882a593Smuzhiyun tei_id_test_dup(struct FsmInst *fi, int event, void *arg)
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun 	struct teimgr	*tm = fi->userdata;
509*4882a593Smuzhiyun 	struct layer2	*l2;
510*4882a593Smuzhiyun 	u_char *dp = arg;
511*4882a593Smuzhiyun 	int tei, ri;
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	ri = ((unsigned int) *dp++ << 8);
514*4882a593Smuzhiyun 	ri += *dp++;
515*4882a593Smuzhiyun 	dp++;
516*4882a593Smuzhiyun 	tei = *dp >> 1;
517*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_TEI)
518*4882a593Smuzhiyun 		tm->tei_m.printdebug(fi, "foreign identity assign ri %d tei %d",
519*4882a593Smuzhiyun 				     ri, tei);
520*4882a593Smuzhiyun 	l2 = findtei(tm->mgr, tei);
521*4882a593Smuzhiyun 	if (l2) {	/* same tei is in use */
522*4882a593Smuzhiyun 		if (ri != l2->tm->ri) {	/* and it wasn't our request */
523*4882a593Smuzhiyun 			tm->tei_m.printdebug(fi,
524*4882a593Smuzhiyun 					     "possible duplicate assignment tei %d", tei);
525*4882a593Smuzhiyun 			mISDN_FsmEvent(&l2->tm->tei_m, EV_VERIFY, NULL);
526*4882a593Smuzhiyun 		}
527*4882a593Smuzhiyun 	}
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun static void
tei_id_denied(struct FsmInst * fi,int event,void * arg)531*4882a593Smuzhiyun tei_id_denied(struct FsmInst *fi, int event, void *arg)
532*4882a593Smuzhiyun {
533*4882a593Smuzhiyun 	struct teimgr *tm = fi->userdata;
534*4882a593Smuzhiyun 	u_char *dp = arg;
535*4882a593Smuzhiyun 	int ri, tei;
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	ri = ((unsigned int) *dp++ << 8);
538*4882a593Smuzhiyun 	ri += *dp++;
539*4882a593Smuzhiyun 	dp++;
540*4882a593Smuzhiyun 	tei = *dp >> 1;
541*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_TEI)
542*4882a593Smuzhiyun 		tm->tei_m.printdebug(fi, "identity denied ri %d tei %d",
543*4882a593Smuzhiyun 				     ri, tei);
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun static void
tei_id_chk_req(struct FsmInst * fi,int event,void * arg)547*4882a593Smuzhiyun tei_id_chk_req(struct FsmInst *fi, int event, void *arg)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun 	struct teimgr *tm = fi->userdata;
550*4882a593Smuzhiyun 	u_char *dp = arg;
551*4882a593Smuzhiyun 	int tei;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	tei = *(dp + 3) >> 1;
554*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_TEI)
555*4882a593Smuzhiyun 		tm->tei_m.printdebug(fi, "identity check req tei %d", tei);
556*4882a593Smuzhiyun 	if ((tm->l2->tei != GROUP_TEI) && ((tei == GROUP_TEI) ||
557*4882a593Smuzhiyun 					   (tei == tm->l2->tei))) {
558*4882a593Smuzhiyun 		mISDN_FsmDelTimer(&tm->timer, 4);
559*4882a593Smuzhiyun 		mISDN_FsmChangeState(&tm->tei_m, ST_TEI_NOP);
560*4882a593Smuzhiyun 		put_tei_msg(tm->mgr, ID_CHK_RES, random_ri(), tm->l2->tei);
561*4882a593Smuzhiyun 	}
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun static void
tei_id_remove(struct FsmInst * fi,int event,void * arg)565*4882a593Smuzhiyun tei_id_remove(struct FsmInst *fi, int event, void *arg)
566*4882a593Smuzhiyun {
567*4882a593Smuzhiyun 	struct teimgr *tm = fi->userdata;
568*4882a593Smuzhiyun 	u_char *dp = arg;
569*4882a593Smuzhiyun 	int tei;
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	tei = *(dp + 3) >> 1;
572*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_TEI)
573*4882a593Smuzhiyun 		tm->tei_m.printdebug(fi, "identity remove tei %d", tei);
574*4882a593Smuzhiyun 	if ((tm->l2->tei != GROUP_TEI) &&
575*4882a593Smuzhiyun 	    ((tei == GROUP_TEI) || (tei == tm->l2->tei))) {
576*4882a593Smuzhiyun 		mISDN_FsmDelTimer(&tm->timer, 5);
577*4882a593Smuzhiyun 		mISDN_FsmChangeState(&tm->tei_m, ST_TEI_NOP);
578*4882a593Smuzhiyun 		tei_l2(tm->l2, MDL_REMOVE_REQ, 0);
579*4882a593Smuzhiyun 	}
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun static void
tei_id_verify(struct FsmInst * fi,int event,void * arg)583*4882a593Smuzhiyun tei_id_verify(struct FsmInst *fi, int event, void *arg)
584*4882a593Smuzhiyun {
585*4882a593Smuzhiyun 	struct teimgr *tm = fi->userdata;
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_TEI)
588*4882a593Smuzhiyun 		tm->tei_m.printdebug(fi, "id verify request for tei %d",
589*4882a593Smuzhiyun 				     tm->l2->tei);
590*4882a593Smuzhiyun 	put_tei_msg(tm->mgr, ID_VERIFY, 0, tm->l2->tei);
591*4882a593Smuzhiyun 	mISDN_FsmChangeState(&tm->tei_m, ST_TEI_IDVERIFY);
592*4882a593Smuzhiyun 	mISDN_FsmAddTimer(&tm->timer, tm->tval, EV_TIMER, NULL, 2);
593*4882a593Smuzhiyun 	tm->nval = 2;
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun static void
tei_id_req_tout(struct FsmInst * fi,int event,void * arg)597*4882a593Smuzhiyun tei_id_req_tout(struct FsmInst *fi, int event, void *arg)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun 	struct teimgr *tm = fi->userdata;
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	if (--tm->nval) {
602*4882a593Smuzhiyun 		tm->ri = random_ri();
603*4882a593Smuzhiyun 		if (*debug & DEBUG_L2_TEI)
604*4882a593Smuzhiyun 			tm->tei_m.printdebug(fi, "assign req(%d) ri %d",
605*4882a593Smuzhiyun 					     4 - tm->nval, tm->ri);
606*4882a593Smuzhiyun 		put_tei_msg(tm->mgr, ID_REQUEST, tm->ri, GROUP_TEI);
607*4882a593Smuzhiyun 		mISDN_FsmAddTimer(&tm->timer, tm->tval, EV_TIMER, NULL, 3);
608*4882a593Smuzhiyun 	} else {
609*4882a593Smuzhiyun 		tm->tei_m.printdebug(fi, "assign req failed");
610*4882a593Smuzhiyun 		tei_l2(tm->l2, MDL_ERROR_RSP, 0);
611*4882a593Smuzhiyun 		mISDN_FsmChangeState(fi, ST_TEI_NOP);
612*4882a593Smuzhiyun 	}
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun static void
tei_id_ver_tout(struct FsmInst * fi,int event,void * arg)616*4882a593Smuzhiyun tei_id_ver_tout(struct FsmInst *fi, int event, void *arg)
617*4882a593Smuzhiyun {
618*4882a593Smuzhiyun 	struct teimgr *tm = fi->userdata;
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 	if (--tm->nval) {
621*4882a593Smuzhiyun 		if (*debug & DEBUG_L2_TEI)
622*4882a593Smuzhiyun 			tm->tei_m.printdebug(fi,
623*4882a593Smuzhiyun 					     "id verify req(%d) for tei %d",
624*4882a593Smuzhiyun 					     3 - tm->nval, tm->l2->tei);
625*4882a593Smuzhiyun 		put_tei_msg(tm->mgr, ID_VERIFY, 0, tm->l2->tei);
626*4882a593Smuzhiyun 		mISDN_FsmAddTimer(&tm->timer, tm->tval, EV_TIMER, NULL, 4);
627*4882a593Smuzhiyun 	} else {
628*4882a593Smuzhiyun 		tm->tei_m.printdebug(fi, "verify req for tei %d failed",
629*4882a593Smuzhiyun 				     tm->l2->tei);
630*4882a593Smuzhiyun 		tei_l2(tm->l2, MDL_REMOVE_REQ, 0);
631*4882a593Smuzhiyun 		mISDN_FsmChangeState(fi, ST_TEI_NOP);
632*4882a593Smuzhiyun 	}
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun static struct FsmNode TeiFnListUser[] =
636*4882a593Smuzhiyun {
637*4882a593Smuzhiyun 	{ST_TEI_NOP, EV_IDREQ, tei_id_request},
638*4882a593Smuzhiyun 	{ST_TEI_NOP, EV_ASSIGN, tei_id_test_dup},
639*4882a593Smuzhiyun 	{ST_TEI_NOP, EV_VERIFY, tei_id_verify},
640*4882a593Smuzhiyun 	{ST_TEI_NOP, EV_REMOVE, tei_id_remove},
641*4882a593Smuzhiyun 	{ST_TEI_NOP, EV_CHKREQ, tei_id_chk_req},
642*4882a593Smuzhiyun 	{ST_TEI_IDREQ, EV_TIMER, tei_id_req_tout},
643*4882a593Smuzhiyun 	{ST_TEI_IDREQ, EV_ASSIGN, tei_id_assign},
644*4882a593Smuzhiyun 	{ST_TEI_IDREQ, EV_DENIED, tei_id_denied},
645*4882a593Smuzhiyun 	{ST_TEI_IDVERIFY, EV_TIMER, tei_id_ver_tout},
646*4882a593Smuzhiyun 	{ST_TEI_IDVERIFY, EV_REMOVE, tei_id_remove},
647*4882a593Smuzhiyun 	{ST_TEI_IDVERIFY, EV_CHKREQ, tei_id_chk_req},
648*4882a593Smuzhiyun };
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun static void
tei_l2remove(struct layer2 * l2)651*4882a593Smuzhiyun tei_l2remove(struct layer2 *l2)
652*4882a593Smuzhiyun {
653*4882a593Smuzhiyun 	put_tei_msg(l2->tm->mgr, ID_REMOVE, 0, l2->tei);
654*4882a593Smuzhiyun 	tei_l2(l2, MDL_REMOVE_REQ, 0);
655*4882a593Smuzhiyun 	list_del(&l2->ch.list);
656*4882a593Smuzhiyun 	l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun static void
tei_assign_req(struct FsmInst * fi,int event,void * arg)660*4882a593Smuzhiyun tei_assign_req(struct FsmInst *fi, int event, void *arg)
661*4882a593Smuzhiyun {
662*4882a593Smuzhiyun 	struct teimgr *tm = fi->userdata;
663*4882a593Smuzhiyun 	u_char *dp = arg;
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	if (tm->l2->tei == GROUP_TEI) {
666*4882a593Smuzhiyun 		tm->tei_m.printdebug(&tm->tei_m,
667*4882a593Smuzhiyun 				     "net tei assign request without tei");
668*4882a593Smuzhiyun 		return;
669*4882a593Smuzhiyun 	}
670*4882a593Smuzhiyun 	tm->ri = ((unsigned int) *dp++ << 8);
671*4882a593Smuzhiyun 	tm->ri += *dp++;
672*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_TEI)
673*4882a593Smuzhiyun 		tm->tei_m.printdebug(&tm->tei_m,
674*4882a593Smuzhiyun 				     "net assign request ri %d teim %d", tm->ri, *dp);
675*4882a593Smuzhiyun 	put_tei_msg(tm->mgr, ID_ASSIGNED, tm->ri, tm->l2->tei);
676*4882a593Smuzhiyun 	mISDN_FsmChangeState(fi, ST_TEI_NOP);
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun static void
tei_id_chk_req_net(struct FsmInst * fi,int event,void * arg)680*4882a593Smuzhiyun tei_id_chk_req_net(struct FsmInst *fi, int event, void *arg)
681*4882a593Smuzhiyun {
682*4882a593Smuzhiyun 	struct teimgr	*tm = fi->userdata;
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_TEI)
685*4882a593Smuzhiyun 		tm->tei_m.printdebug(fi, "id check request for tei %d",
686*4882a593Smuzhiyun 				     tm->l2->tei);
687*4882a593Smuzhiyun 	tm->rcnt = 0;
688*4882a593Smuzhiyun 	put_tei_msg(tm->mgr, ID_CHK_REQ, 0, tm->l2->tei);
689*4882a593Smuzhiyun 	mISDN_FsmChangeState(&tm->tei_m, ST_TEI_IDVERIFY);
690*4882a593Smuzhiyun 	mISDN_FsmAddTimer(&tm->timer, tm->tval, EV_TIMER, NULL, 2);
691*4882a593Smuzhiyun 	tm->nval = 2;
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun static void
tei_id_chk_resp(struct FsmInst * fi,int event,void * arg)695*4882a593Smuzhiyun tei_id_chk_resp(struct FsmInst *fi, int event, void *arg)
696*4882a593Smuzhiyun {
697*4882a593Smuzhiyun 	struct teimgr *tm = fi->userdata;
698*4882a593Smuzhiyun 	u_char *dp = arg;
699*4882a593Smuzhiyun 	int tei;
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	tei = dp[3] >> 1;
702*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_TEI)
703*4882a593Smuzhiyun 		tm->tei_m.printdebug(fi, "identity check resp tei %d", tei);
704*4882a593Smuzhiyun 	if (tei == tm->l2->tei)
705*4882a593Smuzhiyun 		tm->rcnt++;
706*4882a593Smuzhiyun }
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun static void
tei_id_verify_net(struct FsmInst * fi,int event,void * arg)709*4882a593Smuzhiyun tei_id_verify_net(struct FsmInst *fi, int event, void *arg)
710*4882a593Smuzhiyun {
711*4882a593Smuzhiyun 	struct teimgr *tm = fi->userdata;
712*4882a593Smuzhiyun 	u_char *dp = arg;
713*4882a593Smuzhiyun 	int tei;
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 	tei = dp[3] >> 1;
716*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_TEI)
717*4882a593Smuzhiyun 		tm->tei_m.printdebug(fi, "identity verify req tei %d/%d",
718*4882a593Smuzhiyun 				     tei, tm->l2->tei);
719*4882a593Smuzhiyun 	if (tei == tm->l2->tei)
720*4882a593Smuzhiyun 		tei_id_chk_req_net(fi, event, arg);
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun static void
tei_id_ver_tout_net(struct FsmInst * fi,int event,void * arg)724*4882a593Smuzhiyun tei_id_ver_tout_net(struct FsmInst *fi, int event, void *arg)
725*4882a593Smuzhiyun {
726*4882a593Smuzhiyun 	struct teimgr *tm = fi->userdata;
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun 	if (tm->rcnt == 1) {
729*4882a593Smuzhiyun 		if (*debug & DEBUG_L2_TEI)
730*4882a593Smuzhiyun 			tm->tei_m.printdebug(fi,
731*4882a593Smuzhiyun 					     "check req for tei %d successful\n", tm->l2->tei);
732*4882a593Smuzhiyun 		mISDN_FsmChangeState(fi, ST_TEI_NOP);
733*4882a593Smuzhiyun 	} else if (tm->rcnt > 1) {
734*4882a593Smuzhiyun 		/* duplicate assignment; remove */
735*4882a593Smuzhiyun 		tei_l2remove(tm->l2);
736*4882a593Smuzhiyun 	} else if (--tm->nval) {
737*4882a593Smuzhiyun 		if (*debug & DEBUG_L2_TEI)
738*4882a593Smuzhiyun 			tm->tei_m.printdebug(fi,
739*4882a593Smuzhiyun 					     "id check req(%d) for tei %d",
740*4882a593Smuzhiyun 					     3 - tm->nval, tm->l2->tei);
741*4882a593Smuzhiyun 		put_tei_msg(tm->mgr, ID_CHK_REQ, 0, tm->l2->tei);
742*4882a593Smuzhiyun 		mISDN_FsmAddTimer(&tm->timer, tm->tval, EV_TIMER, NULL, 4);
743*4882a593Smuzhiyun 	} else {
744*4882a593Smuzhiyun 		tm->tei_m.printdebug(fi, "check req for tei %d failed",
745*4882a593Smuzhiyun 				     tm->l2->tei);
746*4882a593Smuzhiyun 		mISDN_FsmChangeState(fi, ST_TEI_NOP);
747*4882a593Smuzhiyun 		tei_l2remove(tm->l2);
748*4882a593Smuzhiyun 	}
749*4882a593Smuzhiyun }
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun static struct FsmNode TeiFnListNet[] =
752*4882a593Smuzhiyun {
753*4882a593Smuzhiyun 	{ST_TEI_NOP, EV_ASSIGN_REQ, tei_assign_req},
754*4882a593Smuzhiyun 	{ST_TEI_NOP, EV_VERIFY, tei_id_verify_net},
755*4882a593Smuzhiyun 	{ST_TEI_NOP, EV_CHKREQ, tei_id_chk_req_net},
756*4882a593Smuzhiyun 	{ST_TEI_IDVERIFY, EV_TIMER, tei_id_ver_tout_net},
757*4882a593Smuzhiyun 	{ST_TEI_IDVERIFY, EV_CHKRESP, tei_id_chk_resp},
758*4882a593Smuzhiyun };
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun static void
tei_ph_data_ind(struct teimgr * tm,u_int mt,u_char * dp,int len)761*4882a593Smuzhiyun tei_ph_data_ind(struct teimgr *tm, u_int mt, u_char *dp, int len)
762*4882a593Smuzhiyun {
763*4882a593Smuzhiyun 	if (test_bit(FLG_FIXED_TEI, &tm->l2->flag))
764*4882a593Smuzhiyun 		return;
765*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_TEI)
766*4882a593Smuzhiyun 		tm->tei_m.printdebug(&tm->tei_m, "tei handler mt %x", mt);
767*4882a593Smuzhiyun 	if (mt == ID_ASSIGNED)
768*4882a593Smuzhiyun 		mISDN_FsmEvent(&tm->tei_m, EV_ASSIGN, dp);
769*4882a593Smuzhiyun 	else if (mt == ID_DENIED)
770*4882a593Smuzhiyun 		mISDN_FsmEvent(&tm->tei_m, EV_DENIED, dp);
771*4882a593Smuzhiyun 	else if (mt == ID_CHK_REQ)
772*4882a593Smuzhiyun 		mISDN_FsmEvent(&tm->tei_m, EV_CHKREQ, dp);
773*4882a593Smuzhiyun 	else if (mt == ID_REMOVE)
774*4882a593Smuzhiyun 		mISDN_FsmEvent(&tm->tei_m, EV_REMOVE, dp);
775*4882a593Smuzhiyun 	else if (mt == ID_VERIFY)
776*4882a593Smuzhiyun 		mISDN_FsmEvent(&tm->tei_m, EV_VERIFY, dp);
777*4882a593Smuzhiyun 	else if (mt == ID_CHK_RES)
778*4882a593Smuzhiyun 		mISDN_FsmEvent(&tm->tei_m, EV_CHKRESP, dp);
779*4882a593Smuzhiyun }
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun static struct layer2 *
create_new_tei(struct manager * mgr,int tei,int sapi)782*4882a593Smuzhiyun create_new_tei(struct manager *mgr, int tei, int sapi)
783*4882a593Smuzhiyun {
784*4882a593Smuzhiyun 	unsigned long		opt = 0;
785*4882a593Smuzhiyun 	unsigned long		flags;
786*4882a593Smuzhiyun 	int			id;
787*4882a593Smuzhiyun 	struct layer2		*l2;
788*4882a593Smuzhiyun 	struct channel_req	rq;
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun 	if (!mgr->up)
791*4882a593Smuzhiyun 		return NULL;
792*4882a593Smuzhiyun 	if ((tei >= 0) && (tei < 64))
793*4882a593Smuzhiyun 		test_and_set_bit(OPTION_L2_FIXEDTEI, &opt);
794*4882a593Smuzhiyun 	if (mgr->ch.st->dev->Dprotocols & ((1 << ISDN_P_TE_E1) |
795*4882a593Smuzhiyun 	    (1 << ISDN_P_NT_E1))) {
796*4882a593Smuzhiyun 		test_and_set_bit(OPTION_L2_PMX, &opt);
797*4882a593Smuzhiyun 		rq.protocol = ISDN_P_NT_E1;
798*4882a593Smuzhiyun 	} else {
799*4882a593Smuzhiyun 		rq.protocol = ISDN_P_NT_S0;
800*4882a593Smuzhiyun 	}
801*4882a593Smuzhiyun 	l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, opt, tei, sapi);
802*4882a593Smuzhiyun 	if (!l2) {
803*4882a593Smuzhiyun 		printk(KERN_WARNING "%s:no memory for layer2\n", __func__);
804*4882a593Smuzhiyun 		return NULL;
805*4882a593Smuzhiyun 	}
806*4882a593Smuzhiyun 	l2->tm = kzalloc(sizeof(struct teimgr), GFP_KERNEL);
807*4882a593Smuzhiyun 	if (!l2->tm) {
808*4882a593Smuzhiyun 		kfree(l2);
809*4882a593Smuzhiyun 		printk(KERN_WARNING "%s:no memory for teimgr\n", __func__);
810*4882a593Smuzhiyun 		return NULL;
811*4882a593Smuzhiyun 	}
812*4882a593Smuzhiyun 	l2->tm->mgr = mgr;
813*4882a593Smuzhiyun 	l2->tm->l2 = l2;
814*4882a593Smuzhiyun 	l2->tm->tei_m.debug = *debug & DEBUG_L2_TEIFSM;
815*4882a593Smuzhiyun 	l2->tm->tei_m.userdata = l2->tm;
816*4882a593Smuzhiyun 	l2->tm->tei_m.printdebug = tei_debug;
817*4882a593Smuzhiyun 	l2->tm->tei_m.fsm = &teifsmn;
818*4882a593Smuzhiyun 	l2->tm->tei_m.state = ST_TEI_NOP;
819*4882a593Smuzhiyun 	l2->tm->tval = 2000; /* T202  2 sec */
820*4882a593Smuzhiyun 	mISDN_FsmInitTimer(&l2->tm->tei_m, &l2->tm->timer);
821*4882a593Smuzhiyun 	write_lock_irqsave(&mgr->lock, flags);
822*4882a593Smuzhiyun 	id = get_free_id(mgr);
823*4882a593Smuzhiyun 	list_add_tail(&l2->list, &mgr->layer2);
824*4882a593Smuzhiyun 	write_unlock_irqrestore(&mgr->lock, flags);
825*4882a593Smuzhiyun 	if (id < 0) {
826*4882a593Smuzhiyun 		l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
827*4882a593Smuzhiyun 		printk(KERN_WARNING "%s:no free id\n", __func__);
828*4882a593Smuzhiyun 		return NULL;
829*4882a593Smuzhiyun 	} else {
830*4882a593Smuzhiyun 		l2->ch.nr = id;
831*4882a593Smuzhiyun 		__add_layer2(&l2->ch, mgr->ch.st);
832*4882a593Smuzhiyun 		l2->ch.recv = mgr->ch.recv;
833*4882a593Smuzhiyun 		l2->ch.peer = mgr->ch.peer;
834*4882a593Smuzhiyun 		l2->ch.ctrl(&l2->ch, OPEN_CHANNEL, NULL);
835*4882a593Smuzhiyun 		/* We need open here L1 for the manager as well (refcounting) */
836*4882a593Smuzhiyun 		rq.adr.dev = mgr->ch.st->dev->id;
837*4882a593Smuzhiyun 		id = mgr->ch.st->own.ctrl(&mgr->ch.st->own, OPEN_CHANNEL, &rq);
838*4882a593Smuzhiyun 		if (id < 0) {
839*4882a593Smuzhiyun 			printk(KERN_WARNING "%s: cannot open L1\n", __func__);
840*4882a593Smuzhiyun 			l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
841*4882a593Smuzhiyun 			l2 = NULL;
842*4882a593Smuzhiyun 		}
843*4882a593Smuzhiyun 	}
844*4882a593Smuzhiyun 	return l2;
845*4882a593Smuzhiyun }
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun static void
new_tei_req(struct manager * mgr,u_char * dp)848*4882a593Smuzhiyun new_tei_req(struct manager *mgr, u_char *dp)
849*4882a593Smuzhiyun {
850*4882a593Smuzhiyun 	int		tei, ri;
851*4882a593Smuzhiyun 	struct layer2	*l2;
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 	ri = dp[0] << 8;
854*4882a593Smuzhiyun 	ri += dp[1];
855*4882a593Smuzhiyun 	if (!mgr->up)
856*4882a593Smuzhiyun 		goto denied;
857*4882a593Smuzhiyun 	if (!(dp[3] & 1)) /* Extension bit != 1 */
858*4882a593Smuzhiyun 		goto denied;
859*4882a593Smuzhiyun 	if (dp[3] != 0xff)
860*4882a593Smuzhiyun 		tei = dp[3] >> 1; /* 3GPP TS 08.56 6.1.11.2 */
861*4882a593Smuzhiyun 	else
862*4882a593Smuzhiyun 		tei = get_free_tei(mgr);
863*4882a593Smuzhiyun 	if (tei < 0) {
864*4882a593Smuzhiyun 		printk(KERN_WARNING "%s:No free tei\n", __func__);
865*4882a593Smuzhiyun 		goto denied;
866*4882a593Smuzhiyun 	}
867*4882a593Smuzhiyun 	l2 = create_new_tei(mgr, tei, CTRL_SAPI);
868*4882a593Smuzhiyun 	if (!l2)
869*4882a593Smuzhiyun 		goto denied;
870*4882a593Smuzhiyun 	else
871*4882a593Smuzhiyun 		mISDN_FsmEvent(&l2->tm->tei_m, EV_ASSIGN_REQ, dp);
872*4882a593Smuzhiyun 	return;
873*4882a593Smuzhiyun denied:
874*4882a593Smuzhiyun 	put_tei_msg(mgr, ID_DENIED, ri, GROUP_TEI);
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun static int
ph_data_ind(struct manager * mgr,struct sk_buff * skb)878*4882a593Smuzhiyun ph_data_ind(struct manager *mgr, struct sk_buff *skb)
879*4882a593Smuzhiyun {
880*4882a593Smuzhiyun 	int		ret = -EINVAL;
881*4882a593Smuzhiyun 	struct layer2	*l2, *nl2;
882*4882a593Smuzhiyun 	u_char		mt;
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun 	if (skb->len < 8) {
885*4882a593Smuzhiyun 		if (*debug  & DEBUG_L2_TEI)
886*4882a593Smuzhiyun 			printk(KERN_DEBUG "%s: short mgr frame %d/8\n",
887*4882a593Smuzhiyun 			       __func__, skb->len);
888*4882a593Smuzhiyun 		goto done;
889*4882a593Smuzhiyun 	}
890*4882a593Smuzhiyun 
891*4882a593Smuzhiyun 	if ((skb->data[0] >> 2) != TEI_SAPI) /* not for us */
892*4882a593Smuzhiyun 		goto done;
893*4882a593Smuzhiyun 	if (skb->data[0] & 1) /* EA0 formal error */
894*4882a593Smuzhiyun 		goto done;
895*4882a593Smuzhiyun 	if (!(skb->data[1] & 1)) /* EA1 formal error */
896*4882a593Smuzhiyun 		goto done;
897*4882a593Smuzhiyun 	if ((skb->data[1] >> 1) != GROUP_TEI) /* not for us */
898*4882a593Smuzhiyun 		goto done;
899*4882a593Smuzhiyun 	if ((skb->data[2] & 0xef) != UI) /* not UI */
900*4882a593Smuzhiyun 		goto done;
901*4882a593Smuzhiyun 	if (skb->data[3] != TEI_ENTITY_ID) /* not tei entity */
902*4882a593Smuzhiyun 		goto done;
903*4882a593Smuzhiyun 	mt = skb->data[6];
904*4882a593Smuzhiyun 	switch (mt) {
905*4882a593Smuzhiyun 	case ID_REQUEST:
906*4882a593Smuzhiyun 	case ID_CHK_RES:
907*4882a593Smuzhiyun 	case ID_VERIFY:
908*4882a593Smuzhiyun 		if (!test_bit(MGR_OPT_NETWORK, &mgr->options))
909*4882a593Smuzhiyun 			goto done;
910*4882a593Smuzhiyun 		break;
911*4882a593Smuzhiyun 	case ID_ASSIGNED:
912*4882a593Smuzhiyun 	case ID_DENIED:
913*4882a593Smuzhiyun 	case ID_CHK_REQ:
914*4882a593Smuzhiyun 	case ID_REMOVE:
915*4882a593Smuzhiyun 		if (test_bit(MGR_OPT_NETWORK, &mgr->options))
916*4882a593Smuzhiyun 			goto done;
917*4882a593Smuzhiyun 		break;
918*4882a593Smuzhiyun 	default:
919*4882a593Smuzhiyun 		goto done;
920*4882a593Smuzhiyun 	}
921*4882a593Smuzhiyun 	ret = 0;
922*4882a593Smuzhiyun 	if (mt == ID_REQUEST) {
923*4882a593Smuzhiyun 		new_tei_req(mgr, &skb->data[4]);
924*4882a593Smuzhiyun 		goto done;
925*4882a593Smuzhiyun 	}
926*4882a593Smuzhiyun 	list_for_each_entry_safe(l2, nl2, &mgr->layer2, list) {
927*4882a593Smuzhiyun 		tei_ph_data_ind(l2->tm, mt, &skb->data[4], skb->len - 4);
928*4882a593Smuzhiyun 	}
929*4882a593Smuzhiyun done:
930*4882a593Smuzhiyun 	return ret;
931*4882a593Smuzhiyun }
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun int
l2_tei(struct layer2 * l2,u_int cmd,u_long arg)934*4882a593Smuzhiyun l2_tei(struct layer2 *l2, u_int cmd, u_long arg)
935*4882a593Smuzhiyun {
936*4882a593Smuzhiyun 	struct teimgr	*tm = l2->tm;
937*4882a593Smuzhiyun 
938*4882a593Smuzhiyun 	if (test_bit(FLG_FIXED_TEI, &l2->flag))
939*4882a593Smuzhiyun 		return 0;
940*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_TEI)
941*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s: cmd(%x)\n", __func__, cmd);
942*4882a593Smuzhiyun 	switch (cmd) {
943*4882a593Smuzhiyun 	case MDL_ASSIGN_IND:
944*4882a593Smuzhiyun 		mISDN_FsmEvent(&tm->tei_m, EV_IDREQ, NULL);
945*4882a593Smuzhiyun 		break;
946*4882a593Smuzhiyun 	case MDL_ERROR_IND:
947*4882a593Smuzhiyun 		if (test_bit(MGR_OPT_NETWORK, &tm->mgr->options))
948*4882a593Smuzhiyun 			mISDN_FsmEvent(&tm->tei_m, EV_CHKREQ, &l2->tei);
949*4882a593Smuzhiyun 		if (test_bit(MGR_OPT_USER, &tm->mgr->options))
950*4882a593Smuzhiyun 			mISDN_FsmEvent(&tm->tei_m, EV_VERIFY, NULL);
951*4882a593Smuzhiyun 		break;
952*4882a593Smuzhiyun 	case MDL_STATUS_UP_IND:
953*4882a593Smuzhiyun 		if (test_bit(MGR_OPT_NETWORK, &tm->mgr->options))
954*4882a593Smuzhiyun 			mISDN_FsmEvent(&tm->mgr->deact, EV_ACTIVATE, NULL);
955*4882a593Smuzhiyun 		break;
956*4882a593Smuzhiyun 	case MDL_STATUS_DOWN_IND:
957*4882a593Smuzhiyun 		if (test_bit(MGR_OPT_NETWORK, &tm->mgr->options))
958*4882a593Smuzhiyun 			mISDN_FsmEvent(&tm->mgr->deact, EV_DEACTIVATE, NULL);
959*4882a593Smuzhiyun 		break;
960*4882a593Smuzhiyun 	case MDL_STATUS_UI_IND:
961*4882a593Smuzhiyun 		if (test_bit(MGR_OPT_NETWORK, &tm->mgr->options))
962*4882a593Smuzhiyun 			mISDN_FsmEvent(&tm->mgr->deact, EV_UI, NULL);
963*4882a593Smuzhiyun 		break;
964*4882a593Smuzhiyun 	}
965*4882a593Smuzhiyun 	return 0;
966*4882a593Smuzhiyun }
967*4882a593Smuzhiyun 
968*4882a593Smuzhiyun void
TEIrelease(struct layer2 * l2)969*4882a593Smuzhiyun TEIrelease(struct layer2 *l2)
970*4882a593Smuzhiyun {
971*4882a593Smuzhiyun 	struct teimgr	*tm = l2->tm;
972*4882a593Smuzhiyun 	u_long		flags;
973*4882a593Smuzhiyun 
974*4882a593Smuzhiyun 	mISDN_FsmDelTimer(&tm->timer, 1);
975*4882a593Smuzhiyun 	write_lock_irqsave(&tm->mgr->lock, flags);
976*4882a593Smuzhiyun 	list_del(&l2->list);
977*4882a593Smuzhiyun 	write_unlock_irqrestore(&tm->mgr->lock, flags);
978*4882a593Smuzhiyun 	l2->tm = NULL;
979*4882a593Smuzhiyun 	kfree(tm);
980*4882a593Smuzhiyun }
981*4882a593Smuzhiyun 
982*4882a593Smuzhiyun static int
create_teimgr(struct manager * mgr,struct channel_req * crq)983*4882a593Smuzhiyun create_teimgr(struct manager *mgr, struct channel_req *crq)
984*4882a593Smuzhiyun {
985*4882a593Smuzhiyun 	struct layer2		*l2;
986*4882a593Smuzhiyun 	unsigned long		opt = 0;
987*4882a593Smuzhiyun 	unsigned long		flags;
988*4882a593Smuzhiyun 	int			id;
989*4882a593Smuzhiyun 	struct channel_req	l1rq;
990*4882a593Smuzhiyun 
991*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_TEI)
992*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
993*4882a593Smuzhiyun 		       __func__, dev_name(&mgr->ch.st->dev->dev),
994*4882a593Smuzhiyun 		       crq->protocol, crq->adr.dev, crq->adr.channel,
995*4882a593Smuzhiyun 		       crq->adr.sapi, crq->adr.tei);
996*4882a593Smuzhiyun 	if (crq->adr.tei > GROUP_TEI)
997*4882a593Smuzhiyun 		return -EINVAL;
998*4882a593Smuzhiyun 	if (crq->adr.tei < 64)
999*4882a593Smuzhiyun 		test_and_set_bit(OPTION_L2_FIXEDTEI, &opt);
1000*4882a593Smuzhiyun 	if (crq->adr.tei == 0)
1001*4882a593Smuzhiyun 		test_and_set_bit(OPTION_L2_PTP, &opt);
1002*4882a593Smuzhiyun 	if (test_bit(MGR_OPT_NETWORK, &mgr->options)) {
1003*4882a593Smuzhiyun 		if (crq->protocol == ISDN_P_LAPD_TE)
1004*4882a593Smuzhiyun 			return -EPROTONOSUPPORT;
1005*4882a593Smuzhiyun 		if ((crq->adr.tei != 0) && (crq->adr.tei != 127))
1006*4882a593Smuzhiyun 			return -EINVAL;
1007*4882a593Smuzhiyun 		if (mgr->up) {
1008*4882a593Smuzhiyun 			printk(KERN_WARNING
1009*4882a593Smuzhiyun 			       "%s: only one network manager is allowed\n",
1010*4882a593Smuzhiyun 			       __func__);
1011*4882a593Smuzhiyun 			return -EBUSY;
1012*4882a593Smuzhiyun 		}
1013*4882a593Smuzhiyun 	} else if (test_bit(MGR_OPT_USER, &mgr->options)) {
1014*4882a593Smuzhiyun 		if (crq->protocol == ISDN_P_LAPD_NT)
1015*4882a593Smuzhiyun 			return -EPROTONOSUPPORT;
1016*4882a593Smuzhiyun 		if ((crq->adr.tei >= 64) && (crq->adr.tei < GROUP_TEI))
1017*4882a593Smuzhiyun 			return -EINVAL; /* dyn tei */
1018*4882a593Smuzhiyun 	} else {
1019*4882a593Smuzhiyun 		if (crq->protocol == ISDN_P_LAPD_NT)
1020*4882a593Smuzhiyun 			test_and_set_bit(MGR_OPT_NETWORK, &mgr->options);
1021*4882a593Smuzhiyun 		if (crq->protocol == ISDN_P_LAPD_TE)
1022*4882a593Smuzhiyun 			test_and_set_bit(MGR_OPT_USER, &mgr->options);
1023*4882a593Smuzhiyun 	}
1024*4882a593Smuzhiyun 	l1rq.adr = crq->adr;
1025*4882a593Smuzhiyun 	if (mgr->ch.st->dev->Dprotocols
1026*4882a593Smuzhiyun 	    & ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1)))
1027*4882a593Smuzhiyun 		test_and_set_bit(OPTION_L2_PMX, &opt);
1028*4882a593Smuzhiyun 	if ((crq->protocol == ISDN_P_LAPD_NT) && (crq->adr.tei == 127)) {
1029*4882a593Smuzhiyun 		mgr->up = crq->ch;
1030*4882a593Smuzhiyun 		id = DL_INFO_L2_CONNECT;
1031*4882a593Smuzhiyun 		teiup_create(mgr, DL_INFORMATION_IND, sizeof(id), &id);
1032*4882a593Smuzhiyun 		if (test_bit(MGR_PH_ACTIVE, &mgr->options))
1033*4882a593Smuzhiyun 			teiup_create(mgr, PH_ACTIVATE_IND, 0, NULL);
1034*4882a593Smuzhiyun 		crq->ch = NULL;
1035*4882a593Smuzhiyun 		if (!list_empty(&mgr->layer2)) {
1036*4882a593Smuzhiyun 			read_lock_irqsave(&mgr->lock, flags);
1037*4882a593Smuzhiyun 			list_for_each_entry(l2, &mgr->layer2, list) {
1038*4882a593Smuzhiyun 				l2->up = mgr->up;
1039*4882a593Smuzhiyun 				l2->ch.ctrl(&l2->ch, OPEN_CHANNEL, NULL);
1040*4882a593Smuzhiyun 			}
1041*4882a593Smuzhiyun 			read_unlock_irqrestore(&mgr->lock, flags);
1042*4882a593Smuzhiyun 		}
1043*4882a593Smuzhiyun 		return 0;
1044*4882a593Smuzhiyun 	}
1045*4882a593Smuzhiyun 	l2 = create_l2(crq->ch, crq->protocol, opt,
1046*4882a593Smuzhiyun 		       crq->adr.tei, crq->adr.sapi);
1047*4882a593Smuzhiyun 	if (!l2)
1048*4882a593Smuzhiyun 		return -ENOMEM;
1049*4882a593Smuzhiyun 	l2->tm = kzalloc(sizeof(struct teimgr), GFP_KERNEL);
1050*4882a593Smuzhiyun 	if (!l2->tm) {
1051*4882a593Smuzhiyun 		kfree(l2);
1052*4882a593Smuzhiyun 		printk(KERN_ERR "kmalloc teimgr failed\n");
1053*4882a593Smuzhiyun 		return -ENOMEM;
1054*4882a593Smuzhiyun 	}
1055*4882a593Smuzhiyun 	l2->tm->mgr = mgr;
1056*4882a593Smuzhiyun 	l2->tm->l2 = l2;
1057*4882a593Smuzhiyun 	l2->tm->tei_m.debug = *debug & DEBUG_L2_TEIFSM;
1058*4882a593Smuzhiyun 	l2->tm->tei_m.userdata = l2->tm;
1059*4882a593Smuzhiyun 	l2->tm->tei_m.printdebug = tei_debug;
1060*4882a593Smuzhiyun 	if (crq->protocol == ISDN_P_LAPD_TE) {
1061*4882a593Smuzhiyun 		l2->tm->tei_m.fsm = &teifsmu;
1062*4882a593Smuzhiyun 		l2->tm->tei_m.state = ST_TEI_NOP;
1063*4882a593Smuzhiyun 		l2->tm->tval = 1000; /* T201  1 sec */
1064*4882a593Smuzhiyun 		if (test_bit(OPTION_L2_PMX, &opt))
1065*4882a593Smuzhiyun 			l1rq.protocol = ISDN_P_TE_E1;
1066*4882a593Smuzhiyun 		else
1067*4882a593Smuzhiyun 			l1rq.protocol = ISDN_P_TE_S0;
1068*4882a593Smuzhiyun 	} else {
1069*4882a593Smuzhiyun 		l2->tm->tei_m.fsm = &teifsmn;
1070*4882a593Smuzhiyun 		l2->tm->tei_m.state = ST_TEI_NOP;
1071*4882a593Smuzhiyun 		l2->tm->tval = 2000; /* T202  2 sec */
1072*4882a593Smuzhiyun 		if (test_bit(OPTION_L2_PMX, &opt))
1073*4882a593Smuzhiyun 			l1rq.protocol = ISDN_P_NT_E1;
1074*4882a593Smuzhiyun 		else
1075*4882a593Smuzhiyun 			l1rq.protocol = ISDN_P_NT_S0;
1076*4882a593Smuzhiyun 	}
1077*4882a593Smuzhiyun 	mISDN_FsmInitTimer(&l2->tm->tei_m, &l2->tm->timer);
1078*4882a593Smuzhiyun 	write_lock_irqsave(&mgr->lock, flags);
1079*4882a593Smuzhiyun 	id = get_free_id(mgr);
1080*4882a593Smuzhiyun 	list_add_tail(&l2->list, &mgr->layer2);
1081*4882a593Smuzhiyun 	write_unlock_irqrestore(&mgr->lock, flags);
1082*4882a593Smuzhiyun 	if (id >= 0) {
1083*4882a593Smuzhiyun 		l2->ch.nr = id;
1084*4882a593Smuzhiyun 		l2->up->nr = id;
1085*4882a593Smuzhiyun 		crq->ch = &l2->ch;
1086*4882a593Smuzhiyun 		/* We need open here L1 for the manager as well (refcounting) */
1087*4882a593Smuzhiyun 		id = mgr->ch.st->own.ctrl(&mgr->ch.st->own, OPEN_CHANNEL,
1088*4882a593Smuzhiyun 					  &l1rq);
1089*4882a593Smuzhiyun 	}
1090*4882a593Smuzhiyun 	if (id < 0)
1091*4882a593Smuzhiyun 		l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
1092*4882a593Smuzhiyun 	return id;
1093*4882a593Smuzhiyun }
1094*4882a593Smuzhiyun 
1095*4882a593Smuzhiyun static int
mgr_send(struct mISDNchannel * ch,struct sk_buff * skb)1096*4882a593Smuzhiyun mgr_send(struct mISDNchannel *ch, struct sk_buff *skb)
1097*4882a593Smuzhiyun {
1098*4882a593Smuzhiyun 	struct manager	*mgr;
1099*4882a593Smuzhiyun 	struct mISDNhead	*hh =  mISDN_HEAD_P(skb);
1100*4882a593Smuzhiyun 	int			ret = -EINVAL;
1101*4882a593Smuzhiyun 
1102*4882a593Smuzhiyun 	mgr = container_of(ch, struct manager, ch);
1103*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_RECV)
1104*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s: prim(%x) id(%x)\n",
1105*4882a593Smuzhiyun 		       __func__, hh->prim, hh->id);
1106*4882a593Smuzhiyun 	switch (hh->prim) {
1107*4882a593Smuzhiyun 	case PH_DATA_IND:
1108*4882a593Smuzhiyun 		mISDN_FsmEvent(&mgr->deact, EV_UI, NULL);
1109*4882a593Smuzhiyun 		ret = ph_data_ind(mgr, skb);
1110*4882a593Smuzhiyun 		break;
1111*4882a593Smuzhiyun 	case PH_DATA_CNF:
1112*4882a593Smuzhiyun 		do_ack(mgr, hh->id);
1113*4882a593Smuzhiyun 		ret = 0;
1114*4882a593Smuzhiyun 		break;
1115*4882a593Smuzhiyun 	case PH_ACTIVATE_IND:
1116*4882a593Smuzhiyun 		test_and_set_bit(MGR_PH_ACTIVE, &mgr->options);
1117*4882a593Smuzhiyun 		if (mgr->up)
1118*4882a593Smuzhiyun 			teiup_create(mgr, PH_ACTIVATE_IND, 0, NULL);
1119*4882a593Smuzhiyun 		mISDN_FsmEvent(&mgr->deact, EV_ACTIVATE_IND, NULL);
1120*4882a593Smuzhiyun 		do_send(mgr);
1121*4882a593Smuzhiyun 		ret = 0;
1122*4882a593Smuzhiyun 		break;
1123*4882a593Smuzhiyun 	case PH_DEACTIVATE_IND:
1124*4882a593Smuzhiyun 		test_and_clear_bit(MGR_PH_ACTIVE, &mgr->options);
1125*4882a593Smuzhiyun 		if (mgr->up)
1126*4882a593Smuzhiyun 			teiup_create(mgr, PH_DEACTIVATE_IND, 0, NULL);
1127*4882a593Smuzhiyun 		mISDN_FsmEvent(&mgr->deact, EV_DEACTIVATE_IND, NULL);
1128*4882a593Smuzhiyun 		ret = 0;
1129*4882a593Smuzhiyun 		break;
1130*4882a593Smuzhiyun 	case DL_UNITDATA_REQ:
1131*4882a593Smuzhiyun 		return dl_unit_data(mgr, skb);
1132*4882a593Smuzhiyun 	}
1133*4882a593Smuzhiyun 	if (!ret)
1134*4882a593Smuzhiyun 		dev_kfree_skb(skb);
1135*4882a593Smuzhiyun 	return ret;
1136*4882a593Smuzhiyun }
1137*4882a593Smuzhiyun 
1138*4882a593Smuzhiyun static int
free_teimanager(struct manager * mgr)1139*4882a593Smuzhiyun free_teimanager(struct manager *mgr)
1140*4882a593Smuzhiyun {
1141*4882a593Smuzhiyun 	struct layer2	*l2, *nl2;
1142*4882a593Smuzhiyun 
1143*4882a593Smuzhiyun 	test_and_clear_bit(OPTION_L1_HOLD, &mgr->options);
1144*4882a593Smuzhiyun 	if (test_bit(MGR_OPT_NETWORK, &mgr->options)) {
1145*4882a593Smuzhiyun 		/* not locked lock is taken in release tei */
1146*4882a593Smuzhiyun 		mgr->up = NULL;
1147*4882a593Smuzhiyun 		if (test_bit(OPTION_L2_CLEANUP, &mgr->options)) {
1148*4882a593Smuzhiyun 			list_for_each_entry_safe(l2, nl2, &mgr->layer2, list) {
1149*4882a593Smuzhiyun 				put_tei_msg(mgr, ID_REMOVE, 0, l2->tei);
1150*4882a593Smuzhiyun 				mutex_lock(&mgr->ch.st->lmutex);
1151*4882a593Smuzhiyun 				list_del(&l2->ch.list);
1152*4882a593Smuzhiyun 				mutex_unlock(&mgr->ch.st->lmutex);
1153*4882a593Smuzhiyun 				l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
1154*4882a593Smuzhiyun 			}
1155*4882a593Smuzhiyun 			test_and_clear_bit(MGR_OPT_NETWORK, &mgr->options);
1156*4882a593Smuzhiyun 		} else {
1157*4882a593Smuzhiyun 			list_for_each_entry_safe(l2, nl2, &mgr->layer2, list) {
1158*4882a593Smuzhiyun 				l2->up = NULL;
1159*4882a593Smuzhiyun 			}
1160*4882a593Smuzhiyun 		}
1161*4882a593Smuzhiyun 	}
1162*4882a593Smuzhiyun 	if (test_bit(MGR_OPT_USER, &mgr->options)) {
1163*4882a593Smuzhiyun 		if (list_empty(&mgr->layer2))
1164*4882a593Smuzhiyun 			test_and_clear_bit(MGR_OPT_USER, &mgr->options);
1165*4882a593Smuzhiyun 	}
1166*4882a593Smuzhiyun 	mgr->ch.st->dev->D.ctrl(&mgr->ch.st->dev->D, CLOSE_CHANNEL, NULL);
1167*4882a593Smuzhiyun 	return 0;
1168*4882a593Smuzhiyun }
1169*4882a593Smuzhiyun 
1170*4882a593Smuzhiyun static int
ctrl_teimanager(struct manager * mgr,void * arg)1171*4882a593Smuzhiyun ctrl_teimanager(struct manager *mgr, void *arg)
1172*4882a593Smuzhiyun {
1173*4882a593Smuzhiyun 	/* currently we only have one option */
1174*4882a593Smuzhiyun 	unsigned int *val = (unsigned int *)arg;
1175*4882a593Smuzhiyun 
1176*4882a593Smuzhiyun 	switch (val[0]) {
1177*4882a593Smuzhiyun 	case IMCLEAR_L2:
1178*4882a593Smuzhiyun 		if (val[1])
1179*4882a593Smuzhiyun 			test_and_set_bit(OPTION_L2_CLEANUP, &mgr->options);
1180*4882a593Smuzhiyun 		else
1181*4882a593Smuzhiyun 			test_and_clear_bit(OPTION_L2_CLEANUP, &mgr->options);
1182*4882a593Smuzhiyun 		break;
1183*4882a593Smuzhiyun 	case IMHOLD_L1:
1184*4882a593Smuzhiyun 		if (val[1])
1185*4882a593Smuzhiyun 			test_and_set_bit(OPTION_L1_HOLD, &mgr->options);
1186*4882a593Smuzhiyun 		else
1187*4882a593Smuzhiyun 			test_and_clear_bit(OPTION_L1_HOLD, &mgr->options);
1188*4882a593Smuzhiyun 		break;
1189*4882a593Smuzhiyun 	default:
1190*4882a593Smuzhiyun 		return -EINVAL;
1191*4882a593Smuzhiyun 	}
1192*4882a593Smuzhiyun 	return 0;
1193*4882a593Smuzhiyun }
1194*4882a593Smuzhiyun 
1195*4882a593Smuzhiyun /* This function does create a L2 for fixed TEI in NT Mode */
1196*4882a593Smuzhiyun static int
check_data(struct manager * mgr,struct sk_buff * skb)1197*4882a593Smuzhiyun check_data(struct manager *mgr, struct sk_buff *skb)
1198*4882a593Smuzhiyun {
1199*4882a593Smuzhiyun 	struct mISDNhead	*hh =  mISDN_HEAD_P(skb);
1200*4882a593Smuzhiyun 	int			ret, tei, sapi;
1201*4882a593Smuzhiyun 	struct layer2		*l2;
1202*4882a593Smuzhiyun 
1203*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_CTRL)
1204*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s: prim(%x) id(%x)\n",
1205*4882a593Smuzhiyun 		       __func__, hh->prim, hh->id);
1206*4882a593Smuzhiyun 	if (test_bit(MGR_OPT_USER, &mgr->options))
1207*4882a593Smuzhiyun 		return -ENOTCONN;
1208*4882a593Smuzhiyun 	if (hh->prim != PH_DATA_IND)
1209*4882a593Smuzhiyun 		return -ENOTCONN;
1210*4882a593Smuzhiyun 	if (skb->len != 3)
1211*4882a593Smuzhiyun 		return -ENOTCONN;
1212*4882a593Smuzhiyun 	if (skb->data[0] & 3) /* EA0 and CR must be  0 */
1213*4882a593Smuzhiyun 		return -EINVAL;
1214*4882a593Smuzhiyun 	sapi = skb->data[0] >> 2;
1215*4882a593Smuzhiyun 	if (!(skb->data[1] & 1)) /* invalid EA1 */
1216*4882a593Smuzhiyun 		return -EINVAL;
1217*4882a593Smuzhiyun 	tei = skb->data[1] >> 1;
1218*4882a593Smuzhiyun 	if (tei > 63) /* not a fixed tei */
1219*4882a593Smuzhiyun 		return -ENOTCONN;
1220*4882a593Smuzhiyun 	if ((skb->data[2] & ~0x10) != SABME)
1221*4882a593Smuzhiyun 		return -ENOTCONN;
1222*4882a593Smuzhiyun 	/* We got a SABME for a fixed TEI */
1223*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_CTRL)
1224*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s: SABME sapi(%d) tei(%d)\n",
1225*4882a593Smuzhiyun 		       __func__, sapi, tei);
1226*4882a593Smuzhiyun 	l2 = create_new_tei(mgr, tei, sapi);
1227*4882a593Smuzhiyun 	if (!l2) {
1228*4882a593Smuzhiyun 		if (*debug & DEBUG_L2_CTRL)
1229*4882a593Smuzhiyun 			printk(KERN_DEBUG "%s: failed to create new tei\n",
1230*4882a593Smuzhiyun 			       __func__);
1231*4882a593Smuzhiyun 		return -ENOMEM;
1232*4882a593Smuzhiyun 	}
1233*4882a593Smuzhiyun 	ret = l2->ch.send(&l2->ch, skb);
1234*4882a593Smuzhiyun 	return ret;
1235*4882a593Smuzhiyun }
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun void
delete_teimanager(struct mISDNchannel * ch)1238*4882a593Smuzhiyun delete_teimanager(struct mISDNchannel *ch)
1239*4882a593Smuzhiyun {
1240*4882a593Smuzhiyun 	struct manager	*mgr;
1241*4882a593Smuzhiyun 	struct layer2	*l2, *nl2;
1242*4882a593Smuzhiyun 
1243*4882a593Smuzhiyun 	mgr = container_of(ch, struct manager, ch);
1244*4882a593Smuzhiyun 	/* not locked lock is taken in release tei */
1245*4882a593Smuzhiyun 	list_for_each_entry_safe(l2, nl2, &mgr->layer2, list) {
1246*4882a593Smuzhiyun 		mutex_lock(&mgr->ch.st->lmutex);
1247*4882a593Smuzhiyun 		list_del(&l2->ch.list);
1248*4882a593Smuzhiyun 		mutex_unlock(&mgr->ch.st->lmutex);
1249*4882a593Smuzhiyun 		l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
1250*4882a593Smuzhiyun 	}
1251*4882a593Smuzhiyun 	list_del(&mgr->ch.list);
1252*4882a593Smuzhiyun 	list_del(&mgr->bcast.list);
1253*4882a593Smuzhiyun 	skb_queue_purge(&mgr->sendq);
1254*4882a593Smuzhiyun 	kfree(mgr);
1255*4882a593Smuzhiyun }
1256*4882a593Smuzhiyun 
1257*4882a593Smuzhiyun static int
mgr_ctrl(struct mISDNchannel * ch,u_int cmd,void * arg)1258*4882a593Smuzhiyun mgr_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
1259*4882a593Smuzhiyun {
1260*4882a593Smuzhiyun 	struct manager	*mgr;
1261*4882a593Smuzhiyun 	int		ret = -EINVAL;
1262*4882a593Smuzhiyun 
1263*4882a593Smuzhiyun 	mgr = container_of(ch, struct manager, ch);
1264*4882a593Smuzhiyun 	if (*debug & DEBUG_L2_CTRL)
1265*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s(%x, %p)\n", __func__, cmd, arg);
1266*4882a593Smuzhiyun 	switch (cmd) {
1267*4882a593Smuzhiyun 	case OPEN_CHANNEL:
1268*4882a593Smuzhiyun 		ret = create_teimgr(mgr, arg);
1269*4882a593Smuzhiyun 		break;
1270*4882a593Smuzhiyun 	case CLOSE_CHANNEL:
1271*4882a593Smuzhiyun 		ret = free_teimanager(mgr);
1272*4882a593Smuzhiyun 		break;
1273*4882a593Smuzhiyun 	case CONTROL_CHANNEL:
1274*4882a593Smuzhiyun 		ret = ctrl_teimanager(mgr, arg);
1275*4882a593Smuzhiyun 		break;
1276*4882a593Smuzhiyun 	case CHECK_DATA:
1277*4882a593Smuzhiyun 		ret = check_data(mgr, arg);
1278*4882a593Smuzhiyun 		break;
1279*4882a593Smuzhiyun 	}
1280*4882a593Smuzhiyun 	return ret;
1281*4882a593Smuzhiyun }
1282*4882a593Smuzhiyun 
1283*4882a593Smuzhiyun static int
mgr_bcast(struct mISDNchannel * ch,struct sk_buff * skb)1284*4882a593Smuzhiyun mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb)
1285*4882a593Smuzhiyun {
1286*4882a593Smuzhiyun 	struct manager		*mgr = container_of(ch, struct manager, bcast);
1287*4882a593Smuzhiyun 	struct mISDNhead	*hhc, *hh = mISDN_HEAD_P(skb);
1288*4882a593Smuzhiyun 	struct sk_buff		*cskb = NULL;
1289*4882a593Smuzhiyun 	struct layer2		*l2;
1290*4882a593Smuzhiyun 	u_long			flags;
1291*4882a593Smuzhiyun 	int			ret;
1292*4882a593Smuzhiyun 
1293*4882a593Smuzhiyun 	read_lock_irqsave(&mgr->lock, flags);
1294*4882a593Smuzhiyun 	list_for_each_entry(l2, &mgr->layer2, list) {
1295*4882a593Smuzhiyun 		if ((hh->id & MISDN_ID_SAPI_MASK) ==
1296*4882a593Smuzhiyun 		    (l2->ch.addr & MISDN_ID_SAPI_MASK)) {
1297*4882a593Smuzhiyun 			if (list_is_last(&l2->list, &mgr->layer2)) {
1298*4882a593Smuzhiyun 				cskb = skb;
1299*4882a593Smuzhiyun 				skb = NULL;
1300*4882a593Smuzhiyun 			} else {
1301*4882a593Smuzhiyun 				if (!cskb)
1302*4882a593Smuzhiyun 					cskb = skb_copy(skb, GFP_ATOMIC);
1303*4882a593Smuzhiyun 			}
1304*4882a593Smuzhiyun 			if (cskb) {
1305*4882a593Smuzhiyun 				hhc = mISDN_HEAD_P(cskb);
1306*4882a593Smuzhiyun 				/* save original header behind normal header */
1307*4882a593Smuzhiyun 				hhc++;
1308*4882a593Smuzhiyun 				*hhc = *hh;
1309*4882a593Smuzhiyun 				hhc--;
1310*4882a593Smuzhiyun 				hhc->prim = DL_INTERN_MSG;
1311*4882a593Smuzhiyun 				hhc->id = l2->ch.nr;
1312*4882a593Smuzhiyun 				ret = ch->st->own.recv(&ch->st->own, cskb);
1313*4882a593Smuzhiyun 				if (ret) {
1314*4882a593Smuzhiyun 					if (*debug & DEBUG_SEND_ERR)
1315*4882a593Smuzhiyun 						printk(KERN_DEBUG
1316*4882a593Smuzhiyun 						       "%s ch%d prim(%x) addr(%x)"
1317*4882a593Smuzhiyun 						       " err %d\n",
1318*4882a593Smuzhiyun 						       __func__, l2->ch.nr,
1319*4882a593Smuzhiyun 						       hh->prim, l2->ch.addr, ret);
1320*4882a593Smuzhiyun 				} else
1321*4882a593Smuzhiyun 					cskb = NULL;
1322*4882a593Smuzhiyun 			} else {
1323*4882a593Smuzhiyun 				printk(KERN_WARNING "%s ch%d addr %x no mem\n",
1324*4882a593Smuzhiyun 				       __func__, ch->nr, ch->addr);
1325*4882a593Smuzhiyun 				goto out;
1326*4882a593Smuzhiyun 			}
1327*4882a593Smuzhiyun 		}
1328*4882a593Smuzhiyun 	}
1329*4882a593Smuzhiyun out:
1330*4882a593Smuzhiyun 	read_unlock_irqrestore(&mgr->lock, flags);
1331*4882a593Smuzhiyun 	dev_kfree_skb(cskb);
1332*4882a593Smuzhiyun 	dev_kfree_skb(skb);
1333*4882a593Smuzhiyun 	return 0;
1334*4882a593Smuzhiyun }
1335*4882a593Smuzhiyun 
1336*4882a593Smuzhiyun static int
mgr_bcast_ctrl(struct mISDNchannel * ch,u_int cmd,void * arg)1337*4882a593Smuzhiyun mgr_bcast_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
1338*4882a593Smuzhiyun {
1339*4882a593Smuzhiyun 
1340*4882a593Smuzhiyun 	return -EINVAL;
1341*4882a593Smuzhiyun }
1342*4882a593Smuzhiyun 
1343*4882a593Smuzhiyun int
create_teimanager(struct mISDNdevice * dev)1344*4882a593Smuzhiyun create_teimanager(struct mISDNdevice *dev)
1345*4882a593Smuzhiyun {
1346*4882a593Smuzhiyun 	struct manager *mgr;
1347*4882a593Smuzhiyun 
1348*4882a593Smuzhiyun 	mgr = kzalloc(sizeof(struct manager), GFP_KERNEL);
1349*4882a593Smuzhiyun 	if (!mgr)
1350*4882a593Smuzhiyun 		return -ENOMEM;
1351*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mgr->layer2);
1352*4882a593Smuzhiyun 	rwlock_init(&mgr->lock);
1353*4882a593Smuzhiyun 	skb_queue_head_init(&mgr->sendq);
1354*4882a593Smuzhiyun 	mgr->nextid = 1;
1355*4882a593Smuzhiyun 	mgr->lastid = MISDN_ID_NONE;
1356*4882a593Smuzhiyun 	mgr->ch.send = mgr_send;
1357*4882a593Smuzhiyun 	mgr->ch.ctrl = mgr_ctrl;
1358*4882a593Smuzhiyun 	mgr->ch.st = dev->D.st;
1359*4882a593Smuzhiyun 	set_channel_address(&mgr->ch, TEI_SAPI, GROUP_TEI);
1360*4882a593Smuzhiyun 	add_layer2(&mgr->ch, dev->D.st);
1361*4882a593Smuzhiyun 	mgr->bcast.send = mgr_bcast;
1362*4882a593Smuzhiyun 	mgr->bcast.ctrl = mgr_bcast_ctrl;
1363*4882a593Smuzhiyun 	mgr->bcast.st = dev->D.st;
1364*4882a593Smuzhiyun 	set_channel_address(&mgr->bcast, 0, GROUP_TEI);
1365*4882a593Smuzhiyun 	add_layer2(&mgr->bcast, dev->D.st);
1366*4882a593Smuzhiyun 	mgr->deact.debug = *debug & DEBUG_MANAGER;
1367*4882a593Smuzhiyun 	mgr->deact.userdata = mgr;
1368*4882a593Smuzhiyun 	mgr->deact.printdebug = da_debug;
1369*4882a593Smuzhiyun 	mgr->deact.fsm = &deactfsm;
1370*4882a593Smuzhiyun 	mgr->deact.state = ST_L1_DEACT;
1371*4882a593Smuzhiyun 	mISDN_FsmInitTimer(&mgr->deact, &mgr->datimer);
1372*4882a593Smuzhiyun 	dev->teimgr = &mgr->ch;
1373*4882a593Smuzhiyun 	return 0;
1374*4882a593Smuzhiyun }
1375*4882a593Smuzhiyun 
TEIInit(u_int * deb)1376*4882a593Smuzhiyun int TEIInit(u_int *deb)
1377*4882a593Smuzhiyun {
1378*4882a593Smuzhiyun 	int res;
1379*4882a593Smuzhiyun 	debug = deb;
1380*4882a593Smuzhiyun 	teifsmu.state_count = TEI_STATE_COUNT;
1381*4882a593Smuzhiyun 	teifsmu.event_count = TEI_EVENT_COUNT;
1382*4882a593Smuzhiyun 	teifsmu.strEvent = strTeiEvent;
1383*4882a593Smuzhiyun 	teifsmu.strState = strTeiState;
1384*4882a593Smuzhiyun 	res = mISDN_FsmNew(&teifsmu, TeiFnListUser, ARRAY_SIZE(TeiFnListUser));
1385*4882a593Smuzhiyun 	if (res)
1386*4882a593Smuzhiyun 		goto error;
1387*4882a593Smuzhiyun 	teifsmn.state_count = TEI_STATE_COUNT;
1388*4882a593Smuzhiyun 	teifsmn.event_count = TEI_EVENT_COUNT;
1389*4882a593Smuzhiyun 	teifsmn.strEvent = strTeiEvent;
1390*4882a593Smuzhiyun 	teifsmn.strState = strTeiState;
1391*4882a593Smuzhiyun 	res = mISDN_FsmNew(&teifsmn, TeiFnListNet, ARRAY_SIZE(TeiFnListNet));
1392*4882a593Smuzhiyun 	if (res)
1393*4882a593Smuzhiyun 		goto error_smn;
1394*4882a593Smuzhiyun 	deactfsm.state_count =  DEACT_STATE_COUNT;
1395*4882a593Smuzhiyun 	deactfsm.event_count = DEACT_EVENT_COUNT;
1396*4882a593Smuzhiyun 	deactfsm.strEvent = strDeactEvent;
1397*4882a593Smuzhiyun 	deactfsm.strState = strDeactState;
1398*4882a593Smuzhiyun 	res = mISDN_FsmNew(&deactfsm, DeactFnList, ARRAY_SIZE(DeactFnList));
1399*4882a593Smuzhiyun 	if (res)
1400*4882a593Smuzhiyun 		goto error_deact;
1401*4882a593Smuzhiyun 	return 0;
1402*4882a593Smuzhiyun 
1403*4882a593Smuzhiyun error_deact:
1404*4882a593Smuzhiyun 	mISDN_FsmFree(&teifsmn);
1405*4882a593Smuzhiyun error_smn:
1406*4882a593Smuzhiyun 	mISDN_FsmFree(&teifsmu);
1407*4882a593Smuzhiyun error:
1408*4882a593Smuzhiyun 	return res;
1409*4882a593Smuzhiyun }
1410*4882a593Smuzhiyun 
TEIFree(void)1411*4882a593Smuzhiyun void TEIFree(void)
1412*4882a593Smuzhiyun {
1413*4882a593Smuzhiyun 	mISDN_FsmFree(&teifsmu);
1414*4882a593Smuzhiyun 	mISDN_FsmFree(&teifsmn);
1415*4882a593Smuzhiyun 	mISDN_FsmFree(&deactfsm);
1416*4882a593Smuzhiyun }
1417