data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p)
{
struct mISDN_ctrl_req cq;
- int err = -EINVAL, val;
+ int err = -EINVAL, val[2];
struct mISDNchannel *bchan, *next;
lock_sock(sk);
err = -EINVAL;
break;
}
- if (get_user(val, (int __user *)p)) {
+ val[0] = cmd;
+ if (get_user(val[1], (int __user *)p)) {
err = -EFAULT;
break;
}
err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr,
- CONTROL_CHANNEL, &val);
+ CONTROL_CHANNEL, val);
+ break;
+ case IMHOLD_L1:
+ if (sk->sk_protocol != ISDN_P_LAPD_NT
+ && sk->sk_protocol != ISDN_P_LAPD_TE) {
+ err = -EINVAL;
+ break;
+ }
+ val[0] = cmd;
+ if (get_user(val[1], (int __user *)p)) {
+ err = -EFAULT;
+ break;
+ }
+ err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr,
+ CONTROL_CHANNEL, val);
break;
default:
err = -EINVAL;
}
read_unlock_irqrestore(&mgr->lock, flags);
/* All TEI are inactiv */
- mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, NULL, 1);
- mISDN_FsmChangeState(fi, ST_L1_DEACT_PENDING);
+ if (!test_bit(OPTION_L1_HOLD, &mgr->options)) {
+ mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER,
+ NULL, 1);
+ mISDN_FsmChangeState(fi, ST_L1_DEACT_PENDING);
+ }
}
static void
struct manager *mgr = fi->userdata;
/* restart da timer */
- mISDN_FsmDelTimer(&mgr->datimer, 2);
- mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, NULL, 2);
-
+ if (!test_bit(OPTION_L1_HOLD, &mgr->options)) {
+ mISDN_FsmDelTimer(&mgr->datimer, 2);
+ mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER,
+ NULL, 2);
+ }
}
static void
{
struct layer2 *l2, *nl2;
+ test_and_clear_bit(OPTION_L1_HOLD, &mgr->options);
if (test_bit(MGR_OPT_NETWORK, &mgr->options)) {
/* not locked lock is taken in release tei */
mgr->up = NULL;
ctrl_teimanager(struct manager *mgr, void *arg)
{
/* currently we only have one option */
- int clean = *((int *)arg);
-
- if (clean)
- test_and_set_bit(OPTION_L2_CLEANUP, &mgr->options);
- else
- test_and_clear_bit(OPTION_L2_CLEANUP, &mgr->options);
- return 0;
+ int *val = (int *)arg;
+ int ret = 0;
+
+ switch (val[0]) {
+ case IMCLEAR_L2:
+ if (val[1])
+ test_and_set_bit(OPTION_L2_CLEANUP, &mgr->options);
+ else
+ test_and_clear_bit(OPTION_L2_CLEANUP, &mgr->options);
+ break;
+ case IMHOLD_L1:
+ if (val[1])
+ test_and_set_bit(OPTION_L1_HOLD, &mgr->options);
+ else
+ test_and_clear_bit(OPTION_L1_HOLD, &mgr->options);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
}
/* This function does create a L2 for fixed TEI in NT Mode */
#define OPTION_L2_PTP 2
#define OPTION_L2_FIXEDTEI 3
#define OPTION_L2_CLEANUP 4
+#define OPTION_L1_HOLD 5
/* should be in sync with linux/kobject.h:KOBJ_NAME_LEN */
#define MISDN_MAX_IDLEN 20
#define IMCTRLREQ _IOR('I', 69, int)
#define IMCLEAR_L2 _IOR('I', 70, int)
#define IMSETDEVNAME _IOR('I', 71, struct mISDN_devrename)
+#define IMHOLD_L1 _IOR('I', 72, int)
static inline int
test_channelmap(u_int nr, u_char *map)