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