18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Author Karsten Keil <kkeil@novell.com> 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright 2008 by Karsten Keil <kkeil@novell.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/slab.h> 108c2ecf20Sopenharmony_ci#include <linux/mISDNif.h> 118c2ecf20Sopenharmony_ci#include <linux/kthread.h> 128c2ecf20Sopenharmony_ci#include <linux/sched.h> 138c2ecf20Sopenharmony_ci#include <linux/sched/cputime.h> 148c2ecf20Sopenharmony_ci#include <linux/signal.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "core.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic u_int *debug; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic inline void 218c2ecf20Sopenharmony_ci_queue_message(struct mISDNstack *st, struct sk_buff *skb) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci struct mISDNhead *hh = mISDN_HEAD_P(skb); 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci if (*debug & DEBUG_QUEUE_FUNC) 268c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s prim(%x) id(%x) %p\n", 278c2ecf20Sopenharmony_ci __func__, hh->prim, hh->id, skb); 288c2ecf20Sopenharmony_ci skb_queue_tail(&st->msgq, skb); 298c2ecf20Sopenharmony_ci if (likely(!test_bit(mISDN_STACK_STOPPED, &st->status))) { 308c2ecf20Sopenharmony_ci test_and_set_bit(mISDN_STACK_WORK, &st->status); 318c2ecf20Sopenharmony_ci wake_up_interruptible(&st->workq); 328c2ecf20Sopenharmony_ci } 338c2ecf20Sopenharmony_ci} 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic int 368c2ecf20Sopenharmony_cimISDN_queue_message(struct mISDNchannel *ch, struct sk_buff *skb) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci _queue_message(ch->st, skb); 398c2ecf20Sopenharmony_ci return 0; 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic struct mISDNchannel * 438c2ecf20Sopenharmony_ciget_channel4id(struct mISDNstack *st, u_int id) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci struct mISDNchannel *ch; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci mutex_lock(&st->lmutex); 488c2ecf20Sopenharmony_ci list_for_each_entry(ch, &st->layer2, list) { 498c2ecf20Sopenharmony_ci if (id == ch->nr) 508c2ecf20Sopenharmony_ci goto unlock; 518c2ecf20Sopenharmony_ci } 528c2ecf20Sopenharmony_ci ch = NULL; 538c2ecf20Sopenharmony_ciunlock: 548c2ecf20Sopenharmony_ci mutex_unlock(&st->lmutex); 558c2ecf20Sopenharmony_ci return ch; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic void 598c2ecf20Sopenharmony_cisend_socklist(struct mISDN_sock_list *sl, struct sk_buff *skb) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci struct sock *sk; 628c2ecf20Sopenharmony_ci struct sk_buff *cskb = NULL; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci read_lock(&sl->lock); 658c2ecf20Sopenharmony_ci sk_for_each(sk, &sl->head) { 668c2ecf20Sopenharmony_ci if (sk->sk_state != MISDN_BOUND) 678c2ecf20Sopenharmony_ci continue; 688c2ecf20Sopenharmony_ci if (!cskb) 698c2ecf20Sopenharmony_ci cskb = skb_copy(skb, GFP_ATOMIC); 708c2ecf20Sopenharmony_ci if (!cskb) { 718c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s no skb\n", __func__); 728c2ecf20Sopenharmony_ci break; 738c2ecf20Sopenharmony_ci } 748c2ecf20Sopenharmony_ci if (!sock_queue_rcv_skb(sk, cskb)) 758c2ecf20Sopenharmony_ci cskb = NULL; 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci read_unlock(&sl->lock); 788c2ecf20Sopenharmony_ci dev_kfree_skb(cskb); 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic void 828c2ecf20Sopenharmony_cisend_layer2(struct mISDNstack *st, struct sk_buff *skb) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci struct sk_buff *cskb; 858c2ecf20Sopenharmony_ci struct mISDNhead *hh = mISDN_HEAD_P(skb); 868c2ecf20Sopenharmony_ci struct mISDNchannel *ch; 878c2ecf20Sopenharmony_ci int ret; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci if (!st) 908c2ecf20Sopenharmony_ci return; 918c2ecf20Sopenharmony_ci mutex_lock(&st->lmutex); 928c2ecf20Sopenharmony_ci if ((hh->id & MISDN_ID_ADDR_MASK) == MISDN_ID_ANY) { /* L2 for all */ 938c2ecf20Sopenharmony_ci list_for_each_entry(ch, &st->layer2, list) { 948c2ecf20Sopenharmony_ci if (list_is_last(&ch->list, &st->layer2)) { 958c2ecf20Sopenharmony_ci cskb = skb; 968c2ecf20Sopenharmony_ci skb = NULL; 978c2ecf20Sopenharmony_ci } else { 988c2ecf20Sopenharmony_ci cskb = skb_copy(skb, GFP_KERNEL); 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci if (cskb) { 1018c2ecf20Sopenharmony_ci ret = ch->send(ch, cskb); 1028c2ecf20Sopenharmony_ci if (ret) { 1038c2ecf20Sopenharmony_ci if (*debug & DEBUG_SEND_ERR) 1048c2ecf20Sopenharmony_ci printk(KERN_DEBUG 1058c2ecf20Sopenharmony_ci "%s ch%d prim(%x) addr(%x)" 1068c2ecf20Sopenharmony_ci " err %d\n", 1078c2ecf20Sopenharmony_ci __func__, ch->nr, 1088c2ecf20Sopenharmony_ci hh->prim, ch->addr, ret); 1098c2ecf20Sopenharmony_ci dev_kfree_skb(cskb); 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci } else { 1128c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s ch%d addr %x no mem\n", 1138c2ecf20Sopenharmony_ci __func__, ch->nr, ch->addr); 1148c2ecf20Sopenharmony_ci goto out; 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci } else { 1188c2ecf20Sopenharmony_ci list_for_each_entry(ch, &st->layer2, list) { 1198c2ecf20Sopenharmony_ci if ((hh->id & MISDN_ID_ADDR_MASK) == ch->addr) { 1208c2ecf20Sopenharmony_ci ret = ch->send(ch, skb); 1218c2ecf20Sopenharmony_ci if (!ret) 1228c2ecf20Sopenharmony_ci skb = NULL; 1238c2ecf20Sopenharmony_ci goto out; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci } 1268c2ecf20Sopenharmony_ci ret = st->dev->teimgr->ctrl(st->dev->teimgr, CHECK_DATA, skb); 1278c2ecf20Sopenharmony_ci if (!ret) 1288c2ecf20Sopenharmony_ci skb = NULL; 1298c2ecf20Sopenharmony_ci else if (*debug & DEBUG_SEND_ERR) 1308c2ecf20Sopenharmony_ci printk(KERN_DEBUG 1318c2ecf20Sopenharmony_ci "%s mgr prim(%x) err %d\n", 1328c2ecf20Sopenharmony_ci __func__, hh->prim, ret); 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ciout: 1358c2ecf20Sopenharmony_ci mutex_unlock(&st->lmutex); 1368c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic inline int 1408c2ecf20Sopenharmony_cisend_msg_to_layer(struct mISDNstack *st, struct sk_buff *skb) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci struct mISDNhead *hh = mISDN_HEAD_P(skb); 1438c2ecf20Sopenharmony_ci struct mISDNchannel *ch; 1448c2ecf20Sopenharmony_ci int lm; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci lm = hh->prim & MISDN_LAYERMASK; 1478c2ecf20Sopenharmony_ci if (*debug & DEBUG_QUEUE_FUNC) 1488c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s prim(%x) id(%x) %p\n", 1498c2ecf20Sopenharmony_ci __func__, hh->prim, hh->id, skb); 1508c2ecf20Sopenharmony_ci if (lm == 0x1) { 1518c2ecf20Sopenharmony_ci if (!hlist_empty(&st->l1sock.head)) { 1528c2ecf20Sopenharmony_ci __net_timestamp(skb); 1538c2ecf20Sopenharmony_ci send_socklist(&st->l1sock, skb); 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci return st->layer1->send(st->layer1, skb); 1568c2ecf20Sopenharmony_ci } else if (lm == 0x2) { 1578c2ecf20Sopenharmony_ci if (!hlist_empty(&st->l1sock.head)) 1588c2ecf20Sopenharmony_ci send_socklist(&st->l1sock, skb); 1598c2ecf20Sopenharmony_ci send_layer2(st, skb); 1608c2ecf20Sopenharmony_ci return 0; 1618c2ecf20Sopenharmony_ci } else if (lm == 0x4) { 1628c2ecf20Sopenharmony_ci ch = get_channel4id(st, hh->id); 1638c2ecf20Sopenharmony_ci if (ch) 1648c2ecf20Sopenharmony_ci return ch->send(ch, skb); 1658c2ecf20Sopenharmony_ci else 1668c2ecf20Sopenharmony_ci printk(KERN_WARNING 1678c2ecf20Sopenharmony_ci "%s: dev(%s) prim(%x) id(%x) no channel\n", 1688c2ecf20Sopenharmony_ci __func__, dev_name(&st->dev->dev), hh->prim, 1698c2ecf20Sopenharmony_ci hh->id); 1708c2ecf20Sopenharmony_ci } else if (lm == 0x8) { 1718c2ecf20Sopenharmony_ci WARN_ON(lm == 0x8); 1728c2ecf20Sopenharmony_ci ch = get_channel4id(st, hh->id); 1738c2ecf20Sopenharmony_ci if (ch) 1748c2ecf20Sopenharmony_ci return ch->send(ch, skb); 1758c2ecf20Sopenharmony_ci else 1768c2ecf20Sopenharmony_ci printk(KERN_WARNING 1778c2ecf20Sopenharmony_ci "%s: dev(%s) prim(%x) id(%x) no channel\n", 1788c2ecf20Sopenharmony_ci __func__, dev_name(&st->dev->dev), hh->prim, 1798c2ecf20Sopenharmony_ci hh->id); 1808c2ecf20Sopenharmony_ci } else { 1818c2ecf20Sopenharmony_ci /* broadcast not handled yet */ 1828c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: dev(%s) prim %x not delivered\n", 1838c2ecf20Sopenharmony_ci __func__, dev_name(&st->dev->dev), hh->prim); 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci return -ESRCH; 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic void 1898c2ecf20Sopenharmony_cido_clear_stack(struct mISDNstack *st) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic int 1948c2ecf20Sopenharmony_cimISDNStackd(void *data) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci struct mISDNstack *st = data; 1978c2ecf20Sopenharmony_ci#ifdef MISDN_MSG_STATS 1988c2ecf20Sopenharmony_ci u64 utime, stime; 1998c2ecf20Sopenharmony_ci#endif 2008c2ecf20Sopenharmony_ci int err = 0; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci sigfillset(¤t->blocked); 2038c2ecf20Sopenharmony_ci if (*debug & DEBUG_MSG_THREAD) 2048c2ecf20Sopenharmony_ci printk(KERN_DEBUG "mISDNStackd %s started\n", 2058c2ecf20Sopenharmony_ci dev_name(&st->dev->dev)); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci if (st->notify != NULL) { 2088c2ecf20Sopenharmony_ci complete(st->notify); 2098c2ecf20Sopenharmony_ci st->notify = NULL; 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci for (;;) { 2138c2ecf20Sopenharmony_ci struct sk_buff *skb; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci if (unlikely(test_bit(mISDN_STACK_STOPPED, &st->status))) { 2168c2ecf20Sopenharmony_ci test_and_clear_bit(mISDN_STACK_WORK, &st->status); 2178c2ecf20Sopenharmony_ci test_and_clear_bit(mISDN_STACK_RUNNING, &st->status); 2188c2ecf20Sopenharmony_ci } else 2198c2ecf20Sopenharmony_ci test_and_set_bit(mISDN_STACK_RUNNING, &st->status); 2208c2ecf20Sopenharmony_ci while (test_bit(mISDN_STACK_WORK, &st->status)) { 2218c2ecf20Sopenharmony_ci skb = skb_dequeue(&st->msgq); 2228c2ecf20Sopenharmony_ci if (!skb) { 2238c2ecf20Sopenharmony_ci test_and_clear_bit(mISDN_STACK_WORK, 2248c2ecf20Sopenharmony_ci &st->status); 2258c2ecf20Sopenharmony_ci /* test if a race happens */ 2268c2ecf20Sopenharmony_ci skb = skb_dequeue(&st->msgq); 2278c2ecf20Sopenharmony_ci if (!skb) 2288c2ecf20Sopenharmony_ci continue; 2298c2ecf20Sopenharmony_ci test_and_set_bit(mISDN_STACK_WORK, 2308c2ecf20Sopenharmony_ci &st->status); 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci#ifdef MISDN_MSG_STATS 2338c2ecf20Sopenharmony_ci st->msg_cnt++; 2348c2ecf20Sopenharmony_ci#endif 2358c2ecf20Sopenharmony_ci err = send_msg_to_layer(st, skb); 2368c2ecf20Sopenharmony_ci if (unlikely(err)) { 2378c2ecf20Sopenharmony_ci if (*debug & DEBUG_SEND_ERR) 2388c2ecf20Sopenharmony_ci printk(KERN_DEBUG 2398c2ecf20Sopenharmony_ci "%s: %s prim(%x) id(%x) " 2408c2ecf20Sopenharmony_ci "send call(%d)\n", 2418c2ecf20Sopenharmony_ci __func__, dev_name(&st->dev->dev), 2428c2ecf20Sopenharmony_ci mISDN_HEAD_PRIM(skb), 2438c2ecf20Sopenharmony_ci mISDN_HEAD_ID(skb), err); 2448c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 2458c2ecf20Sopenharmony_ci continue; 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci if (unlikely(test_bit(mISDN_STACK_STOPPED, 2488c2ecf20Sopenharmony_ci &st->status))) { 2498c2ecf20Sopenharmony_ci test_and_clear_bit(mISDN_STACK_WORK, 2508c2ecf20Sopenharmony_ci &st->status); 2518c2ecf20Sopenharmony_ci test_and_clear_bit(mISDN_STACK_RUNNING, 2528c2ecf20Sopenharmony_ci &st->status); 2538c2ecf20Sopenharmony_ci break; 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci if (test_bit(mISDN_STACK_CLEARING, &st->status)) { 2578c2ecf20Sopenharmony_ci test_and_set_bit(mISDN_STACK_STOPPED, &st->status); 2588c2ecf20Sopenharmony_ci test_and_clear_bit(mISDN_STACK_RUNNING, &st->status); 2598c2ecf20Sopenharmony_ci do_clear_stack(st); 2608c2ecf20Sopenharmony_ci test_and_clear_bit(mISDN_STACK_CLEARING, &st->status); 2618c2ecf20Sopenharmony_ci test_and_set_bit(mISDN_STACK_RESTART, &st->status); 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci if (test_and_clear_bit(mISDN_STACK_RESTART, &st->status)) { 2648c2ecf20Sopenharmony_ci test_and_clear_bit(mISDN_STACK_STOPPED, &st->status); 2658c2ecf20Sopenharmony_ci test_and_set_bit(mISDN_STACK_RUNNING, &st->status); 2668c2ecf20Sopenharmony_ci if (!skb_queue_empty(&st->msgq)) 2678c2ecf20Sopenharmony_ci test_and_set_bit(mISDN_STACK_WORK, 2688c2ecf20Sopenharmony_ci &st->status); 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci if (test_bit(mISDN_STACK_ABORT, &st->status)) 2718c2ecf20Sopenharmony_ci break; 2728c2ecf20Sopenharmony_ci if (st->notify != NULL) { 2738c2ecf20Sopenharmony_ci complete(st->notify); 2748c2ecf20Sopenharmony_ci st->notify = NULL; 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci#ifdef MISDN_MSG_STATS 2778c2ecf20Sopenharmony_ci st->sleep_cnt++; 2788c2ecf20Sopenharmony_ci#endif 2798c2ecf20Sopenharmony_ci test_and_clear_bit(mISDN_STACK_ACTIVE, &st->status); 2808c2ecf20Sopenharmony_ci wait_event_interruptible(st->workq, (st->status & 2818c2ecf20Sopenharmony_ci mISDN_STACK_ACTION_MASK)); 2828c2ecf20Sopenharmony_ci if (*debug & DEBUG_MSG_THREAD) 2838c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: %s wake status %08lx\n", 2848c2ecf20Sopenharmony_ci __func__, dev_name(&st->dev->dev), st->status); 2858c2ecf20Sopenharmony_ci test_and_set_bit(mISDN_STACK_ACTIVE, &st->status); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci test_and_clear_bit(mISDN_STACK_WAKEUP, &st->status); 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci if (test_bit(mISDN_STACK_STOPPED, &st->status)) { 2908c2ecf20Sopenharmony_ci test_and_clear_bit(mISDN_STACK_RUNNING, &st->status); 2918c2ecf20Sopenharmony_ci#ifdef MISDN_MSG_STATS 2928c2ecf20Sopenharmony_ci st->stopped_cnt++; 2938c2ecf20Sopenharmony_ci#endif 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci#ifdef MISDN_MSG_STATS 2978c2ecf20Sopenharmony_ci printk(KERN_DEBUG "mISDNStackd daemon for %s proceed %d " 2988c2ecf20Sopenharmony_ci "msg %d sleep %d stopped\n", 2998c2ecf20Sopenharmony_ci dev_name(&st->dev->dev), st->msg_cnt, st->sleep_cnt, 3008c2ecf20Sopenharmony_ci st->stopped_cnt); 3018c2ecf20Sopenharmony_ci task_cputime(st->thread, &utime, &stime); 3028c2ecf20Sopenharmony_ci printk(KERN_DEBUG 3038c2ecf20Sopenharmony_ci "mISDNStackd daemon for %s utime(%llu) stime(%llu)\n", 3048c2ecf20Sopenharmony_ci dev_name(&st->dev->dev), utime, stime); 3058c2ecf20Sopenharmony_ci printk(KERN_DEBUG 3068c2ecf20Sopenharmony_ci "mISDNStackd daemon for %s nvcsw(%ld) nivcsw(%ld)\n", 3078c2ecf20Sopenharmony_ci dev_name(&st->dev->dev), st->thread->nvcsw, st->thread->nivcsw); 3088c2ecf20Sopenharmony_ci printk(KERN_DEBUG "mISDNStackd daemon for %s killed now\n", 3098c2ecf20Sopenharmony_ci dev_name(&st->dev->dev)); 3108c2ecf20Sopenharmony_ci#endif 3118c2ecf20Sopenharmony_ci test_and_set_bit(mISDN_STACK_KILLED, &st->status); 3128c2ecf20Sopenharmony_ci test_and_clear_bit(mISDN_STACK_RUNNING, &st->status); 3138c2ecf20Sopenharmony_ci test_and_clear_bit(mISDN_STACK_ACTIVE, &st->status); 3148c2ecf20Sopenharmony_ci test_and_clear_bit(mISDN_STACK_ABORT, &st->status); 3158c2ecf20Sopenharmony_ci skb_queue_purge(&st->msgq); 3168c2ecf20Sopenharmony_ci st->thread = NULL; 3178c2ecf20Sopenharmony_ci if (st->notify != NULL) { 3188c2ecf20Sopenharmony_ci complete(st->notify); 3198c2ecf20Sopenharmony_ci st->notify = NULL; 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci return 0; 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cistatic int 3258c2ecf20Sopenharmony_cil1_receive(struct mISDNchannel *ch, struct sk_buff *skb) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci if (!ch->st) 3288c2ecf20Sopenharmony_ci return -ENODEV; 3298c2ecf20Sopenharmony_ci __net_timestamp(skb); 3308c2ecf20Sopenharmony_ci _queue_message(ch->st, skb); 3318c2ecf20Sopenharmony_ci return 0; 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_civoid 3358c2ecf20Sopenharmony_ciset_channel_address(struct mISDNchannel *ch, u_int sapi, u_int tei) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci ch->addr = sapi | (tei << 8); 3388c2ecf20Sopenharmony_ci} 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_civoid 3418c2ecf20Sopenharmony_ci__add_layer2(struct mISDNchannel *ch, struct mISDNstack *st) 3428c2ecf20Sopenharmony_ci{ 3438c2ecf20Sopenharmony_ci list_add_tail(&ch->list, &st->layer2); 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_civoid 3478c2ecf20Sopenharmony_ciadd_layer2(struct mISDNchannel *ch, struct mISDNstack *st) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci mutex_lock(&st->lmutex); 3508c2ecf20Sopenharmony_ci __add_layer2(ch, st); 3518c2ecf20Sopenharmony_ci mutex_unlock(&st->lmutex); 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_cistatic int 3558c2ecf20Sopenharmony_cist_own_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci if (!ch->st || !ch->st->layer1) 3588c2ecf20Sopenharmony_ci return -EINVAL; 3598c2ecf20Sopenharmony_ci return ch->st->layer1->ctrl(ch->st->layer1, cmd, arg); 3608c2ecf20Sopenharmony_ci} 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ciint 3638c2ecf20Sopenharmony_cicreate_stack(struct mISDNdevice *dev) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci struct mISDNstack *newst; 3668c2ecf20Sopenharmony_ci int err; 3678c2ecf20Sopenharmony_ci DECLARE_COMPLETION_ONSTACK(done); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci newst = kzalloc(sizeof(struct mISDNstack), GFP_KERNEL); 3708c2ecf20Sopenharmony_ci if (!newst) { 3718c2ecf20Sopenharmony_ci printk(KERN_ERR "kmalloc mISDN_stack failed\n"); 3728c2ecf20Sopenharmony_ci return -ENOMEM; 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci newst->dev = dev; 3758c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&newst->layer2); 3768c2ecf20Sopenharmony_ci INIT_HLIST_HEAD(&newst->l1sock.head); 3778c2ecf20Sopenharmony_ci rwlock_init(&newst->l1sock.lock); 3788c2ecf20Sopenharmony_ci init_waitqueue_head(&newst->workq); 3798c2ecf20Sopenharmony_ci skb_queue_head_init(&newst->msgq); 3808c2ecf20Sopenharmony_ci mutex_init(&newst->lmutex); 3818c2ecf20Sopenharmony_ci dev->D.st = newst; 3828c2ecf20Sopenharmony_ci err = create_teimanager(dev); 3838c2ecf20Sopenharmony_ci if (err) { 3848c2ecf20Sopenharmony_ci printk(KERN_ERR "kmalloc teimanager failed\n"); 3858c2ecf20Sopenharmony_ci kfree(newst); 3868c2ecf20Sopenharmony_ci return err; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci dev->teimgr->peer = &newst->own; 3898c2ecf20Sopenharmony_ci dev->teimgr->recv = mISDN_queue_message; 3908c2ecf20Sopenharmony_ci dev->teimgr->st = newst; 3918c2ecf20Sopenharmony_ci newst->layer1 = &dev->D; 3928c2ecf20Sopenharmony_ci dev->D.recv = l1_receive; 3938c2ecf20Sopenharmony_ci dev->D.peer = &newst->own; 3948c2ecf20Sopenharmony_ci newst->own.st = newst; 3958c2ecf20Sopenharmony_ci newst->own.ctrl = st_own_ctrl; 3968c2ecf20Sopenharmony_ci newst->own.send = mISDN_queue_message; 3978c2ecf20Sopenharmony_ci newst->own.recv = mISDN_queue_message; 3988c2ecf20Sopenharmony_ci if (*debug & DEBUG_CORE_FUNC) 3998c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: st(%s)\n", __func__, 4008c2ecf20Sopenharmony_ci dev_name(&newst->dev->dev)); 4018c2ecf20Sopenharmony_ci newst->notify = &done; 4028c2ecf20Sopenharmony_ci newst->thread = kthread_run(mISDNStackd, (void *)newst, "mISDN_%s", 4038c2ecf20Sopenharmony_ci dev_name(&newst->dev->dev)); 4048c2ecf20Sopenharmony_ci if (IS_ERR(newst->thread)) { 4058c2ecf20Sopenharmony_ci err = PTR_ERR(newst->thread); 4068c2ecf20Sopenharmony_ci printk(KERN_ERR 4078c2ecf20Sopenharmony_ci "mISDN:cannot create kernel thread for %s (%d)\n", 4088c2ecf20Sopenharmony_ci dev_name(&newst->dev->dev), err); 4098c2ecf20Sopenharmony_ci delete_teimanager(dev->teimgr); 4108c2ecf20Sopenharmony_ci kfree(newst); 4118c2ecf20Sopenharmony_ci } else 4128c2ecf20Sopenharmony_ci wait_for_completion(&done); 4138c2ecf20Sopenharmony_ci return err; 4148c2ecf20Sopenharmony_ci} 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ciint 4178c2ecf20Sopenharmony_ciconnect_layer1(struct mISDNdevice *dev, struct mISDNchannel *ch, 4188c2ecf20Sopenharmony_ci u_int protocol, struct sockaddr_mISDN *adr) 4198c2ecf20Sopenharmony_ci{ 4208c2ecf20Sopenharmony_ci struct mISDN_sock *msk = container_of(ch, struct mISDN_sock, ch); 4218c2ecf20Sopenharmony_ci struct channel_req rq; 4228c2ecf20Sopenharmony_ci int err; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (*debug & DEBUG_CORE_FUNC) 4268c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n", 4278c2ecf20Sopenharmony_ci __func__, dev_name(&dev->dev), protocol, adr->dev, 4288c2ecf20Sopenharmony_ci adr->channel, adr->sapi, adr->tei); 4298c2ecf20Sopenharmony_ci switch (protocol) { 4308c2ecf20Sopenharmony_ci case ISDN_P_NT_S0: 4318c2ecf20Sopenharmony_ci case ISDN_P_NT_E1: 4328c2ecf20Sopenharmony_ci case ISDN_P_TE_S0: 4338c2ecf20Sopenharmony_ci case ISDN_P_TE_E1: 4348c2ecf20Sopenharmony_ci ch->recv = mISDN_queue_message; 4358c2ecf20Sopenharmony_ci ch->peer = &dev->D.st->own; 4368c2ecf20Sopenharmony_ci ch->st = dev->D.st; 4378c2ecf20Sopenharmony_ci rq.protocol = protocol; 4388c2ecf20Sopenharmony_ci rq.adr.channel = adr->channel; 4398c2ecf20Sopenharmony_ci err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq); 4408c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: ret %d (dev %d)\n", __func__, err, 4418c2ecf20Sopenharmony_ci dev->id); 4428c2ecf20Sopenharmony_ci if (err) 4438c2ecf20Sopenharmony_ci return err; 4448c2ecf20Sopenharmony_ci write_lock_bh(&dev->D.st->l1sock.lock); 4458c2ecf20Sopenharmony_ci sk_add_node(&msk->sk, &dev->D.st->l1sock.head); 4468c2ecf20Sopenharmony_ci write_unlock_bh(&dev->D.st->l1sock.lock); 4478c2ecf20Sopenharmony_ci break; 4488c2ecf20Sopenharmony_ci default: 4498c2ecf20Sopenharmony_ci return -ENOPROTOOPT; 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci return 0; 4528c2ecf20Sopenharmony_ci} 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ciint 4558c2ecf20Sopenharmony_ciconnect_Bstack(struct mISDNdevice *dev, struct mISDNchannel *ch, 4568c2ecf20Sopenharmony_ci u_int protocol, struct sockaddr_mISDN *adr) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci struct channel_req rq, rq2; 4598c2ecf20Sopenharmony_ci int pmask, err; 4608c2ecf20Sopenharmony_ci struct Bprotocol *bp; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci if (*debug & DEBUG_CORE_FUNC) 4638c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n", 4648c2ecf20Sopenharmony_ci __func__, dev_name(&dev->dev), protocol, 4658c2ecf20Sopenharmony_ci adr->dev, adr->channel, adr->sapi, 4668c2ecf20Sopenharmony_ci adr->tei); 4678c2ecf20Sopenharmony_ci ch->st = dev->D.st; 4688c2ecf20Sopenharmony_ci pmask = 1 << (protocol & ISDN_P_B_MASK); 4698c2ecf20Sopenharmony_ci if (pmask & dev->Bprotocols) { 4708c2ecf20Sopenharmony_ci rq.protocol = protocol; 4718c2ecf20Sopenharmony_ci rq.adr = *adr; 4728c2ecf20Sopenharmony_ci err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq); 4738c2ecf20Sopenharmony_ci if (err) 4748c2ecf20Sopenharmony_ci return err; 4758c2ecf20Sopenharmony_ci ch->recv = rq.ch->send; 4768c2ecf20Sopenharmony_ci ch->peer = rq.ch; 4778c2ecf20Sopenharmony_ci rq.ch->recv = ch->send; 4788c2ecf20Sopenharmony_ci rq.ch->peer = ch; 4798c2ecf20Sopenharmony_ci rq.ch->st = dev->D.st; 4808c2ecf20Sopenharmony_ci } else { 4818c2ecf20Sopenharmony_ci bp = get_Bprotocol4mask(pmask); 4828c2ecf20Sopenharmony_ci if (!bp) 4838c2ecf20Sopenharmony_ci return -ENOPROTOOPT; 4848c2ecf20Sopenharmony_ci rq2.protocol = protocol; 4858c2ecf20Sopenharmony_ci rq2.adr = *adr; 4868c2ecf20Sopenharmony_ci rq2.ch = ch; 4878c2ecf20Sopenharmony_ci err = bp->create(&rq2); 4888c2ecf20Sopenharmony_ci if (err) 4898c2ecf20Sopenharmony_ci return err; 4908c2ecf20Sopenharmony_ci ch->recv = rq2.ch->send; 4918c2ecf20Sopenharmony_ci ch->peer = rq2.ch; 4928c2ecf20Sopenharmony_ci rq2.ch->st = dev->D.st; 4938c2ecf20Sopenharmony_ci rq.protocol = rq2.protocol; 4948c2ecf20Sopenharmony_ci rq.adr = *adr; 4958c2ecf20Sopenharmony_ci err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq); 4968c2ecf20Sopenharmony_ci if (err) { 4978c2ecf20Sopenharmony_ci rq2.ch->ctrl(rq2.ch, CLOSE_CHANNEL, NULL); 4988c2ecf20Sopenharmony_ci return err; 4998c2ecf20Sopenharmony_ci } 5008c2ecf20Sopenharmony_ci rq2.ch->recv = rq.ch->send; 5018c2ecf20Sopenharmony_ci rq2.ch->peer = rq.ch; 5028c2ecf20Sopenharmony_ci rq.ch->recv = rq2.ch->send; 5038c2ecf20Sopenharmony_ci rq.ch->peer = rq2.ch; 5048c2ecf20Sopenharmony_ci rq.ch->st = dev->D.st; 5058c2ecf20Sopenharmony_ci } 5068c2ecf20Sopenharmony_ci ch->protocol = protocol; 5078c2ecf20Sopenharmony_ci ch->nr = rq.ch->nr; 5088c2ecf20Sopenharmony_ci return 0; 5098c2ecf20Sopenharmony_ci} 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ciint 5128c2ecf20Sopenharmony_cicreate_l2entity(struct mISDNdevice *dev, struct mISDNchannel *ch, 5138c2ecf20Sopenharmony_ci u_int protocol, struct sockaddr_mISDN *adr) 5148c2ecf20Sopenharmony_ci{ 5158c2ecf20Sopenharmony_ci struct channel_req rq; 5168c2ecf20Sopenharmony_ci int err; 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci if (*debug & DEBUG_CORE_FUNC) 5198c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n", 5208c2ecf20Sopenharmony_ci __func__, dev_name(&dev->dev), protocol, 5218c2ecf20Sopenharmony_ci adr->dev, adr->channel, adr->sapi, 5228c2ecf20Sopenharmony_ci adr->tei); 5238c2ecf20Sopenharmony_ci rq.protocol = ISDN_P_TE_S0; 5248c2ecf20Sopenharmony_ci if (dev->Dprotocols & (1 << ISDN_P_TE_E1)) 5258c2ecf20Sopenharmony_ci rq.protocol = ISDN_P_TE_E1; 5268c2ecf20Sopenharmony_ci switch (protocol) { 5278c2ecf20Sopenharmony_ci case ISDN_P_LAPD_NT: 5288c2ecf20Sopenharmony_ci rq.protocol = ISDN_P_NT_S0; 5298c2ecf20Sopenharmony_ci if (dev->Dprotocols & (1 << ISDN_P_NT_E1)) 5308c2ecf20Sopenharmony_ci rq.protocol = ISDN_P_NT_E1; 5318c2ecf20Sopenharmony_ci fallthrough; 5328c2ecf20Sopenharmony_ci case ISDN_P_LAPD_TE: 5338c2ecf20Sopenharmony_ci ch->recv = mISDN_queue_message; 5348c2ecf20Sopenharmony_ci ch->peer = &dev->D.st->own; 5358c2ecf20Sopenharmony_ci ch->st = dev->D.st; 5368c2ecf20Sopenharmony_ci rq.adr.channel = 0; 5378c2ecf20Sopenharmony_ci err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq); 5388c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: ret 1 %d\n", __func__, err); 5398c2ecf20Sopenharmony_ci if (err) 5408c2ecf20Sopenharmony_ci break; 5418c2ecf20Sopenharmony_ci rq.protocol = protocol; 5428c2ecf20Sopenharmony_ci rq.adr = *adr; 5438c2ecf20Sopenharmony_ci rq.ch = ch; 5448c2ecf20Sopenharmony_ci err = dev->teimgr->ctrl(dev->teimgr, OPEN_CHANNEL, &rq); 5458c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: ret 2 %d\n", __func__, err); 5468c2ecf20Sopenharmony_ci if (!err) { 5478c2ecf20Sopenharmony_ci if ((protocol == ISDN_P_LAPD_NT) && !rq.ch) 5488c2ecf20Sopenharmony_ci break; 5498c2ecf20Sopenharmony_ci add_layer2(rq.ch, dev->D.st); 5508c2ecf20Sopenharmony_ci rq.ch->recv = mISDN_queue_message; 5518c2ecf20Sopenharmony_ci rq.ch->peer = &dev->D.st->own; 5528c2ecf20Sopenharmony_ci rq.ch->ctrl(rq.ch, OPEN_CHANNEL, NULL); /* can't fail */ 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci break; 5558c2ecf20Sopenharmony_ci default: 5568c2ecf20Sopenharmony_ci err = -EPROTONOSUPPORT; 5578c2ecf20Sopenharmony_ci } 5588c2ecf20Sopenharmony_ci return err; 5598c2ecf20Sopenharmony_ci} 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_civoid 5628c2ecf20Sopenharmony_cidelete_channel(struct mISDNchannel *ch) 5638c2ecf20Sopenharmony_ci{ 5648c2ecf20Sopenharmony_ci struct mISDN_sock *msk = container_of(ch, struct mISDN_sock, ch); 5658c2ecf20Sopenharmony_ci struct mISDNchannel *pch; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci if (!ch->st) { 5688c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: no stack\n", __func__); 5698c2ecf20Sopenharmony_ci return; 5708c2ecf20Sopenharmony_ci } 5718c2ecf20Sopenharmony_ci if (*debug & DEBUG_CORE_FUNC) 5728c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: st(%s) protocol(%x)\n", __func__, 5738c2ecf20Sopenharmony_ci dev_name(&ch->st->dev->dev), ch->protocol); 5748c2ecf20Sopenharmony_ci if (ch->protocol >= ISDN_P_B_START) { 5758c2ecf20Sopenharmony_ci if (ch->peer) { 5768c2ecf20Sopenharmony_ci ch->peer->ctrl(ch->peer, CLOSE_CHANNEL, NULL); 5778c2ecf20Sopenharmony_ci ch->peer = NULL; 5788c2ecf20Sopenharmony_ci } 5798c2ecf20Sopenharmony_ci return; 5808c2ecf20Sopenharmony_ci } 5818c2ecf20Sopenharmony_ci switch (ch->protocol) { 5828c2ecf20Sopenharmony_ci case ISDN_P_NT_S0: 5838c2ecf20Sopenharmony_ci case ISDN_P_TE_S0: 5848c2ecf20Sopenharmony_ci case ISDN_P_NT_E1: 5858c2ecf20Sopenharmony_ci case ISDN_P_TE_E1: 5868c2ecf20Sopenharmony_ci write_lock_bh(&ch->st->l1sock.lock); 5878c2ecf20Sopenharmony_ci sk_del_node_init(&msk->sk); 5888c2ecf20Sopenharmony_ci write_unlock_bh(&ch->st->l1sock.lock); 5898c2ecf20Sopenharmony_ci ch->st->dev->D.ctrl(&ch->st->dev->D, CLOSE_CHANNEL, NULL); 5908c2ecf20Sopenharmony_ci break; 5918c2ecf20Sopenharmony_ci case ISDN_P_LAPD_TE: 5928c2ecf20Sopenharmony_ci pch = get_channel4id(ch->st, ch->nr); 5938c2ecf20Sopenharmony_ci if (pch) { 5948c2ecf20Sopenharmony_ci mutex_lock(&ch->st->lmutex); 5958c2ecf20Sopenharmony_ci list_del(&pch->list); 5968c2ecf20Sopenharmony_ci mutex_unlock(&ch->st->lmutex); 5978c2ecf20Sopenharmony_ci pch->ctrl(pch, CLOSE_CHANNEL, NULL); 5988c2ecf20Sopenharmony_ci pch = ch->st->dev->teimgr; 5998c2ecf20Sopenharmony_ci pch->ctrl(pch, CLOSE_CHANNEL, NULL); 6008c2ecf20Sopenharmony_ci } else 6018c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: no l2 channel\n", 6028c2ecf20Sopenharmony_ci __func__); 6038c2ecf20Sopenharmony_ci break; 6048c2ecf20Sopenharmony_ci case ISDN_P_LAPD_NT: 6058c2ecf20Sopenharmony_ci pch = ch->st->dev->teimgr; 6068c2ecf20Sopenharmony_ci if (pch) { 6078c2ecf20Sopenharmony_ci pch->ctrl(pch, CLOSE_CHANNEL, NULL); 6088c2ecf20Sopenharmony_ci } else 6098c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: no l2 channel\n", 6108c2ecf20Sopenharmony_ci __func__); 6118c2ecf20Sopenharmony_ci break; 6128c2ecf20Sopenharmony_ci default: 6138c2ecf20Sopenharmony_ci break; 6148c2ecf20Sopenharmony_ci } 6158c2ecf20Sopenharmony_ci return; 6168c2ecf20Sopenharmony_ci} 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_civoid 6198c2ecf20Sopenharmony_cidelete_stack(struct mISDNdevice *dev) 6208c2ecf20Sopenharmony_ci{ 6218c2ecf20Sopenharmony_ci struct mISDNstack *st = dev->D.st; 6228c2ecf20Sopenharmony_ci DECLARE_COMPLETION_ONSTACK(done); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci if (*debug & DEBUG_CORE_FUNC) 6258c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: st(%s)\n", __func__, 6268c2ecf20Sopenharmony_ci dev_name(&st->dev->dev)); 6278c2ecf20Sopenharmony_ci if (dev->teimgr) 6288c2ecf20Sopenharmony_ci delete_teimanager(dev->teimgr); 6298c2ecf20Sopenharmony_ci if (st->thread) { 6308c2ecf20Sopenharmony_ci if (st->notify) { 6318c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: notifier in use\n", 6328c2ecf20Sopenharmony_ci __func__); 6338c2ecf20Sopenharmony_ci complete(st->notify); 6348c2ecf20Sopenharmony_ci } 6358c2ecf20Sopenharmony_ci st->notify = &done; 6368c2ecf20Sopenharmony_ci test_and_set_bit(mISDN_STACK_ABORT, &st->status); 6378c2ecf20Sopenharmony_ci test_and_set_bit(mISDN_STACK_WAKEUP, &st->status); 6388c2ecf20Sopenharmony_ci wake_up_interruptible(&st->workq); 6398c2ecf20Sopenharmony_ci wait_for_completion(&done); 6408c2ecf20Sopenharmony_ci } 6418c2ecf20Sopenharmony_ci if (!list_empty(&st->layer2)) 6428c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: layer2 list not empty\n", 6438c2ecf20Sopenharmony_ci __func__); 6448c2ecf20Sopenharmony_ci if (!hlist_empty(&st->l1sock.head)) 6458c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s: layer1 list not empty\n", 6468c2ecf20Sopenharmony_ci __func__); 6478c2ecf20Sopenharmony_ci kfree(st); 6488c2ecf20Sopenharmony_ci} 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_civoid 6518c2ecf20Sopenharmony_cimISDN_initstack(u_int *dp) 6528c2ecf20Sopenharmony_ci{ 6538c2ecf20Sopenharmony_ci debug = dp; 6548c2ecf20Sopenharmony_ci} 655