xref: /OK3568_Linux_fs/kernel/drivers/isdn/mISDN/stack.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 
9*4882a593Smuzhiyun #include <linux/slab.h>
10*4882a593Smuzhiyun #include <linux/mISDNif.h>
11*4882a593Smuzhiyun #include <linux/kthread.h>
12*4882a593Smuzhiyun #include <linux/sched.h>
13*4882a593Smuzhiyun #include <linux/sched/cputime.h>
14*4882a593Smuzhiyun #include <linux/signal.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include "core.h"
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun static u_int	*debug;
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun static inline void
_queue_message(struct mISDNstack * st,struct sk_buff * skb)21*4882a593Smuzhiyun _queue_message(struct mISDNstack *st, struct sk_buff *skb)
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun 	struct mISDNhead	*hh = mISDN_HEAD_P(skb);
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun 	if (*debug & DEBUG_QUEUE_FUNC)
26*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s prim(%x) id(%x) %p\n",
27*4882a593Smuzhiyun 		       __func__, hh->prim, hh->id, skb);
28*4882a593Smuzhiyun 	skb_queue_tail(&st->msgq, skb);
29*4882a593Smuzhiyun 	if (likely(!test_bit(mISDN_STACK_STOPPED, &st->status))) {
30*4882a593Smuzhiyun 		test_and_set_bit(mISDN_STACK_WORK, &st->status);
31*4882a593Smuzhiyun 		wake_up_interruptible(&st->workq);
32*4882a593Smuzhiyun 	}
33*4882a593Smuzhiyun }
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun static int
mISDN_queue_message(struct mISDNchannel * ch,struct sk_buff * skb)36*4882a593Smuzhiyun mISDN_queue_message(struct mISDNchannel *ch, struct sk_buff *skb)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	_queue_message(ch->st, skb);
39*4882a593Smuzhiyun 	return 0;
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun static struct mISDNchannel *
get_channel4id(struct mISDNstack * st,u_int id)43*4882a593Smuzhiyun get_channel4id(struct mISDNstack *st, u_int id)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun 	struct mISDNchannel	*ch;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	mutex_lock(&st->lmutex);
48*4882a593Smuzhiyun 	list_for_each_entry(ch, &st->layer2, list) {
49*4882a593Smuzhiyun 		if (id == ch->nr)
50*4882a593Smuzhiyun 			goto unlock;
51*4882a593Smuzhiyun 	}
52*4882a593Smuzhiyun 	ch = NULL;
53*4882a593Smuzhiyun unlock:
54*4882a593Smuzhiyun 	mutex_unlock(&st->lmutex);
55*4882a593Smuzhiyun 	return ch;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun static void
send_socklist(struct mISDN_sock_list * sl,struct sk_buff * skb)59*4882a593Smuzhiyun send_socklist(struct mISDN_sock_list *sl, struct sk_buff *skb)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun 	struct sock		*sk;
62*4882a593Smuzhiyun 	struct sk_buff		*cskb = NULL;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	read_lock(&sl->lock);
65*4882a593Smuzhiyun 	sk_for_each(sk, &sl->head) {
66*4882a593Smuzhiyun 		if (sk->sk_state != MISDN_BOUND)
67*4882a593Smuzhiyun 			continue;
68*4882a593Smuzhiyun 		if (!cskb)
69*4882a593Smuzhiyun 			cskb = skb_copy(skb, GFP_ATOMIC);
70*4882a593Smuzhiyun 		if (!cskb) {
71*4882a593Smuzhiyun 			printk(KERN_WARNING "%s no skb\n", __func__);
72*4882a593Smuzhiyun 			break;
73*4882a593Smuzhiyun 		}
74*4882a593Smuzhiyun 		if (!sock_queue_rcv_skb(sk, cskb))
75*4882a593Smuzhiyun 			cskb = NULL;
76*4882a593Smuzhiyun 	}
77*4882a593Smuzhiyun 	read_unlock(&sl->lock);
78*4882a593Smuzhiyun 	dev_kfree_skb(cskb);
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun static void
send_layer2(struct mISDNstack * st,struct sk_buff * skb)82*4882a593Smuzhiyun send_layer2(struct mISDNstack *st, struct sk_buff *skb)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	struct sk_buff		*cskb;
85*4882a593Smuzhiyun 	struct mISDNhead	*hh = mISDN_HEAD_P(skb);
86*4882a593Smuzhiyun 	struct mISDNchannel	*ch;
87*4882a593Smuzhiyun 	int			ret;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	if (!st)
90*4882a593Smuzhiyun 		return;
91*4882a593Smuzhiyun 	mutex_lock(&st->lmutex);
92*4882a593Smuzhiyun 	if ((hh->id & MISDN_ID_ADDR_MASK) == MISDN_ID_ANY) { /* L2 for all */
93*4882a593Smuzhiyun 		list_for_each_entry(ch, &st->layer2, list) {
94*4882a593Smuzhiyun 			if (list_is_last(&ch->list, &st->layer2)) {
95*4882a593Smuzhiyun 				cskb = skb;
96*4882a593Smuzhiyun 				skb = NULL;
97*4882a593Smuzhiyun 			} else {
98*4882a593Smuzhiyun 				cskb = skb_copy(skb, GFP_KERNEL);
99*4882a593Smuzhiyun 			}
100*4882a593Smuzhiyun 			if (cskb) {
101*4882a593Smuzhiyun 				ret = ch->send(ch, cskb);
102*4882a593Smuzhiyun 				if (ret) {
103*4882a593Smuzhiyun 					if (*debug & DEBUG_SEND_ERR)
104*4882a593Smuzhiyun 						printk(KERN_DEBUG
105*4882a593Smuzhiyun 						       "%s ch%d prim(%x) addr(%x)"
106*4882a593Smuzhiyun 						       " err %d\n",
107*4882a593Smuzhiyun 						       __func__, ch->nr,
108*4882a593Smuzhiyun 						       hh->prim, ch->addr, ret);
109*4882a593Smuzhiyun 					dev_kfree_skb(cskb);
110*4882a593Smuzhiyun 				}
111*4882a593Smuzhiyun 			} else {
112*4882a593Smuzhiyun 				printk(KERN_WARNING "%s ch%d addr %x no mem\n",
113*4882a593Smuzhiyun 				       __func__, ch->nr, ch->addr);
114*4882a593Smuzhiyun 				goto out;
115*4882a593Smuzhiyun 			}
116*4882a593Smuzhiyun 		}
117*4882a593Smuzhiyun 	} else {
118*4882a593Smuzhiyun 		list_for_each_entry(ch, &st->layer2, list) {
119*4882a593Smuzhiyun 			if ((hh->id & MISDN_ID_ADDR_MASK) == ch->addr) {
120*4882a593Smuzhiyun 				ret = ch->send(ch, skb);
121*4882a593Smuzhiyun 				if (!ret)
122*4882a593Smuzhiyun 					skb = NULL;
123*4882a593Smuzhiyun 				goto out;
124*4882a593Smuzhiyun 			}
125*4882a593Smuzhiyun 		}
126*4882a593Smuzhiyun 		ret = st->dev->teimgr->ctrl(st->dev->teimgr, CHECK_DATA, skb);
127*4882a593Smuzhiyun 		if (!ret)
128*4882a593Smuzhiyun 			skb = NULL;
129*4882a593Smuzhiyun 		else if (*debug & DEBUG_SEND_ERR)
130*4882a593Smuzhiyun 			printk(KERN_DEBUG
131*4882a593Smuzhiyun 			       "%s mgr prim(%x) err %d\n",
132*4882a593Smuzhiyun 			       __func__, hh->prim, ret);
133*4882a593Smuzhiyun 	}
134*4882a593Smuzhiyun out:
135*4882a593Smuzhiyun 	mutex_unlock(&st->lmutex);
136*4882a593Smuzhiyun 	dev_kfree_skb(skb);
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun static inline int
send_msg_to_layer(struct mISDNstack * st,struct sk_buff * skb)140*4882a593Smuzhiyun send_msg_to_layer(struct mISDNstack *st, struct sk_buff *skb)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	struct mISDNhead	*hh = mISDN_HEAD_P(skb);
143*4882a593Smuzhiyun 	struct mISDNchannel	*ch;
144*4882a593Smuzhiyun 	int	lm;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	lm = hh->prim & MISDN_LAYERMASK;
147*4882a593Smuzhiyun 	if (*debug & DEBUG_QUEUE_FUNC)
148*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s prim(%x) id(%x) %p\n",
149*4882a593Smuzhiyun 		       __func__, hh->prim, hh->id, skb);
150*4882a593Smuzhiyun 	if (lm == 0x1) {
151*4882a593Smuzhiyun 		if (!hlist_empty(&st->l1sock.head)) {
152*4882a593Smuzhiyun 			__net_timestamp(skb);
153*4882a593Smuzhiyun 			send_socklist(&st->l1sock, skb);
154*4882a593Smuzhiyun 		}
155*4882a593Smuzhiyun 		return st->layer1->send(st->layer1, skb);
156*4882a593Smuzhiyun 	} else if (lm == 0x2) {
157*4882a593Smuzhiyun 		if (!hlist_empty(&st->l1sock.head))
158*4882a593Smuzhiyun 			send_socklist(&st->l1sock, skb);
159*4882a593Smuzhiyun 		send_layer2(st, skb);
160*4882a593Smuzhiyun 		return 0;
161*4882a593Smuzhiyun 	} else if (lm == 0x4) {
162*4882a593Smuzhiyun 		ch = get_channel4id(st, hh->id);
163*4882a593Smuzhiyun 		if (ch)
164*4882a593Smuzhiyun 			return ch->send(ch, skb);
165*4882a593Smuzhiyun 		else
166*4882a593Smuzhiyun 			printk(KERN_WARNING
167*4882a593Smuzhiyun 			       "%s: dev(%s) prim(%x) id(%x) no channel\n",
168*4882a593Smuzhiyun 			       __func__, dev_name(&st->dev->dev), hh->prim,
169*4882a593Smuzhiyun 			       hh->id);
170*4882a593Smuzhiyun 	} else if (lm == 0x8) {
171*4882a593Smuzhiyun 		WARN_ON(lm == 0x8);
172*4882a593Smuzhiyun 		ch = get_channel4id(st, hh->id);
173*4882a593Smuzhiyun 		if (ch)
174*4882a593Smuzhiyun 			return ch->send(ch, skb);
175*4882a593Smuzhiyun 		else
176*4882a593Smuzhiyun 			printk(KERN_WARNING
177*4882a593Smuzhiyun 			       "%s: dev(%s) prim(%x) id(%x) no channel\n",
178*4882a593Smuzhiyun 			       __func__, dev_name(&st->dev->dev), hh->prim,
179*4882a593Smuzhiyun 			       hh->id);
180*4882a593Smuzhiyun 	} else {
181*4882a593Smuzhiyun 		/* broadcast not handled yet */
182*4882a593Smuzhiyun 		printk(KERN_WARNING "%s: dev(%s) prim %x not delivered\n",
183*4882a593Smuzhiyun 		       __func__, dev_name(&st->dev->dev), hh->prim);
184*4882a593Smuzhiyun 	}
185*4882a593Smuzhiyun 	return -ESRCH;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun static void
do_clear_stack(struct mISDNstack * st)189*4882a593Smuzhiyun do_clear_stack(struct mISDNstack *st)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun static int
mISDNStackd(void * data)194*4882a593Smuzhiyun mISDNStackd(void *data)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun 	struct mISDNstack *st = data;
197*4882a593Smuzhiyun #ifdef MISDN_MSG_STATS
198*4882a593Smuzhiyun 	u64 utime, stime;
199*4882a593Smuzhiyun #endif
200*4882a593Smuzhiyun 	int err = 0;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	sigfillset(&current->blocked);
203*4882a593Smuzhiyun 	if (*debug & DEBUG_MSG_THREAD)
204*4882a593Smuzhiyun 		printk(KERN_DEBUG "mISDNStackd %s started\n",
205*4882a593Smuzhiyun 		       dev_name(&st->dev->dev));
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	if (st->notify != NULL) {
208*4882a593Smuzhiyun 		complete(st->notify);
209*4882a593Smuzhiyun 		st->notify = NULL;
210*4882a593Smuzhiyun 	}
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	for (;;) {
213*4882a593Smuzhiyun 		struct sk_buff	*skb;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 		if (unlikely(test_bit(mISDN_STACK_STOPPED, &st->status))) {
216*4882a593Smuzhiyun 			test_and_clear_bit(mISDN_STACK_WORK, &st->status);
217*4882a593Smuzhiyun 			test_and_clear_bit(mISDN_STACK_RUNNING, &st->status);
218*4882a593Smuzhiyun 		} else
219*4882a593Smuzhiyun 			test_and_set_bit(mISDN_STACK_RUNNING, &st->status);
220*4882a593Smuzhiyun 		while (test_bit(mISDN_STACK_WORK, &st->status)) {
221*4882a593Smuzhiyun 			skb = skb_dequeue(&st->msgq);
222*4882a593Smuzhiyun 			if (!skb) {
223*4882a593Smuzhiyun 				test_and_clear_bit(mISDN_STACK_WORK,
224*4882a593Smuzhiyun 						   &st->status);
225*4882a593Smuzhiyun 				/* test if a race happens */
226*4882a593Smuzhiyun 				skb = skb_dequeue(&st->msgq);
227*4882a593Smuzhiyun 				if (!skb)
228*4882a593Smuzhiyun 					continue;
229*4882a593Smuzhiyun 				test_and_set_bit(mISDN_STACK_WORK,
230*4882a593Smuzhiyun 						 &st->status);
231*4882a593Smuzhiyun 			}
232*4882a593Smuzhiyun #ifdef MISDN_MSG_STATS
233*4882a593Smuzhiyun 			st->msg_cnt++;
234*4882a593Smuzhiyun #endif
235*4882a593Smuzhiyun 			err = send_msg_to_layer(st, skb);
236*4882a593Smuzhiyun 			if (unlikely(err)) {
237*4882a593Smuzhiyun 				if (*debug & DEBUG_SEND_ERR)
238*4882a593Smuzhiyun 					printk(KERN_DEBUG
239*4882a593Smuzhiyun 					       "%s: %s prim(%x) id(%x) "
240*4882a593Smuzhiyun 					       "send call(%d)\n",
241*4882a593Smuzhiyun 					       __func__, dev_name(&st->dev->dev),
242*4882a593Smuzhiyun 					       mISDN_HEAD_PRIM(skb),
243*4882a593Smuzhiyun 					       mISDN_HEAD_ID(skb), err);
244*4882a593Smuzhiyun 				dev_kfree_skb(skb);
245*4882a593Smuzhiyun 				continue;
246*4882a593Smuzhiyun 			}
247*4882a593Smuzhiyun 			if (unlikely(test_bit(mISDN_STACK_STOPPED,
248*4882a593Smuzhiyun 					      &st->status))) {
249*4882a593Smuzhiyun 				test_and_clear_bit(mISDN_STACK_WORK,
250*4882a593Smuzhiyun 						   &st->status);
251*4882a593Smuzhiyun 				test_and_clear_bit(mISDN_STACK_RUNNING,
252*4882a593Smuzhiyun 						   &st->status);
253*4882a593Smuzhiyun 				break;
254*4882a593Smuzhiyun 			}
255*4882a593Smuzhiyun 		}
256*4882a593Smuzhiyun 		if (test_bit(mISDN_STACK_CLEARING, &st->status)) {
257*4882a593Smuzhiyun 			test_and_set_bit(mISDN_STACK_STOPPED, &st->status);
258*4882a593Smuzhiyun 			test_and_clear_bit(mISDN_STACK_RUNNING, &st->status);
259*4882a593Smuzhiyun 			do_clear_stack(st);
260*4882a593Smuzhiyun 			test_and_clear_bit(mISDN_STACK_CLEARING, &st->status);
261*4882a593Smuzhiyun 			test_and_set_bit(mISDN_STACK_RESTART, &st->status);
262*4882a593Smuzhiyun 		}
263*4882a593Smuzhiyun 		if (test_and_clear_bit(mISDN_STACK_RESTART, &st->status)) {
264*4882a593Smuzhiyun 			test_and_clear_bit(mISDN_STACK_STOPPED, &st->status);
265*4882a593Smuzhiyun 			test_and_set_bit(mISDN_STACK_RUNNING, &st->status);
266*4882a593Smuzhiyun 			if (!skb_queue_empty(&st->msgq))
267*4882a593Smuzhiyun 				test_and_set_bit(mISDN_STACK_WORK,
268*4882a593Smuzhiyun 						 &st->status);
269*4882a593Smuzhiyun 		}
270*4882a593Smuzhiyun 		if (test_bit(mISDN_STACK_ABORT, &st->status))
271*4882a593Smuzhiyun 			break;
272*4882a593Smuzhiyun 		if (st->notify != NULL) {
273*4882a593Smuzhiyun 			complete(st->notify);
274*4882a593Smuzhiyun 			st->notify = NULL;
275*4882a593Smuzhiyun 		}
276*4882a593Smuzhiyun #ifdef MISDN_MSG_STATS
277*4882a593Smuzhiyun 		st->sleep_cnt++;
278*4882a593Smuzhiyun #endif
279*4882a593Smuzhiyun 		test_and_clear_bit(mISDN_STACK_ACTIVE, &st->status);
280*4882a593Smuzhiyun 		wait_event_interruptible(st->workq, (st->status &
281*4882a593Smuzhiyun 						     mISDN_STACK_ACTION_MASK));
282*4882a593Smuzhiyun 		if (*debug & DEBUG_MSG_THREAD)
283*4882a593Smuzhiyun 			printk(KERN_DEBUG "%s: %s wake status %08lx\n",
284*4882a593Smuzhiyun 			       __func__, dev_name(&st->dev->dev), st->status);
285*4882a593Smuzhiyun 		test_and_set_bit(mISDN_STACK_ACTIVE, &st->status);
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 		test_and_clear_bit(mISDN_STACK_WAKEUP, &st->status);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 		if (test_bit(mISDN_STACK_STOPPED, &st->status)) {
290*4882a593Smuzhiyun 			test_and_clear_bit(mISDN_STACK_RUNNING, &st->status);
291*4882a593Smuzhiyun #ifdef MISDN_MSG_STATS
292*4882a593Smuzhiyun 			st->stopped_cnt++;
293*4882a593Smuzhiyun #endif
294*4882a593Smuzhiyun 		}
295*4882a593Smuzhiyun 	}
296*4882a593Smuzhiyun #ifdef MISDN_MSG_STATS
297*4882a593Smuzhiyun 	printk(KERN_DEBUG "mISDNStackd daemon for %s proceed %d "
298*4882a593Smuzhiyun 	       "msg %d sleep %d stopped\n",
299*4882a593Smuzhiyun 	       dev_name(&st->dev->dev), st->msg_cnt, st->sleep_cnt,
300*4882a593Smuzhiyun 	       st->stopped_cnt);
301*4882a593Smuzhiyun 	task_cputime(st->thread, &utime, &stime);
302*4882a593Smuzhiyun 	printk(KERN_DEBUG
303*4882a593Smuzhiyun 	       "mISDNStackd daemon for %s utime(%llu) stime(%llu)\n",
304*4882a593Smuzhiyun 	       dev_name(&st->dev->dev), utime, stime);
305*4882a593Smuzhiyun 	printk(KERN_DEBUG
306*4882a593Smuzhiyun 	       "mISDNStackd daemon for %s nvcsw(%ld) nivcsw(%ld)\n",
307*4882a593Smuzhiyun 	       dev_name(&st->dev->dev), st->thread->nvcsw, st->thread->nivcsw);
308*4882a593Smuzhiyun 	printk(KERN_DEBUG "mISDNStackd daemon for %s killed now\n",
309*4882a593Smuzhiyun 	       dev_name(&st->dev->dev));
310*4882a593Smuzhiyun #endif
311*4882a593Smuzhiyun 	test_and_set_bit(mISDN_STACK_KILLED, &st->status);
312*4882a593Smuzhiyun 	test_and_clear_bit(mISDN_STACK_RUNNING, &st->status);
313*4882a593Smuzhiyun 	test_and_clear_bit(mISDN_STACK_ACTIVE, &st->status);
314*4882a593Smuzhiyun 	test_and_clear_bit(mISDN_STACK_ABORT, &st->status);
315*4882a593Smuzhiyun 	skb_queue_purge(&st->msgq);
316*4882a593Smuzhiyun 	st->thread = NULL;
317*4882a593Smuzhiyun 	if (st->notify != NULL) {
318*4882a593Smuzhiyun 		complete(st->notify);
319*4882a593Smuzhiyun 		st->notify = NULL;
320*4882a593Smuzhiyun 	}
321*4882a593Smuzhiyun 	return 0;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun static int
l1_receive(struct mISDNchannel * ch,struct sk_buff * skb)325*4882a593Smuzhiyun l1_receive(struct mISDNchannel *ch, struct sk_buff *skb)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun 	if (!ch->st)
328*4882a593Smuzhiyun 		return -ENODEV;
329*4882a593Smuzhiyun 	__net_timestamp(skb);
330*4882a593Smuzhiyun 	_queue_message(ch->st, skb);
331*4882a593Smuzhiyun 	return 0;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun void
set_channel_address(struct mISDNchannel * ch,u_int sapi,u_int tei)335*4882a593Smuzhiyun set_channel_address(struct mISDNchannel *ch, u_int sapi, u_int tei)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun 	ch->addr = sapi | (tei << 8);
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun void
__add_layer2(struct mISDNchannel * ch,struct mISDNstack * st)341*4882a593Smuzhiyun __add_layer2(struct mISDNchannel *ch, struct mISDNstack *st)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun 	list_add_tail(&ch->list, &st->layer2);
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun void
add_layer2(struct mISDNchannel * ch,struct mISDNstack * st)347*4882a593Smuzhiyun add_layer2(struct mISDNchannel *ch, struct mISDNstack *st)
348*4882a593Smuzhiyun {
349*4882a593Smuzhiyun 	mutex_lock(&st->lmutex);
350*4882a593Smuzhiyun 	__add_layer2(ch, st);
351*4882a593Smuzhiyun 	mutex_unlock(&st->lmutex);
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun static int
st_own_ctrl(struct mISDNchannel * ch,u_int cmd,void * arg)355*4882a593Smuzhiyun st_own_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
356*4882a593Smuzhiyun {
357*4882a593Smuzhiyun 	if (!ch->st || !ch->st->layer1)
358*4882a593Smuzhiyun 		return -EINVAL;
359*4882a593Smuzhiyun 	return ch->st->layer1->ctrl(ch->st->layer1, cmd, arg);
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun int
create_stack(struct mISDNdevice * dev)363*4882a593Smuzhiyun create_stack(struct mISDNdevice *dev)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun 	struct mISDNstack	*newst;
366*4882a593Smuzhiyun 	int			err;
367*4882a593Smuzhiyun 	DECLARE_COMPLETION_ONSTACK(done);
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	newst = kzalloc(sizeof(struct mISDNstack), GFP_KERNEL);
370*4882a593Smuzhiyun 	if (!newst) {
371*4882a593Smuzhiyun 		printk(KERN_ERR "kmalloc mISDN_stack failed\n");
372*4882a593Smuzhiyun 		return -ENOMEM;
373*4882a593Smuzhiyun 	}
374*4882a593Smuzhiyun 	newst->dev = dev;
375*4882a593Smuzhiyun 	INIT_LIST_HEAD(&newst->layer2);
376*4882a593Smuzhiyun 	INIT_HLIST_HEAD(&newst->l1sock.head);
377*4882a593Smuzhiyun 	rwlock_init(&newst->l1sock.lock);
378*4882a593Smuzhiyun 	init_waitqueue_head(&newst->workq);
379*4882a593Smuzhiyun 	skb_queue_head_init(&newst->msgq);
380*4882a593Smuzhiyun 	mutex_init(&newst->lmutex);
381*4882a593Smuzhiyun 	dev->D.st = newst;
382*4882a593Smuzhiyun 	err = create_teimanager(dev);
383*4882a593Smuzhiyun 	if (err) {
384*4882a593Smuzhiyun 		printk(KERN_ERR "kmalloc teimanager failed\n");
385*4882a593Smuzhiyun 		kfree(newst);
386*4882a593Smuzhiyun 		return err;
387*4882a593Smuzhiyun 	}
388*4882a593Smuzhiyun 	dev->teimgr->peer = &newst->own;
389*4882a593Smuzhiyun 	dev->teimgr->recv = mISDN_queue_message;
390*4882a593Smuzhiyun 	dev->teimgr->st = newst;
391*4882a593Smuzhiyun 	newst->layer1 = &dev->D;
392*4882a593Smuzhiyun 	dev->D.recv = l1_receive;
393*4882a593Smuzhiyun 	dev->D.peer = &newst->own;
394*4882a593Smuzhiyun 	newst->own.st = newst;
395*4882a593Smuzhiyun 	newst->own.ctrl = st_own_ctrl;
396*4882a593Smuzhiyun 	newst->own.send = mISDN_queue_message;
397*4882a593Smuzhiyun 	newst->own.recv = mISDN_queue_message;
398*4882a593Smuzhiyun 	if (*debug & DEBUG_CORE_FUNC)
399*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s: st(%s)\n", __func__,
400*4882a593Smuzhiyun 		       dev_name(&newst->dev->dev));
401*4882a593Smuzhiyun 	newst->notify = &done;
402*4882a593Smuzhiyun 	newst->thread = kthread_run(mISDNStackd, (void *)newst, "mISDN_%s",
403*4882a593Smuzhiyun 				    dev_name(&newst->dev->dev));
404*4882a593Smuzhiyun 	if (IS_ERR(newst->thread)) {
405*4882a593Smuzhiyun 		err = PTR_ERR(newst->thread);
406*4882a593Smuzhiyun 		printk(KERN_ERR
407*4882a593Smuzhiyun 		       "mISDN:cannot create kernel thread for %s (%d)\n",
408*4882a593Smuzhiyun 		       dev_name(&newst->dev->dev), err);
409*4882a593Smuzhiyun 		delete_teimanager(dev->teimgr);
410*4882a593Smuzhiyun 		kfree(newst);
411*4882a593Smuzhiyun 	} else
412*4882a593Smuzhiyun 		wait_for_completion(&done);
413*4882a593Smuzhiyun 	return err;
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun int
connect_layer1(struct mISDNdevice * dev,struct mISDNchannel * ch,u_int protocol,struct sockaddr_mISDN * adr)417*4882a593Smuzhiyun connect_layer1(struct mISDNdevice *dev, struct mISDNchannel *ch,
418*4882a593Smuzhiyun 	       u_int protocol, struct sockaddr_mISDN *adr)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun 	struct mISDN_sock	*msk = container_of(ch, struct mISDN_sock, ch);
421*4882a593Smuzhiyun 	struct channel_req	rq;
422*4882a593Smuzhiyun 	int			err;
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	if (*debug &  DEBUG_CORE_FUNC)
426*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
427*4882a593Smuzhiyun 		       __func__, dev_name(&dev->dev), protocol, adr->dev,
428*4882a593Smuzhiyun 		       adr->channel, adr->sapi, adr->tei);
429*4882a593Smuzhiyun 	switch (protocol) {
430*4882a593Smuzhiyun 	case ISDN_P_NT_S0:
431*4882a593Smuzhiyun 	case ISDN_P_NT_E1:
432*4882a593Smuzhiyun 	case ISDN_P_TE_S0:
433*4882a593Smuzhiyun 	case ISDN_P_TE_E1:
434*4882a593Smuzhiyun 		ch->recv = mISDN_queue_message;
435*4882a593Smuzhiyun 		ch->peer = &dev->D.st->own;
436*4882a593Smuzhiyun 		ch->st = dev->D.st;
437*4882a593Smuzhiyun 		rq.protocol = protocol;
438*4882a593Smuzhiyun 		rq.adr.channel = adr->channel;
439*4882a593Smuzhiyun 		err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq);
440*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s: ret %d (dev %d)\n", __func__, err,
441*4882a593Smuzhiyun 		       dev->id);
442*4882a593Smuzhiyun 		if (err)
443*4882a593Smuzhiyun 			return err;
444*4882a593Smuzhiyun 		write_lock_bh(&dev->D.st->l1sock.lock);
445*4882a593Smuzhiyun 		sk_add_node(&msk->sk, &dev->D.st->l1sock.head);
446*4882a593Smuzhiyun 		write_unlock_bh(&dev->D.st->l1sock.lock);
447*4882a593Smuzhiyun 		break;
448*4882a593Smuzhiyun 	default:
449*4882a593Smuzhiyun 		return -ENOPROTOOPT;
450*4882a593Smuzhiyun 	}
451*4882a593Smuzhiyun 	return 0;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun int
connect_Bstack(struct mISDNdevice * dev,struct mISDNchannel * ch,u_int protocol,struct sockaddr_mISDN * adr)455*4882a593Smuzhiyun connect_Bstack(struct mISDNdevice *dev, struct mISDNchannel *ch,
456*4882a593Smuzhiyun 	       u_int protocol, struct sockaddr_mISDN *adr)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun 	struct channel_req	rq, rq2;
459*4882a593Smuzhiyun 	int			pmask, err;
460*4882a593Smuzhiyun 	struct Bprotocol	*bp;
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	if (*debug &  DEBUG_CORE_FUNC)
463*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
464*4882a593Smuzhiyun 		       __func__, dev_name(&dev->dev), protocol,
465*4882a593Smuzhiyun 		       adr->dev, adr->channel, adr->sapi,
466*4882a593Smuzhiyun 		       adr->tei);
467*4882a593Smuzhiyun 	ch->st = dev->D.st;
468*4882a593Smuzhiyun 	pmask = 1 << (protocol & ISDN_P_B_MASK);
469*4882a593Smuzhiyun 	if (pmask & dev->Bprotocols) {
470*4882a593Smuzhiyun 		rq.protocol = protocol;
471*4882a593Smuzhiyun 		rq.adr = *adr;
472*4882a593Smuzhiyun 		err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq);
473*4882a593Smuzhiyun 		if (err)
474*4882a593Smuzhiyun 			return err;
475*4882a593Smuzhiyun 		ch->recv = rq.ch->send;
476*4882a593Smuzhiyun 		ch->peer = rq.ch;
477*4882a593Smuzhiyun 		rq.ch->recv = ch->send;
478*4882a593Smuzhiyun 		rq.ch->peer = ch;
479*4882a593Smuzhiyun 		rq.ch->st = dev->D.st;
480*4882a593Smuzhiyun 	} else {
481*4882a593Smuzhiyun 		bp = get_Bprotocol4mask(pmask);
482*4882a593Smuzhiyun 		if (!bp)
483*4882a593Smuzhiyun 			return -ENOPROTOOPT;
484*4882a593Smuzhiyun 		rq2.protocol = protocol;
485*4882a593Smuzhiyun 		rq2.adr = *adr;
486*4882a593Smuzhiyun 		rq2.ch = ch;
487*4882a593Smuzhiyun 		err = bp->create(&rq2);
488*4882a593Smuzhiyun 		if (err)
489*4882a593Smuzhiyun 			return err;
490*4882a593Smuzhiyun 		ch->recv = rq2.ch->send;
491*4882a593Smuzhiyun 		ch->peer = rq2.ch;
492*4882a593Smuzhiyun 		rq2.ch->st = dev->D.st;
493*4882a593Smuzhiyun 		rq.protocol = rq2.protocol;
494*4882a593Smuzhiyun 		rq.adr = *adr;
495*4882a593Smuzhiyun 		err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq);
496*4882a593Smuzhiyun 		if (err) {
497*4882a593Smuzhiyun 			rq2.ch->ctrl(rq2.ch, CLOSE_CHANNEL, NULL);
498*4882a593Smuzhiyun 			return err;
499*4882a593Smuzhiyun 		}
500*4882a593Smuzhiyun 		rq2.ch->recv = rq.ch->send;
501*4882a593Smuzhiyun 		rq2.ch->peer = rq.ch;
502*4882a593Smuzhiyun 		rq.ch->recv = rq2.ch->send;
503*4882a593Smuzhiyun 		rq.ch->peer = rq2.ch;
504*4882a593Smuzhiyun 		rq.ch->st = dev->D.st;
505*4882a593Smuzhiyun 	}
506*4882a593Smuzhiyun 	ch->protocol = protocol;
507*4882a593Smuzhiyun 	ch->nr = rq.ch->nr;
508*4882a593Smuzhiyun 	return 0;
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun int
create_l2entity(struct mISDNdevice * dev,struct mISDNchannel * ch,u_int protocol,struct sockaddr_mISDN * adr)512*4882a593Smuzhiyun create_l2entity(struct mISDNdevice *dev, struct mISDNchannel *ch,
513*4882a593Smuzhiyun 		u_int protocol, struct sockaddr_mISDN *adr)
514*4882a593Smuzhiyun {
515*4882a593Smuzhiyun 	struct channel_req	rq;
516*4882a593Smuzhiyun 	int			err;
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	if (*debug &  DEBUG_CORE_FUNC)
519*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
520*4882a593Smuzhiyun 		       __func__, dev_name(&dev->dev), protocol,
521*4882a593Smuzhiyun 		       adr->dev, adr->channel, adr->sapi,
522*4882a593Smuzhiyun 		       adr->tei);
523*4882a593Smuzhiyun 	rq.protocol = ISDN_P_TE_S0;
524*4882a593Smuzhiyun 	if (dev->Dprotocols & (1 << ISDN_P_TE_E1))
525*4882a593Smuzhiyun 		rq.protocol = ISDN_P_TE_E1;
526*4882a593Smuzhiyun 	switch (protocol) {
527*4882a593Smuzhiyun 	case ISDN_P_LAPD_NT:
528*4882a593Smuzhiyun 		rq.protocol = ISDN_P_NT_S0;
529*4882a593Smuzhiyun 		if (dev->Dprotocols & (1 << ISDN_P_NT_E1))
530*4882a593Smuzhiyun 			rq.protocol = ISDN_P_NT_E1;
531*4882a593Smuzhiyun 		fallthrough;
532*4882a593Smuzhiyun 	case ISDN_P_LAPD_TE:
533*4882a593Smuzhiyun 		ch->recv = mISDN_queue_message;
534*4882a593Smuzhiyun 		ch->peer = &dev->D.st->own;
535*4882a593Smuzhiyun 		ch->st = dev->D.st;
536*4882a593Smuzhiyun 		rq.adr.channel = 0;
537*4882a593Smuzhiyun 		err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq);
538*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s: ret 1 %d\n", __func__, err);
539*4882a593Smuzhiyun 		if (err)
540*4882a593Smuzhiyun 			break;
541*4882a593Smuzhiyun 		rq.protocol = protocol;
542*4882a593Smuzhiyun 		rq.adr = *adr;
543*4882a593Smuzhiyun 		rq.ch = ch;
544*4882a593Smuzhiyun 		err = dev->teimgr->ctrl(dev->teimgr, OPEN_CHANNEL, &rq);
545*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s: ret 2 %d\n", __func__, err);
546*4882a593Smuzhiyun 		if (!err) {
547*4882a593Smuzhiyun 			if ((protocol == ISDN_P_LAPD_NT) && !rq.ch)
548*4882a593Smuzhiyun 				break;
549*4882a593Smuzhiyun 			add_layer2(rq.ch, dev->D.st);
550*4882a593Smuzhiyun 			rq.ch->recv = mISDN_queue_message;
551*4882a593Smuzhiyun 			rq.ch->peer = &dev->D.st->own;
552*4882a593Smuzhiyun 			rq.ch->ctrl(rq.ch, OPEN_CHANNEL, NULL); /* can't fail */
553*4882a593Smuzhiyun 		}
554*4882a593Smuzhiyun 		break;
555*4882a593Smuzhiyun 	default:
556*4882a593Smuzhiyun 		err = -EPROTONOSUPPORT;
557*4882a593Smuzhiyun 	}
558*4882a593Smuzhiyun 	return err;
559*4882a593Smuzhiyun }
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun void
delete_channel(struct mISDNchannel * ch)562*4882a593Smuzhiyun delete_channel(struct mISDNchannel *ch)
563*4882a593Smuzhiyun {
564*4882a593Smuzhiyun 	struct mISDN_sock	*msk = container_of(ch, struct mISDN_sock, ch);
565*4882a593Smuzhiyun 	struct mISDNchannel	*pch;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	if (!ch->st) {
568*4882a593Smuzhiyun 		printk(KERN_WARNING "%s: no stack\n", __func__);
569*4882a593Smuzhiyun 		return;
570*4882a593Smuzhiyun 	}
571*4882a593Smuzhiyun 	if (*debug & DEBUG_CORE_FUNC)
572*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s: st(%s) protocol(%x)\n", __func__,
573*4882a593Smuzhiyun 		       dev_name(&ch->st->dev->dev), ch->protocol);
574*4882a593Smuzhiyun 	if (ch->protocol >= ISDN_P_B_START) {
575*4882a593Smuzhiyun 		if (ch->peer) {
576*4882a593Smuzhiyun 			ch->peer->ctrl(ch->peer, CLOSE_CHANNEL, NULL);
577*4882a593Smuzhiyun 			ch->peer = NULL;
578*4882a593Smuzhiyun 		}
579*4882a593Smuzhiyun 		return;
580*4882a593Smuzhiyun 	}
581*4882a593Smuzhiyun 	switch (ch->protocol) {
582*4882a593Smuzhiyun 	case ISDN_P_NT_S0:
583*4882a593Smuzhiyun 	case ISDN_P_TE_S0:
584*4882a593Smuzhiyun 	case ISDN_P_NT_E1:
585*4882a593Smuzhiyun 	case ISDN_P_TE_E1:
586*4882a593Smuzhiyun 		write_lock_bh(&ch->st->l1sock.lock);
587*4882a593Smuzhiyun 		sk_del_node_init(&msk->sk);
588*4882a593Smuzhiyun 		write_unlock_bh(&ch->st->l1sock.lock);
589*4882a593Smuzhiyun 		ch->st->dev->D.ctrl(&ch->st->dev->D, CLOSE_CHANNEL, NULL);
590*4882a593Smuzhiyun 		break;
591*4882a593Smuzhiyun 	case ISDN_P_LAPD_TE:
592*4882a593Smuzhiyun 		pch = get_channel4id(ch->st, ch->nr);
593*4882a593Smuzhiyun 		if (pch) {
594*4882a593Smuzhiyun 			mutex_lock(&ch->st->lmutex);
595*4882a593Smuzhiyun 			list_del(&pch->list);
596*4882a593Smuzhiyun 			mutex_unlock(&ch->st->lmutex);
597*4882a593Smuzhiyun 			pch->ctrl(pch, CLOSE_CHANNEL, NULL);
598*4882a593Smuzhiyun 			pch = ch->st->dev->teimgr;
599*4882a593Smuzhiyun 			pch->ctrl(pch, CLOSE_CHANNEL, NULL);
600*4882a593Smuzhiyun 		} else
601*4882a593Smuzhiyun 			printk(KERN_WARNING "%s: no l2 channel\n",
602*4882a593Smuzhiyun 			       __func__);
603*4882a593Smuzhiyun 		break;
604*4882a593Smuzhiyun 	case ISDN_P_LAPD_NT:
605*4882a593Smuzhiyun 		pch = ch->st->dev->teimgr;
606*4882a593Smuzhiyun 		if (pch) {
607*4882a593Smuzhiyun 			pch->ctrl(pch, CLOSE_CHANNEL, NULL);
608*4882a593Smuzhiyun 		} else
609*4882a593Smuzhiyun 			printk(KERN_WARNING "%s: no l2 channel\n",
610*4882a593Smuzhiyun 			       __func__);
611*4882a593Smuzhiyun 		break;
612*4882a593Smuzhiyun 	default:
613*4882a593Smuzhiyun 		break;
614*4882a593Smuzhiyun 	}
615*4882a593Smuzhiyun 	return;
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun void
delete_stack(struct mISDNdevice * dev)619*4882a593Smuzhiyun delete_stack(struct mISDNdevice *dev)
620*4882a593Smuzhiyun {
621*4882a593Smuzhiyun 	struct mISDNstack	*st = dev->D.st;
622*4882a593Smuzhiyun 	DECLARE_COMPLETION_ONSTACK(done);
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 	if (*debug & DEBUG_CORE_FUNC)
625*4882a593Smuzhiyun 		printk(KERN_DEBUG "%s: st(%s)\n", __func__,
626*4882a593Smuzhiyun 		       dev_name(&st->dev->dev));
627*4882a593Smuzhiyun 	if (dev->teimgr)
628*4882a593Smuzhiyun 		delete_teimanager(dev->teimgr);
629*4882a593Smuzhiyun 	if (st->thread) {
630*4882a593Smuzhiyun 		if (st->notify) {
631*4882a593Smuzhiyun 			printk(KERN_WARNING "%s: notifier in use\n",
632*4882a593Smuzhiyun 			       __func__);
633*4882a593Smuzhiyun 			complete(st->notify);
634*4882a593Smuzhiyun 		}
635*4882a593Smuzhiyun 		st->notify = &done;
636*4882a593Smuzhiyun 		test_and_set_bit(mISDN_STACK_ABORT, &st->status);
637*4882a593Smuzhiyun 		test_and_set_bit(mISDN_STACK_WAKEUP, &st->status);
638*4882a593Smuzhiyun 		wake_up_interruptible(&st->workq);
639*4882a593Smuzhiyun 		wait_for_completion(&done);
640*4882a593Smuzhiyun 	}
641*4882a593Smuzhiyun 	if (!list_empty(&st->layer2))
642*4882a593Smuzhiyun 		printk(KERN_WARNING "%s: layer2 list not empty\n",
643*4882a593Smuzhiyun 		       __func__);
644*4882a593Smuzhiyun 	if (!hlist_empty(&st->l1sock.head))
645*4882a593Smuzhiyun 		printk(KERN_WARNING "%s: layer1 list not empty\n",
646*4882a593Smuzhiyun 		       __func__);
647*4882a593Smuzhiyun 	kfree(st);
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun void
mISDN_initstack(u_int * dp)651*4882a593Smuzhiyun mISDN_initstack(u_int *dp)
652*4882a593Smuzhiyun {
653*4882a593Smuzhiyun 	debug = dp;
654*4882a593Smuzhiyun }
655