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(¤t->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