11b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil/* 21b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil * 31b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil * Author Karsten Keil <kkeil@novell.com> 41b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil * 51b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil * Copyright 2008 by Karsten Keil <kkeil@novell.com> 61b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil * 71b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil * This program is free software; you can redistribute it and/or modify 81b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil * it under the terms of the GNU General Public License version 2 as 91b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil * published by the Free Software Foundation. 101b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil * 111b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil * This program is distributed in the hope that it will be useful, 121b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil * but WITHOUT ANY WARRANTY; without even the implied warranty of 131b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil * GNU General Public License for more details. 151b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil * 161b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil */ 171b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 185a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 191b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil#include <linux/mISDNif.h> 201b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil#include <linux/kthread.h> 211b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil#include "core.h" 221b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 231b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilstatic u_int *debug; 241b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 251b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilstatic inline void 261b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil_queue_message(struct mISDNstack *st, struct sk_buff *skb) 271b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 281b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct mISDNhead *hh = mISDN_HEAD_P(skb); 291b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 301b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (*debug & DEBUG_QUEUE_FUNC) 311b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG "%s prim(%x) id(%x) %p\n", 32475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, hh->prim, hh->id, skb); 331b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil skb_queue_tail(&st->msgq, skb); 341b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (likely(!test_bit(mISDN_STACK_STOPPED, &st->status))) { 351b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_set_bit(mISDN_STACK_WORK, &st->status); 361b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil wake_up_interruptible(&st->workq); 371b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 381b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 391b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 405b8343540a3d27f87a4d9d72bb39b7d4cc3dd95eHannes Ederstatic int 411b2b03f8e514e4f68e293846ba511a948b80243cKarsten KeilmISDN_queue_message(struct mISDNchannel *ch, struct sk_buff *skb) 421b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 431b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil _queue_message(ch->st, skb); 441b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return 0; 451b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 461b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 471b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilstatic struct mISDNchannel * 481b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilget_channel4id(struct mISDNstack *st, u_int id) 491b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 501b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct mISDNchannel *ch; 511b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 521b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil mutex_lock(&st->lmutex); 531b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil list_for_each_entry(ch, &st->layer2, list) { 541b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (id == ch->nr) 551b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil goto unlock; 561b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 571b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch = NULL; 581b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilunlock: 591b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil mutex_unlock(&st->lmutex); 601b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return ch; 611b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 621b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 631b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilstatic void 641b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilsend_socklist(struct mISDN_sock_list *sl, struct sk_buff *skb) 651b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 661b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct hlist_node *node; 671b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct sock *sk; 681b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct sk_buff *cskb = NULL; 691b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 701b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil read_lock(&sl->lock); 711b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil sk_for_each(sk, node, &sl->head) { 721b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (sk->sk_state != MISDN_BOUND) 731b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil continue; 741b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!cskb) 751b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil cskb = skb_copy(skb, GFP_KERNEL); 761b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!cskb) { 771b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_WARNING "%s no skb\n", __func__); 781b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil break; 791b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 801b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!sock_queue_rcv_skb(sk, cskb)) 811b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil cskb = NULL; 821b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 831b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil read_unlock(&sl->lock); 841b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (cskb) 851b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil dev_kfree_skb(cskb); 861b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 871b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 881b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilstatic void 891b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilsend_layer2(struct mISDNstack *st, struct sk_buff *skb) 901b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 911b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct sk_buff *cskb; 921b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct mISDNhead *hh = mISDN_HEAD_P(skb); 931b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct mISDNchannel *ch; 941b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil int ret; 951b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 961b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!st) 971b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return; 981b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil mutex_lock(&st->lmutex); 991b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if ((hh->id & MISDN_ID_ADDR_MASK) == MISDN_ID_ANY) { /* L2 for all */ 1001b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil list_for_each_entry(ch, &st->layer2, list) { 1011b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (list_is_last(&ch->list, &st->layer2)) { 1021b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil cskb = skb; 1031b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil skb = NULL; 1041b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } else { 1051b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil cskb = skb_copy(skb, GFP_KERNEL); 1061b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 1071b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (cskb) { 1081b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ret = ch->send(ch, cskb); 1091b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (ret) { 1101b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (*debug & DEBUG_SEND_ERR) 1111b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG 112475be4d85a274d0961593db41cf85689db1d583cJoe Perches "%s ch%d prim(%x) addr(%x)" 113475be4d85a274d0961593db41cf85689db1d583cJoe Perches " err %d\n", 114475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, ch->nr, 115475be4d85a274d0961593db41cf85689db1d583cJoe Perches hh->prim, ch->addr, ret); 1161b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil dev_kfree_skb(cskb); 1171b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 1181b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } else { 1191b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_WARNING "%s ch%d addr %x no mem\n", 120475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, ch->nr, ch->addr); 1211b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil goto out; 1221b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 1231b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 1241b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } else { 1251b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil list_for_each_entry(ch, &st->layer2, list) { 1261b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if ((hh->id & MISDN_ID_ADDR_MASK) == ch->addr) { 1271b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ret = ch->send(ch, skb); 1281b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!ret) 1291b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil skb = NULL; 1301b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil goto out; 1311b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 1321b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 1331b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ret = st->dev->teimgr->ctrl(st->dev->teimgr, CHECK_DATA, skb); 1341b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!ret) 1351b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil skb = NULL; 1361b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil else if (*debug & DEBUG_SEND_ERR) 1371b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG 138475be4d85a274d0961593db41cf85689db1d583cJoe Perches "%s ch%d mgr prim(%x) addr(%x) err %d\n", 139475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, ch->nr, hh->prim, ch->addr, ret); 1401b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 1411b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilout: 1421b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil mutex_unlock(&st->lmutex); 1431b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (skb) 1441b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil dev_kfree_skb(skb); 1451b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 1461b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 1471b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilstatic inline int 1481b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilsend_msg_to_layer(struct mISDNstack *st, struct sk_buff *skb) 1491b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 1501b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct mISDNhead *hh = mISDN_HEAD_P(skb); 1511b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct mISDNchannel *ch; 1521b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil int lm; 1531b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 1541b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil lm = hh->prim & MISDN_LAYERMASK; 1551b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (*debug & DEBUG_QUEUE_FUNC) 1561b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG "%s prim(%x) id(%x) %p\n", 157475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, hh->prim, hh->id, skb); 1581b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (lm == 0x1) { 1591b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!hlist_empty(&st->l1sock.head)) { 1601b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil __net_timestamp(skb); 1611b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil send_socklist(&st->l1sock, skb); 1621b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 1631b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return st->layer1->send(st->layer1, skb); 1641b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } else if (lm == 0x2) { 1651b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!hlist_empty(&st->l1sock.head)) 1661b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil send_socklist(&st->l1sock, skb); 1671b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil send_layer2(st, skb); 1681b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return 0; 1691b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } else if (lm == 0x4) { 1701b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch = get_channel4id(st, hh->id); 1711b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (ch) 1721b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return ch->send(ch, skb); 1731b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil else 1741b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_WARNING 175475be4d85a274d0961593db41cf85689db1d583cJoe Perches "%s: dev(%s) prim(%x) id(%x) no channel\n", 176475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, dev_name(&st->dev->dev), hh->prim, 177475be4d85a274d0961593db41cf85689db1d583cJoe Perches hh->id); 1781b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } else if (lm == 0x8) { 1791b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil WARN_ON(lm == 0x8); 1801b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch = get_channel4id(st, hh->id); 1811b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (ch) 1821b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return ch->send(ch, skb); 1831b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil else 1841b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_WARNING 185475be4d85a274d0961593db41cf85689db1d583cJoe Perches "%s: dev(%s) prim(%x) id(%x) no channel\n", 186475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, dev_name(&st->dev->dev), hh->prim, 187475be4d85a274d0961593db41cf85689db1d583cJoe Perches hh->id); 1881b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } else { 1891b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil /* broadcast not handled yet */ 1901b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_WARNING "%s: dev(%s) prim %x not delivered\n", 191475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, dev_name(&st->dev->dev), hh->prim); 1921b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 1931b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return -ESRCH; 1941b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 1951b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 1961b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilstatic void 1971b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keildo_clear_stack(struct mISDNstack *st) 1981b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 1991b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 2001b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 2011b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilstatic int 2021b2b03f8e514e4f68e293846ba511a948b80243cKarsten KeilmISDNStackd(void *data) 2031b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 2041b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct mISDNstack *st = data; 2051b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil int err = 0; 2061b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 2071b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil sigfillset(¤t->blocked); 2081b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (*debug & DEBUG_MSG_THREAD) 209837468d135dcc49cdabc9fa92fc9550479f60704Matthias Urlichs printk(KERN_DEBUG "mISDNStackd %s started\n", 210475be4d85a274d0961593db41cf85689db1d583cJoe Perches dev_name(&st->dev->dev)); 2111b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 2121b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (st->notify != NULL) { 2131b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil complete(st->notify); 2141b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil st->notify = NULL; 2151b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 2161b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 2171b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil for (;;) { 2181b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct sk_buff *skb; 2191b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 2201b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (unlikely(test_bit(mISDN_STACK_STOPPED, &st->status))) { 2211b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_clear_bit(mISDN_STACK_WORK, &st->status); 2221b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_clear_bit(mISDN_STACK_RUNNING, &st->status); 2231b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } else 2241b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_set_bit(mISDN_STACK_RUNNING, &st->status); 2251b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil while (test_bit(mISDN_STACK_WORK, &st->status)) { 2261b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil skb = skb_dequeue(&st->msgq); 2271b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!skb) { 2281b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_clear_bit(mISDN_STACK_WORK, 229475be4d85a274d0961593db41cf85689db1d583cJoe Perches &st->status); 2301b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil /* test if a race happens */ 2311b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil skb = skb_dequeue(&st->msgq); 2321b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!skb) 2331b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil continue; 2341b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_set_bit(mISDN_STACK_WORK, 235475be4d85a274d0961593db41cf85689db1d583cJoe Perches &st->status); 2361b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 2371b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil#ifdef MISDN_MSG_STATS 2381b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil st->msg_cnt++; 2391b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil#endif 2401b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil err = send_msg_to_layer(st, skb); 2411b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (unlikely(err)) { 2421b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (*debug & DEBUG_SEND_ERR) 2431b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG 244475be4d85a274d0961593db41cf85689db1d583cJoe Perches "%s: %s prim(%x) id(%x) " 245475be4d85a274d0961593db41cf85689db1d583cJoe Perches "send call(%d)\n", 246475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, dev_name(&st->dev->dev), 247475be4d85a274d0961593db41cf85689db1d583cJoe Perches mISDN_HEAD_PRIM(skb), 248475be4d85a274d0961593db41cf85689db1d583cJoe Perches mISDN_HEAD_ID(skb), err); 2491b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil dev_kfree_skb(skb); 2501b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil continue; 2511b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 2521b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (unlikely(test_bit(mISDN_STACK_STOPPED, 253475be4d85a274d0961593db41cf85689db1d583cJoe Perches &st->status))) { 2541b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_clear_bit(mISDN_STACK_WORK, 255475be4d85a274d0961593db41cf85689db1d583cJoe Perches &st->status); 2561b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_clear_bit(mISDN_STACK_RUNNING, 257475be4d85a274d0961593db41cf85689db1d583cJoe Perches &st->status); 2581b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil break; 2591b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 2601b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 2611b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (test_bit(mISDN_STACK_CLEARING, &st->status)) { 2621b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_set_bit(mISDN_STACK_STOPPED, &st->status); 2631b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_clear_bit(mISDN_STACK_RUNNING, &st->status); 2641b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil do_clear_stack(st); 2651b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_clear_bit(mISDN_STACK_CLEARING, &st->status); 2661b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_set_bit(mISDN_STACK_RESTART, &st->status); 2671b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 2681b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (test_and_clear_bit(mISDN_STACK_RESTART, &st->status)) { 2691b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_clear_bit(mISDN_STACK_STOPPED, &st->status); 2701b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_set_bit(mISDN_STACK_RUNNING, &st->status); 2711b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!skb_queue_empty(&st->msgq)) 2721b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_set_bit(mISDN_STACK_WORK, 273475be4d85a274d0961593db41cf85689db1d583cJoe Perches &st->status); 2741b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 2751b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (test_bit(mISDN_STACK_ABORT, &st->status)) 2761b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil break; 2771b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (st->notify != NULL) { 2781b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil complete(st->notify); 2791b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil st->notify = NULL; 2801b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 2811b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil#ifdef MISDN_MSG_STATS 2821b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil st->sleep_cnt++; 2831b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil#endif 2841b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_clear_bit(mISDN_STACK_ACTIVE, &st->status); 2851b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil wait_event_interruptible(st->workq, (st->status & 286475be4d85a274d0961593db41cf85689db1d583cJoe Perches mISDN_STACK_ACTION_MASK)); 2871b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (*debug & DEBUG_MSG_THREAD) 2881b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG "%s: %s wake status %08lx\n", 289475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, dev_name(&st->dev->dev), st->status); 2901b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_set_bit(mISDN_STACK_ACTIVE, &st->status); 2911b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 2921b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_clear_bit(mISDN_STACK_WAKEUP, &st->status); 2931b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 2941b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (test_bit(mISDN_STACK_STOPPED, &st->status)) { 2951b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_clear_bit(mISDN_STACK_RUNNING, &st->status); 2961b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil#ifdef MISDN_MSG_STATS 2971b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil st->stopped_cnt++; 2981b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil#endif 2991b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 3001b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 3011b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil#ifdef MISDN_MSG_STATS 3021b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG "mISDNStackd daemon for %s proceed %d " 303475be4d85a274d0961593db41cf85689db1d583cJoe Perches "msg %d sleep %d stopped\n", 304475be4d85a274d0961593db41cf85689db1d583cJoe Perches dev_name(&st->dev->dev), st->msg_cnt, st->sleep_cnt, 305475be4d85a274d0961593db41cf85689db1d583cJoe Perches st->stopped_cnt); 3061b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG 307475be4d85a274d0961593db41cf85689db1d583cJoe Perches "mISDNStackd daemon for %s utime(%ld) stime(%ld)\n", 308475be4d85a274d0961593db41cf85689db1d583cJoe Perches dev_name(&st->dev->dev), st->thread->utime, st->thread->stime); 3091b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG 310475be4d85a274d0961593db41cf85689db1d583cJoe Perches "mISDNStackd daemon for %s nvcsw(%ld) nivcsw(%ld)\n", 311475be4d85a274d0961593db41cf85689db1d583cJoe Perches dev_name(&st->dev->dev), st->thread->nvcsw, st->thread->nivcsw); 3121b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG "mISDNStackd daemon for %s killed now\n", 313475be4d85a274d0961593db41cf85689db1d583cJoe Perches dev_name(&st->dev->dev)); 3141b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil#endif 3151b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_set_bit(mISDN_STACK_KILLED, &st->status); 3161b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_clear_bit(mISDN_STACK_RUNNING, &st->status); 3171b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_clear_bit(mISDN_STACK_ACTIVE, &st->status); 3181b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_clear_bit(mISDN_STACK_ABORT, &st->status); 3191b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil skb_queue_purge(&st->msgq); 3201b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil st->thread = NULL; 3211b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (st->notify != NULL) { 3221b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil complete(st->notify); 3231b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil st->notify = NULL; 3241b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 3251b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return 0; 3261b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 3271b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 3281b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilstatic int 3291b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keill1_receive(struct mISDNchannel *ch, struct sk_buff *skb) 3301b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 3311b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!ch->st) 3321b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return -ENODEV; 3331b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil __net_timestamp(skb); 3341b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil _queue_message(ch->st, skb); 3351b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return 0; 3361b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 3371b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 3381b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilvoid 3391b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilset_channel_address(struct mISDNchannel *ch, u_int sapi, u_int tei) 3401b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 3411b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->addr = sapi | (tei << 8); 3421b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 3431b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 3441b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilvoid 3451b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil__add_layer2(struct mISDNchannel *ch, struct mISDNstack *st) 3461b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 3471b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil list_add_tail(&ch->list, &st->layer2); 3481b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 3491b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 3501b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilvoid 3511b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keiladd_layer2(struct mISDNchannel *ch, struct mISDNstack *st) 3521b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 3531b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil mutex_lock(&st->lmutex); 3541b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil __add_layer2(ch, st); 3551b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil mutex_unlock(&st->lmutex); 3561b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 3571b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 3581b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilstatic int 3591b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilst_own_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg) 3601b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 36108cb3f60b2f866c906a5a779444b30ba8f9a93c8Dan Carpenter if (!ch->st || !ch->st->layer1) 3621b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return -EINVAL; 3631b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return ch->st->layer1->ctrl(ch->st->layer1, cmd, arg); 3641b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 3651b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 3661b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilint 3671b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilcreate_stack(struct mISDNdevice *dev) 3681b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 3691b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct mISDNstack *newst; 3701b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil int err; 3711b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil DECLARE_COMPLETION_ONSTACK(done); 3721b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 3731b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil newst = kzalloc(sizeof(struct mISDNstack), GFP_KERNEL); 3741b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!newst) { 3751b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_ERR "kmalloc mISDN_stack failed\n"); 3761b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return -ENOMEM; 3771b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 3781b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil newst->dev = dev; 3791b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil INIT_LIST_HEAD(&newst->layer2); 3801b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil INIT_HLIST_HEAD(&newst->l1sock.head); 3811b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rwlock_init(&newst->l1sock.lock); 3821b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil init_waitqueue_head(&newst->workq); 3831b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil skb_queue_head_init(&newst->msgq); 3841b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil mutex_init(&newst->lmutex); 3851b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil dev->D.st = newst; 3861b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil err = create_teimanager(dev); 3871b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (err) { 3881b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_ERR "kmalloc teimanager failed\n"); 3891b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil kfree(newst); 3901b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return err; 3911b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 3921b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil dev->teimgr->peer = &newst->own; 3931b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil dev->teimgr->recv = mISDN_queue_message; 3941b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil dev->teimgr->st = newst; 3951b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil newst->layer1 = &dev->D; 3961b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil dev->D.recv = l1_receive; 3971b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil dev->D.peer = &newst->own; 3981b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil newst->own.st = newst; 3991b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil newst->own.ctrl = st_own_ctrl; 4001b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil newst->own.send = mISDN_queue_message; 4011b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil newst->own.recv = mISDN_queue_message; 4021b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (*debug & DEBUG_CORE_FUNC) 403837468d135dcc49cdabc9fa92fc9550479f60704Matthias Urlichs printk(KERN_DEBUG "%s: st(%s)\n", __func__, 404475be4d85a274d0961593db41cf85689db1d583cJoe Perches dev_name(&newst->dev->dev)); 4051b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil newst->notify = &done; 4061b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil newst->thread = kthread_run(mISDNStackd, (void *)newst, "mISDN_%s", 407475be4d85a274d0961593db41cf85689db1d583cJoe Perches dev_name(&newst->dev->dev)); 4081b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (IS_ERR(newst->thread)) { 4091b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil err = PTR_ERR(newst->thread); 4101b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_ERR 411475be4d85a274d0961593db41cf85689db1d583cJoe Perches "mISDN:cannot create kernel thread for %s (%d)\n", 412475be4d85a274d0961593db41cf85689db1d583cJoe Perches dev_name(&newst->dev->dev), err); 4131b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil delete_teimanager(dev->teimgr); 4141b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil kfree(newst); 4151b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } else 4161b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil wait_for_completion(&done); 4171b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return err; 4181b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 4191b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 4201b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilint 4211b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilconnect_layer1(struct mISDNdevice *dev, struct mISDNchannel *ch, 422475be4d85a274d0961593db41cf85689db1d583cJoe Perches u_int protocol, struct sockaddr_mISDN *adr) 4231b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 4241b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct mISDN_sock *msk = container_of(ch, struct mISDN_sock, ch); 4251b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct channel_req rq; 4261b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil int err; 4271b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 4281b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 4291b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (*debug & DEBUG_CORE_FUNC) 4301b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n", 431475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, dev_name(&dev->dev), protocol, adr->dev, 432475be4d85a274d0961593db41cf85689db1d583cJoe Perches adr->channel, adr->sapi, adr->tei); 4331b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil switch (protocol) { 4341b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil case ISDN_P_NT_S0: 4351b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil case ISDN_P_NT_E1: 4361b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil case ISDN_P_TE_S0: 4371b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil case ISDN_P_TE_E1: 4381b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->recv = mISDN_queue_message; 4391b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->peer = &dev->D.st->own; 4401b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->st = dev->D.st; 4411b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.protocol = protocol; 4421f28fa19d34c0d9186f274e61e4b3dcfc6428c5cMartin Bachem rq.adr.channel = adr->channel; 4431b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq); 4449a812553bdc097a566aa79df7fae3457449c555bAndreas Eversberg printk(KERN_DEBUG "%s: ret %d (dev %d)\n", __func__, err, 445475be4d85a274d0961593db41cf85689db1d583cJoe Perches dev->id); 4461b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (err) 4471b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return err; 4481b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil write_lock_bh(&dev->D.st->l1sock.lock); 4491b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil sk_add_node(&msk->sk, &dev->D.st->l1sock.head); 4501b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil write_unlock_bh(&dev->D.st->l1sock.lock); 4511b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil break; 4521b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil default: 4531b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return -ENOPROTOOPT; 4541b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 4551b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return 0; 4561b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 4571b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 4581b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilint 4591b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilconnect_Bstack(struct mISDNdevice *dev, struct mISDNchannel *ch, 460475be4d85a274d0961593db41cf85689db1d583cJoe Perches u_int protocol, struct sockaddr_mISDN *adr) 4611b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 4621b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct channel_req rq, rq2; 4631b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil int pmask, err; 4641b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct Bprotocol *bp; 4651b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 4661b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (*debug & DEBUG_CORE_FUNC) 4671b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n", 468475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, dev_name(&dev->dev), protocol, 469475be4d85a274d0961593db41cf85689db1d583cJoe Perches adr->dev, adr->channel, adr->sapi, 470475be4d85a274d0961593db41cf85689db1d583cJoe Perches adr->tei); 4711b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->st = dev->D.st; 4721b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil pmask = 1 << (protocol & ISDN_P_B_MASK); 4731b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (pmask & dev->Bprotocols) { 4741b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.protocol = protocol; 4751b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.adr = *adr; 4761b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq); 4771b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (err) 4781b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return err; 4791b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->recv = rq.ch->send; 4801b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->peer = rq.ch; 4811b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.ch->recv = ch->send; 4821b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.ch->peer = ch; 4831b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.ch->st = dev->D.st; 4841b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } else { 4851b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil bp = get_Bprotocol4mask(pmask); 4861b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!bp) 4871b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return -ENOPROTOOPT; 4881b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq2.protocol = protocol; 4891b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq2.adr = *adr; 4901b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq2.ch = ch; 4911b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil err = bp->create(&rq2); 4921b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (err) 4931b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return err; 4941b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->recv = rq2.ch->send; 4951b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->peer = rq2.ch; 4961b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq2.ch->st = dev->D.st; 4971b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.protocol = rq2.protocol; 4981b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.adr = *adr; 4991b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq); 5001b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (err) { 5011b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq2.ch->ctrl(rq2.ch, CLOSE_CHANNEL, NULL); 5021b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return err; 5031b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 5041b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq2.ch->recv = rq.ch->send; 5051b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq2.ch->peer = rq.ch; 5061b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.ch->recv = rq2.ch->send; 5071b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.ch->peer = rq2.ch; 5081b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.ch->st = dev->D.st; 5091b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 5101b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->protocol = protocol; 5111b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->nr = rq.ch->nr; 5121b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return 0; 5131b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 5141b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 5151b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilint 5161b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilcreate_l2entity(struct mISDNdevice *dev, struct mISDNchannel *ch, 517475be4d85a274d0961593db41cf85689db1d583cJoe Perches u_int protocol, struct sockaddr_mISDN *adr) 5181b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 5191b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct channel_req rq; 5201b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil int err; 5211b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 5221b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (*debug & DEBUG_CORE_FUNC) 5231b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n", 524475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, dev_name(&dev->dev), protocol, 525475be4d85a274d0961593db41cf85689db1d583cJoe Perches adr->dev, adr->channel, adr->sapi, 526475be4d85a274d0961593db41cf85689db1d583cJoe Perches adr->tei); 5271b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.protocol = ISDN_P_TE_S0; 5281b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (dev->Dprotocols & (1 << ISDN_P_TE_E1)) 5291b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.protocol = ISDN_P_TE_E1; 5301b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil switch (protocol) { 5311b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil case ISDN_P_LAPD_NT: 5321b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.protocol = ISDN_P_NT_S0; 5331b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (dev->Dprotocols & (1 << ISDN_P_NT_E1)) 5341b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.protocol = ISDN_P_NT_E1; 5351b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil case ISDN_P_LAPD_TE: 5361b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->recv = mISDN_queue_message; 5371b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->peer = &dev->D.st->own; 5381b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->st = dev->D.st; 5391b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.adr.channel = 0; 5401b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq); 5411b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG "%s: ret 1 %d\n", __func__, err); 5421b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (err) 5431b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil break; 5441b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.protocol = protocol; 5451b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.adr = *adr; 5461b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.ch = ch; 5471b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil err = dev->teimgr->ctrl(dev->teimgr, OPEN_CHANNEL, &rq); 5481b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG "%s: ret 2 %d\n", __func__, err); 5491b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!err) { 5501b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if ((protocol == ISDN_P_LAPD_NT) && !rq.ch) 5511b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil break; 5521b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil add_layer2(rq.ch, dev->D.st); 5531b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.ch->recv = mISDN_queue_message; 5541b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.ch->peer = &dev->D.st->own; 5551b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil rq.ch->ctrl(rq.ch, OPEN_CHANNEL, NULL); /* can't fail */ 5561b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 5571b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil break; 5581b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil default: 5591b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil err = -EPROTONOSUPPORT; 5601b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 5611b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return err; 5621b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 5631b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 5641b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilvoid 5651b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keildelete_channel(struct mISDNchannel *ch) 5661b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 5671b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct mISDN_sock *msk = container_of(ch, struct mISDN_sock, ch); 5681b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct mISDNchannel *pch; 5691b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 5701b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!ch->st) { 5711b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_WARNING "%s: no stack\n", __func__); 5721b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return; 5731b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 5741b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (*debug & DEBUG_CORE_FUNC) 5751b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG "%s: st(%s) protocol(%x)\n", __func__, 576475be4d85a274d0961593db41cf85689db1d583cJoe Perches dev_name(&ch->st->dev->dev), ch->protocol); 5771b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (ch->protocol >= ISDN_P_B_START) { 5781b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (ch->peer) { 5791b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->peer->ctrl(ch->peer, CLOSE_CHANNEL, NULL); 5801b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->peer = NULL; 5811b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 5821b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return; 5831b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 5841b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil switch (ch->protocol) { 5851b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil case ISDN_P_NT_S0: 5861b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil case ISDN_P_TE_S0: 5871b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil case ISDN_P_NT_E1: 5881b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil case ISDN_P_TE_E1: 5891b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil write_lock_bh(&ch->st->l1sock.lock); 5901b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil sk_del_node_init(&msk->sk); 5911b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil write_unlock_bh(&ch->st->l1sock.lock); 5921b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil ch->st->dev->D.ctrl(&ch->st->dev->D, CLOSE_CHANNEL, NULL); 5931b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil break; 5941b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil case ISDN_P_LAPD_TE: 5951b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil pch = get_channel4id(ch->st, ch->nr); 5961b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (pch) { 5971b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil mutex_lock(&ch->st->lmutex); 5981b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil list_del(&pch->list); 5991b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil mutex_unlock(&ch->st->lmutex); 6001b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil pch->ctrl(pch, CLOSE_CHANNEL, NULL); 6011b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil pch = ch->st->dev->teimgr; 6021b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil pch->ctrl(pch, CLOSE_CHANNEL, NULL); 6031b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } else 6041b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_WARNING "%s: no l2 channel\n", 605475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__); 6061b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil break; 6071b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil case ISDN_P_LAPD_NT: 6081b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil pch = ch->st->dev->teimgr; 6091b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (pch) { 6101b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil pch->ctrl(pch, CLOSE_CHANNEL, NULL); 6111b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } else 6121b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_WARNING "%s: no l2 channel\n", 613475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__); 6141b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil break; 6151b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil default: 6161b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil break; 6171b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 6181b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil return; 6191b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 6201b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 6211b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilvoid 6221b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keildelete_stack(struct mISDNdevice *dev) 6231b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 6241b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil struct mISDNstack *st = dev->D.st; 6251b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil DECLARE_COMPLETION_ONSTACK(done); 6261b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 6271b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (*debug & DEBUG_CORE_FUNC) 6281b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_DEBUG "%s: st(%s)\n", __func__, 629475be4d85a274d0961593db41cf85689db1d583cJoe Perches dev_name(&st->dev->dev)); 6301b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (dev->teimgr) 6311b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil delete_teimanager(dev->teimgr); 6321b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (st->thread) { 6331b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (st->notify) { 6341b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_WARNING "%s: notifier in use\n", 635475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__); 636475be4d85a274d0961593db41cf85689db1d583cJoe Perches complete(st->notify); 6371b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 6381b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil st->notify = &done; 6391b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_set_bit(mISDN_STACK_ABORT, &st->status); 6401b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil test_and_set_bit(mISDN_STACK_WAKEUP, &st->status); 6411b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil wake_up_interruptible(&st->workq); 6421b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil wait_for_completion(&done); 6431b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil } 6441b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!list_empty(&st->layer2)) 6451b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_WARNING "%s: layer2 list not empty\n", 646475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__); 6471b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil if (!hlist_empty(&st->l1sock.head)) 6481b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil printk(KERN_WARNING "%s: layer1 list not empty\n", 649475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__); 6501b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil kfree(st); 6511b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 6521b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil 6531b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keilvoid 6541b2b03f8e514e4f68e293846ba511a948b80243cKarsten KeilmISDN_initstack(u_int *dp) 6551b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil{ 6561b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil debug = dp; 6571b2b03f8e514e4f68e293846ba511a948b80243cKarsten Keil} 658