11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* $Id: isdnl3.c,v 2.22.2.3 2004/01/13 14:31:25 keil Exp $ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author Karsten Keil 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * based on the teles driver from Jan den Ouden 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright by Karsten Keil <keil@isdn4linux.de> 6475be4d85a274d0961593db41cf85689db1d583cJoe Perches * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software may be used and distributed according to the terms 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the GNU General Public License, incorporated herein by reference. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For changes and modifications please read 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Documentation/isdn/HiSax.cert 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thanks to Jan den Ouden 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fritz Elfert 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 195a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "hisax.h" 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "isdnl3.h" 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsconst char *l3_revision = "$Revision: 2.22.2.3 $"; 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct Fsm l3fsm; 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ST_L3_LC_REL, 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ST_L3_LC_ESTAB_WAIT, 30475be4d85a274d0961593db41cf85689db1d583cJoe Perches ST_L3_LC_REL_DELAY, 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ST_L3_LC_REL_WAIT, 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ST_L3_LC_ESTAB, 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35475be4d85a274d0961593db41cf85689db1d583cJoe Perches#define L3_STATE_COUNT (ST_L3_LC_ESTAB + 1) 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *strL3State[] = 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ST_L3_LC_REL", 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ST_L3_LC_ESTAB_WAIT", 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ST_L3_LC_REL_DELAY", 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ST_L3_LC_REL_WAIT", 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ST_L3_LC_ESTAB", 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EV_ESTABLISH_REQ, 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EV_ESTABLISH_IND, 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EV_ESTABLISH_CNF, 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EV_RELEASE_REQ, 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EV_RELEASE_CNF, 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EV_RELEASE_IND, 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EV_TIMEOUT, 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 56475be4d85a274d0961593db41cf85689db1d583cJoe Perches#define L3_EVENT_COUNT (EV_TIMEOUT + 1) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *strL3Event[] = 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EV_ESTABLISH_REQ", 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EV_ESTABLISH_IND", 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EV_ESTABLISH_CNF", 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EV_RELEASE_REQ", 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EV_RELEASE_CNF", 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EV_RELEASE_IND", 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EV_TIMEOUT", 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 69b9075fa968a0a4347aef35e235e2995c0e57ddddJoe Perchesstatic __printf(2, 3) void 70475be4d85a274d0961593db41cf85689db1d583cJoe Perches l3m_debug(struct FsmInst *fi, char *fmt, ...) 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_list args; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_start(args, fmt); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VHiSax_putstatus(st->l1.hardware, st->l3.debug_id, fmt, args); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_end(args); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu_char * 81475be4d85a274d0961593db41cf85689db1d583cJoe Perchesfindie(u_char *p, int size, u_char ie, int wanted_set) 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int l, codeset, maincodeset; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *pend = p + size; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* skip protocol discriminator, callref and message type */ 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p++; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l = (*p++) & 0xf; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p += l; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p++; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds codeset = 0; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maincodeset = 0; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* while there are bytes left... */ 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (p < pend) { 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((*p & 0xf0) == 0x90) { 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds codeset = *p & 0x07; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(*p & 0x08)) 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maincodeset = codeset; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*p & 0x80) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p++; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (codeset == wanted_set) { 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*p == ie) 105475be4d85a274d0961593db41cf85689db1d583cJoe Perches { /* improved length check (Werner Cornelius) */ 106475be4d85a274d0961593db41cf85689db1d583cJoe Perches if ((pend - p) < 2) 107475be4d85a274d0961593db41cf85689db1d583cJoe Perches return (NULL); 108475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (*(p + 1) > (pend - (p + 2))) 109475be4d85a274d0961593db41cf85689db1d583cJoe Perches return (NULL); 110475be4d85a274d0961593db41cf85689db1d583cJoe Perches return (p); 111475be4d85a274d0961593db41cf85689db1d583cJoe Perches } 112475be4d85a274d0961593db41cf85689db1d583cJoe Perches 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*p > ie) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (NULL); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p++; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l = *p++; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p += l; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds codeset = maincodeset; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (NULL); 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 126475be4d85a274d0961593db41cf85689db1d583cJoe Perchesgetcallref(u_char *p) 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int l, cr = 0; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p++; /* prot discr */ 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*p & 0xfe) /* wrong callref BRI only 1 octet*/ 132475be4d85a274d0961593db41cf85689db1d583cJoe Perches return (-2); 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l = 0xf & *p++; /* callref length */ 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!l) /* dummy CallRef */ 135475be4d85a274d0961593db41cf85689db1d583cJoe Perches return (-1); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cr = *p++; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cr); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int OrigCallRef = 0; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnewcallref(void) 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (OrigCallRef == 127) 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OrigCallRef = 1; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OrigCallRef++; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (OrigCallRef); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnewl3state(struct l3_process *pc, int state) 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pc->debug & L3_DEB_STATE) 156475be4d85a274d0961593db41cf85689db1d583cJoe Perches l3_debug(pc->st, "newstate cr %d %d --> %d", 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pc->callref & 0x7F, 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pc->state, state); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pc->state = state; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsL3ExpireTimer(struct L3Timer *t) 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->pc->st->lli.l4l3(t->pc->st, t->event, t->pc); 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsL3InitTimer(struct l3_process *pc, struct L3Timer *t) 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->pc = pc; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->tl.function = (void *) L3ExpireTimer; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->tl.data = (long) t; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(&t->tl); 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsL3DelTimer(struct L3Timer *t) 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&t->tl); 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsL3AddTimer(struct L3Timer *t, 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int millisec, int event) 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (timer_pending(&t->tl)) { 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "L3AddTimer: timer already active!\n"); 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(&t->tl); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->event = event; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->tl.expires = jiffies + (millisec * HZ) / 1000; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_timer(&t->tl); 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsStopAllL3Timer(struct l3_process *pc) 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds L3DelTimer(&pc->timer); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct sk_buff * 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl3_alloc_skb(int len) 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(skb = alloc_skb(len + MAX_HEADER_LEN, GFP_ATOMIC))) { 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "HiSax: No skb for D-channel\n"); 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (NULL); 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_reserve(skb, MAX_HEADER_LEN); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (skb); 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsno_l3_proto(struct PStack *st, int pr, void *arg) 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb = arg; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds HiSax_putstatus(st->l1.hardware, "L3", "no D protocol"); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb) { 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb(skb); 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsno_l3_proto_spec(struct PStack *st, isdn_ctrl *ic) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 231475be4d85a274d0961593db41cf85689db1d583cJoe Perches printk(KERN_WARNING "HiSax: no specific protocol handler for proto %lu\n", ic->arg & 0xFF); 232475be4d85a274d0961593db41cf85689db1d583cJoe Perches return (-1); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct l3_process 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*getl3proc(struct PStack *st, int cr) 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct l3_process *p = st->l3.proc; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (p) 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->callref == cr) 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (p); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = p->next; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (NULL); 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct l3_process 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*new_l3_process(struct PStack *st, int cr) 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct l3_process *p, *np; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(p = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) { 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "HiSax can't get memory for cr %d\n", cr); 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (NULL); 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!st->l3.proc) 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.proc = p; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np = st->l3.proc; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (np->next) 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np = np->next; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np->next = p; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->next = NULL; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->debug = st->l3.debug; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->callref = cr; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->state = 0; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->chan = NULL; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->st = st; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->N303 = st->l3.N303; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds L3InitTimer(p, &p->timer); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (p); 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsrelease_l3_process(struct l3_process *p) 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct l3_process *np, *pp = NULL; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!p) 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np = p->st->l3.proc; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (np) { 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (np == p) { 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds StopAllL3Timer(p); 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pp) 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pp->next = np->next; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (!(p->st->l3.proc = np->next) && 290475be4d85a274d0961593db41cf85689db1d583cJoe Perches !test_bit(FLG_PTP, &p->st->l2.flag)) { 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->debug) 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(p->st, "release_l3_process: last process"); 293b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller if (skb_queue_empty(&p->st->l3.squeue)) { 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->debug) 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(p->st, "release_l3_process: release link"); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->st->protocol != ISDN_PTYPE_NI1) 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&p->st->l3.l3m, EV_RELEASE_IND, NULL); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->debug) 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(p->st, "release_l3_process: not release link"); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 304475be4d85a274d0961593db41cf85689db1d583cJoe Perches } 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(p); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pp = np; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np = np->next; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "HiSax internal L3 error CR(%d) not in list\n", p->callref); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(p->st, "HiSax internal L3 error CR(%d) not in list", p->callref); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl3ml3p(struct PStack *st, int pr) 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct l3_process *p = st->l3.proc; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct l3_process *np; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (p) { 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* p might be kfreed under us, so we need to save where we want to go on */ 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np = p->next; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3ml3(st, pr, p); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = np; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetstack_l3dc(struct PStack *st, struct Channel *chanp) 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char tmp[64]; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.proc = NULL; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.global = NULL; 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_head_init(&st->l3.squeue); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.fsm = &l3fsm; 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.state = ST_L3_LC_REL; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.debug = 1; 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.userdata = st; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.userint = 0; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.printdebug = l3m_debug; 343475be4d85a274d0961593db41cf85689db1d583cJoe Perches FsmInitTimer(&st->l3.l3m, &st->l3.l3m_timer); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(st->l3.debug_id, "L3DC "); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->lli.l4l3_proto = no_l3_proto_spec; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 347475be4d85a274d0961593db41cf85689db1d583cJoe Perches#ifdef CONFIG_HISAX_EURO 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->protocol == ISDN_PTYPE_EURO) { 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setstack_dss1(st); 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 352475be4d85a274d0961593db41cf85689db1d583cJoe Perches#ifdef CONFIG_HISAX_NI1 353475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (st->protocol == ISDN_PTYPE_NI1) { 354475be4d85a274d0961593db41cf85689db1d583cJoe Perches setstack_ni1(st); 355475be4d85a274d0961593db41cf85689db1d583cJoe Perches } else 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 357475be4d85a274d0961593db41cf85689db1d583cJoe Perches#ifdef CONFIG_HISAX_1TR6 358475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (st->protocol == ISDN_PTYPE_1TR6) { 359475be4d85a274d0961593db41cf85689db1d583cJoe Perches setstack_1tr6(st); 360475be4d85a274d0961593db41cf85689db1d583cJoe Perches } else 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 362475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (st->protocol == ISDN_PTYPE_LEASED) { 363475be4d85a274d0961593db41cf85689db1d583cJoe Perches st->lli.l4l3 = no_l3_proto; 364475be4d85a274d0961593db41cf85689db1d583cJoe Perches st->l2.l2l3 = no_l3_proto; 365475be4d85a274d0961593db41cf85689db1d583cJoe Perches st->l3.l3ml3 = no_l3_proto; 366475be4d85a274d0961593db41cf85689db1d583cJoe Perches printk(KERN_INFO "HiSax: Leased line mode\n"); 367475be4d85a274d0961593db41cf85689db1d583cJoe Perches } else { 368475be4d85a274d0961593db41cf85689db1d583cJoe Perches st->lli.l4l3 = no_l3_proto; 369475be4d85a274d0961593db41cf85689db1d583cJoe Perches st->l2.l2l3 = no_l3_proto; 370475be4d85a274d0961593db41cf85689db1d583cJoe Perches st->l3.l3ml3 = no_l3_proto; 371475be4d85a274d0961593db41cf85689db1d583cJoe Perches sprintf(tmp, "protocol %s not supported", 372475be4d85a274d0961593db41cf85689db1d583cJoe Perches (st->protocol == ISDN_PTYPE_1TR6) ? "1tr6" : 373475be4d85a274d0961593db41cf85689db1d583cJoe Perches (st->protocol == ISDN_PTYPE_EURO) ? "euro" : 374475be4d85a274d0961593db41cf85689db1d583cJoe Perches (st->protocol == ISDN_PTYPE_NI1) ? "ni1" : 375475be4d85a274d0961593db41cf85689db1d583cJoe Perches "unknown"); 376475be4d85a274d0961593db41cf85689db1d583cJoe Perches printk(KERN_WARNING "HiSax: %s\n", tmp); 377475be4d85a274d0961593db41cf85689db1d583cJoe Perches st->protocol = -1; 378475be4d85a274d0961593db41cf85689db1d583cJoe Perches } 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic void 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsisdnl3_trans(struct PStack *st, int pr, void *arg) { 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3l2(st, pr, arg); 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreleasestack_isdnl3(struct PStack *st) 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (st->l3.proc) 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_l3_process(st->l3.proc); 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->l3.global) { 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds StopAllL3Timer(st->l3.global); 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(st->l3.global); 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.global = NULL; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmDelTimer(&st->l3.l3m_timer, 54); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_purge(&st->l3.squeue); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetstack_l3bc(struct PStack *st, struct Channel *chanp) 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.proc = NULL; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.global = NULL; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_head_init(&st->l3.squeue); 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.fsm = &l3fsm; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.state = ST_L3_LC_REL; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.debug = 1; 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.userdata = st; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.userint = 0; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.printdebug = l3m_debug; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(st->l3.debug_id, "L3BC "); 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->lli.l4l3 = isdnl3_trans; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DREL_TIMER_VALUE 40000 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_activate(struct FsmInst *fi, int event, void *arg) 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT); 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3l2(st, DL_ESTABLISH | REQUEST, NULL); 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_connect(struct FsmInst *fi, int event, void *arg) 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb = arg; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dequeued = 0; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmChangeState(fi, ST_L3_LC_ESTAB); 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((skb = skb_dequeue(&st->l3.squeue))) { 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3l2(st, DL_DATA | REQUEST, skb); 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dequeued++; 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((!st->l3.proc) && dequeued) { 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->l3.debug) 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(st, "lc_connect: release link"); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL); 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3ml3p(st, DL_ESTABLISH | INDICATION); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_connected(struct FsmInst *fi, int event, void *arg) 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb = arg; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dequeued = 0; 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmDelTimer(&st->l3.l3m_timer, 51); 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmChangeState(fi, ST_L3_LC_ESTAB); 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((skb = skb_dequeue(&st->l3.squeue))) { 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3l2(st, DL_DATA | REQUEST, skb); 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dequeued++; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((!st->l3.proc) && dequeued) { 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->l3.debug) 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(st, "lc_connected: release link"); 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL); 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3ml3p(st, DL_ESTABLISH | CONFIRM); 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_start_delay(struct FsmInst *fi, int event, void *arg) 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 472475be4d85a274d0961593db41cf85689db1d583cJoe Perches struct PStack *st = fi->userdata; 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 474475be4d85a274d0961593db41cf85689db1d583cJoe Perches FsmChangeState(fi, ST_L3_LC_REL_DELAY); 475475be4d85a274d0961593db41cf85689db1d583cJoe Perches FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50); 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_start_delay_check(struct FsmInst *fi, int event, void *arg) 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 20/09/00 - GE timer not user for NI-1 as layer 2 should stay up */ 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 482475be4d85a274d0961593db41cf85689db1d583cJoe Perches struct PStack *st = fi->userdata; 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 484475be4d85a274d0961593db41cf85689db1d583cJoe Perches FsmChangeState(fi, ST_L3_LC_REL_DELAY); 485475be4d85a274d0961593db41cf85689db1d583cJoe Perches /* 19/09/00 - GE timer not user for NI-1 */ 486475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (st->protocol != ISDN_PTYPE_NI1) 487475be4d85a274d0961593db41cf85689db1d583cJoe Perches FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50); 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_release_req(struct FsmInst *fi, int event, void *arg) 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_bit(FLG_L2BLOCK, &st->l2.flag)) { 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->l3.debug) 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(st, "lc_release_req: l2 blocked"); 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* restart release timer */ 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 51); 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmChangeState(fi, ST_L3_LC_REL_WAIT); 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL); 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_release_ind(struct FsmInst *fi, int event, void *arg) 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmDelTimer(&st->l3.l3m_timer, 52); 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmChangeState(fi, ST_L3_LC_REL); 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_purge(&st->l3.squeue); 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3ml3p(st, DL_RELEASE | INDICATION); 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_release_cnf(struct FsmInst *fi, int event, void *arg) 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmChangeState(fi, ST_L3_LC_REL); 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_purge(&st->l3.squeue); 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3ml3p(st, DL_RELEASE | CONFIRM); 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* *INDENT-OFF* */ 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct FsmNode L3FnList[] __initdata = 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_REL, EV_ESTABLISH_REQ, lc_activate}, 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_REL, EV_ESTABLISH_IND, lc_connect}, 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_REL, EV_ESTABLISH_CNF, lc_connect}, 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_ESTAB_WAIT, EV_ESTABLISH_CNF, lc_connected}, 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_REQ, lc_start_delay}, 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_IND, lc_release_ind}, 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_ESTAB, EV_RELEASE_IND, lc_release_ind}, 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_ESTAB, EV_RELEASE_REQ, lc_start_delay_check}, 539475be4d85a274d0961593db41cf85689db1d583cJoe Perches {ST_L3_LC_REL_DELAY, EV_RELEASE_IND, lc_release_ind}, 540475be4d85a274d0961593db41cf85689db1d583cJoe Perches {ST_L3_LC_REL_DELAY, EV_ESTABLISH_REQ, lc_connected}, 541475be4d85a274d0961593db41cf85689db1d583cJoe Perches {ST_L3_LC_REL_DELAY, EV_TIMEOUT, lc_release_req}, 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_REL_WAIT, EV_RELEASE_CNF, lc_release_cnf}, 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_REL_WAIT, EV_ESTABLISH_REQ, lc_activate}, 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* *INDENT-ON* */ 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl3_msg(struct PStack *st, int pr, void *arg) 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (pr) { 551475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (DL_DATA | REQUEST): 552475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (st->l3.l3m.state == ST_L3_LC_ESTAB) { 553475be4d85a274d0961593db41cf85689db1d583cJoe Perches st->l3.l3l2(st, pr, arg); 554475be4d85a274d0961593db41cf85689db1d583cJoe Perches } else { 555475be4d85a274d0961593db41cf85689db1d583cJoe Perches struct sk_buff *skb = arg; 556475be4d85a274d0961593db41cf85689db1d583cJoe Perches 557475be4d85a274d0961593db41cf85689db1d583cJoe Perches skb_queue_tail(&st->l3.squeue, skb); 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL); 559475be4d85a274d0961593db41cf85689db1d583cJoe Perches } 560475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 561475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (DL_ESTABLISH | REQUEST): 562475be4d85a274d0961593db41cf85689db1d583cJoe Perches FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL); 563475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 564475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (DL_ESTABLISH | CONFIRM): 565475be4d85a274d0961593db41cf85689db1d583cJoe Perches FsmEvent(&st->l3.l3m, EV_ESTABLISH_CNF, NULL); 566475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 567475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (DL_ESTABLISH | INDICATION): 568475be4d85a274d0961593db41cf85689db1d583cJoe Perches FsmEvent(&st->l3.l3m, EV_ESTABLISH_IND, NULL); 569475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 570475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (DL_RELEASE | INDICATION): 571475be4d85a274d0961593db41cf85689db1d583cJoe Perches FsmEvent(&st->l3.l3m, EV_RELEASE_IND, NULL); 572475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 573475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (DL_RELEASE | CONFIRM): 574475be4d85a274d0961593db41cf85689db1d583cJoe Perches FsmEvent(&st->l3.l3m, EV_RELEASE_CNF, NULL); 575475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 576475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (DL_RELEASE | REQUEST): 577475be4d85a274d0961593db41cf85689db1d583cJoe Perches FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL); 578475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsdnl3New(void) 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3fsm.state_count = L3_STATE_COUNT; 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3fsm.event_count = L3_EVENT_COUNT; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3fsm.strEvent = strL3Event; 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3fsm.strState = strL3State; 589ba2d6ccb1df6ebb2c1b2322518ce7be25c1e3469Karsten Keil return FsmNew(&l3fsm, L3FnList, ARRAY_SIZE(L3FnList)); 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsdnl3Free(void) 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmFree(&l3fsm); 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 597