mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
mISDN: Added layer-1-hold feature
Add IMHOLD_L1 ioctl. The feature will be disabled on closing. Signed-off-by: Andreas Eversberg <andreas@eversberg.eu> Signed-off-by: Karsten Keil <keil@b1-systems.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ba3af34ec9
commit
e73f6b2260
3 changed files with 50 additions and 14 deletions
|
@ -292,7 +292,7 @@ static int
|
||||||
data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p)
|
data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p)
|
||||||
{
|
{
|
||||||
struct mISDN_ctrl_req cq;
|
struct mISDN_ctrl_req cq;
|
||||||
int err = -EINVAL, val;
|
int err = -EINVAL, val[2];
|
||||||
struct mISDNchannel *bchan, *next;
|
struct mISDNchannel *bchan, *next;
|
||||||
|
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
|
@ -328,12 +328,27 @@ data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p)
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (get_user(val, (int __user *)p)) {
|
val[0] = cmd;
|
||||||
|
if (get_user(val[1], (int __user *)p)) {
|
||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr,
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
|
|
|
@ -122,8 +122,11 @@ da_deactivate(struct FsmInst *fi, int event, void *arg)
|
||||||
}
|
}
|
||||||
read_unlock_irqrestore(&mgr->lock, flags);
|
read_unlock_irqrestore(&mgr->lock, flags);
|
||||||
/* All TEI are inactiv */
|
/* All TEI are inactiv */
|
||||||
mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, NULL, 1);
|
if (!test_bit(OPTION_L1_HOLD, &mgr->options)) {
|
||||||
mISDN_FsmChangeState(fi, ST_L1_DEACT_PENDING);
|
mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER,
|
||||||
|
NULL, 1);
|
||||||
|
mISDN_FsmChangeState(fi, ST_L1_DEACT_PENDING);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -132,9 +135,11 @@ da_ui(struct FsmInst *fi, int event, void *arg)
|
||||||
struct manager *mgr = fi->userdata;
|
struct manager *mgr = fi->userdata;
|
||||||
|
|
||||||
/* restart da timer */
|
/* restart da timer */
|
||||||
mISDN_FsmDelTimer(&mgr->datimer, 2);
|
if (!test_bit(OPTION_L1_HOLD, &mgr->options)) {
|
||||||
mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, NULL, 2);
|
mISDN_FsmDelTimer(&mgr->datimer, 2);
|
||||||
|
mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER,
|
||||||
|
NULL, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1103,6 +1108,7 @@ free_teimanager(struct manager *mgr)
|
||||||
{
|
{
|
||||||
struct layer2 *l2, *nl2;
|
struct layer2 *l2, *nl2;
|
||||||
|
|
||||||
|
test_and_clear_bit(OPTION_L1_HOLD, &mgr->options);
|
||||||
if (test_bit(MGR_OPT_NETWORK, &mgr->options)) {
|
if (test_bit(MGR_OPT_NETWORK, &mgr->options)) {
|
||||||
/* not locked lock is taken in release tei */
|
/* not locked lock is taken in release tei */
|
||||||
mgr->up = NULL;
|
mgr->up = NULL;
|
||||||
|
@ -1133,13 +1139,26 @@ static int
|
||||||
ctrl_teimanager(struct manager *mgr, void *arg)
|
ctrl_teimanager(struct manager *mgr, void *arg)
|
||||||
{
|
{
|
||||||
/* currently we only have one option */
|
/* currently we only have one option */
|
||||||
int clean = *((int *)arg);
|
int *val = (int *)arg;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (clean)
|
switch (val[0]) {
|
||||||
test_and_set_bit(OPTION_L2_CLEANUP, &mgr->options);
|
case IMCLEAR_L2:
|
||||||
else
|
if (val[1])
|
||||||
test_and_clear_bit(OPTION_L2_CLEANUP, &mgr->options);
|
test_and_set_bit(OPTION_L2_CLEANUP, &mgr->options);
|
||||||
return 0;
|
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 */
|
/* This function does create a L2 for fixed TEI in NT Mode */
|
||||||
|
|
|
@ -229,6 +229,7 @@
|
||||||
#define OPTION_L2_PTP 2
|
#define OPTION_L2_PTP 2
|
||||||
#define OPTION_L2_FIXEDTEI 3
|
#define OPTION_L2_FIXEDTEI 3
|
||||||
#define OPTION_L2_CLEANUP 4
|
#define OPTION_L2_CLEANUP 4
|
||||||
|
#define OPTION_L1_HOLD 5
|
||||||
|
|
||||||
/* should be in sync with linux/kobject.h:KOBJ_NAME_LEN */
|
/* should be in sync with linux/kobject.h:KOBJ_NAME_LEN */
|
||||||
#define MISDN_MAX_IDLEN 20
|
#define MISDN_MAX_IDLEN 20
|
||||||
|
@ -317,6 +318,7 @@ struct ph_info {
|
||||||
#define IMCTRLREQ _IOR('I', 69, int)
|
#define IMCTRLREQ _IOR('I', 69, int)
|
||||||
#define IMCLEAR_L2 _IOR('I', 70, int)
|
#define IMCLEAR_L2 _IOR('I', 70, int)
|
||||||
#define IMSETDEVNAME _IOR('I', 71, struct mISDN_devrename)
|
#define IMSETDEVNAME _IOR('I', 71, struct mISDN_devrename)
|
||||||
|
#define IMHOLD_L1 _IOR('I', 72, int)
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
test_channelmap(u_int nr, u_char *map)
|
test_channelmap(u_int nr, u_char *map)
|
||||||
|
|
Loading…
Reference in a new issue