xref: /openbmc/linux/drivers/isdn/mISDN/l1oip_core.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
1de6cc651SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
23712b42dSKarsten Keil /*
33712b42dSKarsten Keil 
43712b42dSKarsten Keil  * l1oip.c  low level driver for tunneling layer 1 over IP
53712b42dSKarsten Keil  *
63712b42dSKarsten Keil  * NOTE: It is not compatible with TDMoIP nor "ISDN over IP".
73712b42dSKarsten Keil  *
83712b42dSKarsten Keil  * Author	Andreas Eversberg (jolly@eversberg.eu)
93712b42dSKarsten Keil  */
103712b42dSKarsten Keil 
113712b42dSKarsten Keil /* module parameters:
123712b42dSKarsten Keil  * type:
133712b42dSKarsten Keil  Value 1	= BRI
143712b42dSKarsten Keil  Value 2	= PRI
153712b42dSKarsten Keil  Value 3 = BRI (multi channel frame, not supported yet)
163712b42dSKarsten Keil  Value 4 = PRI (multi channel frame, not supported yet)
173712b42dSKarsten Keil  A multi channel frame reduces overhead to a single frame for all
183712b42dSKarsten Keil  b-channels, but increases delay.
193712b42dSKarsten Keil  (NOTE: Multi channel frames are not implemented yet.)
203712b42dSKarsten Keil 
213712b42dSKarsten Keil  * codec:
223712b42dSKarsten Keil  Value 0 = transparent (default)
233712b42dSKarsten Keil  Value 1 = transfer ALAW
243712b42dSKarsten Keil  Value 2 = transfer ULAW
253712b42dSKarsten Keil  Value 3 = transfer generic 4 bit compression.
263712b42dSKarsten Keil 
273712b42dSKarsten Keil  * ulaw:
283712b42dSKarsten Keil  0 = we use a-Law (default)
293712b42dSKarsten Keil  1 = we use u-Law
303712b42dSKarsten Keil 
313712b42dSKarsten Keil  * limit:
323712b42dSKarsten Keil  limitation of B-channels to control bandwidth (1...126)
333712b42dSKarsten Keil  BRI: 1 or 2
343712b42dSKarsten Keil  PRI: 1-30, 31-126 (126, because dchannel ist not counted here)
353712b42dSKarsten Keil  Also limited ressources are used for stack, resulting in less channels.
363712b42dSKarsten Keil  It is possible to have more channels than 30 in PRI mode, this must
373712b42dSKarsten Keil  be supported by the application.
383712b42dSKarsten Keil 
393712b42dSKarsten Keil  * ip:
403712b42dSKarsten Keil  byte representation of remote ip address (127.0.0.1 -> 127,0,0,1)
413712b42dSKarsten Keil  If not given or four 0, no remote address is set.
423712b42dSKarsten Keil  For multiple interfaces, concat ip addresses. (127,0,0,1,127,0,0,1)
433712b42dSKarsten Keil 
443712b42dSKarsten Keil  * port:
453712b42dSKarsten Keil  port number (local interface)
463712b42dSKarsten Keil  If not given or 0, port 931 is used for fist instance, 932 for next...
473712b42dSKarsten Keil  For multiple interfaces, different ports must be given.
483712b42dSKarsten Keil 
493712b42dSKarsten Keil  * remoteport:
503712b42dSKarsten Keil  port number (remote interface)
513712b42dSKarsten Keil  If not given or 0, remote port equals local port
523712b42dSKarsten Keil  For multiple interfaces on equal sites, different ports must be given.
533712b42dSKarsten Keil 
543712b42dSKarsten Keil  * ondemand:
553712b42dSKarsten Keil  0 = fixed (always transmit packets, even when remote side timed out)
563712b42dSKarsten Keil  1 = on demand (only transmit packets, when remote side is detected)
573712b42dSKarsten Keil  the default is 0
583712b42dSKarsten Keil  NOTE: ID must also be set for on demand.
593712b42dSKarsten Keil 
603712b42dSKarsten Keil  * id:
613712b42dSKarsten Keil  optional value to identify frames. This value must be equal on both
623712b42dSKarsten Keil  peers and should be random. If omitted or 0, no ID is transmitted.
633712b42dSKarsten Keil 
643712b42dSKarsten Keil  * debug:
653712b42dSKarsten Keil  NOTE: only one debug value must be given for all cards
663712b42dSKarsten Keil  enable debugging (see l1oip.h for debug options)
673712b42dSKarsten Keil 
683712b42dSKarsten Keil 
693712b42dSKarsten Keil  Special mISDN controls:
703712b42dSKarsten Keil 
713712b42dSKarsten Keil  op = MISDN_CTRL_SETPEER*
723712b42dSKarsten Keil  p1 = bytes 0-3 : remote IP address in network order (left element first)
733712b42dSKarsten Keil  p2 = bytes 1-2 : remote port in network order (high byte first)
743712b42dSKarsten Keil  optional:
753712b42dSKarsten Keil  p2 = bytes 3-4 : local port in network order (high byte first)
763712b42dSKarsten Keil 
773712b42dSKarsten Keil  op = MISDN_CTRL_UNSETPEER*
783712b42dSKarsten Keil 
793712b42dSKarsten Keil  * Use l1oipctrl for comfortable setting or removing ip address.
803712b42dSKarsten Keil  (Layer 1 Over IP CTRL)
813712b42dSKarsten Keil 
823712b42dSKarsten Keil 
833712b42dSKarsten Keil  L1oIP-Protocol
843712b42dSKarsten Keil  --------------
853712b42dSKarsten Keil 
863712b42dSKarsten Keil  Frame Header:
873712b42dSKarsten Keil 
883712b42dSKarsten Keil  7 6 5 4 3 2 1 0
893712b42dSKarsten Keil  +---------------+
903712b42dSKarsten Keil  |Ver|T|I|Coding |
913712b42dSKarsten Keil  +---------------+
923712b42dSKarsten Keil  |  ID byte 3 *  |
933712b42dSKarsten Keil  +---------------+
943712b42dSKarsten Keil  |  ID byte 2 *  |
953712b42dSKarsten Keil  +---------------+
963712b42dSKarsten Keil  |  ID byte 1 *  |
973712b42dSKarsten Keil  +---------------+
983712b42dSKarsten Keil  |  ID byte 0 *  |
993712b42dSKarsten Keil  +---------------+
1003712b42dSKarsten Keil  |M|   Channel   |
1013712b42dSKarsten Keil  +---------------+
1023712b42dSKarsten Keil  |    Length *   |
1033712b42dSKarsten Keil  +---------------+
1043712b42dSKarsten Keil  | Time Base MSB |
1053712b42dSKarsten Keil  +---------------+
1063712b42dSKarsten Keil  | Time Base LSB |
1073712b42dSKarsten Keil  +---------------+
1083712b42dSKarsten Keil  | Data....	|
1093712b42dSKarsten Keil 
1103712b42dSKarsten Keil  ...
1113712b42dSKarsten Keil 
1123712b42dSKarsten Keil  |               |
1133712b42dSKarsten Keil  +---------------+
1143712b42dSKarsten Keil  |M|   Channel   |
1153712b42dSKarsten Keil  +---------------+
1163712b42dSKarsten Keil  |    Length *   |
1173712b42dSKarsten Keil  +---------------+
1183712b42dSKarsten Keil  | Time Base MSB |
1193712b42dSKarsten Keil  +---------------+
1203712b42dSKarsten Keil  | Time Base LSB |
1213712b42dSKarsten Keil  +---------------+
1223712b42dSKarsten Keil  | Data....	|
1233712b42dSKarsten Keil 
1243712b42dSKarsten Keil  ...
1253712b42dSKarsten Keil 
1263712b42dSKarsten Keil 
1273712b42dSKarsten Keil  * Only included in some cases.
1283712b42dSKarsten Keil 
1293712b42dSKarsten Keil  - Ver = Version
1303712b42dSKarsten Keil  If version is missmatch, the frame must be ignored.
1313712b42dSKarsten Keil 
1323712b42dSKarsten Keil  - T = Type of interface
1333712b42dSKarsten Keil  Must be 0 for S0 or 1 for E1.
1343712b42dSKarsten Keil 
1353712b42dSKarsten Keil  - I = Id present
1363712b42dSKarsten Keil  If bit is set, four ID bytes are included in frame.
1373712b42dSKarsten Keil 
1383712b42dSKarsten Keil  - ID = Connection ID
1393712b42dSKarsten Keil  Additional ID to prevent Denial of Service attacs. Also it prevents hijacking
1403712b42dSKarsten Keil  connections with dynamic IP. The ID should be random and must not be 0.
1413712b42dSKarsten Keil 
1423712b42dSKarsten Keil  - Coding = Type of codec
1433712b42dSKarsten Keil  Must be 0 for no transcoding. Also for D-channel and other HDLC frames.
1443712b42dSKarsten Keil  1 and 2 are reserved for explicitly use of a-LAW or u-LAW codec.
1453712b42dSKarsten Keil  3 is used for generic table compressor.
1463712b42dSKarsten Keil 
1473712b42dSKarsten Keil  - M = More channels to come. If this flag is 1, the following byte contains
1483712b42dSKarsten Keil  the length of the channel data. After the data block, the next channel will
1493712b42dSKarsten Keil  be defined. The flag for the last channel block (or if only one channel is
1503712b42dSKarsten Keil  transmitted), must be 0 and no length is given.
1513712b42dSKarsten Keil 
1523712b42dSKarsten Keil  - Channel = Channel number
1533712b42dSKarsten Keil  0 reserved
1543712b42dSKarsten Keil  1-3 channel data for S0 (3 is D-channel)
1553712b42dSKarsten Keil  1-31 channel data for E1 (16 is D-channel)
1563712b42dSKarsten Keil  32-127 channel data for extended E1 (16 is D-channel)
1573712b42dSKarsten Keil 
1583712b42dSKarsten Keil  - The length is used if the M-flag is 1. It is used to find the next channel
1593712b42dSKarsten Keil  inside frame.
1603712b42dSKarsten Keil  NOTE: A value of 0 equals 256 bytes of data.
1613712b42dSKarsten Keil  -> For larger data blocks, a single frame must be used.
1623712b42dSKarsten Keil  -> For larger streams, a single frame or multiple blocks with same channel ID
1633712b42dSKarsten Keil  must be used.
1643712b42dSKarsten Keil 
1653712b42dSKarsten Keil  - Time Base = Timestamp of first sample in frame
1663712b42dSKarsten Keil  The "Time Base" is used to rearange packets and to detect packet loss.
1673712b42dSKarsten Keil  The 16 bits are sent in network order (MSB first) and count 1/8000 th of a
16825985edcSLucas De Marchi  second. This causes a wrap around each 8,192 seconds. There is no requirement
1693712b42dSKarsten Keil  for the initial "Time Base", but 0 should be used for the first packet.
1703712b42dSKarsten Keil  In case of HDLC data, this timestamp counts the packet or byte number.
1713712b42dSKarsten Keil 
1723712b42dSKarsten Keil 
1733712b42dSKarsten Keil  Two Timers:
1743712b42dSKarsten Keil 
1753712b42dSKarsten Keil  After initialisation, a timer of 15 seconds is started. Whenever a packet is
1763712b42dSKarsten Keil  transmitted, the timer is reset to 15 seconds again. If the timer expires, an
1773712b42dSKarsten Keil  empty packet is transmitted. This keep the connection alive.
1783712b42dSKarsten Keil 
1793712b42dSKarsten Keil  When a valid packet is received, a timer 65 seconds is started. The interface
1803712b42dSKarsten Keil  become ACTIVE. If the timer expires, the interface becomes INACTIVE.
1813712b42dSKarsten Keil 
1823712b42dSKarsten Keil 
1833712b42dSKarsten Keil  Dynamic IP handling:
1843712b42dSKarsten Keil 
1853712b42dSKarsten Keil  To allow dynamic IP, the ID must be non 0. In this case, any packet with the
1863712b42dSKarsten Keil  correct port number and ID will be accepted. If the remote side changes its IP
1873712b42dSKarsten Keil  the new IP is used for all transmitted packets until it changes again.
1883712b42dSKarsten Keil 
1893712b42dSKarsten Keil 
1903712b42dSKarsten Keil  On Demand:
1913712b42dSKarsten Keil 
1923712b42dSKarsten Keil  If the ondemand parameter is given, the remote IP is set to 0 on timeout.
1933712b42dSKarsten Keil  This will stop keepalive traffic to remote. If the remote is online again,
19425985edcSLucas De Marchi  traffic will continue to the remote address. This is useful for road warriors.
1953712b42dSKarsten Keil  This feature only works with ID set, otherwhise it is highly unsecure.
1963712b42dSKarsten Keil 
1973712b42dSKarsten Keil 
1983712b42dSKarsten Keil  Socket and Thread
1993712b42dSKarsten Keil  -----------------
2003712b42dSKarsten Keil 
2013712b42dSKarsten Keil  The complete socket opening and closing is done by a thread.
2023712b42dSKarsten Keil  When the thread opened a socket, the hc->socket descriptor is set. Whenever a
20367a580aaSWang Qing  packet shall be sent to the socket, the hc->socket must be checked whether not
2043712b42dSKarsten Keil  NULL. To prevent change in socket descriptor, the hc->socket_lock must be used.
2053712b42dSKarsten Keil  To change the socket, a recall of l1oip_socket_open() will safely kill the
2063712b42dSKarsten Keil  socket process and create a new one.
2073712b42dSKarsten Keil 
2083712b42dSKarsten Keil */
2093712b42dSKarsten Keil 
2103712b42dSKarsten Keil #define L1OIP_VERSION	0	/* 0...3 */
2113712b42dSKarsten Keil 
2123712b42dSKarsten Keil #include <linux/module.h>
2133712b42dSKarsten Keil #include <linux/delay.h>
2143712b42dSKarsten Keil #include <linux/mISDNif.h>
2153712b42dSKarsten Keil #include <linux/mISDNhw.h>
2163712b42dSKarsten Keil #include <linux/mISDNdsp.h>
2173712b42dSKarsten Keil #include <linux/init.h>
2183712b42dSKarsten Keil #include <linux/in.h>
2193712b42dSKarsten Keil #include <linux/inet.h>
2203712b42dSKarsten Keil #include <linux/workqueue.h>
2213712b42dSKarsten Keil #include <linux/kthread.h>
2225a0e3ad6STejun Heo #include <linux/slab.h>
2233f07c014SIngo Molnar #include <linux/sched/signal.h>
2243f07c014SIngo Molnar 
2253712b42dSKarsten Keil #include <net/sock.h>
2263712b42dSKarsten Keil #include "core.h"
2273712b42dSKarsten Keil #include "l1oip.h"
2283712b42dSKarsten Keil 
2293712b42dSKarsten Keil static const char *l1oip_revision = "2.00";
2303712b42dSKarsten Keil 
2313712b42dSKarsten Keil static int l1oip_cnt;
23277053fb7SShixin Liu static DEFINE_SPINLOCK(l1oip_lock);
2335979415dSShixin Liu static LIST_HEAD(l1oip_ilist);
2343712b42dSKarsten Keil 
2353712b42dSKarsten Keil #define MAX_CARDS	16
2363712b42dSKarsten Keil static u_int type[MAX_CARDS];
2373712b42dSKarsten Keil static u_int codec[MAX_CARDS];
2383712b42dSKarsten Keil static u_int ip[MAX_CARDS * 4];
2393712b42dSKarsten Keil static u_int port[MAX_CARDS];
2403712b42dSKarsten Keil static u_int remoteport[MAX_CARDS];
2413712b42dSKarsten Keil static u_int ondemand[MAX_CARDS];
2423712b42dSKarsten Keil static u_int limit[MAX_CARDS];
2433712b42dSKarsten Keil static u_int id[MAX_CARDS];
2443712b42dSKarsten Keil static int debug;
2453712b42dSKarsten Keil static int ulaw;
2463712b42dSKarsten Keil 
2473712b42dSKarsten Keil MODULE_AUTHOR("Andreas Eversberg");
2483712b42dSKarsten Keil MODULE_LICENSE("GPL");
2493712b42dSKarsten Keil module_param_array(type, uint, NULL, S_IRUGO | S_IWUSR);
2503712b42dSKarsten Keil module_param_array(codec, uint, NULL, S_IRUGO | S_IWUSR);
2513712b42dSKarsten Keil module_param_array(ip, uint, NULL, S_IRUGO | S_IWUSR);
2523712b42dSKarsten Keil module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR);
2533712b42dSKarsten Keil module_param_array(remoteport, uint, NULL, S_IRUGO | S_IWUSR);
2543712b42dSKarsten Keil module_param_array(ondemand, uint, NULL, S_IRUGO | S_IWUSR);
2553712b42dSKarsten Keil module_param_array(limit, uint, NULL, S_IRUGO | S_IWUSR);
2563712b42dSKarsten Keil module_param_array(id, uint, NULL, S_IRUGO | S_IWUSR);
2573712b42dSKarsten Keil module_param(ulaw, uint, S_IRUGO | S_IWUSR);
2583712b42dSKarsten Keil module_param(debug, uint, S_IRUGO | S_IWUSR);
2593712b42dSKarsten Keil 
2603712b42dSKarsten Keil /*
2613712b42dSKarsten Keil  * send a frame via socket, if open and restart timer
2623712b42dSKarsten Keil  */
2633712b42dSKarsten Keil static int
l1oip_socket_send(struct l1oip * hc,u8 localcodec,u8 channel,u32 chanmask,u16 timebase,u8 * buf,int len)2643712b42dSKarsten Keil l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask,
2653712b42dSKarsten Keil 		  u16 timebase, u8 *buf, int len)
2663712b42dSKarsten Keil {
2673712b42dSKarsten Keil 	u8 *p;
2689a438161SLaura Abbott 	u8 frame[MAX_DFRAME_LEN_L1 + 32];
2693712b42dSKarsten Keil 	struct socket *socket = NULL;
2703712b42dSKarsten Keil 
2713712b42dSKarsten Keil 	if (debug & DEBUG_L1OIP_MSG)
2723712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: sending data to socket (len = %d)\n",
2733712b42dSKarsten Keil 		       __func__, len);
2743712b42dSKarsten Keil 
2753712b42dSKarsten Keil 	p = frame;
2763712b42dSKarsten Keil 
2773712b42dSKarsten Keil 	/* restart timer */
2782568a7e0SDuoming Zhou 	if (time_before(hc->keep_tl.expires, jiffies + 5 * HZ) && !hc->shutdown)
27987f03cc3SManuel Schölling 		mod_timer(&hc->keep_tl, jiffies + L1OIP_KEEPALIVE * HZ);
28087f03cc3SManuel Schölling 	else
2813712b42dSKarsten Keil 		hc->keep_tl.expires = jiffies + L1OIP_KEEPALIVE * HZ;
2823712b42dSKarsten Keil 
2833712b42dSKarsten Keil 	if (debug & DEBUG_L1OIP_MSG)
2843712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: resetting timer\n", __func__);
2853712b42dSKarsten Keil 
2863712b42dSKarsten Keil 	/* drop if we have no remote ip or port */
2873712b42dSKarsten Keil 	if (!hc->sin_remote.sin_addr.s_addr || !hc->sin_remote.sin_port) {
2883712b42dSKarsten Keil 		if (debug & DEBUG_L1OIP_MSG)
2893712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: dropping frame, because remote "
2903712b42dSKarsten Keil 			       "IP is not set.\n", __func__);
2913712b42dSKarsten Keil 		return len;
2923712b42dSKarsten Keil 	}
2933712b42dSKarsten Keil 
2943712b42dSKarsten Keil 	/* assemble frame */
2953712b42dSKarsten Keil 	*p++ = (L1OIP_VERSION << 6) /* version and coding */
2963712b42dSKarsten Keil 		| (hc->pri ? 0x20 : 0x00) /* type */
2973712b42dSKarsten Keil 		| (hc->id ? 0x10 : 0x00) /* id */
2983712b42dSKarsten Keil 		| localcodec;
2993712b42dSKarsten Keil 	if (hc->id) {
3003712b42dSKarsten Keil 		*p++ = hc->id >> 24; /* id */
3013712b42dSKarsten Keil 		*p++ = hc->id >> 16;
3023712b42dSKarsten Keil 		*p++ = hc->id >> 8;
3033712b42dSKarsten Keil 		*p++ = hc->id;
3043712b42dSKarsten Keil 	}
3050f15b151SAlan Cox 	*p++ =  0x00 + channel; /* m-flag, channel */
3063712b42dSKarsten Keil 	*p++ = timebase >> 8; /* time base */
3073712b42dSKarsten Keil 	*p++ = timebase;
3083712b42dSKarsten Keil 
3093712b42dSKarsten Keil 	if (buf && len) { /* add data to frame */
3103712b42dSKarsten Keil 		if (localcodec == 1 && ulaw)
3113712b42dSKarsten Keil 			l1oip_ulaw_to_alaw(buf, len, p);
3123712b42dSKarsten Keil 		else if (localcodec == 2 && !ulaw)
3133712b42dSKarsten Keil 			l1oip_alaw_to_ulaw(buf, len, p);
3143712b42dSKarsten Keil 		else if (localcodec == 3)
3153712b42dSKarsten Keil 			len = l1oip_law_to_4bit(buf, len, p,
3163712b42dSKarsten Keil 						&hc->chan[channel].codecstate);
3173712b42dSKarsten Keil 		else
3183712b42dSKarsten Keil 			memcpy(p, buf, len);
3193712b42dSKarsten Keil 	}
3203712b42dSKarsten Keil 	len += p - frame;
3213712b42dSKarsten Keil 
3223712b42dSKarsten Keil 	/* check for socket in safe condition */
3233712b42dSKarsten Keil 	spin_lock(&hc->socket_lock);
3243712b42dSKarsten Keil 	if (!hc->socket) {
3253712b42dSKarsten Keil 		spin_unlock(&hc->socket_lock);
3263712b42dSKarsten Keil 		return 0;
3273712b42dSKarsten Keil 	}
3283712b42dSKarsten Keil 	/* seize socket */
3293712b42dSKarsten Keil 	socket = hc->socket;
3303712b42dSKarsten Keil 	hc->socket = NULL;
3313712b42dSKarsten Keil 	spin_unlock(&hc->socket_lock);
3323712b42dSKarsten Keil 	/* send packet */
3333712b42dSKarsten Keil 	if (debug & DEBUG_L1OIP_MSG)
3343712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: sending packet to socket (len "
3353712b42dSKarsten Keil 		       "= %d)\n", __func__, len);
3363712b42dSKarsten Keil 	hc->sendiov.iov_base = frame;
3373712b42dSKarsten Keil 	hc->sendiov.iov_len  = len;
3388c90e11eSArnaldo Carvalho de Melo 	len = kernel_sendmsg(socket, &hc->sendmsg, &hc->sendiov, 1, len);
3393712b42dSKarsten Keil 	/* give socket back */
3403712b42dSKarsten Keil 	hc->socket = socket; /* no locking required */
3413712b42dSKarsten Keil 
3423712b42dSKarsten Keil 	return len;
3433712b42dSKarsten Keil }
3443712b42dSKarsten Keil 
3453712b42dSKarsten Keil 
3463712b42dSKarsten Keil /*
3473712b42dSKarsten Keil  * receive channel data from socket
3483712b42dSKarsten Keil  */
3493712b42dSKarsten Keil static void
l1oip_socket_recv(struct l1oip * hc,u8 remotecodec,u8 channel,u16 timebase,u8 * buf,int len)3503712b42dSKarsten Keil l1oip_socket_recv(struct l1oip *hc, u8 remotecodec, u8 channel, u16 timebase,
3513712b42dSKarsten Keil 		  u8 *buf, int len)
3523712b42dSKarsten Keil {
3533712b42dSKarsten Keil 	struct sk_buff *nskb;
3543712b42dSKarsten Keil 	struct bchannel *bch;
3553712b42dSKarsten Keil 	struct dchannel *dch;
3563712b42dSKarsten Keil 	u8 *p;
3573712b42dSKarsten Keil 	u32 rx_counter;
3583712b42dSKarsten Keil 
3593712b42dSKarsten Keil 	if (len == 0) {
3603712b42dSKarsten Keil 		if (debug & DEBUG_L1OIP_MSG)
3613712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: received empty keepalive data, "
3623712b42dSKarsten Keil 			       "ignoring\n", __func__);
3633712b42dSKarsten Keil 		return;
3643712b42dSKarsten Keil 	}
3653712b42dSKarsten Keil 
3663712b42dSKarsten Keil 	if (debug & DEBUG_L1OIP_MSG)
3673712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: received data, sending to mISDN (%d)\n",
3683712b42dSKarsten Keil 		       __func__, len);
3693712b42dSKarsten Keil 
3703712b42dSKarsten Keil 	if (channel < 1 || channel > 127) {
3713712b42dSKarsten Keil 		printk(KERN_WARNING "%s: packet error - channel %d out of "
3723712b42dSKarsten Keil 		       "range\n", __func__, channel);
3733712b42dSKarsten Keil 		return;
3743712b42dSKarsten Keil 	}
3753712b42dSKarsten Keil 	dch = hc->chan[channel].dch;
3763712b42dSKarsten Keil 	bch = hc->chan[channel].bch;
3773712b42dSKarsten Keil 	if (!dch && !bch) {
3783712b42dSKarsten Keil 		printk(KERN_WARNING "%s: packet error - channel %d not in "
3793712b42dSKarsten Keil 		       "stack\n", __func__, channel);
3803712b42dSKarsten Keil 		return;
3813712b42dSKarsten Keil 	}
3823712b42dSKarsten Keil 
3833712b42dSKarsten Keil 	/* prepare message */
3843712b42dSKarsten Keil 	nskb = mI_alloc_skb((remotecodec == 3) ? (len << 1) : len, GFP_ATOMIC);
3853712b42dSKarsten Keil 	if (!nskb) {
3863712b42dSKarsten Keil 		printk(KERN_ERR "%s: No mem for skb.\n", __func__);
3873712b42dSKarsten Keil 		return;
3883712b42dSKarsten Keil 	}
3893712b42dSKarsten Keil 	p = skb_put(nskb, (remotecodec == 3) ? (len << 1) : len);
3903712b42dSKarsten Keil 
3913712b42dSKarsten Keil 	if (remotecodec == 1 && ulaw)
3923712b42dSKarsten Keil 		l1oip_alaw_to_ulaw(buf, len, p);
3933712b42dSKarsten Keil 	else if (remotecodec == 2 && !ulaw)
3943712b42dSKarsten Keil 		l1oip_ulaw_to_alaw(buf, len, p);
3953712b42dSKarsten Keil 	else if (remotecodec == 3)
3963712b42dSKarsten Keil 		len = l1oip_4bit_to_law(buf, len, p);
3973712b42dSKarsten Keil 	else
3983712b42dSKarsten Keil 		memcpy(p, buf, len);
3993712b42dSKarsten Keil 
4003712b42dSKarsten Keil 	/* send message up */
4013712b42dSKarsten Keil 	if (dch && len >= 2) {
4023712b42dSKarsten Keil 		dch->rx_skb = nskb;
4033712b42dSKarsten Keil 		recv_Dchannel(dch);
4043712b42dSKarsten Keil 	}
4053712b42dSKarsten Keil 	if (bch) {
4063712b42dSKarsten Keil 		/* expand 16 bit sequence number to 32 bit sequence number */
4073712b42dSKarsten Keil 		rx_counter = hc->chan[channel].rx_counter;
4083712b42dSKarsten Keil 		if (((s16)(timebase - rx_counter)) >= 0) {
4093712b42dSKarsten Keil 			/* time has changed forward */
4103712b42dSKarsten Keil 			if (timebase >= (rx_counter & 0xffff))
4113712b42dSKarsten Keil 				rx_counter =
4123712b42dSKarsten Keil 					(rx_counter & 0xffff0000) | timebase;
4133712b42dSKarsten Keil 			else
4143712b42dSKarsten Keil 				rx_counter = ((rx_counter & 0xffff0000) + 0x10000)
4153712b42dSKarsten Keil 					| timebase;
4163712b42dSKarsten Keil 		} else {
4173712b42dSKarsten Keil 			/* time has changed backwards */
4183712b42dSKarsten Keil 			if (timebase < (rx_counter & 0xffff))
4193712b42dSKarsten Keil 				rx_counter =
4203712b42dSKarsten Keil 					(rx_counter & 0xffff0000) | timebase;
4213712b42dSKarsten Keil 			else
4223712b42dSKarsten Keil 				rx_counter = ((rx_counter & 0xffff0000) - 0x10000)
4233712b42dSKarsten Keil 					| timebase;
4243712b42dSKarsten Keil 		}
4253712b42dSKarsten Keil 		hc->chan[channel].rx_counter = rx_counter;
4263712b42dSKarsten Keil 
4273712b42dSKarsten Keil #ifdef REORDER_DEBUG
4283712b42dSKarsten Keil 		if (hc->chan[channel].disorder_flag) {
42928e8c191SGustavo A. R. Silva 			swap(hc->chan[channel].disorder_skb, nskb);
43028e8c191SGustavo A. R. Silva 			swap(hc->chan[channel].disorder_cnt, rx_counter);
4313712b42dSKarsten Keil 		}
4323712b42dSKarsten Keil 		hc->chan[channel].disorder_flag ^= 1;
4333712b42dSKarsten Keil 		if (nskb)
4343712b42dSKarsten Keil #endif
4353712b42dSKarsten Keil 			queue_ch_frame(&bch->ch, PH_DATA_IND, rx_counter, nskb);
4363712b42dSKarsten Keil 	}
4373712b42dSKarsten Keil }
4383712b42dSKarsten Keil 
4393712b42dSKarsten Keil 
4403712b42dSKarsten Keil /*
4413712b42dSKarsten Keil  * parse frame and extract channel data
4423712b42dSKarsten Keil  */
4433712b42dSKarsten Keil static void
l1oip_socket_parse(struct l1oip * hc,struct sockaddr_in * sin,u8 * buf,int len)4443712b42dSKarsten Keil l1oip_socket_parse(struct l1oip *hc, struct sockaddr_in *sin, u8 *buf, int len)
4453712b42dSKarsten Keil {
446863a76e5SHannes Eder 	u32			packet_id;
4473712b42dSKarsten Keil 	u8			channel;
4483712b42dSKarsten Keil 	u8			remotecodec;
4493712b42dSKarsten Keil 	u16			timebase;
4503712b42dSKarsten Keil 	int			m, mlen;
4513712b42dSKarsten Keil 	int			len_start = len; /* initial frame length */
4523712b42dSKarsten Keil 	struct dchannel		*dch = hc->chan[hc->d_idx].dch;
4533712b42dSKarsten Keil 
4543712b42dSKarsten Keil 	if (debug & DEBUG_L1OIP_MSG)
4553712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: received frame, parsing... (%d)\n",
4563712b42dSKarsten Keil 		       __func__, len);
4573712b42dSKarsten Keil 
4581537a363SDaniel Mack 	/* check length */
4593712b42dSKarsten Keil 	if (len < 1 + 1 + 2) {
4603712b42dSKarsten Keil 		printk(KERN_WARNING "%s: packet error - length %d below "
4613712b42dSKarsten Keil 		       "4 bytes\n", __func__, len);
4623712b42dSKarsten Keil 		return;
4633712b42dSKarsten Keil 	}
4643712b42dSKarsten Keil 
4653712b42dSKarsten Keil 	/* check version */
4663712b42dSKarsten Keil 	if (((*buf) >> 6) != L1OIP_VERSION) {
4673712b42dSKarsten Keil 		printk(KERN_WARNING "%s: packet error - unknown version %d\n",
4683712b42dSKarsten Keil 		       __func__, buf[0]>>6);
4693712b42dSKarsten Keil 		return;
4703712b42dSKarsten Keil 	}
4713712b42dSKarsten Keil 
4723712b42dSKarsten Keil 	/* check type */
4733712b42dSKarsten Keil 	if (((*buf) & 0x20) && !hc->pri) {
4743712b42dSKarsten Keil 		printk(KERN_WARNING "%s: packet error - received E1 packet "
4753712b42dSKarsten Keil 		       "on S0 interface\n", __func__);
4763712b42dSKarsten Keil 		return;
4773712b42dSKarsten Keil 	}
4783712b42dSKarsten Keil 	if (!((*buf) & 0x20) && hc->pri) {
4793712b42dSKarsten Keil 		printk(KERN_WARNING "%s: packet error - received S0 packet "
4803712b42dSKarsten Keil 		       "on E1 interface\n", __func__);
4813712b42dSKarsten Keil 		return;
4823712b42dSKarsten Keil 	}
4833712b42dSKarsten Keil 
4843712b42dSKarsten Keil 	/* get id flag */
485863a76e5SHannes Eder 	packet_id = (*buf >> 4) & 1;
4863712b42dSKarsten Keil 
4873712b42dSKarsten Keil 	/* check coding */
4883712b42dSKarsten Keil 	remotecodec = (*buf) & 0x0f;
4893712b42dSKarsten Keil 	if (remotecodec > 3) {
4903712b42dSKarsten Keil 		printk(KERN_WARNING "%s: packet error - remotecodec %d "
4913712b42dSKarsten Keil 		       "unsupported\n", __func__, remotecodec);
4923712b42dSKarsten Keil 		return;
4933712b42dSKarsten Keil 	}
4943712b42dSKarsten Keil 	buf++;
4953712b42dSKarsten Keil 	len--;
4963712b42dSKarsten Keil 
497863a76e5SHannes Eder 	/* check packet_id */
498863a76e5SHannes Eder 	if (packet_id) {
4993712b42dSKarsten Keil 		if (!hc->id) {
5003712b42dSKarsten Keil 			printk(KERN_WARNING "%s: packet error - packet has id "
501863a76e5SHannes Eder 			       "0x%x, but we have not\n", __func__, packet_id);
5023712b42dSKarsten Keil 			return;
5033712b42dSKarsten Keil 		}
5043712b42dSKarsten Keil 		if (len < 4) {
5053712b42dSKarsten Keil 			printk(KERN_WARNING "%s: packet error - packet too "
5063712b42dSKarsten Keil 			       "short for ID value\n", __func__);
5073712b42dSKarsten Keil 			return;
5083712b42dSKarsten Keil 		}
509863a76e5SHannes Eder 		packet_id = (*buf++) << 24;
510863a76e5SHannes Eder 		packet_id += (*buf++) << 16;
511863a76e5SHannes Eder 		packet_id += (*buf++) << 8;
512863a76e5SHannes Eder 		packet_id += (*buf++);
5133712b42dSKarsten Keil 		len -= 4;
5143712b42dSKarsten Keil 
515863a76e5SHannes Eder 		if (packet_id != hc->id) {
5163712b42dSKarsten Keil 			printk(KERN_WARNING "%s: packet error - ID mismatch, "
5173712b42dSKarsten Keil 			       "got 0x%x, we 0x%x\n",
518863a76e5SHannes Eder 			       __func__, packet_id, hc->id);
5193712b42dSKarsten Keil 			return;
5203712b42dSKarsten Keil 		}
5213712b42dSKarsten Keil 	} else {
5223712b42dSKarsten Keil 		if (hc->id) {
5233712b42dSKarsten Keil 			printk(KERN_WARNING "%s: packet error - packet has no "
5243712b42dSKarsten Keil 			       "ID, but we have\n", __func__);
5253712b42dSKarsten Keil 			return;
5263712b42dSKarsten Keil 		}
5273712b42dSKarsten Keil 	}
5283712b42dSKarsten Keil 
5293712b42dSKarsten Keil multiframe:
5303712b42dSKarsten Keil 	if (len < 1) {
5313712b42dSKarsten Keil 		printk(KERN_WARNING "%s: packet error - packet too short, "
5323712b42dSKarsten Keil 		       "channel expected at position %d.\n",
5333712b42dSKarsten Keil 		       __func__, len-len_start + 1);
5343712b42dSKarsten Keil 		return;
5353712b42dSKarsten Keil 	}
5363712b42dSKarsten Keil 
5373712b42dSKarsten Keil 	/* get channel and multiframe flag */
5383712b42dSKarsten Keil 	channel = *buf & 0x7f;
5393712b42dSKarsten Keil 	m = *buf >> 7;
5403712b42dSKarsten Keil 	buf++;
5413712b42dSKarsten Keil 	len--;
5423712b42dSKarsten Keil 
5433712b42dSKarsten Keil 	/* check length on multiframe */
5443712b42dSKarsten Keil 	if (m) {
5453712b42dSKarsten Keil 		if (len < 1) {
5463712b42dSKarsten Keil 			printk(KERN_WARNING "%s: packet error - packet too "
5473712b42dSKarsten Keil 			       "short, length expected at position %d.\n",
5483712b42dSKarsten Keil 			       __func__, len_start - len - 1);
5493712b42dSKarsten Keil 			return;
5503712b42dSKarsten Keil 		}
5513712b42dSKarsten Keil 
5523712b42dSKarsten Keil 		mlen = *buf++;
5533712b42dSKarsten Keil 		len--;
5543712b42dSKarsten Keil 		if (mlen == 0)
5553712b42dSKarsten Keil 			mlen = 256;
5563712b42dSKarsten Keil 		if (len < mlen + 3) {
5573712b42dSKarsten Keil 			printk(KERN_WARNING "%s: packet error - length %d at "
5583712b42dSKarsten Keil 			       "position %d exceeds total length %d.\n",
5593712b42dSKarsten Keil 			       __func__, mlen, len_start-len - 1, len_start);
5603712b42dSKarsten Keil 			return;
5613712b42dSKarsten Keil 		}
5623712b42dSKarsten Keil 		if (len == mlen + 3) {
5633712b42dSKarsten Keil 			printk(KERN_WARNING "%s: packet error - length %d at "
5643712b42dSKarsten Keil 			       "position %d will not allow additional "
5653712b42dSKarsten Keil 			       "packet.\n",
5663712b42dSKarsten Keil 			       __func__, mlen, len_start-len + 1);
5673712b42dSKarsten Keil 			return;
5683712b42dSKarsten Keil 		}
5693712b42dSKarsten Keil 	} else
57025985edcSLucas De Marchi 		mlen = len - 2; /* single frame, subtract timebase */
5713712b42dSKarsten Keil 
5723712b42dSKarsten Keil 	if (len < 2) {
5733712b42dSKarsten Keil 		printk(KERN_WARNING "%s: packet error - packet too short, time "
5743712b42dSKarsten Keil 		       "base expected at position %d.\n",
5753712b42dSKarsten Keil 		       __func__, len-len_start + 1);
5763712b42dSKarsten Keil 		return;
5773712b42dSKarsten Keil 	}
5783712b42dSKarsten Keil 
5793712b42dSKarsten Keil 	/* get time base */
5803712b42dSKarsten Keil 	timebase = (*buf++) << 8;
5813712b42dSKarsten Keil 	timebase |= (*buf++);
5823712b42dSKarsten Keil 	len -= 2;
5833712b42dSKarsten Keil 
5843712b42dSKarsten Keil 	/* if inactive, we send up a PH_ACTIVATE and activate */
5853712b42dSKarsten Keil 	if (!test_bit(FLG_ACTIVE, &dch->Flags)) {
5863712b42dSKarsten Keil 		if (debug & (DEBUG_L1OIP_MSG | DEBUG_L1OIP_SOCKET))
5873712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: interface become active due to "
5883712b42dSKarsten Keil 			       "received packet\n", __func__);
5893712b42dSKarsten Keil 		test_and_set_bit(FLG_ACTIVE, &dch->Flags);
5903712b42dSKarsten Keil 		_queue_data(&dch->dev.D, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
5913712b42dSKarsten Keil 			    NULL, GFP_ATOMIC);
5923712b42dSKarsten Keil 	}
5933712b42dSKarsten Keil 
5943712b42dSKarsten Keil 	/* distribute packet */
5953712b42dSKarsten Keil 	l1oip_socket_recv(hc, remotecodec, channel, timebase, buf, mlen);
5963712b42dSKarsten Keil 	buf += mlen;
5973712b42dSKarsten Keil 	len -= mlen;
5983712b42dSKarsten Keil 
5993712b42dSKarsten Keil 	/* multiframe */
6003712b42dSKarsten Keil 	if (m)
6013712b42dSKarsten Keil 		goto multiframe;
6023712b42dSKarsten Keil 
6033712b42dSKarsten Keil 	/* restart timer */
6042568a7e0SDuoming Zhou 	if ((time_before(hc->timeout_tl.expires, jiffies + 5 * HZ) ||
6052568a7e0SDuoming Zhou 	     !hc->timeout_on) &&
6062568a7e0SDuoming Zhou 	    !hc->shutdown) {
6073712b42dSKarsten Keil 		hc->timeout_on = 1;
60887f03cc3SManuel Schölling 		mod_timer(&hc->timeout_tl, jiffies + L1OIP_TIMEOUT * HZ);
6093712b42dSKarsten Keil 	} else /* only adjust timer */
6103712b42dSKarsten Keil 		hc->timeout_tl.expires = jiffies + L1OIP_TIMEOUT * HZ;
6113712b42dSKarsten Keil 
6123712b42dSKarsten Keil 	/* if ip or source port changes */
6133712b42dSKarsten Keil 	if ((hc->sin_remote.sin_addr.s_addr != sin->sin_addr.s_addr)
6143712b42dSKarsten Keil 	    || (hc->sin_remote.sin_port != sin->sin_port)) {
6153712b42dSKarsten Keil 		if (debug & DEBUG_L1OIP_SOCKET)
6163712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: remote address changes from "
6173712b42dSKarsten Keil 			       "0x%08x to 0x%08x (port %d to %d)\n", __func__,
6183712b42dSKarsten Keil 			       ntohl(hc->sin_remote.sin_addr.s_addr),
6193712b42dSKarsten Keil 			       ntohl(sin->sin_addr.s_addr),
6203712b42dSKarsten Keil 			       ntohs(hc->sin_remote.sin_port),
6213712b42dSKarsten Keil 			       ntohs(sin->sin_port));
6223712b42dSKarsten Keil 		hc->sin_remote.sin_addr.s_addr = sin->sin_addr.s_addr;
6233712b42dSKarsten Keil 		hc->sin_remote.sin_port = sin->sin_port;
6243712b42dSKarsten Keil 	}
6253712b42dSKarsten Keil }
6263712b42dSKarsten Keil 
6273712b42dSKarsten Keil 
6283712b42dSKarsten Keil /*
6293712b42dSKarsten Keil  * socket stuff
6303712b42dSKarsten Keil  */
6313712b42dSKarsten Keil static int
l1oip_socket_thread(void * data)6323712b42dSKarsten Keil l1oip_socket_thread(void *data)
6333712b42dSKarsten Keil {
6343712b42dSKarsten Keil 	struct l1oip *hc = (struct l1oip *)data;
6353712b42dSKarsten Keil 	int ret = 0;
6363712b42dSKarsten Keil 	struct sockaddr_in sin_rx;
637956a27ecSAl Viro 	struct kvec iov;
638956a27ecSAl Viro 	struct msghdr msg = {.msg_name = &sin_rx,
639956a27ecSAl Viro 			     .msg_namelen = sizeof(sin_rx)};
6403dc40393SFrank Seidel 	unsigned char *recvbuf;
6413dc40393SFrank Seidel 	size_t recvbuf_size = 1500;
6423712b42dSKarsten Keil 	int recvlen;
6433712b42dSKarsten Keil 	struct socket *socket = NULL;
64401a1e7ecSYong Zhang 	DECLARE_COMPLETION_ONSTACK(wait);
6453712b42dSKarsten Keil 
6463dc40393SFrank Seidel 	/* allocate buffer memory */
6473dc40393SFrank Seidel 	recvbuf = kmalloc(recvbuf_size, GFP_KERNEL);
6483dc40393SFrank Seidel 	if (!recvbuf) {
6493dc40393SFrank Seidel 		printk(KERN_ERR "%s: Failed to alloc recvbuf.\n", __func__);
6503dc40393SFrank Seidel 		ret = -ENOMEM;
6513dc40393SFrank Seidel 		goto fail;
6523dc40393SFrank Seidel 	}
6533dc40393SFrank Seidel 
654956a27ecSAl Viro 	iov.iov_base = recvbuf;
655956a27ecSAl Viro 	iov.iov_len = recvbuf_size;
656956a27ecSAl Viro 
6573712b42dSKarsten Keil 	/* make daemon */
6583712b42dSKarsten Keil 	allow_signal(SIGTERM);
6593712b42dSKarsten Keil 
6603712b42dSKarsten Keil 	/* create socket */
6613712b42dSKarsten Keil 	if (sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &socket)) {
6623712b42dSKarsten Keil 		printk(KERN_ERR "%s: Failed to create socket.\n", __func__);
6633dc40393SFrank Seidel 		ret = -EIO;
6643dc40393SFrank Seidel 		goto fail;
6653712b42dSKarsten Keil 	}
6663712b42dSKarsten Keil 
6673712b42dSKarsten Keil 	/* set incoming address */
6683712b42dSKarsten Keil 	hc->sin_local.sin_family = AF_INET;
6693712b42dSKarsten Keil 	hc->sin_local.sin_addr.s_addr = INADDR_ANY;
6703712b42dSKarsten Keil 	hc->sin_local.sin_port = htons((unsigned short)hc->localport);
6713712b42dSKarsten Keil 
6723712b42dSKarsten Keil 	/* set outgoing address */
6733712b42dSKarsten Keil 	hc->sin_remote.sin_family = AF_INET;
6743712b42dSKarsten Keil 	hc->sin_remote.sin_addr.s_addr = htonl(hc->remoteip);
6753712b42dSKarsten Keil 	hc->sin_remote.sin_port = htons((unsigned short)hc->remoteport);
6763712b42dSKarsten Keil 
677d82603c6SJorrit Schippers 	/* bind to incoming port */
6783712b42dSKarsten Keil 	if (socket->ops->bind(socket, (struct sockaddr *)&hc->sin_local,
6793712b42dSKarsten Keil 			      sizeof(hc->sin_local))) {
6803712b42dSKarsten Keil 		printk(KERN_ERR "%s: Failed to bind socket to port %d.\n",
6813712b42dSKarsten Keil 		       __func__, hc->localport);
6823712b42dSKarsten Keil 		ret = -EINVAL;
6833712b42dSKarsten Keil 		goto fail;
6843712b42dSKarsten Keil 	}
6853712b42dSKarsten Keil 
6863712b42dSKarsten Keil 	/* check sk */
6873712b42dSKarsten Keil 	if (socket->sk == NULL) {
6883712b42dSKarsten Keil 		printk(KERN_ERR "%s: socket->sk == NULL\n", __func__);
6893712b42dSKarsten Keil 		ret = -EIO;
6903712b42dSKarsten Keil 		goto fail;
6913712b42dSKarsten Keil 	}
6923712b42dSKarsten Keil 
6933712b42dSKarsten Keil 	/* build send message */
6943712b42dSKarsten Keil 	hc->sendmsg.msg_name = &hc->sin_remote;
6953712b42dSKarsten Keil 	hc->sendmsg.msg_namelen = sizeof(hc->sin_remote);
6963712b42dSKarsten Keil 	hc->sendmsg.msg_control = NULL;
6973712b42dSKarsten Keil 	hc->sendmsg.msg_controllen = 0;
6983712b42dSKarsten Keil 
6993712b42dSKarsten Keil 	/* give away socket */
7003712b42dSKarsten Keil 	spin_lock(&hc->socket_lock);
7013712b42dSKarsten Keil 	hc->socket = socket;
7023712b42dSKarsten Keil 	spin_unlock(&hc->socket_lock);
7033712b42dSKarsten Keil 
7043712b42dSKarsten Keil 	/* read loop */
7053712b42dSKarsten Keil 	if (debug & DEBUG_L1OIP_SOCKET)
7063712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: socket created and open\n",
7073712b42dSKarsten Keil 		       __func__);
7083712b42dSKarsten Keil 	while (!signal_pending(current)) {
709de4eda9dSAl Viro 		iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, recvbuf_size);
710956a27ecSAl Viro 		recvlen = sock_recvmsg(socket, &msg, 0);
7113712b42dSKarsten Keil 		if (recvlen > 0) {
7123712b42dSKarsten Keil 			l1oip_socket_parse(hc, &sin_rx, recvbuf, recvlen);
7133712b42dSKarsten Keil 		} else {
7143712b42dSKarsten Keil 			if (debug & DEBUG_L1OIP_SOCKET)
715eac74af9SKarsten Keil 				printk(KERN_WARNING
716eac74af9SKarsten Keil 				       "%s: broken pipe on socket\n", __func__);
7173712b42dSKarsten Keil 		}
7183712b42dSKarsten Keil 	}
7193712b42dSKarsten Keil 
7203712b42dSKarsten Keil 	/* get socket back, check first if in use, maybe by send function */
7213712b42dSKarsten Keil 	spin_lock(&hc->socket_lock);
7223712b42dSKarsten Keil 	/* if hc->socket is NULL, it is in use until it is given back */
7233712b42dSKarsten Keil 	while (!hc->socket) {
7243712b42dSKarsten Keil 		spin_unlock(&hc->socket_lock);
7253712b42dSKarsten Keil 		schedule_timeout(HZ / 10);
7263712b42dSKarsten Keil 		spin_lock(&hc->socket_lock);
7273712b42dSKarsten Keil 	}
7283712b42dSKarsten Keil 	hc->socket = NULL;
7293712b42dSKarsten Keil 	spin_unlock(&hc->socket_lock);
7303712b42dSKarsten Keil 
7313712b42dSKarsten Keil 	if (debug & DEBUG_L1OIP_SOCKET)
7323712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: socket thread terminating\n",
7333712b42dSKarsten Keil 		       __func__);
7343712b42dSKarsten Keil 
7353712b42dSKarsten Keil fail:
7363dc40393SFrank Seidel 	/* free recvbuf */
7373dc40393SFrank Seidel 	kfree(recvbuf);
7383dc40393SFrank Seidel 
7393712b42dSKarsten Keil 	/* close socket */
7403712b42dSKarsten Keil 	if (socket)
7413712b42dSKarsten Keil 		sock_release(socket);
7423712b42dSKarsten Keil 
7433712b42dSKarsten Keil 	/* if we got killed, signal completion */
7443712b42dSKarsten Keil 	complete(&hc->socket_complete);
7453712b42dSKarsten Keil 	hc->socket_thread = NULL; /* show termination of thread */
7463712b42dSKarsten Keil 
7473712b42dSKarsten Keil 	if (debug & DEBUG_L1OIP_SOCKET)
7483712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: socket thread terminated\n",
7493712b42dSKarsten Keil 		       __func__);
7503712b42dSKarsten Keil 	return ret;
7513712b42dSKarsten Keil }
7523712b42dSKarsten Keil 
7533712b42dSKarsten Keil static void
l1oip_socket_close(struct l1oip * hc)7543712b42dSKarsten Keil l1oip_socket_close(struct l1oip *hc)
7553712b42dSKarsten Keil {
7561b4d3312SAndreas Eversberg 	struct dchannel *dch = hc->chan[hc->d_idx].dch;
7571b4d3312SAndreas Eversberg 
7583712b42dSKarsten Keil 	/* kill thread */
7593712b42dSKarsten Keil 	if (hc->socket_thread) {
7603712b42dSKarsten Keil 		if (debug & DEBUG_L1OIP_SOCKET)
7613712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: socket thread exists, "
7623712b42dSKarsten Keil 			       "killing...\n", __func__);
7633712b42dSKarsten Keil 		send_sig(SIGTERM, hc->socket_thread, 0);
7643712b42dSKarsten Keil 		wait_for_completion(&hc->socket_complete);
7653712b42dSKarsten Keil 	}
7661b4d3312SAndreas Eversberg 
7671b4d3312SAndreas Eversberg 	/* if active, we send up a PH_DEACTIVATE and deactivate */
7681b4d3312SAndreas Eversberg 	if (test_bit(FLG_ACTIVE, &dch->Flags)) {
7691b4d3312SAndreas Eversberg 		if (debug & (DEBUG_L1OIP_MSG | DEBUG_L1OIP_SOCKET))
7701b4d3312SAndreas Eversberg 			printk(KERN_DEBUG "%s: interface become deactivated "
7711b4d3312SAndreas Eversberg 			       "due to timeout\n", __func__);
7721b4d3312SAndreas Eversberg 		test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
7731b4d3312SAndreas Eversberg 		_queue_data(&dch->dev.D, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
7741b4d3312SAndreas Eversberg 			    NULL, GFP_ATOMIC);
7751b4d3312SAndreas Eversberg 	}
7763712b42dSKarsten Keil }
7773712b42dSKarsten Keil 
7783712b42dSKarsten Keil static int
l1oip_socket_open(struct l1oip * hc)7793712b42dSKarsten Keil l1oip_socket_open(struct l1oip *hc)
7803712b42dSKarsten Keil {
7813712b42dSKarsten Keil 	/* in case of reopen, we need to close first */
7823712b42dSKarsten Keil 	l1oip_socket_close(hc);
7833712b42dSKarsten Keil 
7843712b42dSKarsten Keil 	init_completion(&hc->socket_complete);
7853712b42dSKarsten Keil 
7863712b42dSKarsten Keil 	/* create receive process */
7873712b42dSKarsten Keil 	hc->socket_thread = kthread_run(l1oip_socket_thread, hc, "l1oip_%s",
7883712b42dSKarsten Keil 					hc->name);
7893712b42dSKarsten Keil 	if (IS_ERR(hc->socket_thread)) {
7903712b42dSKarsten Keil 		int err = PTR_ERR(hc->socket_thread);
7913712b42dSKarsten Keil 		printk(KERN_ERR "%s: Failed (%d) to create socket process.\n",
7923712b42dSKarsten Keil 		       __func__, err);
7933712b42dSKarsten Keil 		hc->socket_thread = NULL;
7943712b42dSKarsten Keil 		sock_release(hc->socket);
7953712b42dSKarsten Keil 		return err;
7963712b42dSKarsten Keil 	}
7973712b42dSKarsten Keil 	if (debug & DEBUG_L1OIP_SOCKET)
7983712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: socket thread created\n", __func__);
7993712b42dSKarsten Keil 
8003712b42dSKarsten Keil 	return 0;
8013712b42dSKarsten Keil }
8023712b42dSKarsten Keil 
8033712b42dSKarsten Keil 
8043712b42dSKarsten Keil static void
l1oip_send_bh(struct work_struct * work)8053712b42dSKarsten Keil l1oip_send_bh(struct work_struct *work)
8063712b42dSKarsten Keil {
8073712b42dSKarsten Keil 	struct l1oip *hc = container_of(work, struct l1oip, workq);
8083712b42dSKarsten Keil 
8093712b42dSKarsten Keil 	if (debug & (DEBUG_L1OIP_MSG | DEBUG_L1OIP_SOCKET))
8103712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: keepalive timer expired, sending empty "
8113712b42dSKarsten Keil 		       "frame on dchannel\n", __func__);
8123712b42dSKarsten Keil 
8133712b42dSKarsten Keil 	/* send an empty l1oip frame at D-channel */
8143712b42dSKarsten Keil 	l1oip_socket_send(hc, 0, hc->d_idx, 0, 0, NULL, 0);
8153712b42dSKarsten Keil }
8163712b42dSKarsten Keil 
8173712b42dSKarsten Keil 
8183712b42dSKarsten Keil /*
8193712b42dSKarsten Keil  * timer stuff
8203712b42dSKarsten Keil  */
8213712b42dSKarsten Keil static void
l1oip_keepalive(struct timer_list * t)822e313ac12SKees Cook l1oip_keepalive(struct timer_list *t)
8233712b42dSKarsten Keil {
824e313ac12SKees Cook 	struct l1oip *hc = from_timer(hc, t, keep_tl);
8253712b42dSKarsten Keil 
8263712b42dSKarsten Keil 	schedule_work(&hc->workq);
8273712b42dSKarsten Keil }
8283712b42dSKarsten Keil 
8293712b42dSKarsten Keil static void
l1oip_timeout(struct timer_list * t)830e313ac12SKees Cook l1oip_timeout(struct timer_list *t)
8313712b42dSKarsten Keil {
832e313ac12SKees Cook 	struct l1oip			*hc = from_timer(hc, t,
833e313ac12SKees Cook 								  timeout_tl);
8343712b42dSKarsten Keil 	struct dchannel		*dch = hc->chan[hc->d_idx].dch;
8353712b42dSKarsten Keil 
8363712b42dSKarsten Keil 	if (debug & DEBUG_L1OIP_MSG)
8373712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: timeout timer expired, turn layer one "
8383712b42dSKarsten Keil 		       "down.\n", __func__);
8393712b42dSKarsten Keil 
8403712b42dSKarsten Keil 	hc->timeout_on = 0; /* state that timer must be initialized next time */
8413712b42dSKarsten Keil 
8423712b42dSKarsten Keil 	/* if timeout, we send up a PH_DEACTIVATE and deactivate */
8433712b42dSKarsten Keil 	if (test_bit(FLG_ACTIVE, &dch->Flags)) {
8443712b42dSKarsten Keil 		if (debug & (DEBUG_L1OIP_MSG | DEBUG_L1OIP_SOCKET))
8453712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: interface become deactivated "
8463712b42dSKarsten Keil 			       "due to timeout\n", __func__);
8473712b42dSKarsten Keil 		test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
8483712b42dSKarsten Keil 		_queue_data(&dch->dev.D, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
8493712b42dSKarsten Keil 			    NULL, GFP_ATOMIC);
8503712b42dSKarsten Keil 	}
8513712b42dSKarsten Keil 
8523712b42dSKarsten Keil 	/* if we have ondemand set, we remove ip address */
8533712b42dSKarsten Keil 	if (hc->ondemand) {
8543712b42dSKarsten Keil 		if (debug & DEBUG_L1OIP_MSG)
8553712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: on demand causes ip address to "
8563712b42dSKarsten Keil 			       "be removed\n", __func__);
8573712b42dSKarsten Keil 		hc->sin_remote.sin_addr.s_addr = 0;
8583712b42dSKarsten Keil 	}
8593712b42dSKarsten Keil }
8603712b42dSKarsten Keil 
8613712b42dSKarsten Keil 
8623712b42dSKarsten Keil /*
8633712b42dSKarsten Keil  * message handling
8643712b42dSKarsten Keil  */
8653712b42dSKarsten Keil static int
handle_dmsg(struct mISDNchannel * ch,struct sk_buff * skb)8663712b42dSKarsten Keil handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb)
8673712b42dSKarsten Keil {
8683712b42dSKarsten Keil 	struct mISDNdevice	*dev = container_of(ch, struct mISDNdevice, D);
8693712b42dSKarsten Keil 	struct dchannel		*dch = container_of(dev, struct dchannel, dev);
8703712b42dSKarsten Keil 	struct l1oip			*hc = dch->hw;
8713712b42dSKarsten Keil 	struct mISDNhead	*hh = mISDN_HEAD_P(skb);
8723712b42dSKarsten Keil 	int			ret = -EINVAL;
8733712b42dSKarsten Keil 	int			l, ll;
8743712b42dSKarsten Keil 	unsigned char		*p;
8753712b42dSKarsten Keil 
8763712b42dSKarsten Keil 	switch (hh->prim) {
8773712b42dSKarsten Keil 	case PH_DATA_REQ:
8783712b42dSKarsten Keil 		if (skb->len < 1) {
8793712b42dSKarsten Keil 			printk(KERN_WARNING "%s: skb too small\n",
8803712b42dSKarsten Keil 			       __func__);
8813712b42dSKarsten Keil 			break;
8823712b42dSKarsten Keil 		}
8833712b42dSKarsten Keil 		if (skb->len > MAX_DFRAME_LEN_L1 || skb->len > L1OIP_MAX_LEN) {
8843712b42dSKarsten Keil 			printk(KERN_WARNING "%s: skb too large\n",
8853712b42dSKarsten Keil 			       __func__);
8863712b42dSKarsten Keil 			break;
8873712b42dSKarsten Keil 		}
8883712b42dSKarsten Keil 		/* send frame */
8893712b42dSKarsten Keil 		p = skb->data;
8903712b42dSKarsten Keil 		l = skb->len;
8913712b42dSKarsten Keil 		while (l) {
8929a438161SLaura Abbott 			/*
8939a438161SLaura Abbott 			 * This is technically bounded by L1OIP_MAX_PERFRAME but
8949a438161SLaura Abbott 			 * MAX_DFRAME_LEN_L1 < L1OIP_MAX_PERFRAME
8959a438161SLaura Abbott 			 */
8969a438161SLaura Abbott 			ll = (l < MAX_DFRAME_LEN_L1) ? l : MAX_DFRAME_LEN_L1;
8973712b42dSKarsten Keil 			l1oip_socket_send(hc, 0, dch->slot, 0,
8983712b42dSKarsten Keil 					  hc->chan[dch->slot].tx_counter++, p, ll);
8993712b42dSKarsten Keil 			p += ll;
9003712b42dSKarsten Keil 			l -= ll;
9013712b42dSKarsten Keil 		}
9023712b42dSKarsten Keil 		skb_trim(skb, 0);
9033712b42dSKarsten Keil 		queue_ch_frame(ch, PH_DATA_CNF, hh->id, skb);
9043712b42dSKarsten Keil 		return 0;
9053712b42dSKarsten Keil 	case PH_ACTIVATE_REQ:
9063712b42dSKarsten Keil 		if (debug & (DEBUG_L1OIP_MSG | DEBUG_L1OIP_SOCKET))
9073712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: PH_ACTIVATE channel %d (1..%d)\n"
9083712b42dSKarsten Keil 			       , __func__, dch->slot, hc->b_num + 1);
9093712b42dSKarsten Keil 		skb_trim(skb, 0);
9103712b42dSKarsten Keil 		if (test_bit(FLG_ACTIVE, &dch->Flags))
9113712b42dSKarsten Keil 			queue_ch_frame(ch, PH_ACTIVATE_IND, hh->id, skb);
9123712b42dSKarsten Keil 		else
9133712b42dSKarsten Keil 			queue_ch_frame(ch, PH_DEACTIVATE_IND, hh->id, skb);
9143712b42dSKarsten Keil 		return 0;
9153712b42dSKarsten Keil 	case PH_DEACTIVATE_REQ:
9163712b42dSKarsten Keil 		if (debug & (DEBUG_L1OIP_MSG | DEBUG_L1OIP_SOCKET))
9173712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: PH_DEACTIVATE channel %d "
9183712b42dSKarsten Keil 			       "(1..%d)\n", __func__, dch->slot,
9193712b42dSKarsten Keil 			       hc->b_num + 1);
9203712b42dSKarsten Keil 		skb_trim(skb, 0);
9213712b42dSKarsten Keil 		if (test_bit(FLG_ACTIVE, &dch->Flags))
9223712b42dSKarsten Keil 			queue_ch_frame(ch, PH_ACTIVATE_IND, hh->id, skb);
9233712b42dSKarsten Keil 		else
9243712b42dSKarsten Keil 			queue_ch_frame(ch, PH_DEACTIVATE_IND, hh->id, skb);
9253712b42dSKarsten Keil 		return 0;
9263712b42dSKarsten Keil 	}
9273712b42dSKarsten Keil 	if (!ret)
9283712b42dSKarsten Keil 		dev_kfree_skb(skb);
9293712b42dSKarsten Keil 	return ret;
9303712b42dSKarsten Keil }
9313712b42dSKarsten Keil 
9323712b42dSKarsten Keil static int
channel_dctrl(struct dchannel * dch,struct mISDN_ctrl_req * cq)9333712b42dSKarsten Keil channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq)
9343712b42dSKarsten Keil {
9353712b42dSKarsten Keil 	int	ret = 0;
9363712b42dSKarsten Keil 	struct l1oip	*hc = dch->hw;
9373712b42dSKarsten Keil 
9383712b42dSKarsten Keil 	switch (cq->op) {
9393712b42dSKarsten Keil 	case MISDN_CTRL_GETOP:
9401b4d3312SAndreas Eversberg 		cq->op = MISDN_CTRL_SETPEER | MISDN_CTRL_UNSETPEER
9411b4d3312SAndreas Eversberg 			| MISDN_CTRL_GETPEER;
9423712b42dSKarsten Keil 		break;
9433712b42dSKarsten Keil 	case MISDN_CTRL_SETPEER:
9443712b42dSKarsten Keil 		hc->remoteip = (u32)cq->p1;
9453712b42dSKarsten Keil 		hc->remoteport = cq->p2 & 0xffff;
9463712b42dSKarsten Keil 		hc->localport = cq->p2 >> 16;
9473712b42dSKarsten Keil 		if (!hc->remoteport)
9483712b42dSKarsten Keil 			hc->remoteport = hc->localport;
9493712b42dSKarsten Keil 		if (debug & DEBUG_L1OIP_SOCKET)
9503712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: got new ip address from user "
9513712b42dSKarsten Keil 			       "space.\n", __func__);
9523712b42dSKarsten Keil 		l1oip_socket_open(hc);
9533712b42dSKarsten Keil 		break;
9543712b42dSKarsten Keil 	case MISDN_CTRL_UNSETPEER:
9553712b42dSKarsten Keil 		if (debug & DEBUG_L1OIP_SOCKET)
9563712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: removing ip address.\n",
9573712b42dSKarsten Keil 			       __func__);
9583712b42dSKarsten Keil 		hc->remoteip = 0;
9593712b42dSKarsten Keil 		l1oip_socket_open(hc);
9603712b42dSKarsten Keil 		break;
9611b4d3312SAndreas Eversberg 	case MISDN_CTRL_GETPEER:
9621b4d3312SAndreas Eversberg 		if (debug & DEBUG_L1OIP_SOCKET)
9631b4d3312SAndreas Eversberg 			printk(KERN_DEBUG "%s: getting ip address.\n",
9641b4d3312SAndreas Eversberg 			       __func__);
9651b36c78fSAndreas Eversberg 		cq->p1 = hc->remoteip;
9661b4d3312SAndreas Eversberg 		cq->p2 = hc->remoteport | (hc->localport << 16);
9671b4d3312SAndreas Eversberg 		break;
9683712b42dSKarsten Keil 	default:
9693712b42dSKarsten Keil 		printk(KERN_WARNING "%s: unknown Op %x\n",
9703712b42dSKarsten Keil 		       __func__, cq->op);
9713712b42dSKarsten Keil 		ret = -EINVAL;
9723712b42dSKarsten Keil 		break;
9733712b42dSKarsten Keil 	}
9743712b42dSKarsten Keil 	return ret;
9753712b42dSKarsten Keil }
9763712b42dSKarsten Keil 
9773712b42dSKarsten Keil static int
open_dchannel(struct l1oip * hc,struct dchannel * dch,struct channel_req * rq)9783712b42dSKarsten Keil open_dchannel(struct l1oip *hc, struct dchannel *dch, struct channel_req *rq)
9793712b42dSKarsten Keil {
9803712b42dSKarsten Keil 	if (debug & DEBUG_HW_OPEN)
9813712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: dev(%d) open from %p\n", __func__,
9823712b42dSKarsten Keil 		       dch->dev.id, __builtin_return_address(0));
9833712b42dSKarsten Keil 	if (rq->protocol == ISDN_P_NONE)
9843712b42dSKarsten Keil 		return -EINVAL;
9853712b42dSKarsten Keil 	if ((dch->dev.D.protocol != ISDN_P_NONE) &&
9863712b42dSKarsten Keil 	    (dch->dev.D.protocol != rq->protocol)) {
9873712b42dSKarsten Keil 		if (debug & DEBUG_HW_OPEN)
9883712b42dSKarsten Keil 			printk(KERN_WARNING "%s: change protocol %x to %x\n",
9893712b42dSKarsten Keil 			       __func__, dch->dev.D.protocol, rq->protocol);
9903712b42dSKarsten Keil 	}
9913712b42dSKarsten Keil 	if (dch->dev.D.protocol != rq->protocol)
9923712b42dSKarsten Keil 		dch->dev.D.protocol = rq->protocol;
9933712b42dSKarsten Keil 
9943712b42dSKarsten Keil 	if (test_bit(FLG_ACTIVE, &dch->Flags)) {
9953712b42dSKarsten Keil 		_queue_data(&dch->dev.D, PH_ACTIVATE_IND, MISDN_ID_ANY,
9963712b42dSKarsten Keil 			    0, NULL, GFP_KERNEL);
9973712b42dSKarsten Keil 	}
9983712b42dSKarsten Keil 	rq->ch = &dch->dev.D;
9993712b42dSKarsten Keil 	if (!try_module_get(THIS_MODULE))
10003712b42dSKarsten Keil 		printk(KERN_WARNING "%s:cannot get module\n", __func__);
10013712b42dSKarsten Keil 	return 0;
10023712b42dSKarsten Keil }
10033712b42dSKarsten Keil 
10043712b42dSKarsten Keil static int
open_bchannel(struct l1oip * hc,struct dchannel * dch,struct channel_req * rq)10053712b42dSKarsten Keil open_bchannel(struct l1oip *hc, struct dchannel *dch, struct channel_req *rq)
10063712b42dSKarsten Keil {
10073712b42dSKarsten Keil 	struct bchannel	*bch;
10083712b42dSKarsten Keil 	int		ch;
10093712b42dSKarsten Keil 
1010ff4cc1deSKarsten Keil 	if (!test_channelmap(rq->adr.channel, dch->dev.channelmap))
10113712b42dSKarsten Keil 		return -EINVAL;
10123712b42dSKarsten Keil 	if (rq->protocol == ISDN_P_NONE)
10133712b42dSKarsten Keil 		return -EINVAL;
10143712b42dSKarsten Keil 	ch = rq->adr.channel; /* BRI: 1=B1 2=B2  PRI: 1..15,17.. */
10153712b42dSKarsten Keil 	bch = hc->chan[ch].bch;
10163712b42dSKarsten Keil 	if (!bch) {
10173712b42dSKarsten Keil 		printk(KERN_ERR "%s:internal error ch %d has no bch\n",
10183712b42dSKarsten Keil 		       __func__, ch);
10193712b42dSKarsten Keil 		return -EINVAL;
10203712b42dSKarsten Keil 	}
10213712b42dSKarsten Keil 	if (test_and_set_bit(FLG_OPEN, &bch->Flags))
10223712b42dSKarsten Keil 		return -EBUSY; /* b-channel can be only open once */
10233712b42dSKarsten Keil 	bch->ch.protocol = rq->protocol;
10243712b42dSKarsten Keil 	rq->ch = &bch->ch;
10253712b42dSKarsten Keil 	if (!try_module_get(THIS_MODULE))
10263712b42dSKarsten Keil 		printk(KERN_WARNING "%s:cannot get module\n", __func__);
10273712b42dSKarsten Keil 	return 0;
10283712b42dSKarsten Keil }
10293712b42dSKarsten Keil 
10303712b42dSKarsten Keil static int
l1oip_dctrl(struct mISDNchannel * ch,u_int cmd,void * arg)10313712b42dSKarsten Keil l1oip_dctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
10323712b42dSKarsten Keil {
10333712b42dSKarsten Keil 	struct mISDNdevice	*dev = container_of(ch, struct mISDNdevice, D);
10343712b42dSKarsten Keil 	struct dchannel		*dch = container_of(dev, struct dchannel, dev);
10353712b42dSKarsten Keil 	struct l1oip			*hc = dch->hw;
10363712b42dSKarsten Keil 	struct channel_req	*rq;
10373712b42dSKarsten Keil 	int			err = 0;
10383712b42dSKarsten Keil 
10393712b42dSKarsten Keil 	if (dch->debug & DEBUG_HW)
10403712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: cmd:%x %p\n",
10413712b42dSKarsten Keil 		       __func__, cmd, arg);
10423712b42dSKarsten Keil 	switch (cmd) {
10433712b42dSKarsten Keil 	case OPEN_CHANNEL:
10443712b42dSKarsten Keil 		rq = arg;
10453712b42dSKarsten Keil 		switch (rq->protocol) {
10463712b42dSKarsten Keil 		case ISDN_P_TE_S0:
10473712b42dSKarsten Keil 		case ISDN_P_NT_S0:
10483712b42dSKarsten Keil 			if (hc->pri) {
10493712b42dSKarsten Keil 				err = -EINVAL;
10503712b42dSKarsten Keil 				break;
10513712b42dSKarsten Keil 			}
10523712b42dSKarsten Keil 			err = open_dchannel(hc, dch, rq);
10533712b42dSKarsten Keil 			break;
10543712b42dSKarsten Keil 		case ISDN_P_TE_E1:
10553712b42dSKarsten Keil 		case ISDN_P_NT_E1:
10563712b42dSKarsten Keil 			if (!hc->pri) {
10573712b42dSKarsten Keil 				err = -EINVAL;
10583712b42dSKarsten Keil 				break;
10593712b42dSKarsten Keil 			}
10603712b42dSKarsten Keil 			err = open_dchannel(hc, dch, rq);
10613712b42dSKarsten Keil 			break;
10623712b42dSKarsten Keil 		default:
10633712b42dSKarsten Keil 			err = open_bchannel(hc, dch, rq);
10643712b42dSKarsten Keil 		}
10653712b42dSKarsten Keil 		break;
10663712b42dSKarsten Keil 	case CLOSE_CHANNEL:
10673712b42dSKarsten Keil 		if (debug & DEBUG_HW_OPEN)
10683712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: dev(%d) close from %p\n",
10693712b42dSKarsten Keil 			       __func__, dch->dev.id,
10703712b42dSKarsten Keil 			       __builtin_return_address(0));
10713712b42dSKarsten Keil 		module_put(THIS_MODULE);
10723712b42dSKarsten Keil 		break;
10733712b42dSKarsten Keil 	case CONTROL_CHANNEL:
10743712b42dSKarsten Keil 		err = channel_dctrl(dch, arg);
10753712b42dSKarsten Keil 		break;
10763712b42dSKarsten Keil 	default:
10773712b42dSKarsten Keil 		if (dch->debug & DEBUG_HW)
10783712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: unknown command %x\n",
10793712b42dSKarsten Keil 			       __func__, cmd);
10803712b42dSKarsten Keil 		err = -EINVAL;
10813712b42dSKarsten Keil 	}
10823712b42dSKarsten Keil 	return err;
10833712b42dSKarsten Keil }
10843712b42dSKarsten Keil 
10853712b42dSKarsten Keil static int
handle_bmsg(struct mISDNchannel * ch,struct sk_buff * skb)10863712b42dSKarsten Keil handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb)
10873712b42dSKarsten Keil {
10883712b42dSKarsten Keil 	struct bchannel		*bch = container_of(ch, struct bchannel, ch);
10893712b42dSKarsten Keil 	struct l1oip			*hc = bch->hw;
10903712b42dSKarsten Keil 	int			ret = -EINVAL;
10913712b42dSKarsten Keil 	struct mISDNhead	*hh = mISDN_HEAD_P(skb);
1092b5d5843aSAkinobu Mita 	int			l, ll;
10933712b42dSKarsten Keil 	unsigned char		*p;
10943712b42dSKarsten Keil 
10953712b42dSKarsten Keil 	switch (hh->prim) {
10963712b42dSKarsten Keil 	case PH_DATA_REQ:
10973712b42dSKarsten Keil 		if (skb->len <= 0) {
10983712b42dSKarsten Keil 			printk(KERN_WARNING "%s: skb too small\n",
10993712b42dSKarsten Keil 			       __func__);
11003712b42dSKarsten Keil 			break;
11013712b42dSKarsten Keil 		}
11023712b42dSKarsten Keil 		if (skb->len > MAX_DFRAME_LEN_L1 || skb->len > L1OIP_MAX_LEN) {
11033712b42dSKarsten Keil 			printk(KERN_WARNING "%s: skb too large\n",
11043712b42dSKarsten Keil 			       __func__);
11053712b42dSKarsten Keil 			break;
11063712b42dSKarsten Keil 		}
11073712b42dSKarsten Keil 		/* check for AIS / ulaw-silence */
11083712b42dSKarsten Keil 		l = skb->len;
1109b5d5843aSAkinobu Mita 		if (!memchr_inv(skb->data, 0xff, l)) {
11103712b42dSKarsten Keil 			if (debug & DEBUG_L1OIP_MSG)
11113712b42dSKarsten Keil 				printk(KERN_DEBUG "%s: got AIS, not sending, "
11123712b42dSKarsten Keil 				       "but counting\n", __func__);
11133712b42dSKarsten Keil 			hc->chan[bch->slot].tx_counter += l;
11143712b42dSKarsten Keil 			skb_trim(skb, 0);
11153712b42dSKarsten Keil 			queue_ch_frame(ch, PH_DATA_CNF, hh->id, skb);
11163712b42dSKarsten Keil 			return 0;
11173712b42dSKarsten Keil 		}
11183712b42dSKarsten Keil 		/* check for silence */
11193712b42dSKarsten Keil 		l = skb->len;
1120b5d5843aSAkinobu Mita 		if (!memchr_inv(skb->data, 0x2a, l)) {
11213712b42dSKarsten Keil 			if (debug & DEBUG_L1OIP_MSG)
11223712b42dSKarsten Keil 				printk(KERN_DEBUG "%s: got silence, not sending"
11233712b42dSKarsten Keil 				       ", but counting\n", __func__);
11243712b42dSKarsten Keil 			hc->chan[bch->slot].tx_counter += l;
11253712b42dSKarsten Keil 			skb_trim(skb, 0);
11263712b42dSKarsten Keil 			queue_ch_frame(ch, PH_DATA_CNF, hh->id, skb);
11273712b42dSKarsten Keil 			return 0;
11283712b42dSKarsten Keil 		}
11293712b42dSKarsten Keil 
11303712b42dSKarsten Keil 		/* send frame */
11313712b42dSKarsten Keil 		p = skb->data;
11323712b42dSKarsten Keil 		l = skb->len;
11333712b42dSKarsten Keil 		while (l) {
11349a438161SLaura Abbott 			/*
11359a438161SLaura Abbott 			 * This is technically bounded by L1OIP_MAX_PERFRAME but
11369a438161SLaura Abbott 			 * MAX_DFRAME_LEN_L1 < L1OIP_MAX_PERFRAME
11379a438161SLaura Abbott 			 */
11389a438161SLaura Abbott 			ll = (l < MAX_DFRAME_LEN_L1) ? l : MAX_DFRAME_LEN_L1;
11393712b42dSKarsten Keil 			l1oip_socket_send(hc, hc->codec, bch->slot, 0,
11403712b42dSKarsten Keil 					  hc->chan[bch->slot].tx_counter, p, ll);
11413712b42dSKarsten Keil 			hc->chan[bch->slot].tx_counter += ll;
11423712b42dSKarsten Keil 			p += ll;
11433712b42dSKarsten Keil 			l -= ll;
11443712b42dSKarsten Keil 		}
11453712b42dSKarsten Keil 		skb_trim(skb, 0);
11463712b42dSKarsten Keil 		queue_ch_frame(ch, PH_DATA_CNF, hh->id, skb);
11473712b42dSKarsten Keil 		return 0;
11483712b42dSKarsten Keil 	case PH_ACTIVATE_REQ:
11493712b42dSKarsten Keil 		if (debug & (DEBUG_L1OIP_MSG | DEBUG_L1OIP_SOCKET))
11503712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: PH_ACTIVATE channel %d (1..%d)\n"
11513712b42dSKarsten Keil 			       , __func__, bch->slot, hc->b_num + 1);
11523712b42dSKarsten Keil 		hc->chan[bch->slot].codecstate = 0;
11533712b42dSKarsten Keil 		test_and_set_bit(FLG_ACTIVE, &bch->Flags);
11543712b42dSKarsten Keil 		skb_trim(skb, 0);
11553712b42dSKarsten Keil 		queue_ch_frame(ch, PH_ACTIVATE_IND, hh->id, skb);
11563712b42dSKarsten Keil 		return 0;
11573712b42dSKarsten Keil 	case PH_DEACTIVATE_REQ:
11583712b42dSKarsten Keil 		if (debug & (DEBUG_L1OIP_MSG | DEBUG_L1OIP_SOCKET))
11593712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: PH_DEACTIVATE channel %d "
11603712b42dSKarsten Keil 			       "(1..%d)\n", __func__, bch->slot,
11613712b42dSKarsten Keil 			       hc->b_num + 1);
11623712b42dSKarsten Keil 		test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
11633712b42dSKarsten Keil 		skb_trim(skb, 0);
11643712b42dSKarsten Keil 		queue_ch_frame(ch, PH_DEACTIVATE_IND, hh->id, skb);
11653712b42dSKarsten Keil 		return 0;
11663712b42dSKarsten Keil 	}
11673712b42dSKarsten Keil 	if (!ret)
11683712b42dSKarsten Keil 		dev_kfree_skb(skb);
11693712b42dSKarsten Keil 	return ret;
11703712b42dSKarsten Keil }
11713712b42dSKarsten Keil 
11723712b42dSKarsten Keil static int
channel_bctrl(struct bchannel * bch,struct mISDN_ctrl_req * cq)11733712b42dSKarsten Keil channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
11743712b42dSKarsten Keil {
11753712b42dSKarsten Keil 	int			ret = 0;
11763712b42dSKarsten Keil 	struct dsp_features	*features =
11773712b42dSKarsten Keil 		(struct dsp_features *)(*((u_long *)&cq->p1));
11783712b42dSKarsten Keil 
11793712b42dSKarsten Keil 	switch (cq->op) {
11803712b42dSKarsten Keil 	case MISDN_CTRL_GETOP:
11813712b42dSKarsten Keil 		cq->op = MISDN_CTRL_HW_FEATURES_OP;
11823712b42dSKarsten Keil 		break;
11833712b42dSKarsten Keil 	case MISDN_CTRL_HW_FEATURES: /* fill features structure */
11843712b42dSKarsten Keil 		if (debug & DEBUG_L1OIP_MSG)
11853712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: HW_FEATURE request\n",
11863712b42dSKarsten Keil 			       __func__);
11873712b42dSKarsten Keil 		/* create confirm */
11883712b42dSKarsten Keil 		features->unclocked = 1;
11893712b42dSKarsten Keil 		features->unordered = 1;
11903712b42dSKarsten Keil 		break;
11913712b42dSKarsten Keil 	default:
11923712b42dSKarsten Keil 		printk(KERN_WARNING "%s: unknown Op %x\n",
11933712b42dSKarsten Keil 		       __func__, cq->op);
11943712b42dSKarsten Keil 		ret = -EINVAL;
11953712b42dSKarsten Keil 		break;
11963712b42dSKarsten Keil 	}
11973712b42dSKarsten Keil 	return ret;
11983712b42dSKarsten Keil }
11993712b42dSKarsten Keil 
12003712b42dSKarsten Keil static int
l1oip_bctrl(struct mISDNchannel * ch,u_int cmd,void * arg)12013712b42dSKarsten Keil l1oip_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
12023712b42dSKarsten Keil {
12033712b42dSKarsten Keil 	struct bchannel	*bch = container_of(ch, struct bchannel, ch);
12043712b42dSKarsten Keil 	int		err = -EINVAL;
12053712b42dSKarsten Keil 
12063712b42dSKarsten Keil 	if (bch->debug & DEBUG_HW)
12073712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: cmd:%x %p\n",
12083712b42dSKarsten Keil 		       __func__, cmd, arg);
12093712b42dSKarsten Keil 	switch (cmd) {
12103712b42dSKarsten Keil 	case CLOSE_CHANNEL:
12113712b42dSKarsten Keil 		test_and_clear_bit(FLG_OPEN, &bch->Flags);
12123712b42dSKarsten Keil 		test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
12133712b42dSKarsten Keil 		ch->protocol = ISDN_P_NONE;
12143712b42dSKarsten Keil 		ch->peer = NULL;
12153712b42dSKarsten Keil 		module_put(THIS_MODULE);
12163712b42dSKarsten Keil 		err = 0;
12173712b42dSKarsten Keil 		break;
12183712b42dSKarsten Keil 	case CONTROL_CHANNEL:
12193712b42dSKarsten Keil 		err = channel_bctrl(bch, arg);
12203712b42dSKarsten Keil 		break;
12213712b42dSKarsten Keil 	default:
12223712b42dSKarsten Keil 		printk(KERN_WARNING "%s: unknown prim(%x)\n",
12233712b42dSKarsten Keil 		       __func__, cmd);
12243712b42dSKarsten Keil 	}
12253712b42dSKarsten Keil 	return err;
12263712b42dSKarsten Keil }
12273712b42dSKarsten Keil 
12283712b42dSKarsten Keil 
12293712b42dSKarsten Keil /*
12303712b42dSKarsten Keil  * cleanup module and stack
12313712b42dSKarsten Keil  */
12323712b42dSKarsten Keil static void
release_card(struct l1oip * hc)12333712b42dSKarsten Keil release_card(struct l1oip *hc)
12343712b42dSKarsten Keil {
12353712b42dSKarsten Keil 	int	ch;
12363712b42dSKarsten Keil 
12372568a7e0SDuoming Zhou 	hc->shutdown = true;
12383712b42dSKarsten Keil 
1239*292a089dSSteven Rostedt (Google) 	timer_shutdown_sync(&hc->keep_tl);
1240*292a089dSSteven Rostedt (Google) 	timer_shutdown_sync(&hc->timeout_tl);
12413712b42dSKarsten Keil 
12420d26aa70STejun Heo 	cancel_work_sync(&hc->workq);
12430d26aa70STejun Heo 
12443712b42dSKarsten Keil 	if (hc->socket_thread)
12453712b42dSKarsten Keil 		l1oip_socket_close(hc);
12463712b42dSKarsten Keil 
12473712b42dSKarsten Keil 	if (hc->registered && hc->chan[hc->d_idx].dch)
12483712b42dSKarsten Keil 		mISDN_unregister_device(&hc->chan[hc->d_idx].dch->dev);
12493712b42dSKarsten Keil 	for (ch = 0; ch < 128; ch++) {
12503712b42dSKarsten Keil 		if (hc->chan[ch].dch) {
12513712b42dSKarsten Keil 			mISDN_freedchannel(hc->chan[ch].dch);
12523712b42dSKarsten Keil 			kfree(hc->chan[ch].dch);
12533712b42dSKarsten Keil 		}
12543712b42dSKarsten Keil 		if (hc->chan[ch].bch) {
12553712b42dSKarsten Keil 			mISDN_freebchannel(hc->chan[ch].bch);
12563712b42dSKarsten Keil 			kfree(hc->chan[ch].bch);
12573712b42dSKarsten Keil #ifdef REORDER_DEBUG
12583712b42dSKarsten Keil 			dev_kfree_skb(hc->chan[ch].disorder_skb);
12593712b42dSKarsten Keil #endif
12603712b42dSKarsten Keil 		}
12613712b42dSKarsten Keil 	}
12623712b42dSKarsten Keil 
12633712b42dSKarsten Keil 	spin_lock(&l1oip_lock);
12643712b42dSKarsten Keil 	list_del(&hc->list);
12653712b42dSKarsten Keil 	spin_unlock(&l1oip_lock);
12663712b42dSKarsten Keil 
12673712b42dSKarsten Keil 	kfree(hc);
12683712b42dSKarsten Keil }
12693712b42dSKarsten Keil 
12703712b42dSKarsten Keil static void
l1oip_cleanup(void)12713712b42dSKarsten Keil l1oip_cleanup(void)
12723712b42dSKarsten Keil {
12733712b42dSKarsten Keil 	struct l1oip *hc, *next;
12743712b42dSKarsten Keil 
12753712b42dSKarsten Keil 	list_for_each_entry_safe(hc, next, &l1oip_ilist, list)
12763712b42dSKarsten Keil 		release_card(hc);
12773712b42dSKarsten Keil 
12783712b42dSKarsten Keil 	l1oip_4bit_free();
12793712b42dSKarsten Keil }
12803712b42dSKarsten Keil 
12813712b42dSKarsten Keil 
12823712b42dSKarsten Keil /*
12833712b42dSKarsten Keil  * module and stack init
12843712b42dSKarsten Keil  */
12853712b42dSKarsten Keil static int
init_card(struct l1oip * hc,int pri,int bundle)12863712b42dSKarsten Keil init_card(struct l1oip *hc, int pri, int bundle)
12873712b42dSKarsten Keil {
12883712b42dSKarsten Keil 	struct dchannel	*dch;
12893712b42dSKarsten Keil 	struct bchannel	*bch;
12903712b42dSKarsten Keil 	int		ret;
12913712b42dSKarsten Keil 	int		i, ch;
12923712b42dSKarsten Keil 
12933712b42dSKarsten Keil 	spin_lock_init(&hc->socket_lock);
12943712b42dSKarsten Keil 	hc->idx = l1oip_cnt;
12953712b42dSKarsten Keil 	hc->pri = pri;
12963712b42dSKarsten Keil 	hc->d_idx = pri ? 16 : 3;
12973712b42dSKarsten Keil 	hc->b_num = pri ? 30 : 2;
12983712b42dSKarsten Keil 	hc->bundle = bundle;
12993712b42dSKarsten Keil 	if (hc->pri)
13003712b42dSKarsten Keil 		sprintf(hc->name, "l1oip-e1.%d", l1oip_cnt + 1);
13013712b42dSKarsten Keil 	else
13023712b42dSKarsten Keil 		sprintf(hc->name, "l1oip-s0.%d", l1oip_cnt + 1);
13033712b42dSKarsten Keil 
13043712b42dSKarsten Keil 	switch (codec[l1oip_cnt]) {
13053712b42dSKarsten Keil 	case 0: /* as is */
13063712b42dSKarsten Keil 	case 1: /* alaw */
13073712b42dSKarsten Keil 	case 2: /* ulaw */
13083712b42dSKarsten Keil 	case 3: /* 4bit */
13093712b42dSKarsten Keil 		break;
13103712b42dSKarsten Keil 	default:
13113712b42dSKarsten Keil 		printk(KERN_ERR "Codec(%d) not supported.\n",
13123712b42dSKarsten Keil 		       codec[l1oip_cnt]);
13133712b42dSKarsten Keil 		return -EINVAL;
13143712b42dSKarsten Keil 	}
13153712b42dSKarsten Keil 	hc->codec = codec[l1oip_cnt];
13163712b42dSKarsten Keil 	if (debug & DEBUG_L1OIP_INIT)
13173712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: using codec %d\n",
13183712b42dSKarsten Keil 		       __func__, hc->codec);
13193712b42dSKarsten Keil 
13203712b42dSKarsten Keil 	if (id[l1oip_cnt] == 0) {
13213712b42dSKarsten Keil 		printk(KERN_WARNING "Warning: No 'id' value given or "
13223712b42dSKarsten Keil 		       "0, this is highly unsecure. Please use 32 "
13236774def6SMasanari Iida 		       "bit random number 0x...\n");
13243712b42dSKarsten Keil 	}
13253712b42dSKarsten Keil 	hc->id = id[l1oip_cnt];
13263712b42dSKarsten Keil 	if (debug & DEBUG_L1OIP_INIT)
13273712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: using id 0x%x\n", __func__, hc->id);
13283712b42dSKarsten Keil 
13293712b42dSKarsten Keil 	hc->ondemand = ondemand[l1oip_cnt];
13303712b42dSKarsten Keil 	if (hc->ondemand && !hc->id) {
13313712b42dSKarsten Keil 		printk(KERN_ERR "%s: ondemand option only allowed in "
13323712b42dSKarsten Keil 		       "conjunction with non 0 ID\n", __func__);
13333712b42dSKarsten Keil 		return -EINVAL;
13343712b42dSKarsten Keil 	}
13353712b42dSKarsten Keil 
13363712b42dSKarsten Keil 	if (limit[l1oip_cnt])
13373712b42dSKarsten Keil 		hc->b_num = limit[l1oip_cnt];
13383712b42dSKarsten Keil 	if (!pri && hc->b_num > 2) {
13393712b42dSKarsten Keil 		printk(KERN_ERR "Maximum limit for BRI interface is 2 "
13403712b42dSKarsten Keil 		       "channels.\n");
13413712b42dSKarsten Keil 		return -EINVAL;
13423712b42dSKarsten Keil 	}
13433712b42dSKarsten Keil 	if (pri && hc->b_num > 126) {
13443712b42dSKarsten Keil 		printk(KERN_ERR "Maximum limit for PRI interface is 126 "
13453712b42dSKarsten Keil 		       "channels.\n");
13463712b42dSKarsten Keil 		return -EINVAL;
13473712b42dSKarsten Keil 	}
13483712b42dSKarsten Keil 	if (pri && hc->b_num > 30) {
13493712b42dSKarsten Keil 		printk(KERN_WARNING "Maximum limit for BRI interface is 30 "
13503712b42dSKarsten Keil 		       "channels.\n");
13513712b42dSKarsten Keil 		printk(KERN_WARNING "Your selection of %d channels must be "
13523712b42dSKarsten Keil 		       "supported by application.\n", hc->limit);
13533712b42dSKarsten Keil 	}
13543712b42dSKarsten Keil 
13553712b42dSKarsten Keil 	hc->remoteip = ip[l1oip_cnt << 2] << 24
13563712b42dSKarsten Keil 		| ip[(l1oip_cnt << 2) + 1] << 16
13573712b42dSKarsten Keil 		| ip[(l1oip_cnt << 2) + 2] << 8
13583712b42dSKarsten Keil 		| ip[(l1oip_cnt << 2) + 3];
13593712b42dSKarsten Keil 	hc->localport = port[l1oip_cnt]?:(L1OIP_DEFAULTPORT + l1oip_cnt);
13603712b42dSKarsten Keil 	if (remoteport[l1oip_cnt])
13613712b42dSKarsten Keil 		hc->remoteport = remoteport[l1oip_cnt];
13623712b42dSKarsten Keil 	else
13633712b42dSKarsten Keil 		hc->remoteport = hc->localport;
13643712b42dSKarsten Keil 	if (debug & DEBUG_L1OIP_INIT)
13653712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: using local port %d remote ip "
13663712b42dSKarsten Keil 		       "%d.%d.%d.%d port %d ondemand %d\n", __func__,
13673712b42dSKarsten Keil 		       hc->localport, hc->remoteip >> 24,
13683712b42dSKarsten Keil 		       (hc->remoteip >> 16) & 0xff,
13693712b42dSKarsten Keil 		       (hc->remoteip >> 8) & 0xff, hc->remoteip & 0xff,
13703712b42dSKarsten Keil 		       hc->remoteport, hc->ondemand);
13713712b42dSKarsten Keil 
13723712b42dSKarsten Keil 	dch = kzalloc(sizeof(struct dchannel), GFP_KERNEL);
13733712b42dSKarsten Keil 	if (!dch)
13743712b42dSKarsten Keil 		return -ENOMEM;
13753712b42dSKarsten Keil 	dch->debug = debug;
13763712b42dSKarsten Keil 	mISDN_initdchannel(dch, MAX_DFRAME_LEN_L1, NULL);
13773712b42dSKarsten Keil 	dch->hw = hc;
13783712b42dSKarsten Keil 	if (pri)
13793712b42dSKarsten Keil 		dch->dev.Dprotocols = (1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1);
13803712b42dSKarsten Keil 	else
13813712b42dSKarsten Keil 		dch->dev.Dprotocols = (1 << ISDN_P_TE_S0) | (1 << ISDN_P_NT_S0);
13823712b42dSKarsten Keil 	dch->dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
13833712b42dSKarsten Keil 		(1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
13843712b42dSKarsten Keil 	dch->dev.D.send = handle_dmsg;
13853712b42dSKarsten Keil 	dch->dev.D.ctrl = l1oip_dctrl;
13863712b42dSKarsten Keil 	dch->dev.nrbchan = hc->b_num;
13873712b42dSKarsten Keil 	dch->slot = hc->d_idx;
13883712b42dSKarsten Keil 	hc->chan[hc->d_idx].dch = dch;
13893712b42dSKarsten Keil 	i = 1;
13903712b42dSKarsten Keil 	for (ch = 0; ch < dch->dev.nrbchan; ch++) {
13913712b42dSKarsten Keil 		if (ch == 15)
13923712b42dSKarsten Keil 			i++;
13933712b42dSKarsten Keil 		bch = kzalloc(sizeof(struct bchannel), GFP_KERNEL);
13943712b42dSKarsten Keil 		if (!bch) {
13953712b42dSKarsten Keil 			printk(KERN_ERR "%s: no memory for bchannel\n",
13963712b42dSKarsten Keil 			       __func__);
13973712b42dSKarsten Keil 			return -ENOMEM;
13983712b42dSKarsten Keil 		}
13993712b42dSKarsten Keil 		bch->nr = i + ch;
14003712b42dSKarsten Keil 		bch->slot = i + ch;
14013712b42dSKarsten Keil 		bch->debug = debug;
1402034005a0SKarsten Keil 		mISDN_initbchannel(bch, MAX_DATA_MEM, 0);
14033712b42dSKarsten Keil 		bch->hw = hc;
14043712b42dSKarsten Keil 		bch->ch.send = handle_bmsg;
14053712b42dSKarsten Keil 		bch->ch.ctrl = l1oip_bctrl;
14063712b42dSKarsten Keil 		bch->ch.nr = i + ch;
14073712b42dSKarsten Keil 		list_add(&bch->ch.list, &dch->dev.bchannels);
14083712b42dSKarsten Keil 		hc->chan[i + ch].bch = bch;
1409ff4cc1deSKarsten Keil 		set_channelmap(bch->nr, dch->dev.channelmap);
14103712b42dSKarsten Keil 	}
1411b36b654aSMatthias Urlichs 	/* TODO: create a parent device for this driver */
1412b36b654aSMatthias Urlichs 	ret = mISDN_register_device(&dch->dev, NULL, hc->name);
14133712b42dSKarsten Keil 	if (ret)
14143712b42dSKarsten Keil 		return ret;
14153712b42dSKarsten Keil 	hc->registered = 1;
14163712b42dSKarsten Keil 
14173712b42dSKarsten Keil 	if (debug & DEBUG_L1OIP_INIT)
14183712b42dSKarsten Keil 		printk(KERN_DEBUG "%s: Setting up network card(%d)\n",
14193712b42dSKarsten Keil 		       __func__, l1oip_cnt + 1);
14203712b42dSKarsten Keil 	ret = l1oip_socket_open(hc);
14213712b42dSKarsten Keil 	if (ret)
14223712b42dSKarsten Keil 		return ret;
14233712b42dSKarsten Keil 
1424e313ac12SKees Cook 	timer_setup(&hc->keep_tl, l1oip_keepalive, 0);
14253712b42dSKarsten Keil 	hc->keep_tl.expires = jiffies + 2 * HZ; /* two seconds first time */
14263712b42dSKarsten Keil 	add_timer(&hc->keep_tl);
14273712b42dSKarsten Keil 
1428e313ac12SKees Cook 	timer_setup(&hc->timeout_tl, l1oip_timeout, 0);
14293712b42dSKarsten Keil 	hc->timeout_on = 0; /* state that we have timer off */
14303712b42dSKarsten Keil 
14313712b42dSKarsten Keil 	return 0;
14323712b42dSKarsten Keil }
14333712b42dSKarsten Keil 
14343712b42dSKarsten Keil static int __init
l1oip_init(void)14353712b42dSKarsten Keil l1oip_init(void)
14363712b42dSKarsten Keil {
14373712b42dSKarsten Keil 	int		pri, bundle;
14383712b42dSKarsten Keil 	struct l1oip		*hc;
14393712b42dSKarsten Keil 	int		ret;
14403712b42dSKarsten Keil 
14413712b42dSKarsten Keil 	printk(KERN_INFO "mISDN: Layer-1-over-IP driver Rev. %s\n",
14423712b42dSKarsten Keil 	       l1oip_revision);
14433712b42dSKarsten Keil 
14443712b42dSKarsten Keil 	if (l1oip_4bit_alloc(ulaw))
14453712b42dSKarsten Keil 		return -ENOMEM;
14463712b42dSKarsten Keil 
14473712b42dSKarsten Keil 	l1oip_cnt = 0;
14489bfdac94Sroel kluin 	while (l1oip_cnt < MAX_CARDS && type[l1oip_cnt]) {
14493712b42dSKarsten Keil 		switch (type[l1oip_cnt] & 0xff) {
14503712b42dSKarsten Keil 		case 1:
14513712b42dSKarsten Keil 			pri = 0;
14523712b42dSKarsten Keil 			bundle = 0;
14533712b42dSKarsten Keil 			break;
14543712b42dSKarsten Keil 		case 2:
14553712b42dSKarsten Keil 			pri = 1;
14563712b42dSKarsten Keil 			bundle = 0;
14573712b42dSKarsten Keil 			break;
14583712b42dSKarsten Keil 		case 3:
14593712b42dSKarsten Keil 			pri = 0;
14603712b42dSKarsten Keil 			bundle = 1;
14613712b42dSKarsten Keil 			break;
14623712b42dSKarsten Keil 		case 4:
14633712b42dSKarsten Keil 			pri = 1;
14643712b42dSKarsten Keil 			bundle = 1;
14653712b42dSKarsten Keil 			break;
14663712b42dSKarsten Keil 		default:
14673712b42dSKarsten Keil 			printk(KERN_ERR "Card type(%d) not supported.\n",
14683712b42dSKarsten Keil 			       type[l1oip_cnt] & 0xff);
14693712b42dSKarsten Keil 			l1oip_cleanup();
14703712b42dSKarsten Keil 			return -EINVAL;
14713712b42dSKarsten Keil 		}
14723712b42dSKarsten Keil 
14733712b42dSKarsten Keil 		if (debug & DEBUG_L1OIP_INIT)
14743712b42dSKarsten Keil 			printk(KERN_DEBUG "%s: interface %d is %s with %s.\n",
14753712b42dSKarsten Keil 			       __func__, l1oip_cnt, pri ? "PRI" : "BRI",
1476eac74af9SKarsten Keil 			       bundle ? "bundled IP packet for all B-channels" :
1477edf86baaSAdam Buchbinder 			       "separate IP packets for every B-channel");
14783712b42dSKarsten Keil 
14793712b42dSKarsten Keil 		hc = kzalloc(sizeof(struct l1oip), GFP_ATOMIC);
14803712b42dSKarsten Keil 		if (!hc) {
14813712b42dSKarsten Keil 			printk(KERN_ERR "No kmem for L1-over-IP driver.\n");
14823712b42dSKarsten Keil 			l1oip_cleanup();
14833712b42dSKarsten Keil 			return -ENOMEM;
14843712b42dSKarsten Keil 		}
14853712b42dSKarsten Keil 		INIT_WORK(&hc->workq, (void *)l1oip_send_bh);
14863712b42dSKarsten Keil 
14873712b42dSKarsten Keil 		spin_lock(&l1oip_lock);
14883712b42dSKarsten Keil 		list_add_tail(&hc->list, &l1oip_ilist);
14893712b42dSKarsten Keil 		spin_unlock(&l1oip_lock);
14903712b42dSKarsten Keil 
14913712b42dSKarsten Keil 		ret = init_card(hc, pri, bundle);
14923712b42dSKarsten Keil 		if (ret) {
14933712b42dSKarsten Keil 			l1oip_cleanup();
14943712b42dSKarsten Keil 			return ret;
14953712b42dSKarsten Keil 		}
14963712b42dSKarsten Keil 
14973712b42dSKarsten Keil 		l1oip_cnt++;
14983712b42dSKarsten Keil 	}
14993712b42dSKarsten Keil 	printk(KERN_INFO "%d virtual devices registered\n", l1oip_cnt);
15003712b42dSKarsten Keil 	return 0;
15013712b42dSKarsten Keil }
15023712b42dSKarsten Keil 
15033712b42dSKarsten Keil module_init(l1oip_init);
15043712b42dSKarsten Keil module_exit(l1oip_cleanup);
1505