11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* $Id: isdnl2.c,v 2.30.2.4 2004/02/11 13:21:34 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/gfp.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "hisax.h"
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "isdnl2.h"
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsconst char *l2_revision = "$Revision: 2.30.2.4 $";
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void l2m_debug(struct FsmInst *fi, char *fmt, ...);
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct Fsm l2fsm;
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum {
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_1,
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_2,
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_3,
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_4,
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_5,
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_6,
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_7,
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_8,
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40475be4d85a274d0961593db41cf85689db1d583cJoe Perches#define L2_STATE_COUNT (ST_L2_8 + 1)
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *strL2State[] =
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_1",
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_2",
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_3",
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_4",
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_5",
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_6",
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_7",
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_8",
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum {
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_UI,
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_SABME,
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_DISC,
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_DM,
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_UA,
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_FRMR,
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_SUPER,
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_I,
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_DL_DATA,
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_ACK_PULL,
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_DL_UNIT_DATA,
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_DL_ESTABLISH_REQ,
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_DL_RELEASE_REQ,
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_MDL_ASSIGN,
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_MDL_REMOVE,
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_MDL_ERROR,
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L1_DEACTIVATE,
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_T200,
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_T203,
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_SET_OWN_BUSY,
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_CLEAR_OWN_BUSY,
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_FRAME_ERROR,
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
79475be4d85a274d0961593db41cf85689db1d583cJoe Perches#define L2_EVENT_COUNT (EV_L2_FRAME_ERROR + 1)
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *strL2Event[] =
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_UI",
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_SABME",
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_DISC",
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_DM",
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_UA",
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_FRMR",
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_SUPER",
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_I",
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_DL_DATA",
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_ACK_PULL",
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_DL_UNIT_DATA",
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_DL_ESTABLISH_REQ",
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_DL_RELEASE_REQ",
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_MDL_ASSIGN",
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_MDL_REMOVE",
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_MDL_ERROR",
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L1_DEACTIVATE",
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_T200",
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_T203",
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_SET_OWN_BUSY",
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_CLEAR_OWN_BUSY",
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_FRAME_ERROR",
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int l2addrsize(struct Layer2 *l2);
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsset_peer_busy(struct Layer2 *l2) {
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(FLG_PEER_BUSY, &l2->flag);
112b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller	if (!skb_queue_empty(&l2->i_queue) ||
113b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller	    !skb_queue_empty(&l2->ui_queue))
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_set_bit(FLG_L2BLOCK, &l2->flag);
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsclear_peer_busy(struct Layer2 *l2) {
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_clear_bit(FLG_PEER_BUSY, &l2->flag))
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_L2BLOCK, &l2->flag);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsInitWin(struct Layer2 *l2)
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MAX_WINDOW; i++)
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2->windowar[i] = NULL;
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfreewin1(struct Layer2 *l2)
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, cnt = 0;
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MAX_WINDOW; i++) {
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (l2->windowar[i]) {
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cnt++;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_kfree_skb(l2->windowar[i]);
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2->windowar[i] = NULL;
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return cnt;
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
147672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfreewin(struct PStack *st)
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin1(&st->l2);
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsReleaseWin(struct Layer2 *l2)
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int cnt;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
158475be4d85a274d0961593db41cf85689db1d583cJoe Perches	if ((cnt = freewin1(l2)))
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "isdl2 freed %d skbuffs in release\n", cnt);
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
162672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline unsigned int
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscansend(struct PStack *st)
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int p1;
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
167475be4d85a274d0961593db41cf85689db1d583cJoe Perches	if (test_bit(FLG_MOD128, &st->l2.flag))
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p1 = (st->l2.vs - st->l2.va) % 128;
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p1 = (st->l2.vs - st->l2.va) % 8;
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((p1 < st->l2.window) && !test_bit(FLG_PEER_BUSY, &st->l2.flag));
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
174672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsclear_exception(struct Layer2 *l2)
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_REJEXC, &l2->flag);
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_OWN_BUSY, &l2->flag);
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clear_peer_busy(l2);
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
183672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2headersize(struct Layer2 *l2, int ui)
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) +
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(test_bit(FLG_LAPD, &l2->flag) ? 2 : 1));
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsinline int
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2addrsize(struct Layer2 *l2)
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1);
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
197475be4d85a274d0961593db41cf85689db1d583cJoe Perchessethdraddr(struct Layer2 *l2, u_char *header, int rsp)
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *ptr = header;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int crbit = rsp;
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPD, &l2->flag)) {
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*ptr++ = (l2->sap << 2) | (rsp ? 2 : 0);
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*ptr++ = (l2->tei << 1) | 1;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (2);
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test_bit(FLG_ORIG, &l2->flag))
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			crbit = !crbit;
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (crbit)
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*ptr++ = 1;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*ptr++ = 3;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (1);
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21777933d7276ee8fa0e2947641941a6f7a100a327bJesper Juhlstatic inline void
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenqueue_super(struct PStack *st,
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      struct sk_buff *skb)
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPB, &st->l2.flag))
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l1.bcs->tx_cnt += skb->len;
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l1(st, PH_DATA | REQUEST, skb);
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define enqueue_ui(a, b) enqueue_super(a, b)
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
228672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
229475be4d85a274d0961593db41cf85689db1d583cJoe PerchesIsUI(u_char *data)
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((data[0] & 0xef) == UI);
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
234672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
235475be4d85a274d0961593db41cf85689db1d583cJoe PerchesIsUA(u_char *data)
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((data[0] & 0xef) == UA);
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
240672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
241475be4d85a274d0961593db41cf85689db1d583cJoe PerchesIsDM(u_char *data)
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((data[0] & 0xef) == DM);
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
246672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
247475be4d85a274d0961593db41cf85689db1d583cJoe PerchesIsDISC(u_char *data)
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((data[0] & 0xef) == DISC);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
252672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
253475be4d85a274d0961593db41cf85689db1d583cJoe PerchesIsSFrame(u_char *data, struct PStack *st)
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register u_char d = *data;
256475be4d85a274d0961593db41cf85689db1d583cJoe Perches
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!test_bit(FLG_MOD128, &st->l2.flag))
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d &= 0xf;
259475be4d85a274d0961593db41cf85689db1d583cJoe Perches	return (((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c));
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
262672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
263475be4d85a274d0961593db41cf85689db1d583cJoe PerchesIsSABME(u_char *data, struct PStack *st)
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char d = data[0] & ~0x10;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (test_bit(FLG_MOD128, &st->l2.flag) ? d == SABME : d == SABM);
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
270672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
271475be4d85a274d0961593db41cf85689db1d583cJoe PerchesIsREJ(u_char *data, struct PStack *st)
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == REJ : (data[0] & 0xf) == REJ);
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
276672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
277475be4d85a274d0961593db41cf85689db1d583cJoe PerchesIsFRMR(u_char *data)
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((data[0] & 0xef) == FRMR);
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
282672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
283475be4d85a274d0961593db41cf85689db1d583cJoe PerchesIsRNR(u_char *data, struct PStack *st)
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == RNR : (data[0] & 0xf) == RNR);
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
288672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic int
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsiframe_error(struct PStack *st, struct sk_buff *skb)
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1);
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rsp = *skb->data & 0x2;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_ORIG, &st->l2.flag))
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsp = !rsp;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rsp)
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'L';
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (skb->len < i)
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'N';
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((skb->len - i) > st->l2.maxlen)
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'O';
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
311672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic int
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuper_error(struct PStack *st, struct sk_buff *skb)
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (skb->len != l2addrsize(&st->l2) +
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1))
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'N';
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
321672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic int
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunnum_error(struct PStack *st, struct sk_buff *skb, int wantrsp)
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rsp = (*skb->data & 0x2) >> 1;
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_ORIG, &st->l2.flag))
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsp = !rsp;
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rsp != wantrsp)
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'L';
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (skb->len != l2addrsize(&st->l2) + 1)
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'N';
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
337672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic int
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsUI_error(struct PStack *st, struct sk_buff *skb)
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rsp = *skb->data & 0x2;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_ORIG, &st->l2.flag))
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsp = !rsp;
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rsp)
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'L';
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (skb->len > st->l2.maxlen + l2addrsize(&st->l2) + 1)
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'O';
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
353672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic int
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsFRMR_error(struct PStack *st, struct sk_buff *skb)
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int headers = l2addrsize(&st->l2) + 1;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *datap = skb->data + headers;
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rsp = *skb->data & 0x2;
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_ORIG, &st->l2.flag))
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsp = !rsp;
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!rsp)
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'L';
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_MOD128, &st->l2.flag)) {
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (skb->len < headers + 5)
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 'N';
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x %2x %2x",
371475be4d85a274d0961593db41cf85689db1d583cJoe Perches				  datap[0], datap[1], datap[2],
372475be4d85a274d0961593db41cf85689db1d583cJoe Perches				  datap[3], datap[4]);
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (skb->len < headers + 3)
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 'N';
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x",
378475be4d85a274d0961593db41cf85689db1d583cJoe Perches				  datap[0], datap[1], datap[2]);
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslegalnr(struct PStack *st, unsigned int nr)
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
387475be4d85a274d0961593db41cf85689db1d583cJoe Perches	struct Layer2 *l2 = &st->l2;
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
389475be4d85a274d0961593db41cf85689db1d583cJoe Perches	if (test_bit(FLG_MOD128, &l2->flag))
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ((nr - l2->va) % 128) <= ((l2->vs - l2->va) % 128);
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ((nr - l2->va) % 8) <= ((l2->vs - l2->va) % 8);
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetva(struct PStack *st, unsigned int nr)
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Layer2 *l2 = &st->l2;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len;
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long flags;
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&l2->lock, flags);
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (l2->va != nr) {
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(l2->va)++;
405475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (test_bit(FLG_MOD128, &l2->flag))
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2->va %= 128;
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2->va %= 8;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = l2->windowar[l2->sow]->len;
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type)
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			len = -1;
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_kfree_skb(l2->windowar[l2->sow]);
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2->windowar[l2->sow] = NULL;
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2->sow = (l2->sow + 1) % l2->window;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(&l2->lock, flags);
416475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (test_bit(FLG_LLI_L2WAKEUP, &st->lli.flag) && (len >= 0))
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lli_writewakeup(st, len);
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_irqsave(&l2->lock, flags);
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&l2->lock, flags);
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssend_uframe(struct PStack *st, u_char cmd, u_char cr)
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char tmp[MAX_HEADER_LEN];
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = sethdraddr(&st->l2, tmp, cr);
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp[i++] = cmd;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(skb = alloc_skb(i, GFP_ATOMIC))) {
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "isdl2 can't alloc sbbuff for send_uframe\n");
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(skb_put(skb, i), tmp, i);
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	enqueue_super(st, skb);
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
440672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline u_char
441475be4d85a274d0961593db41cf85689db1d583cJoe Perchesget_PollFlag(struct PStack *st, struct sk_buff *skb)
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (skb->data[l2addrsize(&(st->l2))] & 0x10);
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
446672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline u_char
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsget_PollFlagFree(struct PStack *st, struct sk_buff *skb)
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char PF;
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	PF = get_PollFlag(st, skb);
452672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk	dev_kfree_skb(skb);
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (PF);
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
456672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstart_t200(struct PStack *st, int i)
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i);
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
463672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsrestart_t200(struct PStack *st, int i)
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i);
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
470672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstop_t200(struct PStack *st, int i)
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
473475be4d85a274d0961593db41cf85689db1d583cJoe Perches	if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmDelTimer(&st->l2.t200, i);
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
477672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsst5_dl_release_l2l3(struct PStack *st)
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
480475be4d85a274d0961593db41cf85689db1d583cJoe Perches	int pr;
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
482475be4d85a274d0961593db41cf85689db1d583cJoe Perches	if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
483475be4d85a274d0961593db41cf85689db1d583cJoe Perches		pr = DL_RELEASE | CONFIRM;
484475be4d85a274d0961593db41cf85689db1d583cJoe Perches	else
485475be4d85a274d0961593db41cf85689db1d583cJoe Perches		pr = DL_RELEASE | INDICATION;
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
487475be4d85a274d0961593db41cf85689db1d583cJoe Perches	st->l2.l2l3(st, pr, NULL);
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
490672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslapb_dl_release_l2l3(struct PStack *st, int f)
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
493475be4d85a274d0961593db41cf85689db1d583cJoe Perches	if (test_bit(FLG_LAPB, &st->l2.flag))
494475be4d85a274d0961593db41cf85689db1d583cJoe Perches		st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
495475be4d85a274d0961593db41cf85689db1d583cJoe Perches	st->l2.l2l3(st, DL_RELEASE | f, NULL);
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsestablishlink(struct FsmInst *fi)
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char cmd;
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clear_exception(&st->l2);
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.rc = 0;
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cmd = (test_bit(FLG_MOD128, &st->l2.flag) ? SABME : SABM) | 0x10;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_uframe(st, cmd, CMD);
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmDelTimer(&st->l2.t203, 1);
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	restart_t200(st, 1);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin(st);
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_5);
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_mdl_error_ua(struct FsmInst *fi, int event, void *arg)
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_PollFlagFree(st, skb))
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'C');
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'D');
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_PollFlagFree(st, skb))
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		establishlink(fi);
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st8_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_PollFlagFree(st, skb))
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	establishlink(fi);
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_go_st3(struct FsmInst *fi, int event, void *arg)
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
560475be4d85a274d0961593db41cf85689db1d583cJoe Perches	FsmChangeState(fi, ST_L2_3);
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_mdl_assign(struct FsmInst *fi, int event, void *arg)
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
568475be4d85a274d0961593db41cf85689db1d583cJoe Perches	FsmChangeState(fi, ST_L2_3);
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_queue_ui_assign(struct FsmInst *fi, int event, void *arg)
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_tail(&st->l2.ui_queue, skb);
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_2);
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_queue_ui(struct FsmInst *fi, int event, void *arg)
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_tail(&st->l2.ui_queue, skb);
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstx_ui(struct PStack *st)
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char header[MAX_HEADER_LEN];
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = sethdraddr(&(st->l2), header, CMD);
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	header[i++] = UI;
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while ((skb = skb_dequeue(&st->l2.ui_queue))) {
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(skb_push(skb, i), header, i);
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enqueue_ui(st, skb);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_send_ui(struct FsmInst *fi, int event, void *arg)
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_tail(&st->l2.ui_queue, skb);
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tx_ui(st);
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_got_ui(struct FsmInst *fi, int event, void *arg)
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_pull(skb, l2headersize(&st->l2, 1));
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_UNIT_DATA | INDICATION, skb);
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		in states 1-3 for broadcast
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_establish(struct FsmInst *fi, int event, void *arg)
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	establishlink(fi);
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_discard_i_setl3(struct FsmInst *fi, int event, void *arg)
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_l3_reestablish(struct FsmInst *fi, int event, void *arg)
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	establishlink(fi);
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_release(struct FsmInst *fi, int event, void *arg)
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_pend_rel(struct FsmInst *fi, int event, void *arg)
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(FLG_PEND_REL, &st->l2.flag);
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_disconnect(struct FsmInst *fi, int event, void *arg)
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin(st);
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_6);
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.rc = 0;
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_uframe(st, DISC | 0x10, CMD);
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmDelTimer(&st->l2.t203, 1);
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	restart_t200(st, 2);
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_start_multi(struct FsmInst *fi, int event, void *arg)
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clear_exception(&st->l2);
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.vs = 0;
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.va = 0;
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.vr = 0;
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.sow = 0;
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_7);
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_send_UA(struct FsmInst *fi, int event, void *arg)
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_send_DM(struct FsmInst *fi, int event, void *arg)
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_uframe(st, DM | get_PollFlagFree(st, skb), RSP);
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_restart_multi(struct FsmInst *fi, int event, void *arg)
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int est = 0, state;
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	state = fi->state;
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'F');
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (st->l2.vs != st->l2.va) {
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_queue_purge(&st->l2.i_queue);
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		est = 1;
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clear_exception(&st->l2);
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.vs = 0;
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.va = 0;
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.vr = 0;
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.sow = 0;
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_7);
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 3);
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmRestartTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (est)
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
758475be4d85a274d0961593db41cf85689db1d583cJoe Perches	if ((ST_L2_7 == state) || (ST_L2_8 == state))
759b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller		if (!skb_queue_empty(&st->l2.i_queue) && cansend(st))
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_stop_multi(struct FsmInst *fi, int event, void *arg)
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_4);
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmDelTimer(&st->l2.t203, 3);
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 4);
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin(st);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lapb_dl_release_l2l3(st, INDICATION);
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_connected(struct FsmInst *fi, int event, void *arg)
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
785475be4d85a274d0961593db41cf85689db1d583cJoe Perches	int pr = -1;
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!get_PollFlag(st, skb)) {
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2_mdl_error_ua(fi, event, arg);
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
791672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk	dev_kfree_skb(skb);
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2_disconnect(fi, event, arg);
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) {
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pr = DL_ESTABLISH | CONFIRM;
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (st->l2.vs != st->l2.va) {
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_queue_purge(&st->l2.i_queue);
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pr = DL_ESTABLISH | INDICATION;
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 5);
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.vr = 0;
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.vs = 0;
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.va = 0;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.sow = 0;
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_7);
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 4);
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pr != -1)
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l3(st, pr, NULL);
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
815b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller	if (!skb_queue_empty(&st->l2.i_queue) && cansend(st))
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_released(struct FsmInst *fi, int event, void *arg)
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!get_PollFlag(st, skb)) {
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2_mdl_error_ua(fi, event, arg);
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
829672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk	dev_kfree_skb(skb);
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 6);
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lapb_dl_release_l2l3(st, CONFIRM);
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_4);
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_reestablish(struct FsmInst *fi, int event, void *arg)
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!get_PollFlagFree(st, skb)) {
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		establishlink(fi);
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st5_dm_release(struct FsmInst *fi, int event, void *arg)
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_PollFlagFree(st, skb)) {
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		stop_t200(st, 7);
856475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (!test_bit(FLG_L3_INIT, &st->l2.flag))
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb_queue_purge(&st->l2.i_queue);
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test_bit(FLG_LAPB, &st->l2.flag))
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st5_dl_release_l2l3(st);
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmChangeState(fi, ST_L2_4);
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st6_dm_release(struct FsmInst *fi, int event, void *arg)
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_PollFlagFree(st, skb)) {
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		stop_t200(st, 8);
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lapb_dl_release_l2l3(st, CONFIRM);
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmChangeState(fi, ST_L2_4);
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
878672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenquiry_cr(struct PStack *st, u_char typ, u_char cr, u_char pf)
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Layer2 *l2;
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char tmp[MAX_HEADER_LEN];
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	l2 = &st->l2;
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = sethdraddr(l2, tmp, cr);
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_MOD128, &l2->flag)) {
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp[i++] = typ;
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp[i++] = (l2->vr << 1) | (pf ? 1 : 0);
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp[i++] = (l2->vr << 5) | typ | (pf ? 0x10 : 0);
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(skb = alloc_skb(i, GFP_ATOMIC))) {
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "isdl2 can't alloc sbbuff for enquiry_cr\n");
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(skb_put(skb, i), tmp, i);
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	enqueue_super(st, skb);
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
901672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenquiry_response(struct PStack *st)
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_OWN_BUSY, &st->l2.flag))
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enquiry_cr(st, RNR, RSP, 1);
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enquiry_cr(st, RR, RSP, 1);
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
911672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstransmit_enquiry(struct PStack *st)
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_OWN_BUSY, &st->l2.flag))
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enquiry_cr(st, RNR, CMD, 1);
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enquiry_cr(st, RR, CMD, 1);
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	start_t200(st, 9);
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnrerrorrecovery(struct FsmInst *fi)
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'J');
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	establishlink(fi);
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsinvoke_retransmission(struct PStack *st, unsigned int nr)
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Layer2 *l2 = &st->l2;
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_int p1;
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long flags;
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&l2->lock, flags);
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (l2->vs != nr) {
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (l2->vs != nr) {
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(l2->vs)--;
944475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (test_bit(FLG_MOD128, &l2->flag)) {
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				l2->vs %= 128;
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				p1 = (l2->vs - l2->va) % 128;
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				l2->vs %= 8;
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				p1 = (l2->vs - l2->va) % 8;
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			p1 = (p1 + l2->sow) % l2->window;
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (test_bit(FLG_LAPB, &l2->flag))
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				st->l1.bcs->tx_cnt += l2->windowar[p1]->len + l2headersize(l2, 0);
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb_queue_head(&l2->i_queue, l2->windowar[p1]);
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2->windowar[p1] = NULL;
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(&l2->lock, flags);
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&l2->lock, flags);
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st7_got_super(struct FsmInst *fi, int event, void *arg)
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int PollFlag, rsp, typ = RR;
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int nr;
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Layer2 *l2 = &st->l2;
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rsp = *skb->data & 0x2;
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_ORIG, &l2->flag))
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsp = !rsp;
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_pull(skb, l2addrsize(l2));
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IsRNR(skb->data, st)) {
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_peer_busy(l2);
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		typ = RNR;
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		clear_peer_busy(l2);
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IsREJ(skb->data, st))
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		typ = REJ;
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_MOD128, &l2->flag)) {
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PollFlag = (skb->data[1] & 0x1) == 0x1;
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nr = skb->data[1] >> 1;
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PollFlag = (skb->data[0] & 0x10);
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nr = (skb->data[0] >> 5) & 0x7;
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
993672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk	dev_kfree_skb(skb);
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (PollFlag) {
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rsp)
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'A');
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			enquiry_response(st);
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (legalnr(st, nr)) {
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (typ == REJ) {
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			setva(st, nr);
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			invoke_retransmission(st, nr);
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			stop_t200(st, 10);
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (FsmAddTimer(&st->l2.t203, st->l2.T203,
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					EV_L2_T203, NULL, 6))
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				l2m_debug(&st->l2.l2m, "Restart T203 ST7 REJ");
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if ((nr == l2->vs) && (typ == RR)) {
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			setva(st, nr);
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			stop_t200(st, 11);
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FsmRestartTimer(&st->l2.t203, st->l2.T203,
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					EV_L2_T203, NULL, 7);
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if ((l2->va != nr) || (typ == RNR)) {
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			setva(st, nr);
1016475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (typ != RR) FsmDelTimer(&st->l2.t203, 9);
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			restart_t200(st, 12);
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1019b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller		if (!skb_queue_empty(&st->l2.i_queue) && (typ == RR))
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nrerrorrecovery(fi);
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_feed_i_if_reest(struct FsmInst *fi, int event, void *arg)
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPB, &st->l2.flag))
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!test_bit(FLG_L3_INIT, &st->l2.flag))
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_queue_tail(&st->l2.i_queue, skb);
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
1036672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk		dev_kfree_skb(skb);
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_feed_i_pull(struct FsmInst *fi, int event, void *arg)
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPB, &st->l2.flag))
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_tail(&st->l2.i_queue, skb);
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_feed_iqueue(struct FsmInst *fi, int event, void *arg)
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPB, &st->l2.flag))
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_tail(&st->l2.i_queue, skb);
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_got_iframe(struct FsmInst *fi, int event, void *arg)
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Layer2 *l2 = &(st->l2);
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int PollFlag, ns, i;
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int nr;
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = l2addrsize(l2);
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_MOD128, &l2->flag)) {
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PollFlag = ((skb->data[i + 1] & 0x1) == 0x1);
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns = skb->data[i] >> 1;
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nr = (skb->data[i + 1] >> 1) & 0x7f;
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PollFlag = (skb->data[i] & 0x10);
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns = (skb->data[i] >> 1) & 0x7;
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nr = (skb->data[i] >> 5) & 0x7;
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_OWN_BUSY, &l2->flag)) {
1082672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk		dev_kfree_skb(skb);
1083475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (PollFlag) enquiry_response(st);
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (l2->vr == ns) {
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(l2->vr)++;
1086475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (test_bit(FLG_MOD128, &l2->flag))
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2->vr %= 128;
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2->vr %= 8;
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_REJEXC, &l2->flag);
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (PollFlag)
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			enquiry_response(st);
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test_and_set_bit(FLG_ACK_PEND, &l2->flag);
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_pull(skb, l2headersize(l2, 0));
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l3(st, DL_DATA | INDICATION, skb);
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* n(s)!=v(r) */
1100672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk		dev_kfree_skb(skb);
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test_and_set_bit(FLG_REJEXC, &l2->flag)) {
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (PollFlag)
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				enquiry_response(st);
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			enquiry_cr(st, REJ, RSP, PollFlag);
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (legalnr(st, nr)) {
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!test_bit(FLG_PEER_BUSY, &st->l2.flag) && (fi->state == ST_L2_7)) {
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (nr == st->l2.vs) {
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				stop_t200(st, 13);
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				FsmRestartTimer(&st->l2.t203, st->l2.T203,
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						EV_L2_T203, NULL, 7);
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (nr != st->l2.va)
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				restart_t200(st, 14);
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		setva(st, nr);
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nrerrorrecovery(fi);
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1125b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller	if (!skb_queue_empty(&st->l2.i_queue) && (fi->state == ST_L2_7))
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag))
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enquiry_cr(st, RR, RSP, 0);
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_got_tei(struct FsmInst *fi, int event, void *arg)
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.tei = (long) arg;
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fi->state == ST_L2_3) {
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		establishlink(fi);
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmChangeState(fi, ST_L2_4);
1143b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller	if (!skb_queue_empty(&st->l2.ui_queue))
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tx_ui(st);
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st5_tout_200(struct FsmInst *fi, int event, void *arg)
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPD, &st->l2.flag) &&
1153475be4d85a274d0961593db41cf85689db1d583cJoe Perches	    test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (st->l2.rc == st->l2.N200) {
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmChangeState(fi, ST_L2_4);
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_queue_purge(&st->l2.i_queue);
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'G');
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test_bit(FLG_LAPB, &st->l2.flag))
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st5_dl_release_l2l3(st);
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.rc++;
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		send_uframe(st, (test_bit(FLG_MOD128, &st->l2.flag) ? SABME : SABM)
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    | 0x10, CMD);
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st6_tout_200(struct FsmInst *fi, int event, void *arg)
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPD, &st->l2.flag) &&
1177475be4d85a274d0961593db41cf85689db1d583cJoe Perches	    test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (st->l2.rc == st->l2.N200) {
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmChangeState(fi, ST_L2_4);
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'H');
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lapb_dl_release_l2l3(st, CONFIRM);
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.rc++;
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200,
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    NULL, 9);
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		send_uframe(st, DISC | 0x10, CMD);
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st7_tout_200(struct FsmInst *fi, int event, void *arg)
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPD, &st->l2.flag) &&
1198475be4d85a274d0961593db41cf85689db1d583cJoe Perches	    test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.rc = 0;
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_8);
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	transmit_enquiry(st);
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.rc++;
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st8_tout_200(struct FsmInst *fi, int event, void *arg)
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPD, &st->l2.flag) &&
1216475be4d85a274d0961593db41cf85689db1d583cJoe Perches	    test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (st->l2.rc == st->l2.N200) {
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'I');
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		establishlink(fi);
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		transmit_enquiry(st);
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.rc++;
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st7_tout_203(struct FsmInst *fi, int event, void *arg)
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPD, &st->l2.flag) &&
1237475be4d85a274d0961593db41cf85689db1d583cJoe Perches	    test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 9);
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_8);
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	transmit_enquiry(st);
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.rc = 0;
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
1250c978e7bb77dfd2cd3d1f547fa4e395cfe47f02b2David S. Miller	struct sk_buff *skb;
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Layer2 *l2 = &st->l2;
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char header[MAX_HEADER_LEN];
1253c978e7bb77dfd2cd3d1f547fa4e395cfe47f02b2David S. Miller	int i, hdr_space_needed;
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int unsigned p1;
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long flags;
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!cansend(st))
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb = skb_dequeue(&l2->i_queue);
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!skb)
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12646d90e8f45697c633f522269368297d7416fd8783David S. Miller	hdr_space_needed = l2headersize(l2, 0);
1265c978e7bb77dfd2cd3d1f547fa4e395cfe47f02b2David S. Miller	if (hdr_space_needed > skb_headroom(skb)) {
1266c978e7bb77dfd2cd3d1f547fa4e395cfe47f02b2David S. Miller		struct sk_buff *orig_skb = skb;
1267c978e7bb77dfd2cd3d1f547fa4e395cfe47f02b2David S. Miller
1268c978e7bb77dfd2cd3d1f547fa4e395cfe47f02b2David S. Miller		skb = skb_realloc_headroom(skb, hdr_space_needed);
1269c978e7bb77dfd2cd3d1f547fa4e395cfe47f02b2David S. Miller		if (!skb) {
1270c978e7bb77dfd2cd3d1f547fa4e395cfe47f02b2David S. Miller			dev_kfree_skb(orig_skb);
1271c978e7bb77dfd2cd3d1f547fa4e395cfe47f02b2David S. Miller			return;
1272c978e7bb77dfd2cd3d1f547fa4e395cfe47f02b2David S. Miller		}
1273c978e7bb77dfd2cd3d1f547fa4e395cfe47f02b2David S. Miller	}
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&l2->lock, flags);
1275475be4d85a274d0961593db41cf85689db1d583cJoe Perches	if (test_bit(FLG_MOD128, &l2->flag))
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p1 = (l2->vs - l2->va) % 128;
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p1 = (l2->vs - l2->va) % 8;
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p1 = (p1 + l2->sow) % l2->window;
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (l2->windowar[p1]) {
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n",
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       p1);
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_kfree_skb(l2->windowar[p1]);
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC);
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = sethdraddr(&st->l2, header, CMD);
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_MOD128, &l2->flag)) {
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		header[i++] = l2->vs << 1;
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		header[i++] = l2->vr << 1;
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2->vs = (l2->vs + 1) % 128;
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		header[i++] = (l2->vr << 5) | (l2->vs << 1);
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2->vs = (l2->vs + 1) % 8;
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&l2->lock, flags);
1298c978e7bb77dfd2cd3d1f547fa4e395cfe47f02b2David S. Miller	memcpy(skb_push(skb, i), header, i);
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l1(st, PH_PULL | INDICATION, skb);
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) {
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmDelTimer(&st->l2.t203, 13);
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 11);
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1305b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller	if (!skb_queue_empty(&l2->i_queue) && cansend(st))
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st8_got_super(struct FsmInst *fi, int event, void *arg)
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int PollFlag, rsp, rnr = 0;
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int nr;
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Layer2 *l2 = &st->l2;
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rsp = *skb->data & 0x2;
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_ORIG, &l2->flag))
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsp = !rsp;
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_pull(skb, l2addrsize(l2));
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IsRNR(skb->data, st)) {
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_peer_busy(l2);
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rnr = 1;
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		clear_peer_busy(l2);
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_MOD128, &l2->flag)) {
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PollFlag = (skb->data[1] & 0x1) == 0x1;
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nr = skb->data[1] >> 1;
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PollFlag = (skb->data[0] & 0x10);
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nr = (skb->data[0] >> 5) & 0x7;
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1337672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk	dev_kfree_skb(skb);
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rsp && PollFlag) {
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (legalnr(st, nr)) {
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (rnr) {
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				restart_t200(st, 15);
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				stop_t200(st, 16);
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				FsmAddTimer(&l2->t203, l2->T203,
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    EV_L2_T203, NULL, 5);
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				setva(st, nr);
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			invoke_retransmission(st, nr);
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FsmChangeState(fi, ST_L2_7);
1351b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller			if (!skb_queue_empty(&l2->i_queue) && cansend(st))
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nrerrorrecovery(fi);
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!rsp && PollFlag)
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			enquiry_response(st);
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (legalnr(st, nr)) {
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			setva(st, nr);
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nrerrorrecovery(fi);
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_got_FRMR(struct FsmInst *fi, int event, void *arg)
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_pull(skb, l2addrsize(&st->l2) + 1);
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(skb->data[0] & 1) || ((skb->data[0] & 3) == 1) ||		/* I or S */
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (IsUA(skb->data) && (fi->state == ST_L2_7))) {
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'K');
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		establishlink(fi);
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1379672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk	dev_kfree_skb(skb);
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st24_tei_remove(struct FsmInst *fi, int event, void *arg)
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.tei = -1;
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_1);
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st3_tei_remove(struct FsmInst *fi, int event, void *arg)
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.tei = -1;
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_1);
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st5_tei_remove(struct FsmInst *fi, int event, void *arg)
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin(st);
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.tei = -1;
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 17);
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st5_dl_release_l2l3(st);
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_1);
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st6_tei_remove(struct FsmInst *fi, int event, void *arg)
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.tei = -1;
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 18);
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_1);
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_tei_remove(struct FsmInst *fi, int event, void *arg)
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin(st);
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.tei = -1;
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 17);
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmDelTimer(&st->l2.t203, 19);
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_1);
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14456b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardtl2_st14_persistent_da(struct FsmInst *fi, int event, void *arg)
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
1448475be4d85a274d0961593db41cf85689db1d583cJoe Perches
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14566b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardtl2_st5_persistent_da(struct FsmInst *fi, int event, void *arg)
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin(st);
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 19);
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st5_dl_release_l2l3(st);
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_4);
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14696b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardtl2_st6_persistent_da(struct FsmInst *fi, int event, void *arg)
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 20);
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_4);
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14806b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardtl2_persistent_da(struct FsmInst *fi, int event, void *arg)
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin(st);
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 19);
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmDelTimer(&st->l2.t203, 19);
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_4);
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_set_own_busy(struct FsmInst *fi, int event, void *arg)
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1498475be4d85a274d0961593db41cf85689db1d583cJoe Perches	if (!test_and_set_bit(FLG_OWN_BUSY, &st->l2.flag)) {
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enquiry_cr(st, RNR, RSP, 0);
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_clear_own_busy(struct FsmInst *fi, int event, void *arg)
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1509475be4d85a274d0961593db41cf85689db1d583cJoe Perches	if (!test_and_clear_bit(FLG_OWN_BUSY, &st->l2.flag)) {
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enquiry_cr(st, RR, RSP, 0);
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_frame_error(struct FsmInst *fi, int event, void *arg)
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->ma.layer(st, MDL_ERROR | INDICATION, arg);
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_frame_error_reest(struct FsmInst *fi, int event, void *arg)
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->ma.layer(st, MDL_ERROR | INDICATION, arg);
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	establishlink(fi);
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct FsmNode L2FnList[] __initdata =
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_1, EV_L2_DL_ESTABLISH_REQ, l2_mdl_assign},
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_2, EV_L2_DL_ESTABLISH_REQ, l2_go_st3},
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_DL_ESTABLISH_REQ, l2_establish},
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_DL_ESTABLISH_REQ, l2_discard_i_setl3},
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_DL_RELEASE_REQ, l2_release},
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_DL_RELEASE_REQ, l2_pend_rel},
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_DL_RELEASE_REQ, l2_disconnect},
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_DL_RELEASE_REQ, l2_disconnect},
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_DL_DATA, l2_feed_i_if_reest},
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_DL_DATA, l2_feed_i_pull},
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_DL_DATA, l2_feed_iqueue},
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_1, EV_L2_DL_UNIT_DATA, l2_queue_ui_assign},
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_2, EV_L2_DL_UNIT_DATA, l2_queue_ui},
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_3, EV_L2_DL_UNIT_DATA, l2_queue_ui},
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_DL_UNIT_DATA, l2_send_ui},
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_DL_UNIT_DATA, l2_send_ui},
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_DL_UNIT_DATA, l2_send_ui},
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_DL_UNIT_DATA, l2_send_ui},
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_DL_UNIT_DATA, l2_send_ui},
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_1, EV_L2_MDL_ASSIGN, l2_got_tei},
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_2, EV_L2_MDL_ASSIGN, l2_got_tei},
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_3, EV_L2_MDL_ASSIGN, l2_got_tei},
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_2, EV_L2_MDL_ERROR, l2_st24_tei_remove},
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_3, EV_L2_MDL_ERROR, l2_st3_tei_remove},
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_MDL_REMOVE, l2_st24_tei_remove},
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_MDL_REMOVE, l2_st5_tei_remove},
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_MDL_REMOVE, l2_st6_tei_remove},
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_MDL_REMOVE, l2_tei_remove},
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_MDL_REMOVE, l2_tei_remove},
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_SABME, l2_start_multi},
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_SABME, l2_send_UA},
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_SABME, l2_send_DM},
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_SABME, l2_restart_multi},
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_SABME, l2_restart_multi},
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_DISC, l2_send_DM},
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_DISC, l2_send_DM},
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_DISC, l2_send_UA},
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_DISC, l2_stop_multi},
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_DISC, l2_stop_multi},
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_UA, l2_mdl_error_ua},
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_UA, l2_connected},
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_UA, l2_released},
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_UA, l2_mdl_error_ua},
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_UA, l2_mdl_error_ua},
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_DM, l2_reestablish},
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_DM, l2_st5_dm_release},
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_DM, l2_st6_dm_release},
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_DM, l2_mdl_error_dm},
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_DM, l2_st8_mdl_error_dm},
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_1, EV_L2_UI, l2_got_ui},
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_2, EV_L2_UI, l2_got_ui},
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_3, EV_L2_UI, l2_got_ui},
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_UI, l2_got_ui},
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_UI, l2_got_ui},
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_UI, l2_got_ui},
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_UI, l2_got_ui},
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_UI, l2_got_ui},
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_FRMR, l2_got_FRMR},
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_FRMR, l2_got_FRMR},
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_SUPER, l2_st7_got_super},
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_SUPER, l2_st8_got_super},
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_I, l2_got_iframe},
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_I, l2_got_iframe},
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_T200, l2_st5_tout_200},
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_T200, l2_st6_tout_200},
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_T200, l2_st7_tout_200},
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_T200, l2_st8_tout_200},
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_T203, l2_st7_tout_203},
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue},
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_FRAME_ERROR, l2_frame_error},
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_FRAME_ERROR, l2_frame_error},
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error},
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest},
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest},
16156b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardt	{ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistent_da},
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove},
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove},
16186b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardt	{ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistent_da},
16196b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardt	{ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistent_da},
16206b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardt	{ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistent_da},
16216b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardt	{ST_L2_7, EV_L1_DEACTIVATE, l2_persistent_da},
16226b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardt	{ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da},
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsisdnl2_l1l2(struct PStack *st, int pr, void *arg)
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *datap;
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 1, len;
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int c = 0;
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (pr) {
1634475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_DATA | INDICATION):
1635475be4d85a274d0961593db41cf85689db1d583cJoe Perches		datap = skb->data;
1636475be4d85a274d0961593db41cf85689db1d583cJoe Perches		len = l2addrsize(&st->l2);
1637475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (skb->len > len)
1638475be4d85a274d0961593db41cf85689db1d583cJoe Perches			datap += len;
1639475be4d85a274d0961593db41cf85689db1d583cJoe Perches		else {
1640475be4d85a274d0961593db41cf85689db1d583cJoe Perches			FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'N');
1641475be4d85a274d0961593db41cf85689db1d583cJoe Perches			dev_kfree_skb(skb);
1642475be4d85a274d0961593db41cf85689db1d583cJoe Perches			return;
1643475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1644475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (!(*datap & 1)) {	/* I-Frame */
1645475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (!(c = iframe_error(st, skb)))
1646475be4d85a274d0961593db41cf85689db1d583cJoe Perches				ret = FsmEvent(&st->l2.l2m, EV_L2_I, skb);
1647475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else if (IsSFrame(datap, st)) {	/* S-Frame */
1648475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (!(c = super_error(st, skb)))
1649475be4d85a274d0961593db41cf85689db1d583cJoe Perches				ret = FsmEvent(&st->l2.l2m, EV_L2_SUPER, skb);
1650475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else if (IsUI(datap)) {
1651475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (!(c = UI_error(st, skb)))
1652475be4d85a274d0961593db41cf85689db1d583cJoe Perches				ret = FsmEvent(&st->l2.l2m, EV_L2_UI, skb);
1653475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else if (IsSABME(datap, st)) {
1654475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (!(c = unnum_error(st, skb, CMD)))
1655475be4d85a274d0961593db41cf85689db1d583cJoe Perches				ret = FsmEvent(&st->l2.l2m, EV_L2_SABME, skb);
1656475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else if (IsUA(datap)) {
1657475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (!(c = unnum_error(st, skb, RSP)))
1658475be4d85a274d0961593db41cf85689db1d583cJoe Perches				ret = FsmEvent(&st->l2.l2m, EV_L2_UA, skb);
1659475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else if (IsDISC(datap)) {
1660475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (!(c = unnum_error(st, skb, CMD)))
1661475be4d85a274d0961593db41cf85689db1d583cJoe Perches				ret = FsmEvent(&st->l2.l2m, EV_L2_DISC, skb);
1662475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else if (IsDM(datap)) {
1663475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (!(c = unnum_error(st, skb, RSP)))
1664475be4d85a274d0961593db41cf85689db1d583cJoe Perches				ret = FsmEvent(&st->l2.l2m, EV_L2_DM, skb);
1665475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else if (IsFRMR(datap)) {
1666475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (!(c = FRMR_error(st, skb)))
1667475be4d85a274d0961593db41cf85689db1d583cJoe Perches				ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb);
1668475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else {
1669475be4d85a274d0961593db41cf85689db1d583cJoe Perches			FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'L');
1670475be4d85a274d0961593db41cf85689db1d583cJoe Perches			dev_kfree_skb(skb);
1671475be4d85a274d0961593db41cf85689db1d583cJoe Perches			ret = 0;
1672475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1673475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (c) {
1674475be4d85a274d0961593db41cf85689db1d583cJoe Perches			dev_kfree_skb(skb);
1675475be4d85a274d0961593db41cf85689db1d583cJoe Perches			FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *)(long)c);
1676475be4d85a274d0961593db41cf85689db1d583cJoe Perches			ret = 0;
1677475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1678475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (ret)
1679475be4d85a274d0961593db41cf85689db1d583cJoe Perches			dev_kfree_skb(skb);
1680475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1681475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_PULL | CONFIRM):
1682475be4d85a274d0961593db41cf85689db1d583cJoe Perches		FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg);
1683475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1684475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_PAUSE | INDICATION):
1685475be4d85a274d0961593db41cf85689db1d583cJoe Perches		test_and_set_bit(FLG_DCHAN_BUSY, &st->l2.flag);
1686475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1687475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_PAUSE | CONFIRM):
1688475be4d85a274d0961593db41cf85689db1d583cJoe Perches		test_and_clear_bit(FLG_DCHAN_BUSY, &st->l2.flag);
1689475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1690475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_ACTIVATE | CONFIRM):
1691475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_ACTIVATE | INDICATION):
1692475be4d85a274d0961593db41cf85689db1d583cJoe Perches		test_and_set_bit(FLG_L1_ACTIV, &st->l2.flag);
1693475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
1694475be4d85a274d0961593db41cf85689db1d583cJoe Perches			FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg);
1695475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1696475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_DEACTIVATE | INDICATION):
1697475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_DEACTIVATE | CONFIRM):
1698475be4d85a274d0961593db41cf85689db1d583cJoe Perches		test_and_clear_bit(FLG_L1_ACTIV, &st->l2.flag);
1699475be4d85a274d0961593db41cf85689db1d583cJoe Perches		FsmEvent(&st->l2.l2m, EV_L1_DEACTIVATE, arg);
1700475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1701475be4d85a274d0961593db41cf85689db1d583cJoe Perches	default:
1702475be4d85a274d0961593db41cf85689db1d583cJoe Perches		l2m_debug(&st->l2.l2m, "l2 unknown pr %04x", pr);
1703475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsisdnl2_l3l2(struct PStack *st, int pr, void *arg)
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (pr) {
1711475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (DL_DATA | REQUEST):
1712475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (FsmEvent(&st->l2.l2m, EV_L2_DL_DATA, arg)) {
1713475be4d85a274d0961593db41cf85689db1d583cJoe Perches			dev_kfree_skb((struct sk_buff *) arg);
1714475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1715475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1716475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (DL_UNIT_DATA | REQUEST):
1717475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (FsmEvent(&st->l2.l2m, EV_L2_DL_UNIT_DATA, arg)) {
1718475be4d85a274d0961593db41cf85689db1d583cJoe Perches			dev_kfree_skb((struct sk_buff *) arg);
1719475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1720475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1721475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (DL_ESTABLISH | REQUEST):
1722475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (test_bit(FLG_L1_ACTIV, &st->l2.flag)) {
1723475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (test_bit(FLG_LAPD, &st->l2.flag) ||
1724475be4d85a274d0961593db41cf85689db1d583cJoe Perches			    test_bit(FLG_ORIG, &st->l2.flag)) {
1725475be4d85a274d0961593db41cf85689db1d583cJoe Perches				FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg);
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1727475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else {
1728475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (test_bit(FLG_LAPD, &st->l2.flag) ||
1729475be4d85a274d0961593db41cf85689db1d583cJoe Perches			    test_bit(FLG_ORIG, &st->l2.flag)) {
1730475be4d85a274d0961593db41cf85689db1d583cJoe Perches				test_and_set_bit(FLG_ESTAB_PEND, &st->l2.flag);
17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1732475be4d85a274d0961593db41cf85689db1d583cJoe Perches			st->l2.l2l1(st, PH_ACTIVATE, NULL);
1733475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1734475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1735475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (DL_RELEASE | REQUEST):
1736475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (test_bit(FLG_LAPB, &st->l2.flag)) {
1737475be4d85a274d0961593db41cf85689db1d583cJoe Perches			st->l2.l2l1(st, PH_DEACTIVATE, NULL);
1738475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1739475be4d85a274d0961593db41cf85689db1d583cJoe Perches		FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE_REQ, arg);
1740475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1741475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (MDL_ASSIGN | REQUEST):
1742475be4d85a274d0961593db41cf85689db1d583cJoe Perches		FsmEvent(&st->l2.l2m, EV_L2_MDL_ASSIGN, arg);
1743475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1744475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (MDL_REMOVE | REQUEST):
1745475be4d85a274d0961593db41cf85689db1d583cJoe Perches		FsmEvent(&st->l2.l2m, EV_L2_MDL_REMOVE, arg);
1746475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1747475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (MDL_ERROR | RESPONSE):
1748475be4d85a274d0961593db41cf85689db1d583cJoe Perches		FsmEvent(&st->l2.l2m, EV_L2_MDL_ERROR, arg);
1749475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreleasestack_isdnl2(struct PStack *st)
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmDelTimer(&st->l2.t200, 21);
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmDelTimer(&st->l2.t203, 16);
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ReleaseWin(&st->l2);
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2m_debug(struct FsmInst *fi, char *fmt, ...)
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	va_list args;
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	va_start(args, fmt);
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	VHiSax_putstatus(st->l1.hardware, st->l2.debug_id, fmt, args);
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	va_end(args);
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetstack_isdnl2(struct PStack *st, char *debug_id)
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&st->l2.lock);
17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l1.l1l2 = isdnl2_l1l2;
17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l3.l3l2 = isdnl2_l3l2;
17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_head_init(&st->l2.i_queue);
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_head_init(&st->l2.ui_queue);
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	InitWin(&st->l2);
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.debug = 0;
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2m.fsm = &l2fsm;
17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPB, &st->l2.flag))
17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2m.state = ST_L2_4;
17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
1790475be4d85a274d0961593db41cf85689db1d583cJoe Perches		st->l2.l2m.state = ST_L2_1;
17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2m.debug = 0;
17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2m.userdata = st;
17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2m.userint = 0;
17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2m.printdebug = l2m_debug;
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strcpy(st->l2.debug_id, debug_id);
17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmInitTimer(&st->l2.l2m, &st->l2.t200);
17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmInitTimer(&st->l2.l2m, &st->l2.t203);
17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstransl2_l3l2(struct PStack *st, int pr, void *arg)
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (pr) {
1805475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (DL_DATA | REQUEST):
1806475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (DL_UNIT_DATA | REQUEST):
1807475be4d85a274d0961593db41cf85689db1d583cJoe Perches		st->l2.l2l1(st, PH_DATA | REQUEST, arg);
1808475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1809475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (DL_ESTABLISH | REQUEST):
1810475be4d85a274d0961593db41cf85689db1d583cJoe Perches		st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
1811475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1812475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (DL_RELEASE | REQUEST):
1813475be4d85a274d0961593db41cf85689db1d583cJoe Perches		st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
1814475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetstack_transl2(struct PStack *st)
18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l3.l3l2 = transl2_l3l2;
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreleasestack_transl2(struct PStack *st)
18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init
18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsdnl2New(void)
18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	l2fsm.state_count = L2_STATE_COUNT;
18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	l2fsm.event_count = L2_EVENT_COUNT;
18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	l2fsm.strEvent = strL2Event;
18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	l2fsm.strState = strL2State;
1836ba2d6ccb1df6ebb2c1b2322518ce7be25c1e3469Karsten Keil	return FsmNew(&l2fsm, L2FnList, ARRAY_SIZE(L2FnList));
18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsdnl2Free(void)
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmFree(&l2fsm);
18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1844