diff options
-rw-r--r-- | drivers/isdn/mISDN/socket.c | 21 | ||||
-rw-r--r-- | drivers/isdn/mISDN/tei.c | 43 | ||||
-rw-r--r-- | include/linux/mISDNif.h | 2 |
3 files changed, 51 insertions, 15 deletions
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index 508945d1b9c1..530f68977361 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c | |||
@@ -292,7 +292,7 @@ static int | |||
292 | data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p) | 292 | data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p) |
293 | { | 293 | { |
294 | struct mISDN_ctrl_req cq; | 294 | struct mISDN_ctrl_req cq; |
295 | int err = -EINVAL, val; | 295 | int err = -EINVAL, val[2]; |
296 | struct mISDNchannel *bchan, *next; | 296 | struct mISDNchannel *bchan, *next; |
297 | 297 | ||
298 | lock_sock(sk); | 298 | lock_sock(sk); |
@@ -328,12 +328,27 @@ data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p) | |||
328 | err = -EINVAL; | 328 | err = -EINVAL; |
329 | break; | 329 | break; |
330 | } | 330 | } |
331 | if (get_user(val, (int __user *)p)) { | 331 | val[0] = cmd; |
332 | if (get_user(val[1], (int __user *)p)) { | ||
332 | err = -EFAULT; | 333 | err = -EFAULT; |
333 | break; | 334 | break; |
334 | } | 335 | } |
335 | err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr, | 336 | err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr, |
336 | CONTROL_CHANNEL, &val); | 337 | CONTROL_CHANNEL, val); |
338 | break; | ||
339 | case IMHOLD_L1: | ||
340 | if (sk->sk_protocol != ISDN_P_LAPD_NT | ||
341 | && sk->sk_protocol != ISDN_P_LAPD_TE) { | ||
342 | err = -EINVAL; | ||
343 | break; | ||
344 | } | ||
345 | val[0] = cmd; | ||
346 | if (get_user(val[1], (int __user *)p)) { | ||
347 | err = -EFAULT; | ||
348 | break; | ||
349 | } | ||
350 | err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr, | ||
351 | CONTROL_CHANNEL, val); | ||
337 | break; | 352 | break; |
338 | default: | 353 | default: |
339 | err = -EINVAL; | 354 | err = -EINVAL; |
diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c index b452dead8fd0..c75af762a067 100644 --- a/drivers/isdn/mISDN/tei.c +++ b/drivers/isdn/mISDN/tei.c | |||
@@ -122,8 +122,11 @@ da_deactivate(struct FsmInst *fi, int event, void *arg) | |||
122 | } | 122 | } |
123 | read_unlock_irqrestore(&mgr->lock, flags); | 123 | read_unlock_irqrestore(&mgr->lock, flags); |
124 | /* All TEI are inactiv */ | 124 | /* All TEI are inactiv */ |
125 | mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, NULL, 1); | 125 | if (!test_bit(OPTION_L1_HOLD, &mgr->options)) { |
126 | mISDN_FsmChangeState(fi, ST_L1_DEACT_PENDING); | 126 | mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, |
127 | NULL, 1); | ||
128 | mISDN_FsmChangeState(fi, ST_L1_DEACT_PENDING); | ||
129 | } | ||
127 | } | 130 | } |
128 | 131 | ||
129 | static void | 132 | static void |
@@ -132,9 +135,11 @@ da_ui(struct FsmInst *fi, int event, void *arg) | |||
132 | struct manager *mgr = fi->userdata; | 135 | struct manager *mgr = fi->userdata; |
133 | 136 | ||
134 | /* restart da timer */ | 137 | /* restart da timer */ |
135 | mISDN_FsmDelTimer(&mgr->datimer, 2); | 138 | if (!test_bit(OPTION_L1_HOLD, &mgr->options)) { |
136 | mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, NULL, 2); | 139 | mISDN_FsmDelTimer(&mgr->datimer, 2); |
137 | 140 | mISDN_FsmAddTimer(&mgr->datimer, DATIMER_VAL, EV_DATIMER, | |
141 | NULL, 2); | ||
142 | } | ||
138 | } | 143 | } |
139 | 144 | ||
140 | static void | 145 | static void |
@@ -1103,6 +1108,7 @@ free_teimanager(struct manager *mgr) | |||
1103 | { | 1108 | { |
1104 | struct layer2 *l2, *nl2; | 1109 | struct layer2 *l2, *nl2; |
1105 | 1110 | ||
1111 | test_and_clear_bit(OPTION_L1_HOLD, &mgr->options); | ||
1106 | if (test_bit(MGR_OPT_NETWORK, &mgr->options)) { | 1112 | if (test_bit(MGR_OPT_NETWORK, &mgr->options)) { |
1107 | /* not locked lock is taken in release tei */ | 1113 | /* not locked lock is taken in release tei */ |
1108 | mgr->up = NULL; | 1114 | mgr->up = NULL; |
@@ -1133,13 +1139,26 @@ static int | |||
1133 | ctrl_teimanager(struct manager *mgr, void *arg) | 1139 | ctrl_teimanager(struct manager *mgr, void *arg) |
1134 | { | 1140 | { |
1135 | /* currently we only have one option */ | 1141 | /* currently we only have one option */ |
1136 | int clean = *((int *)arg); | 1142 | int *val = (int *)arg; |
1137 | 1143 | int ret = 0; | |
1138 | if (clean) | 1144 | |
1139 | test_and_set_bit(OPTION_L2_CLEANUP, &mgr->options); | 1145 | switch (val[0]) { |
1140 | else | 1146 | case IMCLEAR_L2: |
1141 | test_and_clear_bit(OPTION_L2_CLEANUP, &mgr->options); | 1147 | if (val[1]) |
1142 | return 0; | 1148 | test_and_set_bit(OPTION_L2_CLEANUP, &mgr->options); |
1149 | else | ||
1150 | test_and_clear_bit(OPTION_L2_CLEANUP, &mgr->options); | ||
1151 | break; | ||
1152 | case IMHOLD_L1: | ||
1153 | if (val[1]) | ||
1154 | test_and_set_bit(OPTION_L1_HOLD, &mgr->options); | ||
1155 | else | ||
1156 | test_and_clear_bit(OPTION_L1_HOLD, &mgr->options); | ||
1157 | break; | ||
1158 | default: | ||
1159 | ret = -EINVAL; | ||
1160 | } | ||
1161 | return ret; | ||
1143 | } | 1162 | } |
1144 | 1163 | ||
1145 | /* This function does create a L2 for fixed TEI in NT Mode */ | 1164 | /* This function does create a L2 for fixed TEI in NT Mode */ |
diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h index cf974593a99e..0b28fd1e3938 100644 --- a/include/linux/mISDNif.h +++ b/include/linux/mISDNif.h | |||
@@ -229,6 +229,7 @@ | |||
229 | #define OPTION_L2_PTP 2 | 229 | #define OPTION_L2_PTP 2 |
230 | #define OPTION_L2_FIXEDTEI 3 | 230 | #define OPTION_L2_FIXEDTEI 3 |
231 | #define OPTION_L2_CLEANUP 4 | 231 | #define OPTION_L2_CLEANUP 4 |
232 | #define OPTION_L1_HOLD 5 | ||
232 | 233 | ||
233 | /* should be in sync with linux/kobject.h:KOBJ_NAME_LEN */ | 234 | /* should be in sync with linux/kobject.h:KOBJ_NAME_LEN */ |
234 | #define MISDN_MAX_IDLEN 20 | 235 | #define MISDN_MAX_IDLEN 20 |
@@ -317,6 +318,7 @@ struct ph_info { | |||
317 | #define IMCTRLREQ _IOR('I', 69, int) | 318 | #define IMCTRLREQ _IOR('I', 69, int) |
318 | #define IMCLEAR_L2 _IOR('I', 70, int) | 319 | #define IMCLEAR_L2 _IOR('I', 70, int) |
319 | #define IMSETDEVNAME _IOR('I', 71, struct mISDN_devrename) | 320 | #define IMSETDEVNAME _IOR('I', 71, struct mISDN_devrename) |
321 | #define IMHOLD_L1 _IOR('I', 72, int) | ||
320 | 322 | ||
321 | static inline int | 323 | static inline int |
322 | test_channelmap(u_int nr, u_char *map) | 324 | test_channelmap(u_int nr, u_char *map) |