Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
b14ebcfc
Commit
b14ebcfc
authored
Aug 06, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://thebsh.namesys.com/bk/reiser3-linux-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
cb7ada82
16b39f5f
Changes
32
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
1739 additions
and
1649 deletions
+1739
-1649
Documentation/filesystems/ntfs.txt
Documentation/filesystems/ntfs.txt
+11
-0
drivers/isdn/act2000/capi.h
drivers/isdn/act2000/capi.h
+1
-1
drivers/isdn/i4l/isdn_audio.c
drivers/isdn/i4l/isdn_audio.c
+4
-4
drivers/isdn/i4l/isdn_common.c
drivers/isdn/i4l/isdn_common.c
+416
-314
drivers/isdn/i4l/isdn_common.h
drivers/isdn/i4l/isdn_common.h
+62
-6
drivers/isdn/i4l/isdn_net.c
drivers/isdn/i4l/isdn_net.c
+631
-715
drivers/isdn/i4l/isdn_net.h
drivers/isdn/i4l/isdn_net.h
+3
-4
drivers/isdn/i4l/isdn_ppp.c
drivers/isdn/i4l/isdn_ppp.c
+20
-19
drivers/isdn/i4l/isdn_tty.c
drivers/isdn/i4l/isdn_tty.c
+134
-186
drivers/isdn/i4l/isdn_tty.h
drivers/isdn/i4l/isdn_tty.h
+4
-1
drivers/isdn/i4l/isdn_ttyfax.c
drivers/isdn/i4l/isdn_ttyfax.c
+14
-35
drivers/isdn/i4l/isdn_v110.c
drivers/isdn/i4l/isdn_v110.c
+17
-19
drivers/isdn/i4l/isdn_v110.h
drivers/isdn/i4l/isdn_v110.h
+9
-3
drivers/isdn/isdnloop/isdnloop.c
drivers/isdn/isdnloop/isdnloop.c
+6
-2
fs/ntfs/ChangeLog
fs/ntfs/ChangeLog
+30
-0
fs/ntfs/Makefile
fs/ntfs/Makefile
+1
-1
fs/ntfs/aops.c
fs/ntfs/aops.c
+5
-5
fs/ntfs/attrib.c
fs/ntfs/attrib.c
+14
-9
fs/ntfs/compress.c
fs/ntfs/compress.c
+23
-3
fs/ntfs/dir.c
fs/ntfs/dir.c
+109
-93
fs/ntfs/file.c
fs/ntfs/file.c
+8
-1
fs/ntfs/inode.c
fs/ntfs/inode.c
+34
-17
fs/ntfs/inode.h
fs/ntfs/inode.h
+1
-2
fs/ntfs/malloc.h
fs/ntfs/malloc.h
+2
-15
fs/ntfs/mft.c
fs/ntfs/mft.c
+72
-123
fs/ntfs/mft.h
fs/ntfs/mft.h
+3
-3
fs/ntfs/namei.c
fs/ntfs/namei.c
+21
-17
fs/ntfs/super.c
fs/ntfs/super.c
+20
-7
fs/ntfs/volume.h
fs/ntfs/volume.h
+2
-0
include/linux/isdn.h
include/linux/isdn.h
+7
-29
include/linux/isdnif.h
include/linux/isdnif.h
+0
-2
mm/mmap.c
mm/mmap.c
+55
-13
No files found.
Documentation/filesystems/ntfs.txt
View file @
b14ebcfc
...
@@ -247,6 +247,17 @@ ChangeLog
...
@@ -247,6 +247,17 @@ ChangeLog
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.0.24:
- Small internal cleanups.
- Support for sendfile system call. (Christoph Hellwig)
2.0.23:
- Massive internal locking changes to mft record locking. Fixes
various race conditions and deadlocks.
- Fix ntfs over loopback for compressed files by adding an
optimization barrier. (gcc was screwing up otherwise ?)
Thanks go to Christoph Hellwig for pointing these two out:
- Remove now unused function fs/ntfs/malloc.h::vmalloc_nofs().
- Fix ntfs_free() for ia64 and parisc.
2.0.22:
2.0.22:
- Small internal cleanups.
- Small internal cleanups.
2.0.21:
2.0.21:
...
...
drivers/isdn/act2000/capi.h
View file @
b14ebcfc
...
@@ -138,7 +138,7 @@ typedef struct actcapi_ncpd {
...
@@ -138,7 +138,7 @@ typedef struct actcapi_ncpd {
typedef
struct
actcapi_msg
{
typedef
struct
actcapi_msg
{
actcapi_msghdr
hdr
;
actcapi_msghdr
hdr
;
union
msg
{
union
{
__u16
manuf_msg
;
__u16
manuf_msg
;
struct
manufacturer_req_net
{
struct
manufacturer_req_net
{
__u16
manuf_msg
;
__u16
manuf_msg
;
...
...
drivers/isdn/i4l/isdn_audio.c
View file @
b14ebcfc
...
@@ -564,8 +564,8 @@ isdn_audio_eval_dtmf(modem_info * info)
...
@@ -564,8 +564,8 @@ isdn_audio_eval_dtmf(modem_info * info)
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
0
;
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
0
;
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
di
=
i
nfo
->
isdn_driver
;
di
=
i
sdn_slot_driver
(
info
->
isdn_slot
)
;
ch
=
i
nfo
->
isdn_channel
;
ch
=
i
sdn_slot_channel
(
info
->
isdn_slot
)
;
__skb_queue_tail
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
],
skb
);
__skb_queue_tail
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
],
skb
);
dev
->
drv
[
di
]
->
rcvcount
[
ch
]
+=
2
;
dev
->
drv
[
di
]
->
rcvcount
[
ch
]
+=
2
;
restore_flags
(
flags
);
restore_flags
(
flags
);
...
@@ -685,8 +685,8 @@ isdn_audio_put_dle_code(modem_info * info, u_char code)
...
@@ -685,8 +685,8 @@ isdn_audio_put_dle_code(modem_info * info, u_char code)
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
0
;
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
0
;
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
di
=
i
nfo
->
isdn_driver
;
di
=
i
sdn_slot_driver
(
info
->
isdn_slot
)
;
ch
=
i
nfo
->
isdn_channel
;
ch
=
i
sdn_slot_channel
(
info
->
isdn_slot
)
;
__skb_queue_tail
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
],
skb
);
__skb_queue_tail
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
],
skb
);
dev
->
drv
[
di
]
->
rcvcount
[
ch
]
+=
2
;
dev
->
drv
[
di
]
->
rcvcount
[
ch
]
+=
2
;
restore_flags
(
flags
);
restore_flags
(
flags
);
...
...
drivers/isdn/i4l/isdn_common.c
View file @
b14ebcfc
...
@@ -19,6 +19,7 @@
...
@@ -19,6 +19,7 @@
#include <linux/vmalloc.h>
#include <linux/vmalloc.h>
#include <linux/isdn.h>
#include <linux/isdn.h>
#include <linux/smp_lock.h>
#include <linux/smp_lock.h>
#include <linux/ctype.h>
#include "isdn_common.h"
#include "isdn_common.h"
#include "isdn_tty.h"
#include "isdn_tty.h"
#include "isdn_net.h"
#include "isdn_net.h"
...
@@ -26,24 +27,31 @@
...
@@ -26,24 +27,31 @@
#ifdef CONFIG_ISDN_AUDIO
#ifdef CONFIG_ISDN_AUDIO
#include "isdn_audio.h"
#include "isdn_audio.h"
#endif
#endif
#ifdef CONFIG_ISDN_DIVERSION_MODULE
#define CONFIG_ISDN_DIVERSION
#endif
#ifdef CONFIG_ISDN_DIVERSION
#include <linux/isdn_divertif.h>
#include <linux/isdn_divertif.h>
#endif
/* CONFIG_ISDN_DIVERSION */
#include "isdn_v110.h"
#include "isdn_v110.h"
#include <linux/devfs_fs_kernel.h>
#include <linux/devfs_fs_kernel.h>
/* Debugflags */
#undef ISDN_DEBUG_STATCALLB
MODULE_DESCRIPTION
(
"ISDN4Linux: link layer"
);
MODULE_DESCRIPTION
(
"ISDN4Linux: link layer"
);
MODULE_AUTHOR
(
"Fritz Elfert"
);
MODULE_AUTHOR
(
"Fritz Elfert"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
isdn_dev
*
dev
;
isdn_dev
*
dev
;
struct
isdn_slot
{
int
di
;
/* driver index */
int
ch
;
/* channel index (per driver) */
int
usage
;
/* how is it used */
char
num
[
ISDN_MSNLEN
];
/* the current phone number */
unsigned
long
ibytes
;
/* Statistics incoming bytes */
unsigned
long
obytes
;
/* Statistics outgoing bytes */
struct
isdn_v110
iv110
;
/* For V.110 */
int
m_idx
;
/* Index for mdm.... */
isdn_net_dev
*
rx_netdev
;
/* rx netdev-pointers */
isdn_net_dev
*
st_netdev
;
/* stat netdev-pointers */
};
static
struct
isdn_slot
slot
[
ISDN_MAX_CHANNELS
];
static
char
*
isdn_revision
=
"$Revision: 1.114.6.16 $"
;
static
char
*
isdn_revision
=
"$Revision: 1.114.6.16 $"
;
extern
char
*
isdn_net_revision
;
extern
char
*
isdn_net_revision
;
...
@@ -60,15 +68,18 @@ static char *isdn_audio_revision = ": none $";
...
@@ -60,15 +68,18 @@ static char *isdn_audio_revision = ": none $";
#endif
#endif
extern
char
*
isdn_v110_revision
;
extern
char
*
isdn_v110_revision
;
#if
def CONFIG_ISDN_DIVERSION
#if
defined(CONFIG_ISDN_DIVERSION) || defined(CONFIG_ISDN_DIVERSION_MODULE)
static
isdn_divert_if
*
divert_if
;
/* = NULL */
static
isdn_divert_if
*
divert_if
;
/* = NULL */
#endif
/* CONFIG_ISDN_DIVERSION */
#else
#define divert_if ((isdn_divert_if *) NULL)
#endif
static
void
set_global_features
(
void
);
static
void
set_global_features
(
void
);
static
void
isdn_register_devfs
(
int
);
static
void
isdn_register_devfs
(
int
);
static
void
isdn_unregister_devfs
(
int
);
static
void
isdn_unregister_devfs
(
int
);
static
int
isdn_wildmat
(
char
*
s
,
char
*
p
);
static
int
isdn_wildmat
(
char
*
s
,
char
*
p
);
static
int
isdn_command
(
isdn_ctrl
*
cmd
);
void
void
isdn_lock_drivers
(
void
)
isdn_lock_drivers
(
void
)
...
@@ -230,12 +241,11 @@ isdn_dc2minor(int di, int ch)
...
@@ -230,12 +241,11 @@ isdn_dc2minor(int di, int ch)
{
{
int
i
;
int
i
;
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
(
dev
->
chanmap
[
i
]
==
ch
&&
dev
->
drvmap
[
i
]
==
di
)
if
(
slot
[
i
].
ch
==
ch
&&
slot
[
i
].
di
==
di
)
return
i
;
return
i
;
return
-
1
;
return
-
1
;
}
}
static
int
isdn_timer_cnt1
=
0
;
static
int
isdn_timer_cnt2
=
0
;
static
int
isdn_timer_cnt2
=
0
;
static
int
isdn_timer_cnt3
=
0
;
static
int
isdn_timer_cnt3
=
0
;
...
@@ -252,11 +262,6 @@ isdn_timer_funct(ulong dummy)
...
@@ -252,11 +262,6 @@ isdn_timer_funct(ulong dummy)
isdn_tty_modem_xmit
();
isdn_tty_modem_xmit
();
}
}
if
(
tf
&
ISDN_TIMER_SLOW
)
{
if
(
tf
&
ISDN_TIMER_SLOW
)
{
if
(
++
isdn_timer_cnt1
>=
ISDN_TIMER_02SEC
)
{
isdn_timer_cnt1
=
0
;
if
(
tf
&
ISDN_TIMER_NETDIAL
)
isdn_net_dial
();
}
if
(
++
isdn_timer_cnt2
>=
ISDN_TIMER_1SEC
)
{
if
(
++
isdn_timer_cnt2
>=
ISDN_TIMER_1SEC
)
{
isdn_timer_cnt2
=
0
;
isdn_timer_cnt2
=
0
;
if
(
tf
&
ISDN_TIMER_NETHANGUP
)
if
(
tf
&
ISDN_TIMER_NETHANGUP
)
...
@@ -291,7 +296,6 @@ isdn_timer_ctrl(int tf, int onoff)
...
@@ -291,7 +296,6 @@ isdn_timer_ctrl(int tf, int onoff)
cli
();
cli
();
if
((
tf
&
ISDN_TIMER_SLOW
)
&&
(
!
(
dev
->
tflags
&
ISDN_TIMER_SLOW
)))
{
if
((
tf
&
ISDN_TIMER_SLOW
)
&&
(
!
(
dev
->
tflags
&
ISDN_TIMER_SLOW
)))
{
/* If the slow-timer wasn't activated until now */
/* If the slow-timer wasn't activated until now */
isdn_timer_cnt1
=
0
;
isdn_timer_cnt2
=
0
;
isdn_timer_cnt2
=
0
;
}
}
old_tflags
=
dev
->
tflags
;
old_tflags
=
dev
->
tflags
;
...
@@ -317,7 +321,7 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
...
@@ -317,7 +321,7 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
return
;
return
;
}
}
/* Update statistics */
/* Update statistics */
dev
->
ibytes
[
i
]
+=
skb
->
len
;
slot
[
i
].
ibytes
+=
skb
->
len
;
/* First, try to deliver data to network-device */
/* First, try to deliver data to network-device */
if
(
isdn_net_rcv_skb
(
i
,
skb
))
if
(
isdn_net_rcv_skb
(
i
,
skb
))
...
@@ -327,10 +331,10 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
...
@@ -327,10 +331,10 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
* makes sense for async streams only, so it is
* makes sense for async streams only, so it is
* called after possible net-device delivery.
* called after possible net-device delivery.
*/
*/
if
(
dev
->
v110
[
i
]
)
{
if
(
slot
[
i
].
iv110
.
v110
)
{
atomic_inc
(
&
dev
->
v110use
[
i
]
);
atomic_inc
(
&
slot
[
i
].
iv110
.
v110use
);
skb
=
isdn_v110_decode
(
dev
->
v110
[
i
]
,
skb
);
skb
=
isdn_v110_decode
(
slot
[
i
].
iv110
.
v110
,
skb
);
atomic_dec
(
&
dev
->
v110use
[
i
]
);
atomic_dec
(
&
slot
[
i
].
iv110
.
v110use
);
if
(
!
skb
)
if
(
!
skb
)
return
;
return
;
}
}
...
@@ -350,15 +354,16 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
...
@@ -350,15 +354,16 @@ isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
* lowlevel-driver, use driver's transparent mode and handle V.110 in
* lowlevel-driver, use driver's transparent mode and handle V.110 in
* linklevel instead.
* linklevel instead.
*/
*/
int
static
int
isdn_command
(
isdn_ctrl
*
cmd
)
isdn_command
(
isdn_ctrl
*
cmd
)
{
{
int
idx
=
isdn_dc2minor
(
cmd
->
driver
,
cmd
->
arg
&
255
);
if
(
cmd
->
driver
==
-
1
)
{
if
(
cmd
->
driver
==
-
1
)
{
printk
(
KERN_WARNING
"isdn_command command(%x) driver -1
\n
"
,
cmd
->
command
);
printk
(
KERN_WARNING
"isdn_command command(%x) driver -1
\n
"
,
cmd
->
command
);
return
(
1
);
return
(
1
);
}
}
if
(
cmd
->
command
==
ISDN_CMD_SETL2
)
{
if
(
cmd
->
command
==
ISDN_CMD_SETL2
)
{
int
idx
=
isdn_dc2minor
(
cmd
->
driver
,
cmd
->
arg
&
255
);
unsigned
long
l2prot
=
(
cmd
->
arg
>>
8
)
&
255
;
unsigned
long
l2prot
=
(
cmd
->
arg
>>
8
)
&
255
;
unsigned
long
features
=
(
dev
->
drv
[
cmd
->
driver
]
->
interface
->
features
unsigned
long
features
=
(
dev
->
drv
[
cmd
->
driver
]
->
interface
->
features
>>
ISDN_FEATURE_L2_SHIFT
)
&
>>
ISDN_FEATURE_L2_SHIFT
)
&
...
@@ -374,30 +379,38 @@ isdn_command(isdn_ctrl *cmd)
...
@@ -374,30 +379,38 @@ isdn_command(isdn_ctrl *cmd)
* Layer-2 to transparent
* Layer-2 to transparent
*/
*/
if
(
!
(
features
&
l2_feature
))
{
if
(
!
(
features
&
l2_feature
))
{
dev
->
v110emu
[
idx
]
=
l2prot
;
slot
[
idx
].
iv110
.
v110emu
=
l2prot
;
cmd
->
arg
=
(
cmd
->
arg
&
255
)
|
cmd
->
arg
=
(
cmd
->
arg
&
255
)
|
(
ISDN_PROTO_L2_TRANS
<<
8
);
(
ISDN_PROTO_L2_TRANS
<<
8
);
}
else
}
else
dev
->
v110emu
[
idx
]
=
0
;
slot
[
idx
].
iv110
.
v110emu
=
0
;
}
}
}
}
#ifdef ISDN_DEBUG_COMMAND
switch
(
cmd
->
command
)
{
case
ISDN_CMD_SETL2
:
printk
(
KERN_DEBUG
"ISDN_CMD_SETL2 %d
\n
"
,
idx
);
break
;
case
ISDN_CMD_SETL3
:
printk
(
KERN_DEBUG
"ISDN_CMD_SETL3 %d
\n
"
,
idx
);
break
;
case
ISDN_CMD_DIAL
:
printk
(
KERN_DEBUG
"ISDN_CMD_DIAL %d
\n
"
,
idx
);
break
;
case
ISDN_CMD_ACCEPTD
:
printk
(
KERN_DEBUG
"ISDN_CMD_ACCEPTD %d
\n
"
,
idx
);
break
;
case
ISDN_CMD_ACCEPTB
:
printk
(
KERN_DEBUG
"ISDN_CMD_ACCEPTB %d
\n
"
,
idx
);
break
;
case
ISDN_CMD_HANGUP
:
printk
(
KERN_DEBUG
"ISDN_CMD_HANGUP %d
\n
"
,
idx
);
break
;
case
ISDN_CMD_CLREAZ
:
printk
(
KERN_DEBUG
"ISDN_CMD_CLREAZ %d
\n
"
,
idx
);
break
;
case
ISDN_CMD_SETEAZ
:
printk
(
KERN_DEBUG
"ISDN_CMD_SETEAZ %d
\n
"
,
idx
);
break
;
default:
printk
(
KERN_DEBUG
"%s: cmd = %d
\n
"
,
__FUNCTION__
,
cmd
->
command
);
}
#endif
return
dev
->
drv
[
cmd
->
driver
]
->
interface
->
command
(
cmd
);
return
dev
->
drv
[
cmd
->
driver
]
->
interface
->
command
(
cmd
);
}
}
void
isdn_all_eaz
(
int
di
,
int
ch
)
{
isdn_ctrl
cmd
;
if
(
di
<
0
)
return
;
cmd
.
driver
=
di
;
cmd
.
arg
=
ch
;
cmd
.
command
=
ISDN_CMD_SETEAZ
;
cmd
.
parm
.
num
[
0
]
=
'\0'
;
isdn_command
(
&
cmd
);
}
/*
/*
* Begin of a CAPI like LL<->HL interface, currently used only for
* Begin of a CAPI like LL<->HL interface, currently used only for
* supplementary service (CAPI 2.0 part III)
* supplementary service (CAPI 2.0 part III)
...
@@ -430,7 +443,7 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -430,7 +443,7 @@ isdn_status_callback(isdn_ctrl * c)
int
r
;
int
r
;
int
retval
=
0
;
int
retval
=
0
;
isdn_ctrl
cmd
;
isdn_ctrl
cmd
;
isdn_net_dev
*
p
;
struct
list_head
*
l
;
di
=
c
->
driver
;
di
=
c
->
driver
;
i
=
isdn_dc2minor
(
di
,
c
->
arg
);
i
=
isdn_dc2minor
(
di
,
c
->
arg
);
...
@@ -442,7 +455,7 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -442,7 +455,7 @@ isdn_status_callback(isdn_ctrl * c)
return
0
;
return
0
;
if
(
isdn_net_stat_callback
(
i
,
c
))
if
(
isdn_net_stat_callback
(
i
,
c
))
return
0
;
return
0
;
if
(
isdn_v110_stat_callback
(
i
,
c
))
if
(
isdn_v110_stat_callback
(
&
slot
[
i
].
iv110
,
c
))
return
0
;
return
0
;
if
(
isdn_tty_stat_callback
(
i
,
c
))
if
(
isdn_tty_stat_callback
(
i
,
c
))
return
0
;
return
0
;
...
@@ -458,8 +471,8 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -458,8 +471,8 @@ isdn_status_callback(isdn_ctrl * c)
case
ISDN_STAT_RUN
:
case
ISDN_STAT_RUN
:
dev
->
drv
[
di
]
->
flags
|=
DRV_FLAG_RUNNING
;
dev
->
drv
[
di
]
->
flags
|=
DRV_FLAG_RUNNING
;
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
(
dev
->
drvmap
[
i
]
==
di
)
if
(
slot
[
i
].
di
==
di
)
isdn_
all_eaz
(
di
,
dev
->
chanmap
[
i
]
);
isdn_
slot_all_eaz
(
i
);
set_global_features
();
set_global_features
();
break
;
break
;
case
ISDN_STAT_STOP
:
case
ISDN_STAT_STOP
:
...
@@ -468,9 +481,7 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -468,9 +481,7 @@ isdn_status_callback(isdn_ctrl * c)
case
ISDN_STAT_ICALL
:
case
ISDN_STAT_ICALL
:
if
(
i
<
0
)
if
(
i
<
0
)
return
-
1
;
return
-
1
;
#ifdef ISDN_DEBUG_STATCALLB
dbg_statcallb
(
"ICALL: %d (%d,%ld) %s
\n
"
,
i
,
di
,
c
->
arg
,
c
->
parm
.
num
);
printk
(
KERN_DEBUG
"ICALL (net): %d %ld %s
\n
"
,
di
,
c
->
arg
,
c
->
parm
.
num
);
#endif
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
{
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
{
cmd
.
driver
=
di
;
cmd
.
driver
=
di
;
cmd
.
arg
=
c
->
arg
;
cmd
.
arg
=
c
->
arg
;
...
@@ -488,12 +499,10 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -488,12 +499,10 @@ isdn_status_callback(isdn_ctrl * c)
* 3 on eventually match, if CID is longer.
* 3 on eventually match, if CID is longer.
*/
*/
if
(
c
->
command
==
ISDN_STAT_ICALL
)
if
(
c
->
command
==
ISDN_STAT_ICALL
)
if
((
retval
=
isdn_tty_find_icall
(
di
,
c
->
arg
,
&
c
->
parm
.
setup
)))
return
(
retval
);
if
((
retval
=
isdn_tty_find_icall
(
di
,
c
->
arg
,
&
c
->
parm
.
setup
)))
return
(
retval
);
#ifdef CONFIG_ISDN_DIVERSION
if
(
divert_if
)
if
(
divert_if
)
if
((
retval
=
divert_if
->
stat_callback
(
c
)))
if
((
retval
=
divert_if
->
stat_callback
(
c
)))
return
(
retval
);
/* processed */
return
(
retval
);
/* processed */
#endif
/* CONFIG_ISDN_DIVERSION */
if
((
!
retval
)
&&
(
dev
->
drv
[
di
]
->
flags
&
DRV_FLAG_REJBUS
))
{
if
((
!
retval
)
&&
(
dev
->
drv
[
di
]
->
flags
&
DRV_FLAG_REJBUS
))
{
/* No tty responding */
/* No tty responding */
cmd
.
driver
=
di
;
cmd
.
driver
=
di
;
...
@@ -504,19 +513,15 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -504,19 +513,15 @@ isdn_status_callback(isdn_ctrl * c)
}
}
break
;
break
;
case
1
:
case
1
:
/* Schedule connection-setup */
list_for_each
(
l
,
&
isdn_net_devs
)
{
isdn_net_dial
();
isdn_net_dev
*
p
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
cmd
.
driver
=
di
;
if
(
p
->
local
.
isdn_slot
==
i
)
{
cmd
.
arg
=
c
->
arg
;
strcpy
(
cmd
.
parm
.
setup
.
eazmsn
,
p
->
local
.
msn
);
cmd
.
command
=
ISDN_CMD_ACCEPTD
;
isdn_slot_command
(
i
,
ISDN_CMD_ACCEPTD
,
&
cmd
);
for
(
p
=
dev
->
netdev
;
p
;
p
=
p
->
next
)
if
(
p
->
local
->
isdn_channel
==
cmd
.
arg
)
{
strcpy
(
cmd
.
parm
.
setup
.
eazmsn
,
p
->
local
->
msn
);
isdn_command
(
&
cmd
);
retval
=
1
;
retval
=
1
;
break
;
break
;
}
}
}
break
;
break
;
case
2
:
/* For calling back, first reject incoming call ... */
case
2
:
/* For calling back, first reject incoming call ... */
...
@@ -532,24 +537,19 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -532,24 +537,19 @@ isdn_status_callback(isdn_ctrl * c)
/* Fall through */
/* Fall through */
case
4
:
case
4
:
/* ... then start callback. */
/* ... then start callback. */
isdn_net_dial
();
break
;
break
;
case
5
:
case
5
:
/* Number would eventually match, if longer */
/* Number would eventually match, if longer */
retval
=
3
;
retval
=
3
;
break
;
break
;
}
}
#ifdef ISDN_DEBUG_STATCALLB
dbg_statcallb
(
"ICALL: ret=%d
\n
"
,
retval
);
printk
(
KERN_DEBUG
"ICALL: ret=%d
\n
"
,
retval
);
#endif
return
retval
;
return
retval
;
break
;
break
;
case
ISDN_STAT_CINF
:
case
ISDN_STAT_CINF
:
if
(
i
<
0
)
if
(
i
<
0
)
return
-
1
;
return
-
1
;
#ifdef ISDN_DEBUG_STATCALLB
dbg_statcallb
(
"CINF: %d %s
\n
"
,
i
,
c
->
parm
.
num
);
printk
(
KERN_DEBUG
"CINF: %ld %s
\n
"
,
c
->
arg
,
c
->
parm
.
num
);
#endif
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
return
0
;
return
0
;
if
(
strcmp
(
c
->
parm
.
num
,
"0"
))
if
(
strcmp
(
c
->
parm
.
num
,
"0"
))
...
@@ -557,39 +557,29 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -557,39 +557,29 @@ isdn_status_callback(isdn_ctrl * c)
isdn_tty_stat_callback
(
i
,
c
);
isdn_tty_stat_callback
(
i
,
c
);
break
;
break
;
case
ISDN_STAT_CAUSE
:
case
ISDN_STAT_CAUSE
:
#ifdef ISDN_DEBUG_STATCALLB
dbg_statcallb
(
"CAUSE: %d %s
\n
"
,
i
,
c
->
parm
.
num
);
printk
(
KERN_DEBUG
"CAUSE: %ld %s
\n
"
,
c
->
arg
,
c
->
parm
.
num
);
#endif
printk
(
KERN_INFO
"isdn: %s,ch%ld cause: %s
\n
"
,
printk
(
KERN_INFO
"isdn: %s,ch%ld cause: %s
\n
"
,
dev
->
drvid
[
di
],
c
->
arg
,
c
->
parm
.
num
);
dev
->
drvid
[
di
],
c
->
arg
,
c
->
parm
.
num
);
isdn_tty_stat_callback
(
i
,
c
);
isdn_tty_stat_callback
(
i
,
c
);
#ifdef CONFIG_ISDN_DIVERSION
if
(
divert_if
)
if
(
divert_if
)
divert_if
->
stat_callback
(
c
);
divert_if
->
stat_callback
(
c
);
#endif
/* CONFIG_ISDN_DIVERSION */
break
;
break
;
case
ISDN_STAT_DISPLAY
:
case
ISDN_STAT_DISPLAY
:
#ifdef ISDN_DEBUG_STATCALLB
dbg_statcallb
(
"DISPLAY: %d %s
\n
"
,
i
,
c
->
parm
.
display
);
printk
(
KERN_DEBUG
"DISPLAY: %ld %s
\n
"
,
c
->
arg
,
c
->
parm
.
display
);
#endif
isdn_tty_stat_callback
(
i
,
c
);
isdn_tty_stat_callback
(
i
,
c
);
#ifdef CONFIG_ISDN_DIVERSION
if
(
divert_if
)
if
(
divert_if
)
divert_if
->
stat_callback
(
c
);
divert_if
->
stat_callback
(
c
);
#endif
/* CONFIG_ISDN_DIVERSION */
break
;
break
;
case
ISDN_STAT_DCONN
:
case
ISDN_STAT_DCONN
:
if
(
i
<
0
)
if
(
i
<
0
)
return
-
1
;
return
-
1
;
#ifdef ISDN_DEBUG_STATCALLB
dbg_statcallb
(
"DCONN: %d
\n
"
,
i
);
printk
(
KERN_DEBUG
"DCONN: %ld
\n
"
,
c
->
arg
);
#endif
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
return
0
;
return
0
;
/* Find any net-device, waiting for D-channel setup */
/* Find any net-device, waiting for D-channel setup */
if
(
isdn_net_stat_callback
(
i
,
c
))
if
(
isdn_net_stat_callback
(
i
,
c
))
break
;
break
;
isdn_v110_stat_callback
(
i
,
c
);
isdn_v110_stat_callback
(
&
slot
[
i
].
iv110
,
c
);
/* Find any ttyI, waiting for D-channel setup */
/* Find any ttyI, waiting for D-channel setup */
if
(
isdn_tty_stat_callback
(
i
,
c
))
{
if
(
isdn_tty_stat_callback
(
i
,
c
))
{
cmd
.
driver
=
di
;
cmd
.
driver
=
di
;
...
@@ -602,9 +592,7 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -602,9 +592,7 @@ isdn_status_callback(isdn_ctrl * c)
case
ISDN_STAT_DHUP
:
case
ISDN_STAT_DHUP
:
if
(
i
<
0
)
if
(
i
<
0
)
return
-
1
;
return
-
1
;
#ifdef ISDN_DEBUG_STATCALLB
dbg_statcallb
(
"DHUP: %d
\n
"
,
i
);
printk
(
KERN_DEBUG
"DHUP: %ld
\n
"
,
c
->
arg
);
#endif
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
return
0
;
return
0
;
dev
->
drv
[
di
]
->
online
&=
~
(
1
<<
(
c
->
arg
));
dev
->
drv
[
di
]
->
online
&=
~
(
1
<<
(
c
->
arg
));
...
@@ -612,21 +600,16 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -612,21 +600,16 @@ isdn_status_callback(isdn_ctrl * c)
/* Signal hangup to network-devices */
/* Signal hangup to network-devices */
if
(
isdn_net_stat_callback
(
i
,
c
))
if
(
isdn_net_stat_callback
(
i
,
c
))
break
;
break
;
isdn_v110_stat_callback
(
i
,
c
);
isdn_v110_stat_callback
(
&
slot
[
i
].
iv110
,
c
);
if
(
isdn_tty_stat_callback
(
i
,
c
))
if
(
isdn_tty_stat_callback
(
i
,
c
))
break
;
break
;
#ifdef CONFIG_ISDN_DIVERSION
if
(
divert_if
)
if
(
divert_if
)
divert_if
->
stat_callback
(
c
);
divert_if
->
stat_callback
(
c
);
#endif
/* CONFIG_ISDN_DIVERSION */
break
;
break
;
break
;
case
ISDN_STAT_BCONN
:
case
ISDN_STAT_BCONN
:
if
(
i
<
0
)
if
(
i
<
0
)
return
-
1
;
return
-
1
;
#ifdef ISDN_DEBUG_STATCALLB
dbg_statcallb
(
"BCONN: %ld
\n
"
,
c
->
arg
);
printk
(
KERN_DEBUG
"BCONN: %ld
\n
"
,
c
->
arg
);
#endif
/* Signal B-channel-connect to network-devices */
/* Signal B-channel-connect to network-devices */
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
return
0
;
return
0
;
...
@@ -634,16 +617,14 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -634,16 +617,14 @@ isdn_status_callback(isdn_ctrl * c)
isdn_info_update
();
isdn_info_update
();
if
(
isdn_net_stat_callback
(
i
,
c
))
if
(
isdn_net_stat_callback
(
i
,
c
))
break
;
break
;
isdn_v110_stat_callback
(
i
,
c
);
isdn_v110_stat_callback
(
&
slot
[
i
].
iv110
,
c
);
if
(
isdn_tty_stat_callback
(
i
,
c
))
if
(
isdn_tty_stat_callback
(
i
,
c
))
break
;
break
;
break
;
break
;
case
ISDN_STAT_BHUP
:
case
ISDN_STAT_BHUP
:
if
(
i
<
0
)
if
(
i
<
0
)
return
-
1
;
return
-
1
;
#ifdef ISDN_DEBUG_STATCALLB
dbg_statcallb
(
"BHUP: %d
\n
"
,
i
);
printk
(
KERN_DEBUG
"BHUP: %ld
\n
"
,
c
->
arg
);
#endif
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
return
0
;
return
0
;
dev
->
drv
[
di
]
->
online
&=
~
(
1
<<
(
c
->
arg
));
dev
->
drv
[
di
]
->
online
&=
~
(
1
<<
(
c
->
arg
));
...
@@ -653,16 +634,14 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -653,16 +634,14 @@ isdn_status_callback(isdn_ctrl * c)
if
(
isdn_net_stat_callback
(
i
,
c
))
if
(
isdn_net_stat_callback
(
i
,
c
))
break
;
break
;
#endif
#endif
isdn_v110_stat_callback
(
i
,
c
);
isdn_v110_stat_callback
(
&
slot
[
i
].
iv110
,
c
);
if
(
isdn_tty_stat_callback
(
i
,
c
))
if
(
isdn_tty_stat_callback
(
i
,
c
))
break
;
break
;
break
;
break
;
case
ISDN_STAT_NODCH
:
case
ISDN_STAT_NODCH
:
if
(
i
<
0
)
if
(
i
<
0
)
return
-
1
;
return
-
1
;
#ifdef ISDN_DEBUG_STATCALLB
dbg_statcallb
(
"NODCH: %ld
\n
"
,
c
->
arg
);
printk
(
KERN_DEBUG
"NODCH: %ld
\n
"
,
c
->
arg
);
#endif
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
return
0
;
return
0
;
if
(
isdn_net_stat_callback
(
i
,
c
))
if
(
isdn_net_stat_callback
(
i
,
c
))
...
@@ -679,20 +658,17 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -679,20 +658,17 @@ isdn_status_callback(isdn_ctrl * c)
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
((
dev
->
drvmap
[
i
]
==
di
)
&&
if
((
slot
[
i
].
di
==
di
)
&&
(
dev
->
chanmap
[
i
]
==
c
->
arg
))
{
(
slot
[
i
].
ch
==
c
->
arg
))
{
if
(
c
->
parm
.
num
[
0
])
if
(
c
->
parm
.
num
[
0
])
dev
->
usage
[
i
]
&=
~
ISDN_USAGE_DISABLED
;
isdn_slot_set_usage
(
i
,
isdn_slot_usage
(
i
)
&
~
ISDN_USAGE_DISABLED
);
else
else
if
(
USG_NONE
(
isdn_slot_usage
(
i
)))
if
(
USG_NONE
(
dev
->
usage
[
i
]))
{
isdn_slot_set_usage
(
i
,
isdn_slot_usage
(
i
)
|
ISDN_USAGE_DISABLED
);
dev
->
usage
[
i
]
|=
ISDN_USAGE_DISABLED
;
else
}
retval
=
-
1
;
else
break
;
retval
=
-
1
;
break
;
}
}
restore_flags
(
flags
);
restore_flags
(
flags
);
isdn_info_update
();
break
;
break
;
case
ISDN_STAT_UNLOAD
:
case
ISDN_STAT_UNLOAD
:
while
(
dev
->
drv
[
di
]
->
locks
>
0
)
{
while
(
dev
->
drv
[
di
]
->
locks
>
0
)
{
...
@@ -707,10 +683,10 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -707,10 +683,10 @@ isdn_status_callback(isdn_ctrl * c)
cli
();
cli
();
isdn_tty_stat_callback
(
i
,
c
);
isdn_tty_stat_callback
(
i
,
c
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
(
dev
->
drvmap
[
i
]
==
di
)
{
if
(
slot
[
i
].
di
==
di
)
{
dev
->
drvmap
[
i
]
=
-
1
;
slot
[
i
].
di
=
-
1
;
dev
->
chanmap
[
i
]
=
-
1
;
slot
[
i
].
ch
=
-
1
;
dev
->
usage
[
i
]
&=
~
ISDN_USAGE_DISABLED
;
slot
[
i
].
usage
&=
~
ISDN_USAGE_DISABLED
;
isdn_unregister_devfs
(
i
);
isdn_unregister_devfs
(
i
);
}
}
dev
->
drivers
--
;
dev
->
drivers
--
;
...
@@ -742,12 +718,10 @@ isdn_status_callback(isdn_ctrl * c)
...
@@ -742,12 +718,10 @@ isdn_status_callback(isdn_ctrl * c)
isdn_tty_stat_callback
(
i
,
c
);
isdn_tty_stat_callback
(
i
,
c
);
break
;
break
;
#endif
#endif
#ifdef CONFIG_ISDN_DIVERSION
case
ISDN_STAT_PROT
:
case
ISDN_STAT_PROT
:
case
ISDN_STAT_REDIR
:
case
ISDN_STAT_REDIR
:
if
(
divert_if
)
if
(
divert_if
)
return
(
divert_if
->
stat_callback
(
c
));
return
(
divert_if
->
stat_callback
(
c
));
#endif
/* CONFIG_ISDN_DIVERSION */
default:
default:
return
-
1
;
return
-
1
;
}
}
...
@@ -770,50 +744,40 @@ isdn_getnum(char **p)
...
@@ -770,50 +744,40 @@ isdn_getnum(char **p)
#define DLE 0x10
#define DLE 0x10
/*
/*
* isdn_readbchan() tries to get data from the read-queue.
* isdn_
slot_
readbchan() tries to get data from the read-queue.
* It MUST be called with interrupts off.
* It MUST be called with interrupts off.
*
* Be aware that this is not an atomic operation when sleep != 0, even though
* interrupts are turned off! Well, like that we are currently only called
* on behalf of a read system call on raw device files (which are documented
* to be dangerous and for for debugging purpose only). The inode semaphore
* takes care that this is not called for the same minor device number while
* we are sleeping, but access is not serialized against simultaneous read()
* from the corresponding ttyI device. Can other ugly events, like changes
* of the mapping (di,ch)<->minor, happen during the sleep? --he
*/
*/
int
int
isdn_
readbchan
(
int
di
,
int
channel
,
u_char
*
buf
,
u_char
*
fp
,
int
len
,
wait_queue_head_t
*
sleep
)
isdn_
slot_readbchan
(
int
sl
,
u_char
*
buf
,
u_char
*
fp
,
int
len
)
{
{
int
count
;
int
count
;
int
count_pull
;
int
count_pull
;
int
count_put
;
int
count_put
;
int
dflag
;
int
dflag
;
int
di
=
isdn_slot_driver
(
sl
);
int
ch
=
isdn_slot_channel
(
sl
);
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
u_char
*
cp
;
u_char
*
cp
;
if
(
!
dev
->
drv
[
di
])
if
(
!
dev
->
drv
[
di
])
return
0
;
return
0
;
if
(
skb_queue_empty
(
&
dev
->
drv
[
di
]
->
rpqueue
[
channel
]))
{
if
(
skb_queue_empty
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
]))
if
(
sleep
)
return
0
;
interruptible_sleep_on
(
sleep
);
else
if
(
len
>
dev
->
drv
[
di
]
->
rcvcount
[
ch
])
return
0
;
len
=
dev
->
drv
[
di
]
->
rcvcount
[
ch
];
}
if
(
len
>
dev
->
drv
[
di
]
->
rcvcount
[
channel
])
len
=
dev
->
drv
[
di
]
->
rcvcount
[
channel
];
cp
=
buf
;
cp
=
buf
;
count
=
0
;
count
=
0
;
while
(
len
)
{
while
(
len
)
{
if
(
!
(
skb
=
skb_peek
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
annel
])))
if
(
!
(
skb
=
skb_peek
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
])))
break
;
break
;
#ifdef CONFIG_ISDN_AUDIO
#ifdef CONFIG_ISDN_AUDIO
if
(
ISDN_AUDIO_SKB_LOCK
(
skb
))
if
(
ISDN_AUDIO_SKB_LOCK
(
skb
))
break
;
break
;
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
1
;
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
1
;
if
((
ISDN_AUDIO_SKB_DLECOUNT
(
skb
))
||
(
dev
->
drv
[
di
]
->
DLEflag
&
(
1
<<
ch
annel
)))
{
if
((
ISDN_AUDIO_SKB_DLECOUNT
(
skb
))
||
(
dev
->
drv
[
di
]
->
DLEflag
&
(
1
<<
ch
)))
{
char
*
p
=
skb
->
data
;
char
*
p
=
skb
->
data
;
unsigned
long
DLEmask
=
(
1
<<
ch
annel
);
unsigned
long
DLEmask
=
(
1
<<
ch
);
dflag
=
0
;
dflag
=
0
;
count_pull
=
count_put
=
0
;
count_pull
=
count_put
=
0
;
...
@@ -864,7 +828,7 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
...
@@ -864,7 +828,7 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
#ifdef CONFIG_ISDN_AUDIO
#ifdef CONFIG_ISDN_AUDIO
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
0
;
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
0
;
#endif
#endif
skb
=
skb_dequeue
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
annel
]);
skb
=
skb_dequeue
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
]);
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
skb
);
}
else
{
}
else
{
/* Not yet emptied this buff, so it
/* Not yet emptied this buff, so it
...
@@ -876,7 +840,7 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
...
@@ -876,7 +840,7 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
0
;
ISDN_AUDIO_SKB_LOCK
(
skb
)
=
0
;
#endif
#endif
}
}
dev
->
drv
[
di
]
->
rcvcount
[
ch
annel
]
-=
count_put
;
dev
->
drv
[
di
]
->
rcvcount
[
ch
]
-=
count_put
;
}
}
return
count
;
return
count
;
}
}
...
@@ -884,13 +848,13 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
...
@@ -884,13 +848,13 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
static
__inline
int
static
__inline
int
isdn_minor2drv
(
int
minor
)
isdn_minor2drv
(
int
minor
)
{
{
return
(
dev
->
drvmap
[
minor
])
;
return
slot
[
minor
].
di
;
}
}
static
__inline
int
static
__inline
int
isdn_minor2chan
(
int
minor
)
isdn_minor2chan
(
int
minor
)
{
{
return
(
dev
->
chanmap
[
minor
])
;
return
slot
[
minor
].
ch
;
}
}
static
char
*
static
char
*
...
@@ -903,25 +867,25 @@ isdn_statstr(void)
...
@@ -903,25 +867,25 @@ isdn_statstr(void)
sprintf
(
istatbuf
,
"idmap:
\t
"
);
sprintf
(
istatbuf
,
"idmap:
\t
"
);
p
=
istatbuf
+
strlen
(
istatbuf
);
p
=
istatbuf
+
strlen
(
istatbuf
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
sprintf
(
p
,
"%s "
,
(
dev
->
drvmap
[
i
]
<
0
)
?
"-"
:
dev
->
drvid
[
dev
->
drvmap
[
i
]
]);
sprintf
(
p
,
"%s "
,
(
slot
[
i
].
di
<
0
)
?
"-"
:
dev
->
drvid
[
slot
[
i
].
di
]);
p
=
istatbuf
+
strlen
(
istatbuf
);
p
=
istatbuf
+
strlen
(
istatbuf
);
}
}
sprintf
(
p
,
"
\n
chmap:
\t
"
);
sprintf
(
p
,
"
\n
chmap:
\t
"
);
p
=
istatbuf
+
strlen
(
istatbuf
);
p
=
istatbuf
+
strlen
(
istatbuf
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
sprintf
(
p
,
"%d "
,
dev
->
chanmap
[
i
]
);
sprintf
(
p
,
"%d "
,
slot
[
i
].
ch
);
p
=
istatbuf
+
strlen
(
istatbuf
);
p
=
istatbuf
+
strlen
(
istatbuf
);
}
}
sprintf
(
p
,
"
\n
drmap:
\t
"
);
sprintf
(
p
,
"
\n
drmap:
\t
"
);
p
=
istatbuf
+
strlen
(
istatbuf
);
p
=
istatbuf
+
strlen
(
istatbuf
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
sprintf
(
p
,
"%d "
,
dev
->
drvmap
[
i
]
);
sprintf
(
p
,
"%d "
,
slot
[
i
].
di
);
p
=
istatbuf
+
strlen
(
istatbuf
);
p
=
istatbuf
+
strlen
(
istatbuf
);
}
}
sprintf
(
p
,
"
\n
usage:
\t
"
);
sprintf
(
p
,
"
\n
usage:
\t
"
);
p
=
istatbuf
+
strlen
(
istatbuf
);
p
=
istatbuf
+
strlen
(
istatbuf
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
sprintf
(
p
,
"%d "
,
dev
->
usage
[
i
]
);
sprintf
(
p
,
"%d "
,
slot
[
i
].
usage
);
p
=
istatbuf
+
strlen
(
istatbuf
);
p
=
istatbuf
+
strlen
(
istatbuf
);
}
}
sprintf
(
p
,
"
\n
flags:
\t
"
);
sprintf
(
p
,
"
\n
flags:
\t
"
);
...
@@ -938,7 +902,7 @@ isdn_statstr(void)
...
@@ -938,7 +902,7 @@ isdn_statstr(void)
sprintf
(
p
,
"
\n
phone:
\t
"
);
sprintf
(
p
,
"
\n
phone:
\t
"
);
p
=
istatbuf
+
strlen
(
istatbuf
);
p
=
istatbuf
+
strlen
(
istatbuf
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
sprintf
(
p
,
"%s "
,
dev
->
num
[
i
]
);
sprintf
(
p
,
"%s "
,
isdn_slot_num
(
i
)
);
p
=
istatbuf
+
strlen
(
istatbuf
);
p
=
istatbuf
+
strlen
(
istatbuf
);
}
}
sprintf
(
p
,
"
\n
"
);
sprintf
(
p
,
"
\n
"
);
...
@@ -1095,8 +1059,8 @@ isdn_status_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
...
@@ -1095,8 +1059,8 @@ isdn_status_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
sizeof
(
ulong
)
*
ISDN_MAX_CHANNELS
*
2
)))
sizeof
(
ulong
)
*
ISDN_MAX_CHANNELS
*
2
)))
return
ret
;
return
ret
;
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
put_user
(
dev
->
ibytes
[
i
]
,
p
++
);
put_user
(
slot
[
i
].
ibytes
,
p
++
);
put_user
(
dev
->
obytes
[
i
]
,
p
++
);
put_user
(
slot
[
i
].
obytes
,
p
++
);
}
}
return
0
;
return
0
;
}
else
}
else
...
@@ -1279,10 +1243,9 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
...
@@ -1279,10 +1243,9 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
int
ret
;
int
ret
;
int
i
;
int
i
;
char
*
p
;
char
*
p
;
char
*
s
;
union
iocpar
{
union
iocpar
{
char
name
[
10
];
char
name
[
10
];
char
bname
[
2
2
];
char
bname
[
2
0
];
isdn_ioctl_struct
iocts
;
isdn_ioctl_struct
iocts
;
isdn_net_ioctl_phone
phone
;
isdn_net_ioctl_phone
phone
;
isdn_net_ioctl_cfg
cfg
;
isdn_net_ioctl_cfg
cfg
;
...
@@ -1310,42 +1273,24 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
...
@@ -1310,42 +1273,24 @@ isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
#ifdef CONFIG_NETDEVICES
#ifdef CONFIG_NETDEVICES
case
IIOCNETAIF
:
case
IIOCNETAIF
:
/* Add a network-interface */
/* Add a network-interface */
if
(
arg
)
{
if
(
copy_from_user
(
name
,
(
char
*
)
arg
,
sizeof
(
name
)
-
1
))
if
(
copy_from_user
(
name
,
(
char
*
)
arg
,
sizeof
(
name
)))
return
-
EFAULT
;
return
-
EFAULT
;
name
[
sizeof
(
name
)
-
1
]
=
0
;
s
=
name
;
}
else
{
s
=
NULL
;
}
ret
=
down_interruptible
(
&
dev
->
sem
);
ret
=
down_interruptible
(
&
dev
->
sem
);
if
(
ret
)
return
ret
;
if
(
ret
)
if
((
s
=
isdn_net_new
(
s
,
NULL
)))
{
return
ret
;
if
(
copy_to_user
((
char
*
)
arg
,
s
,
strlen
(
s
)
+
1
)){
ret
=
isdn_net_new
(
name
,
NULL
);
ret
=
-
EFAULT
;
}
else
{
ret
=
0
;
}
}
else
ret
=
-
ENODEV
;
up
(
&
dev
->
sem
);
up
(
&
dev
->
sem
);
return
ret
;
return
ret
;
case
IIOCNETASL
:
case
IIOCNETASL
:
/* Add a slave to a network-interface */
/* Add a slave to a network-interface */
if
(
arg
)
{
if
(
copy_from_user
(
bname
,
(
char
*
)
arg
,
sizeof
(
bname
)
-
1
))
if
(
copy_from_user
(
bname
,
(
char
*
)
arg
,
sizeof
(
bname
)
-
1
))
return
-
EFAULT
;
return
-
EFAULT
;
bname
[
sizeof
(
bname
)
-
1
]
=
0
;
}
else
return
-
EINVAL
;
ret
=
down_interruptible
(
&
dev
->
sem
);
ret
=
down_interruptible
(
&
dev
->
sem
);
if
(
ret
)
return
ret
;
if
(
ret
)
if
((
s
=
isdn_net_newslave
(
bname
)))
{
return
ret
;
if
(
copy_to_user
((
char
*
)
arg
,
s
,
strlen
(
s
)
+
1
)){
ret
=
isdn_net_newslave
(
bname
);
ret
=
-
EFAULT
;
}
else
{
ret
=
0
;
}
}
else
ret
=
-
ENODEV
;
up
(
&
dev
->
sem
);
up
(
&
dev
->
sem
);
return
ret
;
return
ret
;
case
IIOCNETDIF
:
case
IIOCNETDIF
:
...
@@ -1742,8 +1687,8 @@ isdn_map_eaz2msn(char *msn, int di)
...
@@ -1742,8 +1687,8 @@ isdn_map_eaz2msn(char *msn, int di)
#define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038))
#define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038))
int
int
isdn_get_free_
channel
(
int
usage
,
int
l2_proto
,
int
l3_proto
,
int
pre_dev
isdn_get_free_
slot
(
int
usage
,
int
l2_proto
,
int
l3_proto
,
,
int
pre_chan
,
char
*
msn
)
int
pre_dev
,
int
pre_chan
,
char
*
msn
)
{
{
int
i
;
int
i
;
ulong
flags
;
ulong
flags
;
...
@@ -1760,34 +1705,28 @@ isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
...
@@ -1760,34 +1705,28 @@ isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
* because we can emulate this in linklevel.
* because we can emulate this in linklevel.
*/
*/
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
(
USG_NONE
(
dev
->
usage
[
i
]
)
&&
if
(
USG_NONE
(
slot
[
i
].
usage
)
&&
(
dev
->
drvmap
[
i
]
!=
-
1
))
{
(
slot
[
i
].
di
!=
-
1
))
{
int
d
=
dev
->
drvmap
[
i
]
;
int
d
=
slot
[
i
].
di
;
if
((
dev
->
usage
[
i
]
&
ISDN_USAGE_EXCLUSIVE
)
&&
if
((
slot
[
i
].
usage
&
ISDN_USAGE_EXCLUSIVE
)
&&
((
pre_dev
!=
d
)
||
(
pre_chan
!=
dev
->
chanmap
[
i
]
)))
((
pre_dev
!=
d
)
||
(
pre_chan
!=
slot
[
i
].
ch
)))
continue
;
continue
;
if
(
!
strcmp
(
isdn_map_eaz2msn
(
msn
,
d
),
"-"
))
if
(
!
strcmp
(
isdn_map_eaz2msn
(
msn
,
d
),
"-"
))
continue
;
continue
;
if
(
dev
->
usage
[
i
]
&
ISDN_USAGE_DISABLED
)
if
(
slot
[
i
].
usage
&
ISDN_USAGE_DISABLED
)
continue
;
/* usage not allowed */
continue
;
/* usage not allowed */
if
(
dev
->
drv
[
d
]
->
flags
&
DRV_FLAG_RUNNING
)
{
if
(
dev
->
drv
[
d
]
->
flags
&
DRV_FLAG_RUNNING
)
{
if
(((
dev
->
drv
[
d
]
->
interface
->
features
&
features
)
==
features
)
||
if
(((
dev
->
drv
[
d
]
->
interface
->
features
&
features
)
==
features
)
||
(((
dev
->
drv
[
d
]
->
interface
->
features
&
vfeatures
)
==
vfeatures
)
&&
(((
dev
->
drv
[
d
]
->
interface
->
features
&
vfeatures
)
==
vfeatures
)
&&
(
dev
->
drv
[
d
]
->
interface
->
features
&
ISDN_FEATURE_L2_TRANS
)))
{
(
dev
->
drv
[
d
]
->
interface
->
features
&
ISDN_FEATURE_L2_TRANS
)))
{
if
((
pre_dev
<
0
)
||
(
pre_chan
<
0
))
{
if
((
pre_dev
<
0
)
||
(
pre_chan
<
0
))
{
dev
->
usage
[
i
]
&=
ISDN_USAGE_EXCLUSIVE
;
isdn_slot_set_usage
(
i
,
(
isdn_slot_usage
(
i
)
&
ISDN_USAGE_EXCLUSIVE
)
|
usage
);
dev
->
usage
[
i
]
|=
usage
;
restore_flags
(
flags
);
isdn_info_update
();
return
i
;
}
else
if
((
pre_dev
==
d
)
&&
(
pre_chan
==
slot
[
i
].
ch
))
{
isdn_slot_set_usage
(
i
,
(
isdn_slot_usage
(
i
)
&
ISDN_USAGE_EXCLUSIVE
)
|
usage
);
restore_flags
(
flags
);
restore_flags
(
flags
);
return
i
;
return
i
;
}
else
{
if
((
pre_dev
==
d
)
&&
(
pre_chan
==
dev
->
chanmap
[
i
]))
{
dev
->
usage
[
i
]
&=
ISDN_USAGE_EXCLUSIVE
;
dev
->
usage
[
i
]
|=
usage
;
isdn_info_update
();
restore_flags
(
flags
);
return
i
;
}
}
}
}
}
}
}
...
@@ -1802,28 +1741,32 @@ isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
...
@@ -1802,28 +1741,32 @@ isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
void
void
isdn_free_channel
(
int
di
,
int
ch
,
int
usage
)
isdn_free_channel
(
int
di
,
int
ch
,
int
usage
)
{
{
int
i
;
int
sl
;
ulong
flags
;
sl
=
isdn_dc2minor
(
di
,
ch
);
isdn_slot_free
(
sl
,
usage
);
}
void
isdn_slot_free
(
int
sl
,
int
usage
)
{
unsigned
long
flags
;
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
(
!
usage
||
(
slot
[
sl
].
usage
&
ISDN_USAGE_MASK
)
==
usage
)
{
if
(((
!
usage
)
||
((
dev
->
usage
[
i
]
&
ISDN_USAGE_MASK
)
==
usage
))
&&
strcpy
(
isdn_slot_num
(
sl
),
"???"
);
(
dev
->
drvmap
[
i
]
==
di
)
&&
slot
[
sl
].
ibytes
=
0
;
(
dev
->
chanmap
[
i
]
==
ch
))
{
slot
[
sl
].
obytes
=
0
;
dev
->
usage
[
i
]
&=
(
ISDN_USAGE_NONE
|
ISDN_USAGE_EXCLUSIVE
);
strcpy
(
dev
->
num
[
i
],
"???"
);
dev
->
ibytes
[
i
]
=
0
;
dev
->
obytes
[
i
]
=
0
;
// 20.10.99 JIM, try to reinitialize v110 !
// 20.10.99 JIM, try to reinitialize v110 !
dev
->
v110emu
[
i
]
=
0
;
slot
[
sl
].
iv110
.
v110emu
=
0
;
atomic_set
(
&
(
dev
->
v110use
[
i
])
,
0
);
atomic_set
(
&
slot
[
sl
].
iv110
.
v110use
,
0
);
isdn_v110_close
(
dev
->
v110
[
i
]
);
isdn_v110_close
(
slot
[
sl
].
iv110
.
v110
);
dev
->
v110
[
i
]
=
NULL
;
slot
[
sl
].
iv110
.
v110
=
NULL
;
// 20.10.99 JIM, try to reinitialize v110 !
// 20.10.99 JIM, try to reinitialize v110 !
isdn_info_update
(
);
isdn_slot_set_usage
(
sl
,
isdn_slot_usage
(
sl
)
&
(
ISDN_USAGE_NONE
|
ISDN_USAGE_EXCLUSIVE
)
);
skb_queue_purge
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
]);
skb_queue_purge
(
&
dev
->
drv
[
isdn_slot_driver
(
sl
)]
->
rpqueue
[
isdn_slot_channel
(
sl
)
]);
}
}
restore_flags
(
flags
);
restore_flags
(
flags
);
}
}
...
@@ -1839,10 +1782,9 @@ isdn_unexclusive_channel(int di, int ch)
...
@@ -1839,10 +1782,9 @@ isdn_unexclusive_channel(int di, int ch)
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
((
dev
->
drvmap
[
i
]
==
di
)
&&
if
((
slot
[
i
].
di
==
di
)
&&
(
dev
->
chanmap
[
i
]
==
ch
))
{
(
slot
[
i
].
ch
==
ch
))
{
dev
->
usage
[
i
]
&=
~
ISDN_USAGE_EXCLUSIVE
;
isdn_slot_set_usage
(
i
,
isdn_slot_usage
(
i
)
&
~
ISDN_USAGE_EXCLUSIVE
);
isdn_info_update
();
restore_flags
(
flags
);
restore_flags
(
flags
);
return
;
return
;
}
}
...
@@ -1853,17 +1795,20 @@ isdn_unexclusive_channel(int di, int ch)
...
@@ -1853,17 +1795,20 @@ isdn_unexclusive_channel(int di, int ch)
* Return: length of data on success, -ERRcode on failure.
* Return: length of data on success, -ERRcode on failure.
*/
*/
int
int
isdn_
writebuf_skb_stub
(
int
drvidx
,
int
chan
,
int
ack
,
struct
sk_buff
*
skb
)
isdn_
slot_write
(
int
sl
,
struct
sk_buff
*
skb
)
{
{
int
ret
;
int
ret
;
struct
sk_buff
*
nskb
=
NULL
;
struct
sk_buff
*
nskb
=
NULL
;
int
v110_ret
=
skb
->
len
;
int
v110_ret
=
skb
->
len
;
int
idx
=
isdn_dc2minor
(
drvidx
,
chan
);
int
di
=
isdn_slot_driver
(
sl
);
int
ch
=
isdn_slot_channel
(
sl
);
BUG_ON
(
sl
<
0
);
if
(
dev
->
v110
[
idx
]
)
{
if
(
slot
[
sl
].
iv110
.
v110
)
{
atomic_inc
(
&
dev
->
v110use
[
idx
]
);
atomic_inc
(
&
slot
[
sl
].
iv110
.
v110use
);
nskb
=
isdn_v110_encode
(
dev
->
v110
[
idx
]
,
skb
);
nskb
=
isdn_v110_encode
(
slot
[
sl
].
iv110
.
v110
,
skb
);
atomic_dec
(
&
dev
->
v110use
[
idx
]
);
atomic_dec
(
&
slot
[
sl
].
iv110
.
v110use
);
if
(
!
nskb
)
if
(
!
nskb
)
return
0
;
return
0
;
v110_ret
=
*
((
int
*
)
nskb
->
data
);
v110_ret
=
*
((
int
*
)
nskb
->
data
);
...
@@ -1873,10 +1818,9 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
...
@@ -1873,10 +1818,9 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
return
v110_ret
;
return
v110_ret
;
}
}
/* V.110 must always be acknowledged */
/* V.110 must always be acknowledged */
ack
=
1
;
ret
=
dev
->
drv
[
di
]
->
interface
->
writebuf_skb
(
di
,
ch
,
1
,
nskb
);
ret
=
dev
->
drv
[
drvidx
]
->
interface
->
writebuf_skb
(
drvidx
,
chan
,
ack
,
nskb
);
}
else
{
}
else
{
int
hl
=
dev
->
drv
[
drvidx
]
->
interface
->
hl_hdrlen
;
int
hl
=
isdn_slot_hdrlen
(
sl
)
;
if
(
skb_headroom
(
skb
)
<
hl
){
if
(
skb_headroom
(
skb
)
<
hl
){
/*
/*
...
@@ -1892,22 +1836,22 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
...
@@ -1892,22 +1836,22 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
skb_tmp
=
skb_realloc_headroom
(
skb
,
hl
);
skb_tmp
=
skb_realloc_headroom
(
skb
,
hl
);
printk
(
KERN_DEBUG
"isdn_writebuf_skb_stub: reallocating headroom%s
\n
"
,
skb_tmp
?
""
:
" failed"
);
printk
(
KERN_DEBUG
"isdn_writebuf_skb_stub: reallocating headroom%s
\n
"
,
skb_tmp
?
""
:
" failed"
);
if
(
!
skb_tmp
)
return
-
ENOMEM
;
/* 0 better? */
if
(
!
skb_tmp
)
return
-
ENOMEM
;
/* 0 better? */
ret
=
dev
->
drv
[
d
rvidx
]
->
interface
->
writebuf_skb
(
drvidx
,
chan
,
ack
,
skb_tmp
);
ret
=
dev
->
drv
[
d
i
]
->
interface
->
writebuf_skb
(
di
,
ch
,
1
,
skb_tmp
);
if
(
ret
>
0
){
if
(
ret
>
0
){
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
skb
);
}
else
{
}
else
{
dev_kfree_skb
(
skb_tmp
);
dev_kfree_skb
(
skb_tmp
);
}
}
}
else
{
}
else
{
ret
=
dev
->
drv
[
d
rvidx
]
->
interface
->
writebuf_skb
(
drvidx
,
chan
,
ack
,
skb
);
ret
=
dev
->
drv
[
d
i
]
->
interface
->
writebuf_skb
(
di
,
ch
,
1
,
skb
);
}
}
}
}
if
(
ret
>
0
)
{
if
(
ret
>
0
)
{
dev
->
obytes
[
idx
]
+=
ret
;
slot
[
sl
].
obytes
+=
ret
;
if
(
dev
->
v110
[
idx
]
)
{
if
(
slot
[
sl
].
iv110
.
v110
)
{
atomic_inc
(
&
dev
->
v110use
[
idx
]
);
atomic_inc
(
&
slot
[
sl
].
iv110
.
v110use
);
dev
->
v110
[
idx
]
->
skbuser
++
;
slot
[
sl
].
iv110
.
v110
->
skbuser
++
;
atomic_dec
(
&
dev
->
v110use
[
idx
]
);
atomic_dec
(
&
slot
[
sl
].
iv110
.
v110use
);
/* For V.110 return unencoded data length */
/* For V.110 return unencoded data length */
ret
=
v110_ret
;
ret
=
v110_ret
;
/* if the complete frame was send we free the skb;
/* if the complete frame was send we free the skb;
...
@@ -1916,7 +1860,7 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
...
@@ -1916,7 +1860,7 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
skb
);
}
}
}
else
}
else
if
(
dev
->
v110
[
idx
]
)
if
(
slot
[
sl
].
iv110
.
v110
)
dev_kfree_skb
(
nskb
);
dev_kfree_skb
(
nskb
);
return
ret
;
return
ret
;
}
}
...
@@ -1997,9 +1941,9 @@ isdn_add_channels(driver *d, int drvidx, int n, int adding)
...
@@ -1997,9 +1941,9 @@ isdn_add_channels(driver *d, int drvidx, int n, int adding)
cli
();
cli
();
for
(
j
=
d
->
channels
;
j
<
m
;
j
++
)
for
(
j
=
d
->
channels
;
j
<
m
;
j
++
)
for
(
k
=
0
;
k
<
ISDN_MAX_CHANNELS
;
k
++
)
for
(
k
=
0
;
k
<
ISDN_MAX_CHANNELS
;
k
++
)
if
(
dev
->
chanmap
[
k
]
<
0
)
{
if
(
slot
[
k
].
ch
<
0
)
{
dev
->
chanmap
[
k
]
=
j
;
slot
[
k
].
ch
=
j
;
dev
->
drvmap
[
k
]
=
drvidx
;
slot
[
k
].
di
=
drvidx
;
isdn_register_devfs
(
k
);
isdn_register_devfs
(
k
);
break
;
break
;
}
}
...
@@ -2026,7 +1970,7 @@ set_global_features(void)
...
@@ -2026,7 +1970,7 @@ set_global_features(void)
}
}
}
}
#if
def CONFIG_ISDN_DIVERSION
#if
defined(CONFIG_ISDN_DIVERSION) || defined(CONFIG_ISDN_DIVERSION_MODULE)
static
char
*
map_drvname
(
int
di
)
static
char
*
map_drvname
(
int
di
)
{
{
...
@@ -2075,7 +2019,7 @@ int DIVERT_REG_NAME(isdn_divert_if *i_div)
...
@@ -2075,7 +2019,7 @@ int DIVERT_REG_NAME(isdn_divert_if *i_div)
EXPORT_SYMBOL
(
DIVERT_REG_NAME
);
EXPORT_SYMBOL
(
DIVERT_REG_NAME
);
#endif
/* CONFIG_ISDN_DIVERSION */
#endif
EXPORT_SYMBOL
(
register_isdn
);
EXPORT_SYMBOL
(
register_isdn
);
...
@@ -2140,6 +2084,186 @@ register_isdn(isdn_if * i)
...
@@ -2140,6 +2084,186 @@ register_isdn(isdn_if * i)
return
1
;
return
1
;
}
}
int
isdn_slot_driver
(
int
sl
)
{
BUG_ON
(
sl
<
0
);
return
slot
[
sl
].
di
;
}
int
isdn_slot_channel
(
int
sl
)
{
BUG_ON
(
sl
<
0
);
return
slot
[
sl
].
ch
;
}
int
isdn_slot_hdrlen
(
int
sl
)
{
int
di
=
isdn_slot_driver
(
sl
);
return
dev
->
drv
[
di
]
->
interface
->
hl_hdrlen
;
}
char
*
isdn_slot_map_eaz2msn
(
int
sl
,
char
*
msn
)
{
int
di
=
isdn_slot_driver
(
sl
);
return
isdn_map_eaz2msn
(
msn
,
di
);
}
int
isdn_slot_command
(
int
sl
,
int
cmd
,
isdn_ctrl
*
ctrl
)
{
ctrl
->
command
=
cmd
;
ctrl
->
driver
=
isdn_slot_driver
(
sl
);
switch
(
cmd
)
{
case
ISDN_CMD_SETL2
:
case
ISDN_CMD_SETL3
:
case
ISDN_CMD_PROT_IO
:
ctrl
->
arg
&=
~
0xff
;
ctrl
->
arg
|=
isdn_slot_channel
(
sl
);
break
;
default:
ctrl
->
arg
=
isdn_slot_channel
(
sl
);
break
;
}
return
isdn_command
(
ctrl
);
}
int
isdn_slot_dial
(
int
sl
,
struct
dial_info
*
dial
)
{
isdn_ctrl
cmd
;
int
retval
;
char
*
msn
=
isdn_slot_map_eaz2msn
(
sl
,
dial
->
msn
);
/* check for DOV */
if
(
dial
->
si1
==
7
&&
tolower
(
dial
->
phone
[
0
])
==
'v'
)
{
/* DOV call */
dial
->
si1
=
1
;
dial
->
phone
++
;
/* skip v/V */
}
strcpy
(
isdn_slot_num
(
sl
),
dial
->
phone
);
isdn_slot_set_usage
(
sl
,
isdn_slot_usage
(
sl
)
|
ISDN_USAGE_OUTGOING
);
retval
=
isdn_slot_command
(
sl
,
ISDN_CMD_CLREAZ
,
&
cmd
);
if
(
retval
)
return
retval
;
strcpy
(
cmd
.
parm
.
num
,
msn
);
retval
=
isdn_slot_command
(
sl
,
ISDN_CMD_SETEAZ
,
&
cmd
);
cmd
.
arg
=
dial
->
l2_proto
<<
8
;
cmd
.
parm
.
fax
=
dial
->
fax
;
retval
=
isdn_slot_command
(
sl
,
ISDN_CMD_SETL2
,
&
cmd
);
if
(
retval
)
return
retval
;
cmd
.
arg
=
dial
->
l3_proto
<<
8
;
retval
=
isdn_slot_command
(
sl
,
ISDN_CMD_SETL3
,
&
cmd
);
if
(
retval
)
return
retval
;
cmd
.
parm
.
setup
.
si1
=
dial
->
si1
;
cmd
.
parm
.
setup
.
si2
=
dial
->
si2
;
strcpy
(
cmd
.
parm
.
setup
.
eazmsn
,
msn
);
strcpy
(
cmd
.
parm
.
setup
.
phone
,
dial
->
phone
);
printk
(
KERN_INFO
"ISDN: slot %d: Dialing %s -> %s (SI %d/%d) (B %d/%d)
\n
"
,
sl
,
cmd
.
parm
.
setup
.
eazmsn
,
cmd
.
parm
.
setup
.
phone
,
cmd
.
parm
.
setup
.
si1
,
cmd
.
parm
.
setup
.
si2
,
dial
->
l2_proto
,
dial
->
l3_proto
);
return
isdn_slot_command
(
sl
,
ISDN_CMD_DIAL
,
&
cmd
);
}
void
isdn_slot_all_eaz
(
int
sl
)
{
isdn_ctrl
cmd
;
cmd
.
parm
.
num
[
0
]
=
'\0'
;
isdn_slot_command
(
sl
,
ISDN_CMD_SETEAZ
,
&
cmd
);
}
int
isdn_slot_usage
(
int
sl
)
{
BUG_ON
(
sl
<
0
);
return
slot
[
sl
].
usage
;
}
void
isdn_slot_set_usage
(
int
sl
,
int
usage
)
{
BUG_ON
(
sl
<
0
);
slot
[
sl
].
usage
=
usage
;
isdn_info_update
();
}
int
isdn_slot_m_idx
(
int
sl
)
{
BUG_ON
(
sl
<
0
);
return
slot
[
sl
].
m_idx
;
}
void
isdn_slot_set_m_idx
(
int
sl
,
int
midx
)
{
BUG_ON
(
sl
<
0
);
slot
[
sl
].
m_idx
=
midx
;
}
char
*
isdn_slot_num
(
int
sl
)
{
BUG_ON
(
sl
<
0
);
return
slot
[
sl
].
num
;
}
void
isdn_slot_set_rx_netdev
(
int
sl
,
isdn_net_dev
*
nd
)
{
BUG_ON
(
sl
<
0
);
slot
[
sl
].
rx_netdev
=
nd
;
}
isdn_net_dev
*
isdn_slot_rx_netdev
(
int
sl
)
{
BUG_ON
(
sl
<
0
);
return
slot
[
sl
].
rx_netdev
;
}
void
isdn_slot_set_st_netdev
(
int
sl
,
isdn_net_dev
*
nd
)
{
BUG_ON
(
sl
<
0
);
slot
[
sl
].
st_netdev
=
nd
;
}
isdn_net_dev
*
isdn_slot_st_netdev
(
int
sl
)
{
BUG_ON
(
sl
<
0
);
return
slot
[
sl
].
st_netdev
;
}
/*
/*
*****************************************************************************
*****************************************************************************
* And now the modules code.
* And now the modules code.
...
@@ -2247,53 +2371,43 @@ static void isdn_cleanup_devfs(void)
...
@@ -2247,53 +2371,43 @@ static void isdn_cleanup_devfs(void)
static
int
__init
isdn_init
(
void
)
static
int
__init
isdn_init
(
void
)
{
{
int
i
;
int
i
;
int
retval
;
char
tmprev
[
50
];
char
tmprev
[
50
];
if
(
!
(
dev
=
(
isdn_dev
*
)
vmalloc
(
sizeof
(
isdn_dev
))))
{
dev
=
vmalloc
(
sizeof
(
*
dev
));
printk
(
KERN_WARNING
"isdn: Could not allocate device-struct.
\n
"
);
if
(
!
dev
)
{
return
-
EIO
;
retval
=
-
ENOMEM
;
goto
err
;
}
}
memset
(
(
char
*
)
dev
,
0
,
sizeof
(
isdn_
dev
));
memset
(
dev
,
0
,
sizeof
(
*
dev
));
init_timer
(
&
dev
->
timer
);
init_timer
(
&
dev
->
timer
);
dev
->
timer
.
function
=
isdn_timer_funct
;
dev
->
timer
.
function
=
isdn_timer_funct
;
init_MUTEX
(
&
dev
->
sem
);
init_MUTEX
(
&
dev
->
sem
);
init_waitqueue_head
(
&
dev
->
info_waitq
);
init_waitqueue_head
(
&
dev
->
info_waitq
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
dev
->
drvmap
[
i
]
=
-
1
;
slot
[
i
].
di
=
-
1
;
dev
->
chanmap
[
i
]
=
-
1
;
slot
[
i
].
ch
=
-
1
;
dev
->
m_idx
[
i
]
=
-
1
;
slot
[
i
].
m_idx
=
-
1
;
strcpy
(
dev
->
num
[
i
]
,
"???"
);
strcpy
(
isdn_slot_num
(
i
)
,
"???"
);
init_waitqueue_head
(
&
dev
->
mdm
.
info
[
i
].
open_wait
);
init_waitqueue_head
(
&
dev
->
mdm
.
info
[
i
].
open_wait
);
init_waitqueue_head
(
&
dev
->
mdm
.
info
[
i
].
close_wait
);
init_waitqueue_head
(
&
dev
->
mdm
.
info
[
i
].
close_wait
);
}
}
if
(
register_chrdev
(
ISDN_MAJOR
,
"isdn"
,
&
isdn_fops
))
{
retval
=
register_chrdev
(
ISDN_MAJOR
,
"isdn"
,
&
isdn_fops
);
if
(
retval
)
{
printk
(
KERN_WARNING
"isdn: Could not register control devices
\n
"
);
printk
(
KERN_WARNING
"isdn: Could not register control devices
\n
"
);
vfree
(
dev
);
goto
err_vfree
;
return
-
EIO
;
}
}
isdn_init_devfs
();
isdn_init_devfs
();
if
((
i
=
isdn_tty_modem_init
())
<
0
)
{
retval
=
isdn_tty_init
();
if
(
retval
<
0
)
{
printk
(
KERN_WARNING
"isdn: Could not register tty devices
\n
"
);
printk
(
KERN_WARNING
"isdn: Could not register tty devices
\n
"
);
if
(
i
==
-
3
)
goto
err_cleanup_devfs
;
tty_unregister_driver
(
&
dev
->
mdm
.
cua_modem
);
if
(
i
<=
-
2
)
tty_unregister_driver
(
&
dev
->
mdm
.
tty_modem
);
vfree
(
dev
);
isdn_cleanup_devfs
();
unregister_chrdev
(
ISDN_MAJOR
,
"isdn"
);
return
-
EIO
;
}
}
#ifdef CONFIG_ISDN_PPP
#ifdef CONFIG_ISDN_PPP
if
(
isdn_ppp_init
()
<
0
)
{
retval
=
isdn_ppp_init
();
if
(
retval
<
0
)
{
printk
(
KERN_WARNING
"isdn: Could not create PPP-device-structs
\n
"
);
printk
(
KERN_WARNING
"isdn: Could not create PPP-device-structs
\n
"
);
tty_unregister_driver
(
&
dev
->
mdm
.
tty_modem
);
goto
err_tty_modem
;
tty_unregister_driver
(
&
dev
->
mdm
.
cua_modem
);
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
kfree
(
dev
->
mdm
.
info
[
i
].
xmit_buf
-
4
);
isdn_cleanup_devfs
();
unregister_chrdev
(
ISDN_MAJOR
,
"isdn"
);
vfree
(
dev
);
return
-
EIO
;
}
}
#endif
/* CONFIG_ISDN_PPP */
#endif
/* CONFIG_ISDN_PPP */
...
@@ -2317,6 +2431,16 @@ static int __init isdn_init(void)
...
@@ -2317,6 +2431,16 @@ static int __init isdn_init(void)
#endif
#endif
isdn_info_update
();
isdn_info_update
();
return
0
;
return
0
;
err_tty_modem:
isdn_tty_exit
();
err_cleanup_devfs:
isdn_cleanup_devfs
();
unregister_chrdev
(
ISDN_MAJOR
,
"isdn"
);
err_vfree:
vfree
(
dev
);
err:
return
retval
;
}
}
/*
/*
...
@@ -2325,46 +2449,24 @@ static int __init isdn_init(void)
...
@@ -2325,46 +2449,24 @@ static int __init isdn_init(void)
static
void
__exit
isdn_exit
(
void
)
static
void
__exit
isdn_exit
(
void
)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
int
i
;
#ifdef CONFIG_ISDN_PPP
#ifdef CONFIG_ISDN_PPP
isdn_ppp_cleanup
();
isdn_ppp_cleanup
();
#endif
#endif
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
if
(
isdn_net_rmall
()
<
0
)
{
if
(
isdn_net_rmall
()
<
0
)
printk
(
KERN_WARNING
"isdn: net-device busy, remove cancelled
\n
"
);
BUG
();
restore_flags
(
flags
);
return
;
isdn_tty_exit
();
}
if
(
unregister_chrdev
(
ISDN_MAJOR
,
"isdn"
))
if
(
tty_unregister_driver
(
&
dev
->
mdm
.
tty_modem
))
{
BUG
();
printk
(
KERN_WARNING
"isdn: ttyI-device busy, remove cancelled
\n
"
);
restore_flags
(
flags
);
isdn_cleanup_devfs
();
return
;
del_timer
(
&
dev
->
timer
);
}
restore_flags
(
flags
);
if
(
tty_unregister_driver
(
&
dev
->
mdm
.
cua_modem
))
{
/* call vfree with interrupts enabled, else it will hang */
printk
(
KERN_WARNING
"isdn: cui-device busy, remove cancelled
\n
"
);
vfree
(
dev
);
restore_flags
(
flags
);
return
;
}
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
isdn_tty_cleanup_xmit
(
&
dev
->
mdm
.
info
[
i
]);
kfree
(
dev
->
mdm
.
info
[
i
].
xmit_buf
-
4
);
#ifdef CONFIG_ISDN_TTY_FAX
kfree
(
dev
->
mdm
.
info
[
i
].
fax
);
#endif
}
if
(
unregister_chrdev
(
ISDN_MAJOR
,
"isdn"
)
!=
0
)
{
printk
(
KERN_WARNING
"isdn: controldevice busy, remove cancelled
\n
"
);
restore_flags
(
flags
);
}
else
{
isdn_cleanup_devfs
();
del_timer
(
&
dev
->
timer
);
restore_flags
(
flags
);
/* call vfree with interrupts enabled, else it will hang */
vfree
(
dev
);
printk
(
KERN_NOTICE
"ISDN-subsystem unloaded
\n
"
);
}
}
}
module_init
(
isdn_init
);
module_init
(
isdn_init
);
...
...
drivers/isdn/i4l/isdn_common.h
View file @
b14ebcfc
...
@@ -23,6 +23,32 @@
...
@@ -23,6 +23,32 @@
#undef ISDN_DEBUG_NET_DUMP
#undef ISDN_DEBUG_NET_DUMP
#undef ISDN_DEBUG_NET_DIAL
#undef ISDN_DEBUG_NET_DIAL
#undef ISDN_DEBUG_NET_ICALL
#undef ISDN_DEBUG_NET_ICALL
#undef ISDN_DEBUG_STATCALLB
#undef ISDN_DEBUG_COMMAND
#ifdef ISDN_DEBUG_NET_DIAL
#define dbg_net_dial(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_net_dial(arg...) do {} while (0)
#endif
#ifdef ISDN_DEBUG_NET_ICALL
#define dbg_net_icall(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_net_icall(arg...) do {} while (0)
#endif
#ifdef ISDN_DEBUG_STATCALLB
#define dbg_statcallb(arg...) printk(KERN_DEBUG arg)
#else
#define dbg_statcallb(arg...) do {} while (0)
#endif
#define isdn_BUG() \
do { printk(KERN_WARNING "ISDN Bug at %s:%d\n", __FILE__, __LINE__); \
} while(0)
#define HERE printk("%s:%d (%s)\n", __FILE__, __LINE__, __FUNCTION__)
/* Prototypes */
/* Prototypes */
extern
void
isdn_MOD_INC_USE_COUNT
(
void
);
extern
void
isdn_MOD_INC_USE_COUNT
(
void
);
...
@@ -30,20 +56,50 @@ extern void isdn_MOD_DEC_USE_COUNT(void);
...
@@ -30,20 +56,50 @@ extern void isdn_MOD_DEC_USE_COUNT(void);
extern
void
isdn_lock_drivers
(
void
);
extern
void
isdn_lock_drivers
(
void
);
extern
void
isdn_unlock_drivers
(
void
);
extern
void
isdn_unlock_drivers
(
void
);
extern
void
isdn_free_channel
(
int
di
,
int
ch
,
int
usage
);
extern
void
isdn_free_channel
(
int
di
,
int
ch
,
int
usage
);
extern
void
isdn_all_eaz
(
int
di
,
int
ch
);
extern
int
isdn_command
(
isdn_ctrl
*
);
extern
int
isdn_dc2minor
(
int
di
,
int
ch
);
extern
int
isdn_dc2minor
(
int
di
,
int
ch
);
extern
void
isdn_info_update
(
void
);
extern
void
isdn_info_update
(
void
);
extern
char
*
isdn_map_eaz2msn
(
char
*
msn
,
int
di
);
extern
char
*
isdn_map_eaz2msn
(
char
*
msn
,
int
di
);
extern
void
isdn_timer_ctrl
(
int
tf
,
int
onoff
);
extern
void
isdn_timer_ctrl
(
int
tf
,
int
onoff
);
extern
void
isdn_unexclusive_channel
(
int
di
,
int
ch
);
extern
void
isdn_unexclusive_channel
(
int
di
,
int
ch
);
extern
int
isdn_getnum
(
char
**
);
extern
int
isdn_getnum
(
char
**
);
extern
int
isdn_readbchan
(
int
,
int
,
u_char
*
,
u_char
*
,
int
,
wait_queue_head_t
*
);
extern
int
isdn_get_free_channel
(
int
,
int
,
int
,
int
,
int
,
char
*
);
extern
int
isdn_writebuf_skb_stub
(
int
,
int
,
int
,
struct
sk_buff
*
);
extern
int
register_isdn
(
isdn_if
*
i
);
extern
int
isdn_msncmp
(
const
char
*
,
const
char
*
);
extern
int
isdn_msncmp
(
const
char
*
,
const
char
*
);
extern
int
isdn_add_channels
(
driver
*
,
int
,
int
,
int
);
extern
int
isdn_add_channels
(
driver
*
,
int
,
int
,
int
);
#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
extern
void
isdn_dumppkt
(
char
*
,
u_char
*
,
int
,
int
);
extern
void
isdn_dumppkt
(
char
*
,
u_char
*
,
int
,
int
);
#else
static
inline
void
isdn_dumppkt
(
char
*
s
,
u_char
*
d
,
int
l
,
int
m
)
{
}
#endif
#endif
struct
dial_info
{
int
l2_proto
;
int
l3_proto
;
struct
T30_s
*
fax
;
unsigned
char
si1
;
unsigned
char
si2
;
unsigned
char
*
msn
;
unsigned
char
*
phone
;
};
extern
struct
list_head
isdn_net_devs
;
extern
int
isdn_get_free_slot
(
int
,
int
,
int
,
int
,
int
,
char
*
);
extern
void
isdn_slot_free
(
int
slot
,
int
usage
);
extern
void
isdn_slot_all_eaz
(
int
slot
);
extern
int
isdn_slot_command
(
int
slot
,
int
cmd
,
isdn_ctrl
*
);
extern
int
isdn_slot_dial
(
int
slot
,
struct
dial_info
*
dial
);
extern
char
*
isdn_slot_map_eaz2msn
(
int
slot
,
char
*
msn
);
extern
int
isdn_slot_write
(
int
slot
,
struct
sk_buff
*
);
extern
int
isdn_slot_readbchan
(
int
slot
,
u_char
*
,
u_char
*
,
int
);
extern
int
isdn_slot_hdrlen
(
int
slot
);
extern
int
isdn_slot_driver
(
int
slot
);
extern
int
isdn_slot_channel
(
int
slot
);
extern
int
isdn_slot_usage
(
int
slot
);
extern
void
isdn_slot_set_usage
(
int
slot
,
int
usage
);
extern
char
*
isdn_slot_num
(
int
slot
);
extern
int
isdn_slot_m_idx
(
int
slot
);
extern
void
isdn_slot_set_m_idx
(
int
slot
,
int
midx
);
extern
void
isdn_slot_set_rx_netdev
(
int
sl
,
isdn_net_dev
*
nd
);
extern
void
isdn_slot_set_st_netdev
(
int
sl
,
isdn_net_dev
*
nd
);
extern
isdn_net_dev
*
isdn_slot_rx_netdev
(
int
sl
);
extern
isdn_net_dev
*
isdn_slot_st_netdev
(
int
sl
);
drivers/isdn/i4l/isdn_net.c
View file @
b14ebcfc
...
@@ -38,6 +38,27 @@
...
@@ -38,6 +38,27 @@
#include "isdn_concap.h"
#include "isdn_concap.h"
#endif
#endif
enum
{
ST_NULL
,
ST_OUT_WAIT_DCONN
,
ST_OUT_WAIT_BCONN
,
ST_IN_WAIT_DCONN
,
ST_IN_WAIT_BCONN
,
ST_ACTIVE
,
ST_WAIT_BEFORE_CB
,
};
/* keep clear of ISDN_CMD_* and ISDN_STAT_* */
enum
{
EV_NET_DIAL
=
0x200
,
EV_NET_TIMER_IN_DCONN
=
0x201
,
EV_NET_TIMER_IN_BCONN
=
0x202
,
EV_NET_TIMER_OUT_DCONN
=
0x203
,
EV_NET_TIMER_OUT_BCONN
=
0x204
,
EV_NET_TIMER_CB
=
0x205
,
};
LIST_HEAD
(
isdn_net_devs
);
/* Linked list of isdn_net_dev's */
/*
/*
* Outline of new tbusy handling:
* Outline of new tbusy handling:
...
@@ -72,7 +93,7 @@
...
@@ -72,7 +93,7 @@
*/
*/
static
__inline__
int
isdn_net_device_started
(
isdn_net_dev
*
n
)
static
__inline__
int
isdn_net_device_started
(
isdn_net_dev
*
n
)
{
{
isdn_net_local
*
lp
=
n
->
local
;
isdn_net_local
*
lp
=
&
n
->
local
;
struct
net_device
*
dev
;
struct
net_device
*
dev
;
if
(
lp
->
master
)
if
(
lp
->
master
)
...
@@ -179,10 +200,13 @@ static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp)
...
@@ -179,10 +200,13 @@ static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp)
int
isdn_net_force_dial_lp
(
isdn_net_local
*
);
int
isdn_net_force_dial_lp
(
isdn_net_local
*
);
static
int
isdn_net_start_xmit
(
struct
sk_buff
*
,
struct
net_device
*
);
static
int
isdn_net_start_xmit
(
struct
sk_buff
*
,
struct
net_device
*
);
static
int
do_dialout
(
isdn_net_local
*
lp
);
static
void
isdn_net_ciscohdlck_connected
(
isdn_net_local
*
lp
);
static
void
isdn_net_ciscohdlck_connected
(
isdn_net_local
*
lp
);
static
void
isdn_net_ciscohdlck_disconnected
(
isdn_net_local
*
lp
);
static
void
isdn_net_ciscohdlck_disconnected
(
isdn_net_local
*
lp
);
static
int
isdn_net_handle_event
(
isdn_net_local
*
lp
,
int
pr
,
void
*
arg
);
char
*
isdn_net_revision
=
"$Revision: 1.140.6.11 $"
;
char
*
isdn_net_revision
=
"$Revision: 1.140.6.11 $"
;
/*
/*
...
@@ -280,10 +304,9 @@ isdn_net_bind_channel(isdn_net_local * lp, int idx)
...
@@ -280,10 +304,9 @@ isdn_net_bind_channel(isdn_net_local * lp, int idx)
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
lp
->
flags
|=
ISDN_NET_CONNECTED
;
lp
->
flags
|=
ISDN_NET_CONNECTED
;
lp
->
isdn_device
=
dev
->
drvmap
[
idx
];
lp
->
isdn_slot
=
idx
;
lp
->
isdn_channel
=
dev
->
chanmap
[
idx
];
isdn_slot_set_rx_netdev
(
lp
->
isdn_slot
,
lp
->
netdev
);
dev
->
rx_netdev
[
idx
]
=
lp
->
netdev
;
isdn_slot_set_st_netdev
(
lp
->
isdn_slot
,
lp
->
netdev
);
dev
->
st_netdev
[
idx
]
=
lp
->
netdev
;
restore_flags
(
flags
);
restore_flags
(
flags
);
}
}
...
@@ -306,13 +329,14 @@ isdn_net_unbind_channel(isdn_net_local * lp)
...
@@ -306,13 +329,14 @@ isdn_net_unbind_channel(isdn_net_local * lp)
*/
*/
qdisc_reset
(
lp
->
netdev
->
dev
.
qdisc
);
qdisc_reset
(
lp
->
netdev
->
dev
.
qdisc
);
}
}
lp
->
dialstate
=
0
;
lp
->
dialstate
=
ST_NULL
;
dev
->
rx_netdev
[
isdn_dc2minor
(
lp
->
isdn_device
,
lp
->
isdn_channel
)]
=
NULL
;
if
(
lp
->
isdn_slot
>=
0
)
{
dev
->
st_netdev
[
isdn_dc2minor
(
lp
->
isdn_device
,
lp
->
isdn_channel
)]
=
NULL
;
isdn_slot_set_rx_netdev
(
lp
->
isdn_slot
,
NULL
);
isdn_free_channel
(
lp
->
isdn_device
,
lp
->
isdn_channel
,
ISDN_USAGE_NET
);
isdn_slot_set_st_netdev
(
lp
->
isdn_slot
,
NULL
);
isdn_slot_free
(
lp
->
isdn_slot
,
ISDN_USAGE_NET
);
}
lp
->
flags
&=
~
ISDN_NET_CONNECTED
;
lp
->
flags
&=
~
ISDN_NET_CONNECTED
;
lp
->
isdn_device
=
-
1
;
lp
->
isdn_slot
=
-
1
;
lp
->
isdn_channel
=
-
1
;
restore_flags
(
flags
);
restore_flags
(
flags
);
}
}
...
@@ -335,12 +359,13 @@ unsigned long last_jiffies = -HZ;
...
@@ -335,12 +359,13 @@ unsigned long last_jiffies = -HZ;
void
void
isdn_net_autohup
()
isdn_net_autohup
()
{
{
isdn_net_dev
*
p
=
dev
->
netdev
;
struct
list_head
*
l
;
int
anymore
;
int
anymore
;
anymore
=
0
;
anymore
=
0
;
while
(
p
)
{
list_for_each
(
l
,
&
isdn_net_devs
)
{
isdn_net_local
*
l
=
p
->
local
;
isdn_net_dev
*
p
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
isdn_net_local
*
l
=
&
p
->
local
;
if
(
jiffies
==
last_jiffies
)
if
(
jiffies
==
last_jiffies
)
l
->
cps
=
l
->
transcount
;
l
->
cps
=
l
->
transcount
;
else
else
...
@@ -348,9 +373,10 @@ isdn_net_autohup()
...
@@ -348,9 +373,10 @@ isdn_net_autohup()
l
->
transcount
=
0
;
l
->
transcount
=
0
;
if
(
dev
->
net_verbose
>
3
)
if
(
dev
->
net_verbose
>
3
)
printk
(
KERN_DEBUG
"%s: %d bogocps
\n
"
,
l
->
name
,
l
->
cps
);
printk
(
KERN_DEBUG
"%s: %d bogocps
\n
"
,
l
->
name
,
l
->
cps
);
if
((
l
->
flags
&
ISDN_NET_CONNECTED
)
&&
(
!
l
->
dialstate
))
{
if
((
l
->
flags
&
ISDN_NET_CONNECTED
)
&&
(
l
->
dialstate
==
ST_ACTIVE
))
{
anymore
=
1
;
anymore
=
1
;
l
->
huptimer
++
;
l
->
huptimer
++
;
printk
(
"huptimer %d, onhtime %d, chargetime %d, chargeint %d
\n
"
,
l
->
huptimer
,
l
->
onhtime
,
l
->
chargetime
,
l
->
chargeint
);
/*
/*
* if there is some dialmode where timeout-hangup
* if there is some dialmode where timeout-hangup
* should _not_ be done, check for that here
* should _not_ be done, check for that here
...
@@ -363,8 +389,10 @@ isdn_net_autohup()
...
@@ -363,8 +389,10 @@ isdn_net_autohup()
while
(
time_after
(
jiffies
,
l
->
chargetime
+
l
->
chargeint
))
while
(
time_after
(
jiffies
,
l
->
chargetime
+
l
->
chargeint
))
l
->
chargetime
+=
l
->
chargeint
;
l
->
chargetime
+=
l
->
chargeint
;
if
(
time_after
(
jiffies
,
l
->
chargetime
+
l
->
chargeint
-
2
*
HZ
))
if
(
time_after
(
jiffies
,
l
->
chargetime
+
l
->
chargeint
-
2
*
HZ
))
if
(
l
->
outgoing
||
l
->
hupflags
&
ISDN_INHUP
)
if
(
l
->
outgoing
||
l
->
hupflags
&
ISDN_INHUP
)
{
HERE
;
isdn_net_hangup
(
&
p
->
dev
);
isdn_net_hangup
(
&
p
->
dev
);
}
}
else
if
(
l
->
outgoing
)
{
}
else
if
(
l
->
outgoing
)
{
if
(
l
->
hupflags
&
ISDN_CHARGEHUP
)
{
if
(
l
->
hupflags
&
ISDN_CHARGEHUP
)
{
if
(
l
->
hupflags
&
ISDN_WAITCHARGE
)
{
if
(
l
->
hupflags
&
ISDN_WAITCHARGE
)
{
...
@@ -378,8 +406,10 @@ isdn_net_autohup()
...
@@ -378,8 +406,10 @@ isdn_net_autohup()
isdn_net_hangup
(
&
p
->
dev
);
isdn_net_hangup
(
&
p
->
dev
);
}
}
}
}
}
else
if
(
l
->
hupflags
&
ISDN_INHUP
)
}
else
if
(
l
->
hupflags
&
ISDN_INHUP
)
{
HERE
;
isdn_net_hangup
(
&
p
->
dev
);
isdn_net_hangup
(
&
p
->
dev
);
}
}
}
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
||
(
ISDN_NET_DIALMODE
(
*
l
)
==
ISDN_NET_DM_OFF
))
{
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
||
(
ISDN_NET_DIALMODE
(
*
l
)
==
ISDN_NET_DM_OFF
))
{
...
@@ -387,7 +417,6 @@ isdn_net_autohup()
...
@@ -387,7 +417,6 @@ isdn_net_autohup()
break
;
break
;
}
}
}
}
p
=
(
isdn_net_dev
*
)
p
->
next
;
}
}
last_jiffies
=
jiffies
;
last_jiffies
=
jiffies
;
isdn_timer_ctrl
(
ISDN_TIMER_NETHANGUP
,
anymore
);
isdn_timer_ctrl
(
ISDN_TIMER_NETHANGUP
,
anymore
);
...
@@ -398,6 +427,47 @@ static void isdn_net_lp_disconnected(isdn_net_local *lp)
...
@@ -398,6 +427,47 @@ static void isdn_net_lp_disconnected(isdn_net_local *lp)
isdn_net_rm_from_bundle
(
lp
);
isdn_net_rm_from_bundle
(
lp
);
}
}
static
void
isdn_net_connected
(
isdn_net_local
*
lp
)
{
#ifdef CONFIG_ISDN_X25
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
struct
concap_proto_ops
*
pops
=
cprot
?
cprot
->
pops
:
0
;
#endif
lp
->
dialstate
=
ST_ACTIVE
;
isdn_timer_ctrl
(
ISDN_TIMER_NETHANGUP
,
1
);
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_CISCOHDLCK
)
isdn_net_ciscohdlck_connected
(
lp
);
if
(
lp
->
p_encap
!=
ISDN_NET_ENCAP_SYNCPPP
)
{
if
(
lp
->
master
)
{
/* is lp a slave? */
isdn_net_dev
*
nd
=
((
isdn_net_local
*
)
lp
->
master
->
priv
)
->
netdev
;
isdn_net_add_to_bundle
(
nd
,
lp
);
}
}
printk
(
KERN_INFO
"isdn_net: %s connected
\n
"
,
lp
->
name
);
/* If first Chargeinfo comes before B-Channel connect,
* we correct the timestamp here.
*/
lp
->
chargetime
=
jiffies
;
/* reset dial-timeout */
lp
->
dialstarted
=
0
;
lp
->
dialwait_timer
=
0
;
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
isdn_ppp_wakeup_daemon
(
lp
);
#endif
#ifdef CONFIG_ISDN_X25
/* try if there are generic concap receiver routines */
if
(
pops
)
if
(
pops
->
connect_ind
)
pops
->
connect_ind
(
cprot
);
#endif
/* CONFIG_ISDN_X25 */
/* ppp needs to do negotiations first */
if
(
lp
->
p_encap
!=
ISDN_NET_ENCAP_SYNCPPP
)
isdn_net_device_wake_queue
(
lp
);
}
/*
/*
* Handle status-messages from ISDN-interfacecard.
* Handle status-messages from ISDN-interfacecard.
* This function is called from within the main-status-dispatcher
* This function is called from within the main-status-dispatcher
...
@@ -407,443 +477,343 @@ static void isdn_net_lp_disconnected(isdn_net_local *lp)
...
@@ -407,443 +477,343 @@ static void isdn_net_lp_disconnected(isdn_net_local *lp)
int
int
isdn_net_stat_callback
(
int
idx
,
isdn_ctrl
*
c
)
isdn_net_stat_callback
(
int
idx
,
isdn_ctrl
*
c
)
{
{
isdn_net_dev
*
p
=
dev
->
st_netdev
[
idx
];
isdn_net_dev
*
p
=
isdn_slot_st_netdev
(
idx
);
isdn_net_local
*
lp
;
int
cmd
=
c
->
command
;
int
cmd
=
c
->
command
;
if
(
p
)
{
if
(
!
p
)
{
isdn_net_local
*
lp
=
p
->
local
;
HERE
;
#ifdef CONFIG_ISDN_X25
return
0
;
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
}
struct
concap_proto_ops
*
pops
=
cprot
?
cprot
->
pops
:
0
;
lp
=
&
p
->
local
;
#endif
switch
(
cmd
)
{
case
ISDN_STAT_BSENT
:
/* A packet has successfully been sent out */
if
((
lp
->
flags
&
ISDN_NET_CONNECTED
)
&&
(
!
lp
->
dialstate
))
{
isdn_net_dec_frame_cnt
(
lp
);
lp
->
stats
.
tx_packets
++
;
lp
->
stats
.
tx_bytes
+=
c
->
parm
.
length
;
}
return
1
;
case
ISDN_STAT_DCONN
:
/* D-Channel is up */
switch
(
lp
->
dialstate
)
{
case
4
:
case
7
:
case
8
:
lp
->
dialstate
++
;
return
1
;
case
12
:
lp
->
dialstate
=
5
;
return
1
;
}
break
;
case
ISDN_STAT_DHUP
:
/* Either D-Channel-hangup or error during dialout */
#ifdef CONFIG_ISDN_X25
/* If we are not connencted then dialing had
failed. If there are generic encap protocol
receiver routines signal the closure of
the link*/
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
&&
pops
&&
pops
->
disconn_ind
)
pops
->
disconn_ind
(
cprot
);
#endif
/* CONFIG_ISDN_X25 */
if
((
!
lp
->
dialstate
)
&&
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
{
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_CISCOHDLCK
)
isdn_net_ciscohdlck_disconnected
(
lp
);
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
isdn_ppp_free
(
lp
);
#endif
isdn_net_lp_disconnected
(
lp
);
isdn_all_eaz
(
lp
->
isdn_device
,
lp
->
isdn_channel
);
printk
(
KERN_INFO
"%s: remote hangup
\n
"
,
lp
->
name
);
printk
(
KERN_INFO
"%s: Chargesum is %d
\n
"
,
lp
->
name
,
lp
->
charge
);
isdn_net_unbind_channel
(
lp
);
return
1
;
}
break
;
#ifdef CONFIG_ISDN_X25
case
ISDN_STAT_BHUP
:
/* B-Channel-hangup */
/* try if there are generic encap protocol
receiver routines and signal the closure of
the link */
if
(
pops
&&
pops
->
disconn_ind
){
pops
->
disconn_ind
(
cprot
);
return
1
;
}
break
;
#endif
/* CONFIG_ISDN_X25 */
case
ISDN_STAT_BCONN
:
/* B-Channel is up */
isdn_net_zero_frame_cnt
(
lp
);
switch
(
lp
->
dialstate
)
{
case
5
:
case
6
:
case
7
:
case
8
:
case
9
:
case
10
:
case
12
:
if
(
lp
->
dialstate
<=
6
)
{
dev
->
usage
[
idx
]
|=
ISDN_USAGE_OUTGOING
;
isdn_info_update
();
}
else
dev
->
rx_netdev
[
idx
]
=
p
;
lp
->
dialstate
=
0
;
isdn_timer_ctrl
(
ISDN_TIMER_NETHANGUP
,
1
);
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_CISCOHDLCK
)
isdn_net_ciscohdlck_connected
(
lp
);
if
(
lp
->
p_encap
!=
ISDN_NET_ENCAP_SYNCPPP
)
{
if
(
lp
->
master
)
{
/* is lp a slave? */
isdn_net_dev
*
nd
=
((
isdn_net_local
*
)
lp
->
master
->
priv
)
->
netdev
;
isdn_net_add_to_bundle
(
nd
,
lp
);
}
}
printk
(
KERN_INFO
"isdn_net: %s connected
\n
"
,
lp
->
name
);
/* If first Chargeinfo comes before B-Channel connect,
* we correct the timestamp here.
*/
lp
->
chargetime
=
jiffies
;
/* reset dial-timeout */
lp
->
dialstarted
=
0
;
lp
->
dialwait_timer
=
0
;
#ifdef CONFIG_ISDN_PPP
return
isdn_net_handle_event
(
lp
,
cmd
,
c
);
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
}
isdn_ppp_wakeup_daemon
(
lp
);
#endif
static
void
#ifdef CONFIG_ISDN_X25
isdn_net_dial_timer
(
unsigned
long
data
)
/* try if there are generic concap receiver routines */
{
if
(
pops
)
isdn_net_local
*
lp
=
(
isdn_net_local
*
)
data
;
if
(
pops
->
connect_ind
)
pops
->
connect_ind
(
cprot
);
if
(
!
lp
)
{
#endif
/* CONFIG_ISDN_X25 */
isdn_BUG
();
/* ppp needs to do negotiations first */
return
;
if
(
lp
->
p_encap
!=
ISDN_NET_ENCAP_SYNCPPP
)
isdn_net_device_wake_queue
(
lp
);
return
1
;
}
break
;
case
ISDN_STAT_NODCH
:
/* No D-Channel avail. */
if
(
lp
->
dialstate
==
4
)
{
lp
->
dialstate
--
;
return
1
;
}
break
;
case
ISDN_STAT_CINF
:
/* Charge-info from TelCo. Calculate interval between
* charge-infos and set timestamp for last info for
* usage by isdn_net_autohup()
*/
lp
->
charge
++
;
if
(
lp
->
hupflags
&
ISDN_HAVECHARGE
)
{
lp
->
hupflags
&=
~
ISDN_WAITCHARGE
;
lp
->
chargeint
=
jiffies
-
lp
->
chargetime
-
(
2
*
HZ
);
}
if
(
lp
->
hupflags
&
ISDN_WAITCHARGE
)
lp
->
hupflags
|=
ISDN_HAVECHARGE
;
lp
->
chargetime
=
jiffies
;
printk
(
KERN_DEBUG
"isdn_net: Got CINF chargetime of %s now %lu
\n
"
,
lp
->
name
,
lp
->
chargetime
);
return
1
;
}
}
}
return
0
;
printk
(
"%s: %s %#x
\n
"
,
__FUNCTION__
,
lp
->
name
,
lp
->
dial_event
);
isdn_net_handle_event
(
lp
,
lp
->
dial_event
,
NULL
);
}
}
/*
/* Initiate dialout. Set phone-number-pointer to first number
* Perform dialout for net-interfaces and timeout-handling for
* of interface.
* D-Channel-up and B-Channel-up Messages.
* This function is initially called from within isdn_net_start_xmit() or
* or isdn_net_find_icall() after initializing the dialstate for an
* interface. If further calls are needed, the function schedules itself
* for a timer-callback via isdn_timer_function().
* The dialstate is also affected by incoming status-messages from
* the ISDN-Channel which are handled in isdn_net_stat_callback() above.
*/
*/
void
static
int
i
sdn_net_dial
(
void
)
i
nit_dialout
(
isdn_net_local
*
lp
)
{
{
isdn_net_dev
*
p
=
dev
->
netdev
;
int
anymore
=
0
;
int
i
;
unsigned
long
flags
;
unsigned
long
flags
;
isdn_ctrl
cmd
;
u_char
*
phone_number
;
while
(
p
)
{
isdn_net_local
*
lp
=
p
->
local
;
#ifdef ISDN_DEBUG_NET_DIAL
if
(
lp
->
dialstate
)
printk
(
KERN_DEBUG
"%s: dialstate=%d
\n
"
,
lp
->
name
,
lp
->
dialstate
);
#endif
switch
(
lp
->
dialstate
)
{
case
0
:
/* Nothing to do for this interface */
break
;
case
1
:
/* Initiate dialout. Set phone-number-pointer to first number
* of interface.
*/
save_flags
(
flags
);
cli
();
lp
->
dial
=
lp
->
phone
[
1
];
restore_flags
(
flags
);
if
(
!
lp
->
dial
)
{
printk
(
KERN_WARNING
"%s: phone number deleted?
\n
"
,
lp
->
name
);
isdn_net_hangup
(
&
p
->
dev
);
break
;
}
anymore
=
1
;
if
(
lp
->
dialtimeout
>
0
)
save_flags
(
flags
);
if
(
lp
->
dialstarted
==
0
||
time_after
(
jiffies
,
lp
->
dialstarted
+
lp
->
dialtimeout
+
lp
->
dialwait
))
{
cli
();
lp
->
dialstarted
=
jiffies
;
lp
->
dial
=
lp
->
phone
[
1
];
lp
->
dialwait_timer
=
0
;
restore_flags
(
flags
);
}
lp
->
dialstate
++
;
if
(
!
lp
->
dial
)
{
/* Fall through */
printk
(
KERN_WARNING
"%s: phone number deleted?
\n
"
,
case
2
:
lp
->
name
);
/* Prepare dialing. Clear EAZ, then set EAZ. */
isdn_net_hangup
(
&
lp
->
netdev
->
dev
);
cmd
.
driver
=
lp
->
isdn_device
;
return
0
;
cmd
.
arg
=
lp
->
isdn_channel
;
}
cmd
.
command
=
ISDN_CMD_CLREAZ
;
if
(
lp
->
dialtimeout
>
0
&&
isdn_command
(
&
cmd
);
(
lp
->
dialstarted
==
0
||
sprintf
(
cmd
.
parm
.
num
,
"%s"
,
isdn_map_eaz2msn
(
lp
->
msn
,
cmd
.
driver
));
time_after
(
jiffies
,
lp
->
dialstarted
+
lp
->
dialtimeout
+
lp
->
dialwait
)))
{
cmd
.
command
=
ISDN_CMD_SETEAZ
;
lp
->
dialstarted
=
jiffies
;
isdn_command
(
&
cmd
);
lp
->
dialwait_timer
=
0
;
lp
->
dialretry
=
0
;
}
anymore
=
1
;
lp
->
dialretry
=
0
;
lp
->
dialstate
++
;
return
do_dialout
(
lp
);
/* Fall through */
}
case
3
:
/* Setup interface, dial current phone-number, switch to next number.
* If list of phone-numbers is exhausted, increment
* retry-counter.
*/
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
||
(
ISDN_NET_DIALMODE
(
*
lp
)
==
ISDN_NET_DM_OFF
))
{
char
*
s
;
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
s
=
"dial suppressed: isdn system stopped"
;
else
s
=
"dial suppressed: dialmode `off'"
;
isdn_net_unreachable
(
&
p
->
dev
,
0
,
s
);
isdn_net_hangup
(
&
p
->
dev
);
break
;
}
cmd
.
driver
=
lp
->
isdn_device
;
cmd
.
command
=
ISDN_CMD_SETL2
;
cmd
.
arg
=
lp
->
isdn_channel
+
(
lp
->
l2_proto
<<
8
);
isdn_command
(
&
cmd
);
cmd
.
driver
=
lp
->
isdn_device
;
cmd
.
command
=
ISDN_CMD_SETL3
;
cmd
.
arg
=
lp
->
isdn_channel
+
(
lp
->
l3_proto
<<
8
);
isdn_command
(
&
cmd
);
cmd
.
driver
=
lp
->
isdn_device
;
cmd
.
arg
=
lp
->
isdn_channel
;
save_flags
(
flags
);
cli
();
if
(
!
lp
->
dial
)
{
restore_flags
(
flags
);
printk
(
KERN_WARNING
"%s: phone number deleted?
\n
"
,
lp
->
name
);
isdn_net_hangup
(
&
p
->
dev
);
break
;
}
if
(
!
strncmp
(
lp
->
dial
->
num
,
"LEASED"
,
strlen
(
"LEASED"
)))
{
restore_flags
(
flags
);
lp
->
dialstate
=
4
;
printk
(
KERN_INFO
"%s: Open leased line ...
\n
"
,
lp
->
name
);
}
else
{
if
(
lp
->
dialtimeout
>
0
)
if
(
time_after
(
jiffies
,
lp
->
dialstarted
+
lp
->
dialtimeout
))
{
restore_flags
(
flags
);
lp
->
dialwait_timer
=
jiffies
+
lp
->
dialwait
;
lp
->
dialstarted
=
0
;
isdn_net_unreachable
(
&
p
->
dev
,
0
,
"dial: timed out"
);
isdn_net_hangup
(
&
p
->
dev
);
break
;
}
cmd
.
driver
=
lp
->
isdn_device
;
/* Setup interface, dial current phone-number, switch to next number.
cmd
.
command
=
ISDN_CMD_DIAL
;
* If list of phone-numbers is exhausted, increment
cmd
.
parm
.
setup
.
si2
=
0
;
* retry-counter.
*/
/* check for DOV */
static
int
phone_number
=
lp
->
dial
->
num
;
do_dialout
(
isdn_net_local
*
lp
)
if
((
*
phone_number
==
'v'
)
||
{
(
*
phone_number
==
'V'
))
{
/* DOV call */
unsigned
long
flags
;
cmd
.
parm
.
setup
.
si1
=
1
;
}
else
{
/* DATA call */
cmd
.
parm
.
setup
.
si1
=
7
;
}
strcpy
(
cmd
.
parm
.
setup
.
phone
,
phone_number
);
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
||
(
ISDN_NET_DIALMODE
(
*
lp
)
==
ISDN_NET_DM_OFF
))
{
/*
char
*
s
;
* Switch to next number or back to start if at end of list.
if
(
dev
->
global_flags
&
ISDN_GLOBAL_STOPPED
)
*/
s
=
"dial suppressed: isdn system stopped"
;
if
(
!
(
lp
->
dial
=
(
isdn_net_phone
*
)
lp
->
dial
->
next
))
{
else
lp
->
dial
=
lp
->
phone
[
1
];
s
=
"dial suppressed: dialmode `off'"
;
lp
->
dialretry
++
;
isdn_net_unreachable
(
&
lp
->
netdev
->
dev
,
0
,
s
);
isdn_net_hangup
(
&
lp
->
netdev
->
dev
);
return
0
;
}
if
(
lp
->
dialretry
>
lp
->
dialmax
)
{
save_flags
(
flags
);
restore_flags
(
flags
);
cli
();
if
(
lp
->
dialtimeout
==
0
)
{
if
(
!
lp
->
dial
)
{
lp
->
dialwait_timer
=
jiffies
+
lp
->
dialwait
;
restore_flags
(
flags
);
lp
->
dialstarted
=
0
;
printk
(
KERN_WARNING
"%s: phone number deleted?
\n
"
,
isdn_net_unreachable
(
&
p
->
dev
,
0
,
"dial: tried all numbers dialmax times"
);
lp
->
name
);
}
isdn_net_hangup
(
&
lp
->
netdev
->
dev
);
isdn_net_hangup
(
&
p
->
dev
);
return
0
;
break
;
}
}
if
(
!
strncmp
(
lp
->
dial
->
num
,
"LEASED"
,
strlen
(
"LEASED"
)))
{
}
restore_flags
(
flags
);
restore_flags
(
flags
);
lp
->
dialstate
=
ST_OUT_WAIT_DCONN
;
sprintf
(
cmd
.
parm
.
setup
.
eazmsn
,
"%s"
,
printk
(
KERN_INFO
"%s: Open leased line ...
\n
"
,
lp
->
name
);
isdn_map_eaz2msn
(
lp
->
msn
,
cmd
.
driver
));
return
1
;
i
=
isdn_dc2minor
(
lp
->
isdn_device
,
lp
->
isdn_channel
);
}
else
{
if
(
i
>=
0
)
{
struct
dial_info
dial
=
{
strcpy
(
dev
->
num
[
i
],
cmd
.
parm
.
setup
.
phone
);
.
l2_proto
=
lp
->
l2_proto
,
dev
->
usage
[
i
]
|=
ISDN_USAGE_OUTGOING
;
.
l3_proto
=
lp
->
l3_proto
,
isdn_info_update
();
.
si1
=
7
,
}
.
si2
=
0
,
printk
(
KERN_INFO
"%s: dialing %d %s... %s
\n
"
,
lp
->
name
,
.
msn
=
lp
->
msn
,
lp
->
dialretry
,
cmd
.
parm
.
setup
.
phone
,
.
phone
=
lp
->
dial
->
num
,
(
cmd
.
parm
.
setup
.
si1
==
1
)
?
"DOV"
:
""
);
};
lp
->
dtimer
=
0
;
if
(
lp
->
dialtimeout
>
0
)
{
#ifdef ISDN_DEBUG_NET_DIAL
if
(
time_after
(
jiffies
,
lp
->
dialstarted
+
lp
->
dialtimeout
))
{
printk
(
KERN_DEBUG
"dial: d=%d c=%d
\n
"
,
lp
->
isdn_device
,
restore_flags
(
flags
);
lp
->
isdn_channel
);
lp
->
dialwait_timer
=
jiffies
+
lp
->
dialwait
;
#endif
lp
->
dialstarted
=
0
;
isdn_command
(
&
cmd
);
isdn_net_unreachable
(
&
lp
->
netdev
->
dev
,
0
,
"dial: timed out"
);
}
isdn_net_hangup
(
&
lp
->
netdev
->
dev
);
lp
->
huptimer
=
0
;
return
0
;
lp
->
outgoing
=
1
;
}
if
(
lp
->
chargeint
)
{
}
lp
->
hupflags
|=
ISDN_HAVECHARGE
;
/*
lp
->
hupflags
&=
~
ISDN_WAITCHARGE
;
* Switch to next number or back to start if at end of list.
}
else
{
*/
lp
->
hupflags
|=
ISDN_WAITCHARGE
;
if
(
!
(
lp
->
dial
=
(
isdn_net_phone
*
)
lp
->
dial
->
next
))
{
lp
->
hupflags
&=
~
ISDN_HAVECHARGE
;
lp
->
dial
=
lp
->
phone
[
1
];
lp
->
dialretry
++
;
if
(
lp
->
dialretry
>
lp
->
dialmax
)
{
restore_flags
(
flags
);
if
(
lp
->
dialtimeout
==
0
)
{
lp
->
dialwait_timer
=
jiffies
+
lp
->
dialwait
;
lp
->
dialstarted
=
0
;
isdn_net_unreachable
(
&
lp
->
netdev
->
dev
,
0
,
"dial: tried all numbers dialmax times"
);
}
}
anymore
=
1
;
isdn_net_hangup
(
&
lp
->
netdev
->
dev
);
lp
->
dialstate
=
return
0
;
(
lp
->
cbdelay
&&
}
(
lp
->
flags
&
ISDN_NET_CBOUT
))
?
12
:
4
;
}
break
;
restore_flags
(
flags
);
case
4
:
isdn_slot_dial
(
lp
->
isdn_slot
,
&
dial
);
/* Wait for D-Channel-connect.
}
* If timeout, switch back to state 3.
lp
->
huptimer
=
0
;
* Dialmax-handling moved to state 3.
lp
->
outgoing
=
1
;
*/
if
(
lp
->
chargeint
)
{
if
(
lp
->
dtimer
++
>
ISDN_TIMER_DTIMEOUT10
)
lp
->
hupflags
|=
ISDN_HAVECHARGE
;
lp
->
dialstate
=
3
;
lp
->
hupflags
&=
~
ISDN_WAITCHARGE
;
anymore
=
1
;
}
else
{
break
;
lp
->
hupflags
|=
ISDN_WAITCHARGE
;
case
5
:
lp
->
hupflags
&=
~
ISDN_HAVECHARGE
;
/* Got D-Channel-Connect, send B-Channel-request */
}
cmd
.
driver
=
lp
->
isdn_device
;
if
(
lp
->
cbdelay
&&
(
lp
->
flags
&
ISDN_NET_CBOUT
))
{
cmd
.
arg
=
lp
->
isdn_channel
;
lp
->
dial_timer
.
expires
=
jiffies
+
lp
->
cbdelay
;
cmd
.
command
=
ISDN_CMD_ACCEPTB
;
lp
->
dial_event
=
EV_NET_TIMER_CB
;
anymore
=
1
;
}
else
{
lp
->
dtimer
=
0
;
lp
->
dial_timer
.
expires
=
jiffies
+
10
*
HZ
;
lp
->
dialstate
++
;
lp
->
dial_event
=
EV_NET_TIMER_OUT_DCONN
;
isdn_command
(
&
cmd
);
}
break
;
lp
->
dialstate
=
ST_OUT_WAIT_DCONN
;
case
6
:
add_timer
(
&
lp
->
dial_timer
);
/* Wait for B- or D-Channel-connect. If timeout,
return
1
;
* switch back to state 3.
}
*/
#ifdef ISDN_DEBUG_NET_DIAL
/* For EV_NET_DIAL, returns 1 if timer callback is needed
printk
(
KERN_DEBUG
"dialtimer2: %d
\n
"
,
lp
->
dtimer
);
* For ISDN_STAT_*, returns 1 if event was for us
#endif
*/
if
(
lp
->
dtimer
++
>
ISDN_TIMER_DTIMEOUT10
)
static
int
lp
->
dialstate
=
3
;
isdn_net_handle_event
(
isdn_net_local
*
lp
,
int
pr
,
void
*
arg
)
anymore
=
1
;
{
break
;
#ifdef CONFIG_ISDN_X25
case
7
:
struct
concap_proto
*
cprot
=
lp
->
netdev
->
cprot
;
/* Got incoming Call, setup L2 and L3 protocols,
struct
concap_proto_ops
*
pops
=
cprot
?
cprot
->
pops
:
0
;
* then wait for D-Channel-connect
*/
#ifdef ISDN_DEBUG_NET_DIAL
printk
(
KERN_DEBUG
"dialtimer4: %d
\n
"
,
lp
->
dtimer
);
#endif
#endif
cmd
.
driver
=
lp
->
isdn_device
;
isdn_net_dev
*
p
=
lp
->
netdev
;
cmd
.
command
=
ISDN_CMD_SETL2
;
isdn_ctrl
*
c
=
arg
;
cmd
.
arg
=
lp
->
isdn_channel
+
(
lp
->
l2_proto
<<
8
);
isdn_ctrl
cmd
;
isdn_command
(
&
cmd
);
cmd
.
driver
=
lp
->
isdn_device
;
dbg_net_dial
(
"%s: dialstate=%d pr=%#x
\n
"
,
lp
->
name
,
lp
->
dialstate
,
pr
);
cmd
.
command
=
ISDN_CMD_SETL3
;
cmd
.
arg
=
lp
->
isdn_channel
+
(
lp
->
l3_proto
<<
8
);
switch
(
lp
->
dialstate
)
{
isdn_command
(
&
cmd
);
case
ST_ACTIVE
:
if
(
lp
->
dtimer
++
>
ISDN_TIMER_DTIMEOUT15
)
switch
(
pr
)
{
isdn_net_hangup
(
&
p
->
dev
);
case
ISDN_STAT_BSENT
:
else
{
/* A packet has successfully been sent out */
anymore
=
1
;
if
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
{
lp
->
dialstate
++
;
isdn_net_dec_frame_cnt
(
lp
);
}
lp
->
stats
.
tx_packets
++
;
break
;
lp
->
stats
.
tx_bytes
+=
c
->
parm
.
length
;
case
9
:
return
1
;
/* Got incoming D-Channel-Connect, send B-Channel-request */
}
cmd
.
driver
=
lp
->
isdn_device
;
break
;
cmd
.
arg
=
lp
->
isdn_channel
;
case
ISDN_STAT_DHUP
:
cmd
.
command
=
ISDN_CMD_ACCEPTB
;
/* Either D-Channel-hangup or error during dialout */
isdn_command
(
&
cmd
);
#ifdef CONFIG_ISDN_X25 // FIXME handle != ST_0?
anymore
=
1
;
/* If we are not connencted then dialing had
lp
->
dtimer
=
0
;
failed. If there are generic encap protocol
lp
->
dialstate
++
;
receiver routines signal the closure of
break
;
the link*/
case
8
:
case
10
:
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
/* Wait for B- or D-channel-connect */
&&
pops
&&
pops
->
disconn_ind
)
#ifdef ISDN_DEBUG_NET_DIAL
pops
->
disconn_ind
(
cprot
);
printk
(
KERN_DEBUG
"dialtimer4: %d
\n
"
,
lp
->
dtimer
);
#endif
/* CONFIG_ISDN_X25 */
if
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
{
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_CISCOHDLCK
)
isdn_net_ciscohdlck_disconnected
(
lp
);
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
isdn_ppp_free
(
lp
);
#endif
#endif
if
(
lp
->
dtimer
++
>
ISDN_TIMER_DTIMEOUT10
)
isdn_net_lp_disconnected
(
lp
);
isdn_net_hangup
(
&
p
->
dev
);
isdn_slot_all_eaz
(
lp
->
isdn_slot
);
else
printk
(
KERN_INFO
"%s: remote hangup
\n
"
,
lp
->
name
);
anymore
=
1
;
printk
(
KERN_INFO
"%s: Chargesum is %d
\n
"
,
lp
->
name
,
break
;
lp
->
charge
);
case
11
:
isdn_net_unbind_channel
(
lp
);
/* Callback Delay */
return
1
;
if
(
lp
->
dtimer
++
>
lp
->
cbdelay
)
}
lp
->
dialstate
=
1
;
break
;
anymore
=
1
;
#ifdef CONFIG_ISDN_X25 // FIXME handle != ST_0?
break
;
case
ISDN_STAT_BHUP
:
case
12
:
/* B-Channel-hangup */
/* Remote does callback. Hangup after cbdelay, then wait for incoming
/* try if there are generic encap protocol
* call (in state 4).
receiver routines and signal the closure of
*/
the link */
if
(
lp
->
dtimer
++
>
lp
->
cbdelay
)
if
(
pops
&&
pops
->
disconn_ind
){
{
pops
->
disconn_ind
(
cprot
);
printk
(
KERN_INFO
"%s: hangup waiting for callback ...
\n
"
,
lp
->
name
);
return
1
;
lp
->
dtimer
=
0
;
}
lp
->
dialstate
=
4
;
break
;
cmd
.
driver
=
lp
->
isdn_device
;
#endif
/* CONFIG_ISDN_X25 */
cmd
.
command
=
ISDN_CMD_HANGUP
;
case
ISDN_STAT_CINF
:
cmd
.
arg
=
lp
->
isdn_channel
;
/* Charge-info from TelCo. Calculate interval between
isdn_command
(
&
cmd
);
* charge-infos and set timestamp for last info for
isdn_all_eaz
(
lp
->
isdn_device
,
lp
->
isdn_channel
);
* usage by isdn_net_autohup()
}
*/
anymore
=
1
;
lp
->
charge
++
;
break
;
if
(
lp
->
hupflags
&
ISDN_HAVECHARGE
)
{
default:
lp
->
hupflags
&=
~
ISDN_WAITCHARGE
;
printk
(
KERN_WARNING
"isdn_net: Illegal dialstate %d for device %s
\n
"
,
lp
->
chargeint
=
jiffies
-
lp
->
chargetime
-
(
2
*
HZ
);
lp
->
dialstate
,
lp
->
name
);
}
if
(
lp
->
hupflags
&
ISDN_WAITCHARGE
)
lp
->
hupflags
|=
ISDN_HAVECHARGE
;
lp
->
chargetime
=
jiffies
;
printk
(
KERN_DEBUG
"isdn_net: Got CINF chargetime of %s now %lu
\n
"
,
lp
->
name
,
lp
->
chargetime
);
return
1
;
}
break
;
case
ST_OUT_WAIT_DCONN
:
switch
(
pr
)
{
case
EV_NET_TIMER_OUT_DCONN
:
/* try again */
do_dialout
(
lp
);
return
1
;
case
EV_NET_TIMER_CB
:
/* Remote does callback. Hangup after cbdelay,
* then wait for incoming call */
printk
(
KERN_INFO
"%s: hangup waiting for callback ...
\n
"
,
lp
->
name
);
isdn_net_hangup
(
&
lp
->
netdev
->
dev
);
return
1
;
case
ISDN_STAT_DCONN
:
/* Got D-Channel-Connect, send B-Channel-request */
del_timer
(
&
lp
->
dial_timer
);
lp
->
dialstate
=
ST_OUT_WAIT_BCONN
;
isdn_slot_command
(
lp
->
isdn_slot
,
ISDN_CMD_ACCEPTB
,
&
cmd
);
lp
->
dial_timer
.
expires
=
jiffies
+
10
*
HZ
;
lp
->
dial_event
=
EV_NET_TIMER_OUT_BCONN
;
add_timer
(
&
lp
->
dial_timer
);
return
1
;
case
ISDN_STAT_DHUP
:
del_timer
(
&
lp
->
dial_timer
);
isdn_slot_all_eaz
(
lp
->
isdn_slot
);
printk
(
KERN_INFO
"%s: remote hangup
\n
"
,
lp
->
name
);
isdn_net_unbind_channel
(
lp
);
return
1
;
}
break
;
case
ST_OUT_WAIT_BCONN
:
switch
(
pr
)
{
case
EV_NET_TIMER_OUT_BCONN
:
/* try again */
do_dialout
(
lp
);
return
1
;
case
ISDN_STAT_BCONN
:
del_timer
(
&
lp
->
dial_timer
);
isdn_slot_set_usage
(
lp
->
isdn_slot
,
isdn_slot_usage
(
lp
->
isdn_slot
)
|
ISDN_USAGE_OUTGOING
);
isdn_net_connected
(
lp
);
return
1
;
case
ISDN_STAT_DHUP
:
del_timer
(
&
lp
->
dial_timer
);
isdn_slot_all_eaz
(
lp
->
isdn_slot
);
printk
(
KERN_INFO
"%s: remote hangup
\n
"
,
lp
->
name
);
isdn_net_unbind_channel
(
lp
);
return
1
;
}
break
;
case
ST_IN_WAIT_DCONN
:
switch
(
pr
)
{
case
EV_NET_TIMER_IN_DCONN
:
isdn_net_hangup
(
&
p
->
dev
);
return
1
;
case
ISDN_STAT_DCONN
:
del_timer
(
&
lp
->
dial_timer
);
lp
->
dialstate
=
ST_IN_WAIT_BCONN
;
isdn_slot_command
(
lp
->
isdn_slot
,
ISDN_CMD_ACCEPTB
,
&
cmd
);
lp
->
dial_timer
.
expires
=
jiffies
+
10
*
HZ
;
lp
->
dial_event
=
EV_NET_TIMER_IN_BCONN
;
add_timer
(
&
lp
->
dial_timer
);
return
1
;
case
ISDN_STAT_DHUP
:
del_timer
(
&
lp
->
dial_timer
);
isdn_slot_all_eaz
(
lp
->
isdn_slot
);
printk
(
KERN_INFO
"%s: remote hangup
\n
"
,
lp
->
name
);
isdn_net_unbind_channel
(
lp
);
return
1
;
}
break
;
case
ST_IN_WAIT_BCONN
:
switch
(
pr
)
{
case
EV_NET_TIMER_IN_BCONN
:
isdn_net_hangup
(
&
p
->
dev
);
break
;
case
ISDN_STAT_BCONN
:
del_timer
(
&
lp
->
dial_timer
);
isdn_slot_set_rx_netdev
(
lp
->
isdn_slot
,
p
);
isdn_net_connected
(
lp
);
return
1
;
case
ISDN_STAT_DHUP
:
del_timer
(
&
lp
->
dial_timer
);
isdn_slot_all_eaz
(
lp
->
isdn_slot
);
printk
(
KERN_INFO
"%s: remote hangup
\n
"
,
lp
->
name
);
isdn_net_unbind_channel
(
lp
);
return
1
;
}
}
p
=
(
isdn_net_dev
*
)
p
->
next
;
break
;
case
ST_WAIT_BEFORE_CB
:
switch
(
pr
)
{
case
EV_NET_TIMER_CB
:
/* Callback Delay */
init_dialout
(
lp
);
return
1
;
}
break
;
default:
isdn_BUG
();
break
;
}
}
isdn_timer_ctrl
(
ISDN_TIMER_NETDIAL
,
anymore
);
printk
(
"NOT HANDLED?
\n
"
);
return
0
;
}
}
/*
/*
...
@@ -883,12 +853,9 @@ isdn_net_hangup(struct net_device *d)
...
@@ -883,12 +853,9 @@ isdn_net_hangup(struct net_device *d)
pops
->
disconn_ind
(
cprot
);
pops
->
disconn_ind
(
cprot
);
#endif
/* CONFIG_ISDN_X25 */
#endif
/* CONFIG_ISDN_X25 */
cmd
.
driver
=
lp
->
isdn_device
;
isdn_slot_command
(
lp
->
isdn_slot
,
ISDN_CMD_HANGUP
,
&
cmd
);
cmd
.
command
=
ISDN_CMD_HANGUP
;
cmd
.
arg
=
lp
->
isdn_channel
;
isdn_command
(
&
cmd
);
printk
(
KERN_INFO
"%s: Chargesum is %d
\n
"
,
lp
->
name
,
lp
->
charge
);
printk
(
KERN_INFO
"%s: Chargesum is %d
\n
"
,
lp
->
name
,
lp
->
charge
);
isdn_
all_eaz
(
lp
->
isdn_device
,
lp
->
isdn_channel
);
isdn_
slot_all_eaz
(
lp
->
isdn_slot
);
}
}
isdn_net_unbind_channel
(
lp
);
isdn_net_unbind_channel
(
lp
);
}
}
...
@@ -1041,15 +1008,15 @@ void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb)
...
@@ -1041,15 +1008,15 @@ void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb)
/* before obtaining the lock the caller should have checked that
/* before obtaining the lock the caller should have checked that
the lp isn't busy */
the lp isn't busy */
if
(
isdn_net_lp_busy
(
lp
))
{
if
(
isdn_net_lp_busy
(
lp
))
{
printk
(
"isdn BUG at %s:%d!
\n
"
,
__FILE__
,
__LINE__
);
isdn_BUG
(
);
goto
error
;
goto
error
;
}
}
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
{
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
{
printk
(
"isdn BUG at %s:%d!
\n
"
,
__FILE__
,
__LINE__
);
isdn_BUG
(
);
goto
error
;
goto
error
;
}
}
ret
=
isdn_
writebuf_skb_stub
(
lp
->
isdn_device
,
lp
->
isdn_channel
,
1
,
skb
);
ret
=
isdn_
slot_write
(
lp
->
isdn_slot
,
skb
);
if
(
ret
!=
len
)
{
if
(
ret
!=
len
)
{
/* we should never get here */
/* we should never get here */
printk
(
KERN_WARNING
"%s: HL driver queue full
\n
"
,
lp
->
name
);
printk
(
KERN_WARNING
"%s: HL driver queue full
\n
"
,
lp
->
name
);
...
@@ -1137,7 +1104,7 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
...
@@ -1137,7 +1104,7 @@ isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
lp
->
sqfull
=
0
;
lp
->
sqfull
=
0
;
}
}
/* this is a hack to allow auto-hangup for slaves on moderate loads */
/* this is a hack to allow auto-hangup for slaves on moderate loads */
nd
->
queue
=
nd
->
local
;
nd
->
queue
=
&
nd
->
local
;
}
}
return
retv
;
return
retv
;
...
@@ -1165,7 +1132,7 @@ void isdn_net_tx_timeout(struct net_device * ndev)
...
@@ -1165,7 +1132,7 @@ void isdn_net_tx_timeout(struct net_device * ndev)
isdn_net_local
*
lp
=
(
isdn_net_local
*
)
ndev
->
priv
;
isdn_net_local
*
lp
=
(
isdn_net_local
*
)
ndev
->
priv
;
printk
(
KERN_WARNING
"isdn_tx_timeout dev %s dialstate %d
\n
"
,
ndev
->
name
,
lp
->
dialstate
);
printk
(
KERN_WARNING
"isdn_tx_timeout dev %s dialstate %d
\n
"
,
ndev
->
name
,
lp
->
dialstate
);
if
(
!
lp
->
dialstate
){
if
(
lp
->
dialstate
==
ST_ACTIVE
){
lp
->
stats
.
tx_errors
++
;
lp
->
stats
.
tx_errors
++
;
/*
/*
* There is a certain probability that this currently
* There is a certain probability that this currently
...
@@ -1220,14 +1187,8 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
...
@@ -1220,14 +1187,8 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
#endif
#endif
/* auto-dialing xmit function */
/* auto-dialing xmit function */
{
{
#ifdef ISDN_DEBUG_NET_DUMP
u_char
*
buf
;
#endif
isdn_net_adjust_hdr
(
skb
,
ndev
);
isdn_net_adjust_hdr
(
skb
,
ndev
);
#ifdef ISDN_DEBUG_NET_DUMP
isdn_dumppkt
(
"S:"
,
skb
->
data
,
skb
->
len
,
40
);
buf
=
skb
->
data
;
isdn_dumppkt
(
"S:"
,
buf
,
skb
->
len
,
40
);
#endif
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
{
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
{
int
chi
;
int
chi
;
...
@@ -1257,7 +1218,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
...
@@ -1257,7 +1218,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
}
}
/* Grab a free ISDN-Channel */
/* Grab a free ISDN-Channel */
if
(((
chi
=
if
(((
chi
=
isdn_get_free_
channel
(
isdn_get_free_
slot
(
ISDN_USAGE_NET
,
ISDN_USAGE_NET
,
lp
->
l2_proto
,
lp
->
l2_proto
,
lp
->
l3_proto
,
lp
->
l3_proto
,
...
@@ -1266,7 +1227,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
...
@@ -1266,7 +1227,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
lp
->
msn
)
lp
->
msn
)
)
<
0
)
&&
)
<
0
)
&&
((
chi
=
((
chi
=
isdn_get_free_
channel
(
isdn_get_free_
slot
(
ISDN_USAGE_NET
,
ISDN_USAGE_NET
,
lp
->
l2_proto
,
lp
->
l2_proto
,
lp
->
l3_proto
,
lp
->
l3_proto
,
...
@@ -1283,7 +1244,6 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
...
@@ -1283,7 +1244,6 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
/* Log packet, which triggered dialing */
/* Log packet, which triggered dialing */
if
(
dev
->
net_verbose
)
if
(
dev
->
net_verbose
)
isdn_net_log_skb
(
skb
,
lp
);
isdn_net_log_skb
(
skb
,
lp
);
lp
->
dialstate
=
1
;
/* Connect interface with channel */
/* Connect interface with channel */
isdn_net_bind_channel
(
lp
,
chi
);
isdn_net_bind_channel
(
lp
,
chi
);
#ifdef CONFIG_ISDN_PPP
#ifdef CONFIG_ISDN_PPP
...
@@ -1296,14 +1256,14 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
...
@@ -1296,14 +1256,14 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
return
0
;
/* STN (skb to nirvana) ;) */
return
0
;
/* STN (skb to nirvana) ;) */
}
}
restore_flags
(
flags
);
restore_flags
(
flags
);
i
sdn_net_dial
();
/* Initiate dialing */
i
nit_dialout
(
lp
);
netif_stop_queue
(
ndev
);
netif_stop_queue
(
ndev
);
return
1
;
/* let upper layer requeue skb packet */
return
1
;
/* let upper layer requeue skb packet */
}
}
#endif
#endif
/* Initiate dialing */
/* Initiate dialing */
restore_flags
(
flags
);
restore_flags
(
flags
);
i
sdn_net_dial
(
);
i
nit_dialout
(
lp
);
isdn_net_device_stop_queue
(
lp
);
isdn_net_device_stop_queue
(
lp
);
return
1
;
return
1
;
}
else
{
}
else
{
...
@@ -1315,7 +1275,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
...
@@ -1315,7 +1275,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
}
else
{
}
else
{
/* Device is connected to an ISDN channel */
/* Device is connected to an ISDN channel */
ndev
->
trans_start
=
jiffies
;
ndev
->
trans_start
=
jiffies
;
if
(
!
lp
->
dialstate
)
{
if
(
lp
->
dialstate
==
ST_ACTIVE
)
{
/* ISDN connection is established, try sending */
/* ISDN connection is established, try sending */
int
ret
;
int
ret
;
ret
=
(
isdn_net_xmit
(
ndev
,
skb
));
ret
=
(
isdn_net_xmit
(
ndev
,
skb
));
...
@@ -1433,7 +1393,7 @@ isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
...
@@ -1433,7 +1393,7 @@ isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
static
struct
sk_buff
*
static
struct
sk_buff
*
isdn_net_ciscohdlck_alloc_skb
(
isdn_net_local
*
lp
,
int
len
)
isdn_net_ciscohdlck_alloc_skb
(
isdn_net_local
*
lp
,
int
len
)
{
{
unsigned
short
hl
=
dev
->
drv
[
lp
->
isdn_device
]
->
interface
->
hl_hdrlen
;
unsigned
short
hl
=
isdn_slot_hdrlen
(
lp
->
isdn_slot
)
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
skb
=
alloc_skb
(
hl
+
len
,
GFP_ATOMIC
);
skb
=
alloc_skb
(
hl
+
len
,
GFP_ATOMIC
);
...
@@ -1523,8 +1483,8 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
...
@@ -1523,8 +1483,8 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
unsigned
long
last_cisco_myseq
=
lp
->
cisco_myseq
;
unsigned
long
last_cisco_myseq
=
lp
->
cisco_myseq
;
int
myseq_diff
=
0
;
int
myseq_diff
=
0
;
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
||
lp
->
dialstate
)
{
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
)
||
lp
->
dialstate
!=
ST_ACTIVE
)
{
printk
(
"isdn BUG at %s:%d!
\n
"
,
__FILE__
,
__LINE__
);
isdn_BUG
(
);
return
;
return
;
}
}
lp
->
cisco_myseq
++
;
lp
->
cisco_myseq
++
;
...
@@ -1814,9 +1774,7 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
...
@@ -1814,9 +1774,7 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
skb
->
dev
=
ndev
;
skb
->
dev
=
ndev
;
skb
->
pkt_type
=
PACKET_HOST
;
skb
->
pkt_type
=
PACKET_HOST
;
skb
->
mac
.
raw
=
skb
->
data
;
skb
->
mac
.
raw
=
skb
->
data
;
#ifdef ISDN_DEBUG_NET_DUMP
isdn_dumppkt
(
"R:"
,
skb
->
data
,
skb
->
len
,
40
);
isdn_dumppkt
(
"R:"
,
skb
->
data
,
skb
->
len
,
40
);
#endif
switch
(
lp
->
p_encap
)
{
switch
(
lp
->
p_encap
)
{
case
ISDN_NET_ENCAP_ETHER
:
case
ISDN_NET_ENCAP_ETHER
:
/* Ethernet over ISDN */
/* Ethernet over ISDN */
...
@@ -1893,12 +1851,12 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
...
@@ -1893,12 +1851,12 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
int
int
isdn_net_rcv_skb
(
int
idx
,
struct
sk_buff
*
skb
)
isdn_net_rcv_skb
(
int
idx
,
struct
sk_buff
*
skb
)
{
{
isdn_net_dev
*
p
=
dev
->
rx_netdev
[
idx
]
;
isdn_net_dev
*
p
=
isdn_slot_rx_netdev
(
idx
)
;
if
(
p
)
{
if
(
p
)
{
isdn_net_local
*
lp
=
p
->
local
;
isdn_net_local
*
lp
=
&
p
->
local
;
if
((
lp
->
flags
&
ISDN_NET_CONNECTED
)
&&
if
((
lp
->
flags
&
ISDN_NET_CONNECTED
)
&&
(
!
lp
->
dialstate
))
{
(
lp
->
dialstate
==
ST_ACTIVE
))
{
isdn_net_receive
(
&
p
->
dev
,
skb
);
isdn_net_receive
(
&
p
->
dev
,
skb
);
return
1
;
return
1
;
}
}
...
@@ -2093,40 +2051,34 @@ isdn_net_init(struct net_device *ndev)
...
@@ -2093,40 +2051,34 @@ isdn_net_init(struct net_device *ndev)
static
void
static
void
isdn_net_swapbind
(
int
drvidx
)
isdn_net_swapbind
(
int
drvidx
)
{
{
isdn_net_dev
*
p
;
struct
list_head
*
l
;
#ifdef ISDN_DEBUG_NET_ICALL
dbg_net_icall
(
"n_fi: swapping ch of %d
\n
"
,
drvidx
);
printk
(
KERN_DEBUG
"n_fi: swapping ch of %d
\n
"
,
drvidx
);
list_for_each
(
l
,
&
isdn_net_devs
)
{
#endif
isdn_net_dev
*
p
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
p
=
dev
->
netdev
;
if
(
p
->
local
.
pre_device
!=
drvidx
)
while
(
p
)
{
continue
;
if
(
p
->
local
->
pre_device
==
drvidx
)
switch
(
p
->
local
->
pre_channel
)
{
switch
(
p
->
local
.
pre_channel
)
{
case
0
:
case
0
:
p
->
local
->
pre_channel
=
1
;
p
->
local
.
pre_channel
=
1
;
break
;
break
;
case
1
:
case
1
:
p
->
local
->
pre_channel
=
0
;
p
->
local
.
pre_channel
=
0
;
break
;
break
;
}
}
p
=
(
isdn_net_dev
*
)
p
->
next
;
}
}
}
}
static
void
static
void
isdn_net_swap_usage
(
int
i1
,
int
i2
)
isdn_net_swap_usage
(
int
i1
,
int
i2
)
{
{
int
u1
=
dev
->
usage
[
i1
]
&
ISDN_USAGE_EXCLUSIVE
;
int
u1
=
isdn_slot_usage
(
i1
)
;
int
u2
=
dev
->
usage
[
i2
]
&
ISDN_USAGE_EXCLUSIVE
;
int
u2
=
isdn_slot_usage
(
i2
)
;
#ifdef ISDN_DEBUG_NET_ICALL
dbg_net_icall
(
"n_fi: usage of %d and %d
\n
"
,
i1
,
i2
);
printk
(
KERN_DEBUG
"n_fi: usage of %d and %d
\n
"
,
i1
,
i2
);
isdn_slot_set_usage
(
i1
,
(
u1
&
~
ISDN_USAGE_EXCLUSIVE
)
|
(
u2
&
ISDN_USAGE_EXCLUSIVE
));
#endif
isdn_slot_set_usage
(
i2
,
(
u2
&
~
ISDN_USAGE_EXCLUSIVE
)
|
(
u1
&
ISDN_USAGE_EXCLUSIVE
));
dev
->
usage
[
i1
]
&=
~
ISDN_USAGE_EXCLUSIVE
;
dev
->
usage
[
i1
]
|=
u2
;
dev
->
usage
[
i2
]
&=
~
ISDN_USAGE_EXCLUSIVE
;
dev
->
usage
[
i2
]
|=
u1
;
isdn_info_update
();
}
}
/*
/*
...
@@ -2155,12 +2107,14 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
...
@@ -2155,12 +2107,14 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
int
wret
;
int
wret
;
int
swapped
;
int
swapped
;
int
sidx
=
0
;
int
sidx
=
0
;
isdn_net_dev
*
p
;
struct
list_head
*
l
;
isdn_net_phone
*
n
;
isdn_net_phone
*
n
;
ulong
flags
;
ulong
flags
;
char
nr
[
32
];
char
nr
[
32
];
char
*
my_eaz
;
char
*
my_eaz
;
isdn_ctrl
cmd
;
int
slot
=
isdn_dc2minor
(
di
,
ch
);
/* Search name in netdev-chain */
/* Search name in netdev-chain */
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
...
@@ -2188,16 +2142,15 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
...
@@ -2188,16 +2142,15 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
return
0
;
return
0
;
}
}
n
=
(
isdn_net_phone
*
)
0
;
n
=
(
isdn_net_phone
*
)
0
;
p
=
dev
->
netdev
;
ematch
=
wret
=
swapped
=
0
;
ematch
=
wret
=
swapped
=
0
;
#ifdef ISDN_DEBUG_NET_ICALL
dbg_net_icall
(
"n_fi: di=%d ch=%d idx=%d usg=%d
\n
"
,
di
,
ch
,
idx
,
printk
(
KERN_DEBUG
"n_fi: di=%d ch=%d idx=%d usg=%d
\n
"
,
di
,
ch
,
idx
,
isdn_slot_usage
(
idx
));
dev
->
usage
[
idx
]);
#endif
list_for_each
(
l
,
&
isdn_net_devs
)
{
while
(
p
)
{
int
matchret
;
int
matchret
;
isdn_net_local
*
lp
=
p
->
local
;
isdn_net_dev
*
p
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
isdn_net_local
*
lp
=
&
p
->
local
;
/* If last check has triggered as binding-swap, revert it */
/* If last check has triggered as binding-swap, revert it */
switch
(
swapped
)
{
switch
(
swapped
)
{
...
@@ -2210,7 +2163,7 @@ p = dev->netdev;
...
@@ -2210,7 +2163,7 @@ p = dev->netdev;
}
}
swapped
=
0
;
swapped
=
0
;
/* check acceptable call types for DOV */
/* check acceptable call types for DOV */
my_eaz
=
isdn_
map_eaz2msn
(
lp
->
msn
,
di
);
my_eaz
=
isdn_
slot_map_eaz2msn
(
slot
,
lp
->
msn
);
if
(
si1
==
1
)
{
/* it's a DOV call, check if we allow it */
if
(
si1
==
1
)
{
/* it's a DOV call, check if we allow it */
if
(
*
my_eaz
==
'v'
||
*
my_eaz
==
'V'
||
if
(
*
my_eaz
==
'v'
||
*
my_eaz
==
'V'
||
*
my_eaz
==
'b'
||
*
my_eaz
==
'B'
)
*
my_eaz
==
'b'
||
*
my_eaz
==
'B'
)
...
@@ -2231,22 +2184,18 @@ p = dev->netdev;
...
@@ -2231,22 +2184,18 @@ p = dev->netdev;
/* Remember if more numbers eventually can match */
/* Remember if more numbers eventually can match */
if
(
matchret
>
wret
)
if
(
matchret
>
wret
)
wret
=
matchret
;
wret
=
matchret
;
#ifdef ISDN_DEBUG_NET_ICALL
dbg_net_icall
(
"n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d
\n
"
,
printk
(
KERN_DEBUG
"n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d
\n
"
,
lp
->
name
,
lp
->
msn
,
lp
->
flags
,
lp
->
dialstate
);
lp
->
name
,
lp
->
msn
,
lp
->
flags
,
lp
->
dialstate
);
#endif
if
((
!
matchret
)
&&
/* EAZ is matching */
if
((
!
matchret
)
&&
/* EAZ is matching */
(((
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
&&
/* but not connected */
(((
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
&&
/* but not connected */
(
USG_NONE
(
dev
->
usage
[
idx
]
)))
||
/* and ch. unused or */
(
USG_NONE
(
isdn_slot_usage
(
idx
)
)))
||
/* and ch. unused or */
((((
lp
->
dialstate
==
4
)
||
(
lp
->
dialstate
==
12
))
&&
/* if dialing */
((((
lp
->
dialstate
==
ST_OUT_WAIT_DCONN
)
||
(
lp
->
dialstate
==
ST_OUT_WAIT_DCONN
))
&&
/* if dialing */
(
!
(
lp
->
flags
&
ISDN_NET_CALLBACK
)))
/* but no callback */
(
!
(
lp
->
flags
&
ISDN_NET_CALLBACK
)))
/* but no callback */
)))
)))
{
{
#ifdef ISDN_DEBUG_NET_ICALL
dbg_net_icall
(
"n_fi: match1, pdev=%d pch=%d
\n
"
,
printk
(
KERN_DEBUG
"n_fi: match1, pdev=%d pch=%d
\n
"
,
lp
->
pre_device
,
lp
->
pre_channel
);
lp
->
pre_device
,
lp
->
pre_channel
);
#endif
if
(
isdn_slot_usage
(
idx
)
&
ISDN_USAGE_EXCLUSIVE
)
{
if
(
dev
->
usage
[
idx
]
&
ISDN_USAGE_EXCLUSIVE
)
{
if
((
lp
->
pre_channel
!=
ch
)
||
if
((
lp
->
pre_channel
!=
ch
)
||
(
lp
->
pre_device
!=
di
))
{
(
lp
->
pre_device
!=
di
))
{
/* Here we got a problem:
/* Here we got a problem:
...
@@ -2260,16 +2209,12 @@ p = dev->netdev;
...
@@ -2260,16 +2209,12 @@ p = dev->netdev;
*/
*/
if
(
ch
==
0
)
{
if
(
ch
==
0
)
{
sidx
=
isdn_dc2minor
(
di
,
1
);
sidx
=
isdn_dc2minor
(
di
,
1
);
#ifdef ISDN_DEBUG_NET_ICALL
dbg_net_icall
(
"n_fi: ch is 0
\n
"
);
printk
(
KERN_DEBUG
"n_fi: ch is 0
\n
"
);
if
(
USG_NONE
(
isdn_slot_usage
(
sidx
)))
{
#endif
if
(
USG_NONE
(
dev
->
usage
[
sidx
]))
{
/* Second Channel is free, now see if it is bound
/* Second Channel is free, now see if it is bound
* exclusive too. */
* exclusive too. */
if
(
dev
->
usage
[
sidx
]
&
ISDN_USAGE_EXCLUSIVE
)
{
if
(
isdn_slot_usage
(
sidx
)
&
ISDN_USAGE_EXCLUSIVE
)
{
#ifdef ISDN_DEBUG_NET_ICALL
dbg_net_icall
(
"n_fi: 2nd channel is down and bound
\n
"
);
printk
(
KERN_DEBUG
"n_fi: 2nd channel is down and bound
\n
"
);
#endif
/* Yes, swap bindings only, if the original
/* Yes, swap bindings only, if the original
* binding is bound to channel 1 of this driver */
* binding is bound to channel 1 of this driver */
if
((
lp
->
pre_device
==
di
)
&&
if
((
lp
->
pre_device
==
di
)
&&
...
@@ -2278,43 +2223,31 @@ p = dev->netdev;
...
@@ -2278,43 +2223,31 @@ p = dev->netdev;
swapped
=
1
;
swapped
=
1
;
}
else
{
}
else
{
/* ... else iterate next device */
/* ... else iterate next device */
p
=
(
isdn_net_dev
*
)
p
->
next
;
continue
;
continue
;
}
}
}
else
{
}
else
{
#ifdef ISDN_DEBUG_NET_ICALL
dbg_net_icall
(
"n_fi: 2nd channel is down and unbound
\n
"
);
printk
(
KERN_DEBUG
"n_fi: 2nd channel is down and unbound
\n
"
);
#endif
/* No, swap always and swap excl-usage also */
/* No, swap always and swap excl-usage also */
isdn_net_swap_usage
(
idx
,
sidx
);
isdn_net_swap_usage
(
idx
,
sidx
);
isdn_net_swapbind
(
di
);
isdn_net_swapbind
(
di
);
swapped
=
2
;
swapped
=
2
;
}
}
/* Now check for exclusive binding again */
/* Now check for exclusive binding again */
#ifdef ISDN_DEBUG_NET_ICALL
dbg_net_icall
(
"n_fi: final check
\n
"
);
printk
(
KERN_DEBUG
"n_fi: final check
\n
"
);
if
((
isdn_slot_usage
(
idx
)
&
ISDN_USAGE_EXCLUSIVE
)
&&
#endif
if
((
dev
->
usage
[
idx
]
&
ISDN_USAGE_EXCLUSIVE
)
&&
((
lp
->
pre_channel
!=
ch
)
||
((
lp
->
pre_channel
!=
ch
)
||
(
lp
->
pre_device
!=
di
)))
{
(
lp
->
pre_device
!=
di
)))
{
#ifdef ISDN_DEBUG_NET_ICALL
dbg_net_icall
(
"n_fi: final check failed
\n
"
);
printk
(
KERN_DEBUG
"n_fi: final check failed
\n
"
);
#endif
p
=
(
isdn_net_dev
*
)
p
->
next
;
continue
;
continue
;
}
}
}
}
}
else
{
}
else
{
/* We are already on the second channel, so nothing to do */
/* We are already on the second channel, so nothing to do */
#ifdef ISDN_DEBUG_NET_ICALL
dbg_net_icall
(
"n_fi: already on 2nd channel
\n
"
);
printk
(
KERN_DEBUG
"n_fi: already on 2nd channel
\n
"
);
#endif
}
}
}
}
}
}
#ifdef ISDN_DEBUG_NET_ICALL
dbg_net_icall
(
"n_fi: match2
\n
"
);
printk
(
KERN_DEBUG
"n_fi: match2
\n
"
);
#endif
n
=
lp
->
phone
[
0
];
n
=
lp
->
phone
[
0
];
if
(
lp
->
flags
&
ISDN_NET_SECURE
)
{
if
(
lp
->
flags
&
ISDN_NET_SECURE
)
{
while
(
n
)
{
while
(
n
)
{
...
@@ -2324,9 +2257,7 @@ p = dev->netdev;
...
@@ -2324,9 +2257,7 @@ p = dev->netdev;
}
}
}
}
if
(
n
||
(
!
(
lp
->
flags
&
ISDN_NET_SECURE
)))
{
if
(
n
||
(
!
(
lp
->
flags
&
ISDN_NET_SECURE
)))
{
#ifdef ISDN_DEBUG_NET_ICALL
dbg_net_icall
(
"n_fi: match3
\n
"
);
printk
(
KERN_DEBUG
"n_fi: match3
\n
"
);
#endif
/* matching interface found */
/* matching interface found */
/*
/*
...
@@ -2370,7 +2301,6 @@ p = dev->netdev;
...
@@ -2370,7 +2301,6 @@ p = dev->netdev;
/* Found parent, if it's offline iterate next device */
/* Found parent, if it's offline iterate next device */
printk
(
KERN_DEBUG
"mlpf: %d
\n
"
,
mlp
->
flags
&
ISDN_NET_CONNECTED
);
printk
(
KERN_DEBUG
"mlpf: %d
\n
"
,
mlp
->
flags
&
ISDN_NET_CONNECTED
);
if
(
!
(
mlp
->
flags
&
ISDN_NET_CONNECTED
))
{
if
(
!
(
mlp
->
flags
&
ISDN_NET_CONNECTED
))
{
p
=
(
isdn_net_dev
*
)
p
->
next
;
continue
;
continue
;
}
}
}
}
...
@@ -2392,7 +2322,7 @@ p = dev->netdev;
...
@@ -2392,7 +2322,7 @@ p = dev->netdev;
if
(
lp
->
phone
[
1
])
{
if
(
lp
->
phone
[
1
])
{
/* Grab a free ISDN-Channel */
/* Grab a free ISDN-Channel */
if
((
chi
=
if
((
chi
=
isdn_get_free_
channel
(
isdn_get_free_
slot
(
ISDN_USAGE_NET
,
ISDN_USAGE_NET
,
lp
->
l2_proto
,
lp
->
l2_proto
,
lp
->
l3_proto
,
lp
->
l3_proto
,
...
@@ -2406,8 +2336,11 @@ p = dev->netdev;
...
@@ -2406,8 +2336,11 @@ p = dev->netdev;
return
0
;
return
0
;
}
}
/* Setup dialstate. */
/* Setup dialstate. */
lp
->
dtimer
=
0
;
lp
->
dial_timer
.
expires
=
jiffies
+
lp
->
cbdelay
;
lp
->
dialstate
=
11
;
lp
->
dial_event
=
EV_NET_TIMER_CB
;
add_timer
(
&
lp
->
dial_timer
);
lp
->
dialstate
=
ST_WAIT_BEFORE_CB
;
/* Connect interface with channel */
/* Connect interface with channel */
isdn_net_bind_channel
(
lp
,
chi
);
isdn_net_bind_channel
(
lp
,
chi
);
#ifdef CONFIG_ISDN_PPP
#ifdef CONFIG_ISDN_PPP
...
@@ -2430,30 +2363,39 @@ p = dev->netdev;
...
@@ -2430,30 +2363,39 @@ p = dev->netdev;
eaz
);
eaz
);
/* if this interface is dialing, it does it probably on a different
/* if this interface is dialing, it does it probably on a different
device, so free this device */
device, so free this device */
if
(
(
lp
->
dialstate
==
4
)
||
(
lp
->
dialstate
==
12
)
)
{
if
(
lp
->
dialstate
==
ST_OUT_WAIT_DCONN
)
{
#ifdef CONFIG_ISDN_PPP
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
isdn_ppp_free
(
lp
);
isdn_ppp_free
(
lp
);
#endif
#endif
isdn_net_lp_disconnected
(
lp
);
isdn_net_lp_disconnected
(
lp
);
isdn_
free_channel
(
lp
->
isdn_device
,
lp
->
isdn_channel
,
isdn_
slot_free
(
lp
->
isdn_slot
,
ISDN_USAGE_NET
);
ISDN_USAGE_NET
);
}
}
dev
->
usage
[
idx
]
&=
ISDN_USAGE_EXCLUSIVE
;
strcpy
(
isdn_slot_num
(
idx
),
nr
);
dev
->
usage
[
idx
]
|=
ISDN_USAGE_NET
;
isdn_slot_set_usage
(
idx
,
(
isdn_slot_usage
(
idx
)
&
ISDN_USAGE_EXCLUSIVE
)
|
ISDN_USAGE_NET
);
strcpy
(
dev
->
num
[
idx
],
nr
);
isdn_slot_set_st_netdev
(
idx
,
lp
->
netdev
);
isdn_info_update
();
lp
->
isdn_slot
=
slot
;
dev
->
st_netdev
[
idx
]
=
lp
->
netdev
;
lp
->
isdn_device
=
di
;
lp
->
isdn_channel
=
ch
;
lp
->
ppp_slot
=
-
1
;
lp
->
ppp_slot
=
-
1
;
lp
->
flags
|=
ISDN_NET_CONNECTED
;
lp
->
flags
|=
ISDN_NET_CONNECTED
;
lp
->
dialstate
=
7
;
lp
->
dtimer
=
0
;
lp
->
outgoing
=
0
;
lp
->
outgoing
=
0
;
lp
->
huptimer
=
0
;
lp
->
huptimer
=
0
;
lp
->
hupflags
|=
ISDN_WAITCHARGE
;
lp
->
hupflags
|=
ISDN_WAITCHARGE
;
lp
->
hupflags
&=
~
ISDN_HAVECHARGE
;
lp
->
hupflags
&=
~
ISDN_HAVECHARGE
;
/* Got incoming Call, setup L2 and L3 protocols,
* then wait for D-Channel-connect
*/
cmd
.
arg
=
lp
->
l2_proto
<<
8
;
isdn_slot_command
(
lp
->
isdn_slot
,
ISDN_CMD_SETL2
,
&
cmd
);
cmd
.
arg
=
lp
->
l3_proto
<<
8
;
isdn_slot_command
(
lp
->
isdn_slot
,
ISDN_CMD_SETL3
,
&
cmd
);
lp
->
dial_timer
.
expires
=
jiffies
+
15
*
HZ
;
lp
->
dial_event
=
EV_NET_TIMER_IN_DCONN
;
add_timer
(
&
lp
->
dial_timer
);
lp
->
dialstate
=
ST_IN_WAIT_DCONN
;
#ifdef CONFIG_ISDN_PPP
#ifdef CONFIG_ISDN_PPP
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
if
(
lp
->
p_encap
==
ISDN_NET_ENCAP_SYNCPPP
)
if
(
isdn_ppp_bind
(
lp
)
<
0
)
{
if
(
isdn_ppp_bind
(
lp
)
<
0
)
{
...
@@ -2467,11 +2409,10 @@ p = dev->netdev;
...
@@ -2467,11 +2409,10 @@ p = dev->netdev;
}
}
}
}
}
}
p
=
(
isdn_net_dev
*
)
p
->
next
;
}
}
/* If none of configured EAZ/MSN matched and not verbose, be silent */
/* If none of configured EAZ/MSN matched and not verbose, be silent */
if
(
!
ematch
||
dev
->
net_verbose
)
if
(
!
ematch
||
dev
->
net_verbose
)
printk
(
KERN_INFO
"isdn_net: call from %s -> %d %s ignored
\n
"
,
nr
,
di
,
eaz
);
printk
(
KERN_INFO
"isdn_net: call from %s -> %d %s ignored
\n
"
,
nr
,
slot
,
eaz
);
restore_flags
(
flags
);
restore_flags
(
flags
);
return
(
wret
==
2
)
?
5
:
0
;
return
(
wret
==
2
)
?
5
:
0
;
}
}
...
@@ -2482,14 +2423,14 @@ p = dev->netdev;
...
@@ -2482,14 +2423,14 @@ p = dev->netdev;
isdn_net_dev
*
isdn_net_dev
*
isdn_net_findif
(
char
*
name
)
isdn_net_findif
(
char
*
name
)
{
{
isdn_net_dev
*
p
=
dev
->
netdev
;
struct
list_head
*
l
;
while
(
p
)
{
list_for_each
(
l
,
&
isdn_net_devs
)
{
if
(
!
strcmp
(
p
->
local
->
name
,
name
))
isdn_net_dev
*
p
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
if
(
!
strcmp
(
p
->
local
.
name
,
name
))
return
p
;
return
p
;
p
=
(
isdn_net_dev
*
)
p
->
next
;
}
}
return
(
isdn_net_dev
*
)
NULL
;
return
NULL
;
}
}
/*
/*
...
@@ -2500,7 +2441,7 @@ isdn_net_findif(char *name)
...
@@ -2500,7 +2441,7 @@ isdn_net_findif(char *name)
int
int
isdn_net_force_dial_lp
(
isdn_net_local
*
lp
)
isdn_net_force_dial_lp
(
isdn_net_local
*
lp
)
{
{
if
((
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
&&
!
lp
->
dialstate
)
{
if
((
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
&&
lp
->
dialstate
==
ST_NULL
)
{
int
chi
;
int
chi
;
if
(
lp
->
phone
[
1
])
{
if
(
lp
->
phone
[
1
])
{
ulong
flags
;
ulong
flags
;
...
@@ -2509,7 +2450,7 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
...
@@ -2509,7 +2450,7 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
/* Grab a free ISDN-Channel */
/* Grab a free ISDN-Channel */
if
((
chi
=
if
((
chi
=
isdn_get_free_
channel
(
isdn_get_free_
slot
(
ISDN_USAGE_NET
,
ISDN_USAGE_NET
,
lp
->
l2_proto
,
lp
->
l2_proto
,
lp
->
l3_proto
,
lp
->
l3_proto
,
...
@@ -2521,7 +2462,6 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
...
@@ -2521,7 +2462,6 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
restore_flags
(
flags
);
restore_flags
(
flags
);
return
-
EAGAIN
;
return
-
EAGAIN
;
}
}
lp
->
dialstate
=
1
;
/* Connect interface with channel */
/* Connect interface with channel */
isdn_net_bind_channel
(
lp
,
chi
);
isdn_net_bind_channel
(
lp
,
chi
);
#ifdef CONFIG_ISDN_PPP
#ifdef CONFIG_ISDN_PPP
...
@@ -2534,7 +2474,7 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
...
@@ -2534,7 +2474,7 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
#endif
#endif
/* Initiate dialing */
/* Initiate dialing */
restore_flags
(
flags
);
restore_flags
(
flags
);
i
sdn_net_dial
(
);
i
nit_dialout
(
lp
);
return
0
;
return
0
;
}
else
}
else
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -2567,47 +2507,39 @@ isdn_net_force_dial(char *name)
...
@@ -2567,47 +2507,39 @@ isdn_net_force_dial(char *name)
if
(
!
p
)
if
(
!
p
)
return
-
ENODEV
;
return
-
ENODEV
;
return
(
isdn_net_force_dial_lp
(
p
->
local
));
return
(
isdn_net_force_dial_lp
(
&
p
->
local
));
}
}
/*
/*
* Allocate a new network-interface and initialize its data structures.
* Allocate a new network-interface and initialize its data structures.
*/
*/
char
*
int
isdn_net_new
(
char
*
name
,
struct
net_device
*
master
)
isdn_net_new
(
char
*
name
,
struct
net_device
*
master
)
{
{
int
retval
;
isdn_net_dev
*
netdev
;
isdn_net_dev
*
netdev
;
/* Avoid creating an existing interface */
/* Avoid creating an existing interface */
if
(
isdn_net_findif
(
name
))
{
if
(
isdn_net_findif
(
name
))
{
printk
(
KERN_WARNING
"isdn_net: interface %s already exists
\n
"
,
name
);
printk
(
KERN_WARNING
"isdn_net: interface %s already exists
\n
"
,
name
);
return
NULL
;
return
-
EEXIST
;
}
}
if
(
!
(
netdev
=
(
isdn_net_dev
*
)
kmalloc
(
sizeof
(
isdn_net_dev
),
GFP_KERNEL
)))
{
if
(
!
(
netdev
=
kmalloc
(
sizeof
(
isdn_net_dev
),
GFP_KERNEL
)))
{
printk
(
KERN_WARNING
"isdn_net: Could not allocate net-device
\n
"
);
printk
(
KERN_WARNING
"isdn_net: Could not allocate net-device
\n
"
);
return
NULL
;
return
-
ENOMEM
;
}
}
memset
(
netdev
,
0
,
sizeof
(
isdn_net_dev
));
memset
(
netdev
,
0
,
sizeof
(
isdn_net_dev
));
if
(
!
(
netdev
->
local
=
(
isdn_net_local
*
)
kmalloc
(
sizeof
(
isdn_net_local
),
GFP_KERNEL
)))
{
strcpy
(
netdev
->
local
.
name
,
name
);
printk
(
KERN_WARNING
"isdn_net: Could not allocate device locals
\n
"
);
strcpy
(
netdev
->
dev
.
name
,
name
);
kfree
(
netdev
);
netdev
->
dev
.
priv
=
&
netdev
->
local
;
return
NULL
;
}
memset
(
netdev
->
local
,
0
,
sizeof
(
isdn_net_local
));
if
(
name
==
NULL
)
strcpy
(
netdev
->
local
->
name
,
" "
);
else
strcpy
(
netdev
->
local
->
name
,
name
);
strcpy
(
netdev
->
dev
.
name
,
netdev
->
local
->
name
);
netdev
->
dev
.
priv
=
netdev
->
local
;
netdev
->
dev
.
init
=
isdn_net_init
;
netdev
->
dev
.
init
=
isdn_net_init
;
netdev
->
local
->
p_encap
=
ISDN_NET_ENCAP_RAWIP
;
netdev
->
local
.
p_encap
=
ISDN_NET_ENCAP_RAWIP
;
if
(
master
)
{
if
(
master
)
{
/* Device shall be a slave */
/* Device shall be a slave */
struct
net_device
*
p
=
(((
isdn_net_local
*
)
master
->
priv
)
->
slave
);
struct
net_device
*
p
=
(((
isdn_net_local
*
)
master
->
priv
)
->
slave
);
struct
net_device
*
q
=
master
;
struct
net_device
*
q
=
master
;
netdev
->
local
->
master
=
master
;
netdev
->
local
.
master
=
master
;
/* Put device at end of slave-chain */
/* Put device at end of slave-chain */
while
(
p
)
{
while
(
p
)
{
q
=
p
;
q
=
p
;
...
@@ -2621,81 +2553,80 @@ isdn_net_new(char *name, struct net_device *master)
...
@@ -2621,81 +2553,80 @@ isdn_net_new(char *name, struct net_device *master)
*/
*/
netdev
->
dev
.
tx_timeout
=
isdn_net_tx_timeout
;
netdev
->
dev
.
tx_timeout
=
isdn_net_tx_timeout
;
netdev
->
dev
.
watchdog_timeo
=
ISDN_NET_TX_TIMEOUT
;
netdev
->
dev
.
watchdog_timeo
=
ISDN_NET_TX_TIMEOUT
;
if
(
register_netdev
(
&
netdev
->
dev
)
!=
0
)
{
retval
=
register_netdev
(
&
netdev
->
dev
);
if
(
retval
)
{
printk
(
KERN_WARNING
"isdn_net: Could not register net-device
\n
"
);
printk
(
KERN_WARNING
"isdn_net: Could not register net-device
\n
"
);
kfree
(
netdev
->
local
);
kfree
(
netdev
);
kfree
(
netdev
);
return
NULL
;
return
retval
;
}
}
}
}
netdev
->
local
->
magic
=
ISDN_NET_MAGIC
;
netdev
->
local
.
magic
=
ISDN_NET_MAGIC
;
netdev
->
queue
=
netdev
->
local
;
netdev
->
queue
=
&
netdev
->
local
;
spin_lock_init
(
&
netdev
->
queue_lock
);
spin_lock_init
(
&
netdev
->
queue_lock
);
netdev
->
local
->
last
=
netdev
->
local
;
netdev
->
local
.
last
=
&
netdev
->
local
;
netdev
->
local
->
netdev
=
netdev
;
netdev
->
local
.
netdev
=
netdev
;
netdev
->
local
->
next
=
netdev
->
local
;
netdev
->
local
.
next
=
&
netdev
->
local
;
netdev
->
local
->
tqueue
.
sync
=
0
;
netdev
->
local
.
tqueue
.
sync
=
0
;
netdev
->
local
->
tqueue
.
routine
=
isdn_net_softint
;
netdev
->
local
.
tqueue
.
routine
=
isdn_net_softint
;
netdev
->
local
->
tqueue
.
data
=
netdev
->
local
;
netdev
->
local
.
tqueue
.
data
=
&
netdev
->
local
;
spin_lock_init
(
&
netdev
->
local
->
xmit_lock
);
spin_lock_init
(
&
netdev
->
local
.
xmit_lock
);
netdev
->
local
->
isdn_device
=
-
1
;
netdev
->
local
.
isdn_slot
=
-
1
;
netdev
->
local
->
isdn_channel
=
-
1
;
netdev
->
local
.
pre_device
=
-
1
;
netdev
->
local
->
pre_device
=
-
1
;
netdev
->
local
.
pre_channel
=
-
1
;
netdev
->
local
->
pre_channel
=
-
1
;
netdev
->
local
.
exclusive
=
-
1
;
netdev
->
local
->
exclusive
=
-
1
;
netdev
->
local
.
ppp_slot
=
-
1
;
netdev
->
local
->
ppp_slot
=
-
1
;
netdev
->
local
.
pppbind
=
-
1
;
netdev
->
local
->
pppbind
=
-
1
;
skb_queue_head_init
(
&
netdev
->
local
.
super_tx_queue
);
skb_queue_head_init
(
&
netdev
->
local
->
super_tx_queue
);
netdev
->
local
.
l2_proto
=
ISDN_PROTO_L2_X75I
;
netdev
->
local
->
l2_proto
=
ISDN_PROTO_L2_X75I
;
netdev
->
local
.
l3_proto
=
ISDN_PROTO_L3_TRANS
;
netdev
->
local
->
l3_proto
=
ISDN_PROTO_L3_TRANS
;
netdev
->
local
.
triggercps
=
6000
;
netdev
->
local
->
triggercps
=
6000
;
netdev
->
local
.
slavedelay
=
10
*
HZ
;
netdev
->
local
->
slavedelay
=
10
*
HZ
;
netdev
->
local
.
hupflags
=
ISDN_INHUP
;
/* Do hangup even on incoming calls */
netdev
->
local
->
hupflags
=
ISDN_INHUP
;
/* Do hangup even on incoming calls */
netdev
->
local
.
onhtime
=
10
;
/* Default hangup-time for saving costs
netdev
->
local
->
onhtime
=
10
;
/* Default hangup-time for saving costs
of those who forget configuring this */
of those who forget configuring this */
netdev
->
local
->
dialmax
=
1
;
netdev
->
local
.
dialmax
=
1
;
netdev
->
local
->
flags
=
ISDN_NET_CBHUP
|
ISDN_NET_DM_MANUAL
;
/* Hangup before Callback, manual dial */
netdev
->
local
.
flags
=
ISDN_NET_CBHUP
|
ISDN_NET_DM_MANUAL
;
/* Hangup before Callback, manual dial */
netdev
->
local
->
cbdelay
=
25
;
/* Wait 5 secs before Callback */
netdev
->
local
.
cbdelay
=
5
*
HZ
;
/* Wait 5 secs before Callback */
netdev
->
local
->
dialtimeout
=
-
1
;
/* Infinite Dial-Timeout */
netdev
->
local
.
dialtimeout
=
-
1
;
/* Infinite Dial-Timeout */
netdev
->
local
->
dialwait
=
5
*
HZ
;
/* Wait 5 sec. after failed dial */
netdev
->
local
.
dialwait
=
5
*
HZ
;
/* Wait 5 sec. after failed dial */
netdev
->
local
->
dialstarted
=
0
;
/* Jiffies of last dial-start */
netdev
->
local
.
dialstarted
=
0
;
/* Jiffies of last dial-start */
netdev
->
local
->
dialwait_timer
=
0
;
/* Jiffies of earliest next dial-start */
netdev
->
local
.
dialwait_timer
=
0
;
/* Jiffies of earliest next dial-start */
init_timer
(
&
netdev
->
local
.
dial_timer
);
netdev
->
local
.
dial_timer
.
data
=
(
unsigned
long
)
&
netdev
->
local
;
netdev
->
local
.
dial_timer
.
function
=
isdn_net_dial_timer
;
/* Put into to netdev-chain */
/* Put into to netdev-chain */
netdev
->
next
=
(
void
*
)
dev
->
netdev
;
list_add
(
&
netdev
->
global_list
,
&
isdn_net_devs
);
dev
->
netdev
=
netdev
;
return
0
;
return
netdev
->
dev
.
name
;
}
}
char
*
int
isdn_net_newslave
(
char
*
parm
)
isdn_net_newslave
(
char
*
parm
)
{
{
char
*
p
=
strchr
(
parm
,
','
);
char
*
p
=
strchr
(
parm
,
','
);
isdn_net_dev
*
n
;
isdn_net_dev
*
m
;
char
newname
[
10
];
if
(
p
)
{
/* Slave-Name MUST not be empty */
/* Slave-Name MUST not be empty */
if
(
!
p
||
!
p
[
1
])
if
(
!
strlen
(
p
+
1
))
return
-
EINVAL
;
return
NULL
;
strcpy
(
newname
,
p
+
1
);
*
p
=
0
;
*
p
=
0
;
/* Master must already exist */
/* Master must already exist */
if
(
!
(
m
=
isdn_net_findif
(
parm
)))
if
(
!
(
n
=
isdn_net_findif
(
parm
)))
return
-
ESRCH
;
return
NULL
;
/* Master must be a real interface, not a slave */
/* Master must be a real interface, not a slave */
if
(
m
->
local
.
master
)
if
(
n
->
local
->
master
)
return
-
ENXIO
;
return
NULL
;
/* Master must not be started yet */
/* Master must not be started yet */
if
(
isdn_net_device_started
(
m
))
if
(
isdn_net_device_started
(
n
))
return
-
EBUSY
;
return
NULL
;
return
(
isdn_net_new
(
newname
,
&
(
n
->
dev
)));
return
isdn_net_new
(
p
+
1
,
&
m
->
dev
);
}
return
NULL
;
}
}
/*
/*
...
@@ -2717,7 +2648,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
...
@@ -2717,7 +2648,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
ulong
flags
;
ulong
flags
;
#endif
#endif
if
(
p
)
{
if
(
p
)
{
isdn_net_local
*
lp
=
p
->
local
;
isdn_net_local
*
lp
=
&
p
->
local
;
/* See if any registered driver supports the features we want */
/* See if any registered driver supports the features we want */
features
=
((
1
<<
cfg
->
l2_proto
)
<<
ISDN_FEATURE_L2_SHIFT
)
|
features
=
((
1
<<
cfg
->
l2_proto
)
<<
ISDN_FEATURE_L2_SHIFT
)
|
...
@@ -2777,7 +2708,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
...
@@ -2777,7 +2708,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
case
ISDN_NET_ENCAP_X25IFACE
:
case
ISDN_NET_ENCAP_X25IFACE
:
#ifndef CONFIG_ISDN_X25
#ifndef CONFIG_ISDN_X25
printk
(
KERN_WARNING
"%s: isdn-x25 support not configured
\n
"
,
printk
(
KERN_WARNING
"%s: isdn-x25 support not configured
\n
"
,
p
->
local
->
name
);
p
->
local
.
name
);
return
-
EINVAL
;
return
-
EINVAL
;
#else
#else
p
->
dev
.
type
=
ARPHRD_X25
;
/* change ARP type */
p
->
dev
.
type
=
ARPHRD_X25
;
/* change ARP type */
...
@@ -2793,7 +2724,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
...
@@ -2793,7 +2724,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
break
;
break
;
printk
(
KERN_WARNING
printk
(
KERN_WARNING
"%s: encapsulation protocol %d not supported
\n
"
,
"%s: encapsulation protocol %d not supported
\n
"
,
p
->
local
->
name
,
cfg
->
p_encap
);
p
->
local
.
name
,
cfg
->
p_encap
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
strlen
(
cfg
->
drvid
))
{
if
(
strlen
(
cfg
->
drvid
))
{
...
@@ -2830,7 +2761,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
...
@@ -2830,7 +2761,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
/* If binding is exclusive, try to grab the channel */
/* If binding is exclusive, try to grab the channel */
save_flags
(
flags
);
save_flags
(
flags
);
if
((
i
=
isdn_get_free_
channel
(
ISDN_USAGE_NET
,
if
((
i
=
isdn_get_free_
slot
(
ISDN_USAGE_NET
,
lp
->
l2_proto
,
lp
->
l3_proto
,
drvidx
,
lp
->
l2_proto
,
lp
->
l3_proto
,
drvidx
,
chidx
,
lp
->
msn
))
<
0
)
{
chidx
,
lp
->
msn
))
<
0
)
{
/* Grab failed, because desired channel is in use */
/* Grab failed, because desired channel is in use */
...
@@ -2839,8 +2770,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
...
@@ -2839,8 +2770,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
return
-
EBUSY
;
return
-
EBUSY
;
}
}
/* All went ok, so update isdninfo */
/* All went ok, so update isdninfo */
dev
->
usage
[
i
]
=
ISDN_USAGE_EXCLUSIVE
;
isdn_slot_set_usage
(
i
,
ISDN_USAGE_EXCLUSIVE
);
isdn_info_update
();
restore_flags
(
flags
);
restore_flags
(
flags
);
lp
->
exclusive
=
i
;
lp
->
exclusive
=
i
;
}
else
{
}
else
{
...
@@ -2860,7 +2790,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
...
@@ -2860,7 +2790,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
lp
->
charge
=
cfg
->
charge
;
lp
->
charge
=
cfg
->
charge
;
lp
->
l2_proto
=
cfg
->
l2_proto
;
lp
->
l2_proto
=
cfg
->
l2_proto
;
lp
->
l3_proto
=
cfg
->
l3_proto
;
lp
->
l3_proto
=
cfg
->
l3_proto
;
lp
->
cbdelay
=
cfg
->
cbdelay
;
lp
->
cbdelay
=
cfg
->
cbdelay
*
HZ
/
5
;
lp
->
dialmax
=
cfg
->
dialmax
;
lp
->
dialmax
=
cfg
->
dialmax
;
lp
->
triggercps
=
cfg
->
triggercps
;
lp
->
triggercps
=
cfg
->
triggercps
;
lp
->
slavedelay
=
cfg
->
slavedelay
*
HZ
;
lp
->
slavedelay
=
cfg
->
slavedelay
*
HZ
;
...
@@ -2944,7 +2874,7 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
...
@@ -2944,7 +2874,7 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
isdn_net_dev
*
p
=
isdn_net_findif
(
cfg
->
name
);
isdn_net_dev
*
p
=
isdn_net_findif
(
cfg
->
name
);
if
(
p
)
{
if
(
p
)
{
isdn_net_local
*
lp
=
p
->
local
;
isdn_net_local
*
lp
=
&
p
->
local
;
strcpy
(
cfg
->
eaz
,
lp
->
msn
);
strcpy
(
cfg
->
eaz
,
lp
->
msn
);
cfg
->
exclusive
=
lp
->
exclusive
;
cfg
->
exclusive
=
lp
->
exclusive
;
...
@@ -2968,7 +2898,7 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
...
@@ -2968,7 +2898,7 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
cfg
->
dialmode
=
lp
->
flags
&
ISDN_NET_DIALMODE_MASK
;
cfg
->
dialmode
=
lp
->
flags
&
ISDN_NET_DIALMODE_MASK
;
cfg
->
chargehup
=
(
lp
->
hupflags
&
4
)
?
1
:
0
;
cfg
->
chargehup
=
(
lp
->
hupflags
&
4
)
?
1
:
0
;
cfg
->
ihup
=
(
lp
->
hupflags
&
8
)
?
1
:
0
;
cfg
->
ihup
=
(
lp
->
hupflags
&
8
)
?
1
:
0
;
cfg
->
cbdelay
=
lp
->
cbdelay
;
cfg
->
cbdelay
=
lp
->
cbdelay
*
5
/
HZ
;
cfg
->
dialmax
=
lp
->
dialmax
;
cfg
->
dialmax
=
lp
->
dialmax
;
cfg
->
triggercps
=
lp
->
triggercps
;
cfg
->
triggercps
=
lp
->
triggercps
;
cfg
->
slavedelay
=
lp
->
slavedelay
/
HZ
;
cfg
->
slavedelay
=
lp
->
slavedelay
/
HZ
;
...
@@ -3003,8 +2933,8 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone)
...
@@ -3003,8 +2933,8 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone)
if
(
!
(
n
=
(
isdn_net_phone
*
)
kmalloc
(
sizeof
(
isdn_net_phone
),
GFP_KERNEL
)))
if
(
!
(
n
=
(
isdn_net_phone
*
)
kmalloc
(
sizeof
(
isdn_net_phone
),
GFP_KERNEL
)))
return
-
ENOMEM
;
return
-
ENOMEM
;
strcpy
(
n
->
num
,
phone
->
phone
);
strcpy
(
n
->
num
,
phone
->
phone
);
n
->
next
=
p
->
local
->
phone
[
phone
->
outgoing
&
1
];
n
->
next
=
p
->
local
.
phone
[
phone
->
outgoing
&
1
];
p
->
local
->
phone
[
phone
->
outgoing
&
1
]
=
n
;
p
->
local
.
phone
[
phone
->
outgoing
&
1
]
=
n
;
return
0
;
return
0
;
}
}
return
-
ENODEV
;
return
-
ENODEV
;
...
@@ -3026,7 +2956,7 @@ isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
...
@@ -3026,7 +2956,7 @@ isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
if
(
!
p
)
if
(
!
p
)
return
-
ENODEV
;
return
-
ENODEV
;
inout
&=
1
;
inout
&=
1
;
for
(
n
=
p
->
local
->
phone
[
inout
];
n
;
n
=
n
->
next
)
{
for
(
n
=
p
->
local
.
phone
[
inout
];
n
;
n
=
n
->
next
)
{
if
(
more
)
{
if
(
more
)
{
put_user
(
' '
,
phones
++
);
put_user
(
' '
,
phones
++
);
count
++
;
count
++
;
...
@@ -3051,7 +2981,7 @@ int
...
@@ -3051,7 +2981,7 @@ int
isdn_net_getpeer
(
isdn_net_ioctl_phone
*
phone
,
isdn_net_ioctl_phone
*
peer
)
isdn_net_getpeer
(
isdn_net_ioctl_phone
*
phone
,
isdn_net_ioctl_phone
*
peer
)
{
{
isdn_net_dev
*
p
=
isdn_net_findif
(
phone
->
name
);
isdn_net_dev
*
p
=
isdn_net_findif
(
phone
->
name
);
int
ch
,
dv
,
idx
;
int
idx
;
if
(
!
p
)
return
-
ENODEV
;
if
(
!
p
)
return
-
ENODEV
;
/*
/*
...
@@ -3060,15 +2990,12 @@ isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer)
...
@@ -3060,15 +2990,12 @@ isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer)
* in (partially) wrong number copied to user. This race
* in (partially) wrong number copied to user. This race
* currently ignored.
* currently ignored.
*/
*/
ch
=
p
->
local
->
isdn_channel
;
idx
=
p
->
local
.
isdn_slot
;
dv
=
p
->
local
->
isdn_device
;
if
(
idx
<
0
)
return
-
ENOTCONN
;
if
(
ch
<
0
&&
dv
<
0
)
return
-
ENOTCONN
;
idx
=
isdn_dc2minor
(
dv
,
ch
);
if
(
idx
<
0
)
return
-
ENODEV
;
/* for pre-bound channels, we need this extra check */
/* for pre-bound channels, we need this extra check */
if
(
strncmp
(
dev
->
num
[
idx
]
,
"???"
,
3
)
==
0
)
return
-
ENOTCONN
;
if
(
strncmp
(
isdn_slot_num
(
idx
)
,
"???"
,
3
)
==
0
)
return
-
ENOTCONN
;
strncpy
(
phone
->
phone
,
dev
->
num
[
idx
]
,
ISDN_MSNLEN
);
strncpy
(
phone
->
phone
,
isdn_slot_num
(
idx
)
,
ISDN_MSNLEN
);
phone
->
outgoing
=
USG_OUTGOING
(
dev
->
usage
[
idx
]
);
phone
->
outgoing
=
USG_OUTGOING
(
isdn_slot_usage
(
idx
)
);
if
(
copy_to_user
(
peer
,
phone
,
sizeof
(
*
peer
))
)
return
-
EFAULT
;
if
(
copy_to_user
(
peer
,
phone
,
sizeof
(
*
peer
))
)
return
-
EFAULT
;
return
0
;
return
0
;
}
}
...
@@ -3087,16 +3014,16 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone)
...
@@ -3087,16 +3014,16 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone)
if
(
p
)
{
if
(
p
)
{
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
n
=
p
->
local
->
phone
[
inout
];
n
=
p
->
local
.
phone
[
inout
];
m
=
NULL
;
m
=
NULL
;
while
(
n
)
{
while
(
n
)
{
if
(
!
strcmp
(
n
->
num
,
phone
->
phone
))
{
if
(
!
strcmp
(
n
->
num
,
phone
->
phone
))
{
if
(
p
->
local
->
dial
==
n
)
if
(
p
->
local
.
dial
==
n
)
p
->
local
->
dial
=
n
->
next
;
p
->
local
.
dial
=
n
->
next
;
if
(
m
)
if
(
m
)
m
->
next
=
n
->
next
;
m
->
next
=
n
->
next
;
else
else
p
->
local
->
phone
[
inout
]
=
n
->
next
;
p
->
local
.
phone
[
inout
]
=
n
->
next
;
kfree
(
n
);
kfree
(
n
);
restore_flags
(
flags
);
restore_flags
(
flags
);
return
0
;
return
0
;
...
@@ -3124,15 +3051,15 @@ isdn_net_rmallphone(isdn_net_dev * p)
...
@@ -3124,15 +3051,15 @@ isdn_net_rmallphone(isdn_net_dev * p)
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
for
(
i
=
0
;
i
<
2
;
i
++
)
{
for
(
i
=
0
;
i
<
2
;
i
++
)
{
n
=
p
->
local
->
phone
[
i
];
n
=
p
->
local
.
phone
[
i
];
while
(
n
)
{
while
(
n
)
{
m
=
n
->
next
;
m
=
n
->
next
;
kfree
(
n
);
kfree
(
n
);
n
=
m
;
n
=
m
;
}
}
p
->
local
->
phone
[
i
]
=
NULL
;
p
->
local
.
phone
[
i
]
=
NULL
;
}
}
p
->
local
->
dial
=
NULL
;
p
->
local
.
dial
=
NULL
;
restore_flags
(
flags
);
restore_flags
(
flags
);
return
0
;
return
0
;
}
}
...
@@ -3147,9 +3074,9 @@ isdn_net_force_hangup(char *name)
...
@@ -3147,9 +3074,9 @@ isdn_net_force_hangup(char *name)
struct
net_device
*
q
;
struct
net_device
*
q
;
if
(
p
)
{
if
(
p
)
{
if
(
p
->
local
->
isdn_device
<
0
)
if
(
p
->
local
.
isdn_slot
<
0
)
return
1
;
return
1
;
q
=
p
->
local
->
slave
;
q
=
p
->
local
.
slave
;
/* If this interface has slaves, do a hangup for them also. */
/* If this interface has slaves, do a hangup for them also. */
while
(
q
)
{
while
(
q
)
{
isdn_net_hangup
(
q
);
isdn_net_hangup
(
q
);
...
@@ -3165,7 +3092,7 @@ isdn_net_force_hangup(char *name)
...
@@ -3165,7 +3092,7 @@ isdn_net_force_hangup(char *name)
* Helper-function for isdn_net_rm: Do the real work.
* Helper-function for isdn_net_rm: Do the real work.
*/
*/
static
int
static
int
isdn_net_realrm
(
isdn_net_dev
*
p
,
isdn_net_dev
*
q
)
isdn_net_realrm
(
isdn_net_dev
*
p
)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
...
@@ -3182,42 +3109,37 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
...
@@ -3182,42 +3109,37 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
/* Free all phone-entries */
/* Free all phone-entries */
isdn_net_rmallphone
(
p
);
isdn_net_rmallphone
(
p
);
/* If interface is bound exclusive, free channel-usage */
/* If interface is bound exclusive, free channel-usage */
if
(
p
->
local
->
exclusive
!=
-
1
)
if
(
p
->
local
.
exclusive
!=
-
1
)
isdn_unexclusive_channel
(
p
->
local
->
pre_device
,
p
->
local
->
pre_channel
);
isdn_unexclusive_channel
(
p
->
local
.
pre_device
,
p
->
local
.
pre_channel
);
if
(
p
->
local
->
master
)
{
if
(
p
->
local
.
master
)
{
/* It's a slave-device, so update master's slave-pointer if necessary */
/* It's a slave-device, so update master's slave-pointer if necessary */
if
(((
isdn_net_local
*
)
(
p
->
local
->
master
->
priv
))
->
slave
==
&
p
->
dev
)
if
(((
isdn_net_local
*
)
(
p
->
local
.
master
->
priv
))
->
slave
==
&
p
->
dev
)
((
isdn_net_local
*
)
(
p
->
local
->
master
->
priv
))
->
slave
=
p
->
local
->
slave
;
((
isdn_net_local
*
)
(
p
->
local
.
master
->
priv
))
->
slave
=
p
->
local
.
slave
;
}
else
{
}
else
{
/* Unregister only if it's a master-device */
/* Unregister only if it's a master-device */
p
->
dev
.
hard_header_cache
=
p
->
local
->
org_hhc
;
p
->
dev
.
hard_header_cache
=
p
->
local
.
org_hhc
;
p
->
dev
.
header_cache_update
=
p
->
local
->
org_hcu
;
p
->
dev
.
header_cache_update
=
p
->
local
.
org_hcu
;
unregister_netdev
(
&
p
->
dev
);
unregister_netdev
(
&
p
->
dev
);
}
}
/* Unlink device from chain */
/* Unlink device from chain */
if
(
q
)
list_del
(
&
p
->
global_list
);
q
->
next
=
p
->
next
;
if
(
p
->
local
.
slave
)
{
else
dev
->
netdev
=
p
->
next
;
if
(
p
->
local
->
slave
)
{
/* If this interface has a slave, remove it also */
/* If this interface has a slave, remove it also */
char
*
slavename
=
((
isdn_net_local
*
)
(
p
->
local
->
slave
->
priv
))
->
name
;
char
*
slavename
=
((
isdn_net_local
*
)
(
p
->
local
.
slave
->
priv
))
->
name
;
isdn_net_dev
*
n
=
dev
->
netdev
;
struct
list_head
*
l
;
q
=
NULL
;
while
(
n
)
{
list_for_each
(
l
,
&
isdn_net_devs
)
{
if
(
!
strcmp
(
n
->
local
->
name
,
slavename
))
{
isdn_net_dev
*
n
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
isdn_net_realrm
(
n
,
q
);
if
(
!
strcmp
(
n
->
local
.
name
,
slavename
))
{
isdn_net_realrm
(
n
);
break
;
break
;
}
}
q
=
n
;
n
=
(
isdn_net_dev
*
)
n
->
next
;
}
}
}
}
/* If no more net-devices remain, disable auto-hangup timer */
/* If no more net-devices remain, disable auto-hangup timer */
if
(
dev
->
netdev
==
NULL
)
if
(
list_empty
(
&
isdn_net_devs
)
)
isdn_timer_ctrl
(
ISDN_TIMER_NETHANGUP
,
0
);
isdn_timer_ctrl
(
ISDN_TIMER_NETHANGUP
,
0
);
restore_flags
(
flags
);
restore_flags
(
flags
);
kfree
(
p
->
local
);
kfree
(
p
);
kfree
(
p
);
return
0
;
return
0
;
...
@@ -3229,21 +3151,14 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
...
@@ -3229,21 +3151,14 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
int
int
isdn_net_rm
(
char
*
name
)
isdn_net_rm
(
char
*
name
)
{
{
isdn_net_dev
*
p
;
struct
list_head
*
l
;
isdn_net_dev
*
q
;
/* Search name in netdev-chain */
/* Search name in netdev-chain */
p
=
dev
->
netdev
;
list_for_each
(
l
,
&
isdn_net_devs
)
{
q
=
NULL
;
isdn_net_dev
*
p
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
while
(
p
)
{
if
(
!
strcmp
(
p
->
local
.
name
,
name
))
if
(
!
strcmp
(
p
->
local
->
name
,
name
))
return
isdn_net_realrm
(
p
);
return
(
isdn_net_realrm
(
p
,
q
));
q
=
p
;
p
=
(
isdn_net_dev
*
)
p
->
next
;
}
}
/* If no more net-devices remain, disable auto-hangup timer */
if
(
dev
->
netdev
==
NULL
)
isdn_timer_ctrl
(
ISDN_TIMER_NETHANGUP
,
0
);
return
-
ENODEV
;
return
-
ENODEV
;
}
}
...
@@ -3259,16 +3174,17 @@ isdn_net_rmall(void)
...
@@ -3259,16 +3174,17 @@ isdn_net_rmall(void)
/* Walk through netdev-chain */
/* Walk through netdev-chain */
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
while
(
dev
->
netdev
)
{
while
(
!
list_empty
(
&
isdn_net_devs
))
{
if
(
!
dev
->
netdev
->
local
->
master
)
{
isdn_net_dev
*
p
=
list_entry
(
isdn_net_devs
.
next
,
isdn_net_dev
,
global_list
);
/* Remove master-devices only, slaves get removed with their master */
if
((
ret
=
isdn_net_realrm
(
dev
->
netdev
,
NULL
)))
{
/* Remove master-devices only, slaves get removed with their master */
if
(
!
p
->
local
.
master
)
{
if
((
ret
=
isdn_net_realrm
(
p
)))
{
restore_flags
(
flags
);
restore_flags
(
flags
);
return
ret
;
return
ret
;
}
}
}
}
}
}
dev
->
netdev
=
NULL
;
restore_flags
(
flags
);
restore_flags
(
flags
);
return
0
;
return
0
;
}
}
drivers/isdn/i4l/isdn_net.h
View file @
b14ebcfc
...
@@ -31,8 +31,8 @@
...
@@ -31,8 +31,8 @@
#define CISCO_SLARP_REPLY 1
#define CISCO_SLARP_REPLY 1
#define CISCO_SLARP_KEEPALIVE 2
#define CISCO_SLARP_KEEPALIVE 2
extern
char
*
isdn_net_new
(
char
*
,
struct
net_device
*
);
extern
int
isdn_net_new
(
char
*
,
struct
net_device
*
);
extern
char
*
isdn_net_newslave
(
char
*
);
extern
int
isdn_net_newslave
(
char
*
);
extern
int
isdn_net_rm
(
char
*
);
extern
int
isdn_net_rm
(
char
*
);
extern
int
isdn_net_rmall
(
void
);
extern
int
isdn_net_rmall
(
void
);
extern
int
isdn_net_stat_callback
(
int
,
isdn_ctrl
*
);
extern
int
isdn_net_stat_callback
(
int
,
isdn_ctrl
*
);
...
@@ -44,7 +44,6 @@ extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *);
...
@@ -44,7 +44,6 @@ extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *);
extern
int
isdn_net_delphone
(
isdn_net_ioctl_phone
*
);
extern
int
isdn_net_delphone
(
isdn_net_ioctl_phone
*
);
extern
int
isdn_net_find_icall
(
int
,
int
,
int
,
setup_parm
*
);
extern
int
isdn_net_find_icall
(
int
,
int
,
int
,
setup_parm
*
);
extern
void
isdn_net_hangup
(
struct
net_device
*
);
extern
void
isdn_net_hangup
(
struct
net_device
*
);
extern
void
isdn_net_dial
(
void
);
extern
void
isdn_net_autohup
(
void
);
extern
void
isdn_net_autohup
(
void
);
extern
int
isdn_net_force_hangup
(
char
*
);
extern
int
isdn_net_force_hangup
(
char
*
);
extern
int
isdn_net_force_dial
(
char
*
);
extern
int
isdn_net_force_dial
(
char
*
);
...
@@ -131,7 +130,7 @@ static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp)
...
@@ -131,7 +130,7 @@ static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp)
if
(
master_lp
->
netdev
->
queue
==
lp
)
{
if
(
master_lp
->
netdev
->
queue
==
lp
)
{
master_lp
->
netdev
->
queue
=
lp
->
next
;
master_lp
->
netdev
->
queue
=
lp
->
next
;
if
(
lp
->
next
==
lp
)
{
/* last in queue */
if
(
lp
->
next
==
lp
)
{
/* last in queue */
master_lp
->
netdev
->
queue
=
master_lp
->
netdev
->
local
;
master_lp
->
netdev
->
queue
=
&
master_lp
->
netdev
->
local
;
}
}
}
}
lp
->
next
=
lp
->
last
=
lp
;
/* (re)set own pointers */
lp
->
next
=
lp
->
last
=
lp
;
/* (re)set own pointers */
...
...
drivers/isdn/i4l/isdn_ppp.c
View file @
b14ebcfc
...
@@ -165,14 +165,15 @@ isdn_ppp_bind(isdn_net_local * lp)
...
@@ -165,14 +165,15 @@ isdn_ppp_bind(isdn_net_local * lp)
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
if
(
lp
->
pppbind
<
0
)
{
/* device bounded to ippp device ? */
if
(
lp
->
pppbind
<
0
)
{
/* device bounded to ippp device ? */
isdn_net_dev
*
net_dev
=
dev
->
netdev
;
struct
list_head
*
l
;
char
exclusive
[
ISDN_MAX_CHANNELS
];
/* exclusive flags */
char
exclusive
[
ISDN_MAX_CHANNELS
];
/* exclusive flags */
memset
(
exclusive
,
0
,
ISDN_MAX_CHANNELS
);
memset
(
exclusive
,
0
,
ISDN_MAX_CHANNELS
);
while
(
net_dev
)
{
/* step through net devices to find exclusive minors */
/* step through net devices to find exclusive minors */
isdn_net_local
*
lp
=
net_dev
->
local
;
list_for_each
(
l
,
&
isdn_net_devs
)
{
isdn_net_dev
*
p
=
list_entry
(
l
,
isdn_net_dev
,
global_list
);
isdn_net_local
*
lp
=
&
p
->
local
;
if
(
lp
->
pppbind
>=
0
)
if
(
lp
->
pppbind
>=
0
)
exclusive
[
lp
->
pppbind
]
=
1
;
exclusive
[
lp
->
pppbind
]
=
1
;
net_dev
=
net_dev
->
next
;
}
}
/*
/*
* search a free device / slot
* search a free device / slot
...
@@ -804,11 +805,11 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
...
@@ -804,11 +805,11 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
if
(
proto
!=
PPP_LCP
)
if
(
proto
!=
PPP_LCP
)
lp
->
huptimer
=
0
;
lp
->
huptimer
=
0
;
if
(
lp
->
isdn_
device
<
0
||
lp
->
isdn_channel
<
0
)
{
if
(
lp
->
isdn_
slot
<
0
)
{
retval
=
0
;
retval
=
0
;
goto
out
;
goto
out
;
}
}
if
((
dev
->
drv
[
lp
->
isdn_device
]
->
flags
&
DRV_FLAG_RUNNING
)
&&
if
((
dev
->
drv
[
isdn_slot_driver
(
lp
->
isdn_slot
)
]
->
flags
&
DRV_FLAG_RUNNING
)
&&
lp
->
dialstate
==
0
&&
lp
->
dialstate
==
0
&&
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
{
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
{
unsigned
short
hl
;
unsigned
short
hl
;
...
@@ -818,7 +819,7 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
...
@@ -818,7 +819,7 @@ isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
* sk_buff. old call to dev_alloc_skb only reserved
* sk_buff. old call to dev_alloc_skb only reserved
* 16 bytes, now we are looking what the driver want
* 16 bytes, now we are looking what the driver want
*/
*/
hl
=
dev
->
drv
[
lp
->
isdn_device
]
->
interface
->
hl_hdrlen
;
hl
=
isdn_slot_hdrlen
(
lp
->
isdn_slot
)
;
skb
=
alloc_skb
(
hl
+
count
,
GFP_ATOMIC
);
skb
=
alloc_skb
(
hl
+
count
,
GFP_ATOMIC
);
if
(
!
skb
)
{
if
(
!
skb
)
{
printk
(
KERN_WARNING
"isdn_ppp_write: out of memory!
\n
"
);
printk
(
KERN_WARNING
"isdn_ppp_write: out of memory!
\n
"
);
...
@@ -974,7 +975,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
...
@@ -974,7 +975,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
int
slot
;
int
slot
;
int
proto
;
int
proto
;
if
(
net_dev
->
local
->
master
)
if
(
net_dev
->
local
.
master
)
BUG
();
// we're called with the master device always
BUG
();
// we're called with the master device always
slot
=
lp
->
ppp_slot
;
slot
=
lp
->
ppp_slot
;
...
@@ -1077,12 +1078,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
...
@@ -1077,12 +1078,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
case
PPP_VJC_UNCOMP
:
case
PPP_VJC_UNCOMP
:
if
(
is
->
debug
&
0x20
)
if
(
is
->
debug
&
0x20
)
printk
(
KERN_DEBUG
"isdn_ppp: VJC_UNCOMP
\n
"
);
printk
(
KERN_DEBUG
"isdn_ppp: VJC_UNCOMP
\n
"
);
if
(
net_dev
->
local
->
ppp_slot
<
0
)
{
if
(
net_dev
->
local
.
ppp_slot
<
0
)
{
printk
(
KERN_ERR
__FUNCTION__
": net_dev->local->ppp_slot(%d) out of range
\n
"
,
printk
(
KERN_ERR
__FUNCTION__
": net_dev->local->ppp_slot(%d) out of range
\n
"
,
net_dev
->
local
->
ppp_slot
);
net_dev
->
local
.
ppp_slot
);
goto
drop_packet
;
goto
drop_packet
;
}
}
if
(
slhc_remember
(
ippp_table
[
net_dev
->
local
->
ppp_slot
]
->
slcomp
,
skb
->
data
,
skb
->
len
)
<=
0
)
{
if
(
slhc_remember
(
ippp_table
[
net_dev
->
local
.
ppp_slot
]
->
slcomp
,
skb
->
data
,
skb
->
len
)
<=
0
)
{
printk
(
KERN_WARNING
"isdn_ppp: received illegal VJC_UNCOMP frame!
\n
"
);
printk
(
KERN_WARNING
"isdn_ppp: received illegal VJC_UNCOMP frame!
\n
"
);
goto
drop_packet
;
goto
drop_packet
;
}
}
...
@@ -1103,12 +1104,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
...
@@ -1103,12 +1104,12 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
}
}
skb_put
(
skb
,
skb_old
->
len
+
128
);
skb_put
(
skb
,
skb_old
->
len
+
128
);
memcpy
(
skb
->
data
,
skb_old
->
data
,
skb_old
->
len
);
memcpy
(
skb
->
data
,
skb_old
->
data
,
skb_old
->
len
);
if
(
net_dev
->
local
->
ppp_slot
<
0
)
{
if
(
net_dev
->
local
.
ppp_slot
<
0
)
{
printk
(
KERN_ERR
__FUNCTION__
": net_dev->local->ppp_slot(%d) out of range
\n
"
,
printk
(
KERN_ERR
__FUNCTION__
": net_dev->local->ppp_slot(%d) out of range
\n
"
,
net_dev
->
local
->
ppp_slot
);
net_dev
->
local
.
ppp_slot
);
goto
drop_packet
;
goto
drop_packet
;
}
}
pkt_len
=
slhc_uncompress
(
ippp_table
[
net_dev
->
local
->
ppp_slot
]
->
slcomp
,
pkt_len
=
slhc_uncompress
(
ippp_table
[
net_dev
->
local
.
ppp_slot
]
->
slcomp
,
skb
->
data
,
skb_old
->
len
);
skb
->
data
,
skb_old
->
len
);
kfree_skb
(
skb_old
);
kfree_skb
(
skb_old
);
if
(
pkt_len
<
0
)
if
(
pkt_len
<
0
)
...
@@ -1144,7 +1145,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
...
@@ -1144,7 +1145,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
return
;
return
;
drop_packet:
drop_packet:
net_dev
->
local
->
stats
.
rx_dropped
++
;
net_dev
->
local
.
stats
.
rx_dropped
++
;
kfree_skb
(
skb
);
kfree_skb
(
skb
);
}
}
...
@@ -1263,7 +1264,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
...
@@ -1263,7 +1264,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
* sk_buff. old call to dev_alloc_skb only reserved
* sk_buff. old call to dev_alloc_skb only reserved
* 16 bytes, now we are looking what the driver want.
* 16 bytes, now we are looking what the driver want.
*/
*/
hl
=
dev
->
drv
[
lp
->
isdn_device
]
->
interface
->
hl_hdrlen
+
IPPP_MAX_HEADER
;
hl
=
isdn_slot_hdrlen
(
lp
->
isdn_slot
)
+
IPPP_MAX_HEADER
;
;
/*
/*
* Note: hl might still be insufficient because the method
* Note: hl might still be insufficient because the method
* above does not account for a possibible MPPP slave channel
* above does not account for a possibible MPPP slave channel
...
@@ -1976,7 +1977,7 @@ isdn_ppp_dial_slave(char *name)
...
@@ -1976,7 +1977,7 @@ isdn_ppp_dial_slave(char *name)
if
(
!
(
ndev
=
isdn_net_findif
(
name
)))
if
(
!
(
ndev
=
isdn_net_findif
(
name
)))
return
1
;
return
1
;
lp
=
ndev
->
local
;
lp
=
&
ndev
->
local
;
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
return
5
;
return
5
;
...
@@ -2007,7 +2008,7 @@ isdn_ppp_hangup_slave(char *name)
...
@@ -2007,7 +2008,7 @@ isdn_ppp_hangup_slave(char *name)
if
(
!
(
ndev
=
isdn_net_findif
(
name
)))
if
(
!
(
ndev
=
isdn_net_findif
(
name
)))
return
1
;
return
1
;
lp
=
ndev
->
local
;
lp
=
&
ndev
->
local
;
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
if
(
!
(
lp
->
flags
&
ISDN_NET_CONNECTED
))
return
5
;
return
5
;
...
@@ -2094,7 +2095,7 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
...
@@ -2094,7 +2095,7 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
isdn_net_local
*
lp
=
is
->
lp
;
isdn_net_local
*
lp
=
is
->
lp
;
/* Alloc large enough skb */
/* Alloc large enough skb */
hl
=
dev
->
drv
[
lp
->
isdn_device
]
->
interface
->
hl_hdrlen
;
hl
=
isdn_slot_hdrlen
(
lp
->
isdn_slot
)
;
skb
=
alloc_skb
(
len
+
hl
+
16
,
GFP_ATOMIC
);
skb
=
alloc_skb
(
len
+
hl
+
16
,
GFP_ATOMIC
);
if
(
!
skb
)
{
if
(
!
skb
)
{
printk
(
KERN_WARNING
printk
(
KERN_WARNING
...
...
drivers/isdn/i4l/isdn_tty.c
View file @
b14ebcfc
...
@@ -128,7 +128,7 @@ isdn_tty_readmodem(void)
...
@@ -128,7 +128,7 @@ isdn_tty_readmodem(void)
modem_info
*
info
;
modem_info
*
info
;
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
if
((
midx
=
dev
->
m_idx
[
i
]
)
>=
0
)
{
if
((
midx
=
isdn_slot_m_idx
(
i
)
)
>=
0
)
{
info
=
&
dev
->
mdm
.
info
[
midx
];
info
=
&
dev
->
mdm
.
info
[
midx
];
if
(
info
->
online
)
{
if
(
info
->
online
)
{
r
=
0
;
r
=
0
;
...
@@ -143,9 +143,9 @@ isdn_tty_readmodem(void)
...
@@ -143,9 +143,9 @@ isdn_tty_readmodem(void)
if
(
c
>
0
)
{
if
(
c
>
0
)
{
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
r
=
isdn_
readbchan
(
info
->
isdn_driver
,
info
->
isdn_channel
,
r
=
isdn_
slot_readbchan
(
info
->
isdn_slot
,
tty
->
flip
.
char_buf_ptr
,
tty
->
flip
.
char_buf_ptr
,
tty
->
flip
.
flag_buf_ptr
,
c
,
0
);
tty
->
flip
.
flag_buf_ptr
,
c
);
/* CISCO AsyncPPP Hack */
/* CISCO AsyncPPP Hack */
if
(
!
(
info
->
emu
.
mdmreg
[
REG_CPPP
]
&
BIT_CPPP
))
if
(
!
(
info
->
emu
.
mdmreg
[
REG_CPPP
]
&
BIT_CPPP
))
memset
(
tty
->
flip
.
flag_buf_ptr
,
0
,
r
);
memset
(
tty
->
flip
.
flag_buf_ptr
,
0
,
r
);
...
@@ -182,7 +182,7 @@ isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
...
@@ -182,7 +182,7 @@ isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
#endif
#endif
modem_info
*
info
;
modem_info
*
info
;
if
((
midx
=
dev
->
m_idx
[
i
]
)
<
0
)
{
if
((
midx
=
isdn_slot_m_idx
(
i
)
)
<
0
)
{
/* if midx is invalid, packet is not for tty */
/* if midx is invalid, packet is not for tty */
return
0
;
return
0
;
}
}
...
@@ -315,8 +315,7 @@ isdn_tty_tint(modem_info * info)
...
@@ -315,8 +315,7 @@ isdn_tty_tint(modem_info * info)
if
(
!
skb
)
if
(
!
skb
)
return
;
return
;
len
=
skb
->
len
;
len
=
skb
->
len
;
if
((
slen
=
isdn_writebuf_skb_stub
(
info
->
isdn_driver
,
if
((
slen
=
isdn_slot_write
(
info
->
isdn_slot
,
skb
))
==
len
)
{
info
->
isdn_channel
,
1
,
skb
))
==
len
)
{
struct
tty_struct
*
tty
=
info
->
tty
;
struct
tty_struct
*
tty
=
info
->
tty
;
info
->
send_outstanding
++
;
info
->
send_outstanding
++
;
info
->
msr
&=
~
UART_MSR_CTS
;
info
->
msr
&=
~
UART_MSR_CTS
;
...
@@ -479,11 +478,11 @@ isdn_tty_senddown(modem_info * info)
...
@@ -479,11 +478,11 @@ isdn_tty_senddown(modem_info * info)
atomic_inc
(
&
info
->
xmit_lock
);
atomic_inc
(
&
info
->
xmit_lock
);
if
(
!
(
atomic_dec_and_test
(
&
info
->
xmit_lock
)))
if
(
!
(
atomic_dec_and_test
(
&
info
->
xmit_lock
)))
return
;
return
;
if
(
info
->
isdn_
driver
<
0
)
{
if
(
info
->
isdn_
slot
<
0
)
{
info
->
xmit_count
=
0
;
info
->
xmit_count
=
0
;
return
;
return
;
}
}
skb_res
=
dev
->
drv
[
info
->
isdn_driver
]
->
interface
->
hl_hdrlen
+
4
;
skb_res
=
isdn_slot_hdrlen
(
info
->
isdn_slot
)
;
#ifdef CONFIG_ISDN_AUDIO
#ifdef CONFIG_ISDN_AUDIO
if
(
info
->
vonline
&
2
)
if
(
info
->
vonline
&
2
)
audio_len
=
buflen
*
voice_cf
[
info
->
emu
.
vpar
[
3
]];
audio_len
=
buflen
*
voice_cf
[
info
->
emu
.
vpar
[
3
]];
...
@@ -627,7 +626,6 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m)
...
@@ -627,7 +626,6 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m)
int
usg
=
ISDN_USAGE_MODEM
;
int
usg
=
ISDN_USAGE_MODEM
;
int
si
=
7
;
int
si
=
7
;
int
l2
=
m
->
mdmreg
[
REG_L2PROT
];
int
l2
=
m
->
mdmreg
[
REG_L2PROT
];
isdn_ctrl
cmd
;
ulong
flags
;
ulong
flags
;
int
i
;
int
i
;
int
j
;
int
j
;
...
@@ -652,56 +650,34 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m)
...
@@ -652,56 +650,34 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m)
m
->
mdmreg
[
REG_SI1I
]
=
si2bit
[
si
];
m
->
mdmreg
[
REG_SI1I
]
=
si2bit
[
si
];
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
i
=
isdn_get_free_
channel
(
usg
,
l2
,
m
->
mdmreg
[
REG_L3PROT
],
-
1
,
-
1
,
m
->
msn
);
i
=
isdn_get_free_
slot
(
usg
,
l2
,
m
->
mdmreg
[
REG_L3PROT
],
-
1
,
-
1
,
m
->
msn
);
if
(
i
<
0
)
{
if
(
i
<
0
)
{
restore_flags
(
flags
);
restore_flags
(
flags
);
isdn_tty_modem_result
(
RESULT_NO_DIALTONE
,
info
);
isdn_tty_modem_result
(
RESULT_NO_DIALTONE
,
info
);
}
else
{
}
else
{
info
->
isdn_driver
=
dev
->
drvmap
[
i
];
struct
dial_info
dial
=
{
info
->
isdn_channel
=
dev
->
chanmap
[
i
];
.
l2_proto
=
l2
,
info
->
drv_index
=
i
;
.
l3_proto
=
m
->
mdmreg
[
REG_L3PROT
],
dev
->
m_idx
[
i
]
=
info
->
line
;
.
si1
=
si
,
dev
->
usage
[
i
]
|=
ISDN_USAGE_OUTGOING
;
.
si2
=
m
->
mdmreg
[
REG_SI2
],
.
msn
=
m
->
msn
,
.
phone
=
n
,
};
info
->
isdn_slot
=
i
;
isdn_slot_set_m_idx
(
i
,
info
->
line
);
info
->
last_dir
=
1
;
info
->
last_dir
=
1
;
info
->
last_l2
=
l2
;
strcpy
(
info
->
last_num
,
n
);
strcpy
(
info
->
last_num
,
n
);
isdn_info_update
();
restore_flags
(
flags
);
restore_flags
(
flags
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_CLREAZ
;
isdn_command
(
&
cmd
);
strcpy
(
cmd
.
parm
.
num
,
isdn_map_eaz2msn
(
m
->
msn
,
info
->
isdn_driver
));
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETEAZ
;
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETL2
;
info
->
last_l2
=
l2
;
cmd
.
arg
=
info
->
isdn_channel
+
(
l2
<<
8
);
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETL3
;
cmd
.
arg
=
info
->
isdn_channel
+
(
m
->
mdmreg
[
REG_L3PROT
]
<<
8
);
#ifdef CONFIG_ISDN_TTY_FAX
#ifdef CONFIG_ISDN_TTY_FAX
if
(
l2
==
ISDN_PROTO_L2_FAX
)
{
if
(
l2
==
ISDN_PROTO_L2_FAX
)
{
cmd
.
parm
.
fax
=
info
->
fax
;
dial
.
fax
=
info
->
fax
;
info
->
fax
->
direction
=
ISDN_TTY_FAX_CONN_OUT
;
info
->
fax
->
direction
=
ISDN_TTY_FAX_CONN_OUT
;
}
}
#endif
#endif
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
sprintf
(
cmd
.
parm
.
setup
.
phone
,
"%s"
,
n
);
sprintf
(
cmd
.
parm
.
setup
.
eazmsn
,
"%s"
,
isdn_map_eaz2msn
(
m
->
msn
,
info
->
isdn_driver
));
cmd
.
parm
.
setup
.
si1
=
si
;
cmd
.
parm
.
setup
.
si2
=
m
->
mdmreg
[
REG_SI2
];
cmd
.
command
=
ISDN_CMD_DIAL
;
info
->
dialing
=
1
;
info
->
dialing
=
1
;
info
->
emu
.
carrierwait
=
0
;
info
->
emu
.
carrierwait
=
0
;
strcpy
(
dev
->
num
[
i
],
n
);
isdn_slot_dial
(
info
->
isdn_slot
,
&
dial
);
isdn_info_update
();
isdn_command
(
&
cmd
);
isdn_timer_ctrl
(
ISDN_TIMER_CARRIER
,
1
);
isdn_timer_ctrl
(
ISDN_TIMER_CARRIER
,
1
);
}
}
}
}
...
@@ -714,19 +690,15 @@ void
...
@@ -714,19 +690,15 @@ void
isdn_tty_modem_hup
(
modem_info
*
info
,
int
local
)
isdn_tty_modem_hup
(
modem_info
*
info
,
int
local
)
{
{
isdn_ctrl
cmd
;
isdn_ctrl
cmd
;
int
di
,
ch
;
int
slot
;
if
(
!
info
)
if
(
!
info
)
return
;
return
;
di
=
info
->
isdn_driver
;
slot
=
info
->
isdn_slot
;
ch
=
info
->
isdn_channel
;
if
(
slot
<
0
)
if
(
di
<
0
||
ch
<
0
)
return
;
return
;
info
->
isdn_driver
=
-
1
;
info
->
isdn_channel
=
-
1
;
#ifdef ISDN_DEBUG_MODEM_HUP
#ifdef ISDN_DEBUG_MODEM_HUP
printk
(
KERN_DEBUG
"Mhup ttyI%d
\n
"
,
info
->
line
);
printk
(
KERN_DEBUG
"Mhup ttyI%d
\n
"
,
info
->
line
);
#endif
#endif
...
@@ -768,21 +740,14 @@ isdn_tty_modem_hup(modem_info * info, int local)
...
@@ -768,21 +740,14 @@ isdn_tty_modem_hup(modem_info * info, int local)
info
->
msr
&=
~
(
UART_MSR_DCD
|
UART_MSR_RI
);
info
->
msr
&=
~
(
UART_MSR_DCD
|
UART_MSR_RI
);
info
->
lsr
|=
UART_LSR_TEMT
;
info
->
lsr
|=
UART_LSR_TEMT
;
if
(
local
)
{
if
(
local
)
cmd
.
driver
=
di
;
isdn_slot_command
(
slot
,
ISDN_CMD_HANGUP
,
&
cmd
);
cmd
.
command
=
ISDN_CMD_HANGUP
;
cmd
.
arg
=
ch
;
isdn_command
(
&
cmd
);
}
isdn_
all_eaz
(
di
,
ch
);
isdn_
slot_all_eaz
(
slot
);
info
->
emu
.
mdmreg
[
REG_RINGCNT
]
=
0
;
info
->
emu
.
mdmreg
[
REG_RINGCNT
]
=
0
;
isdn_free_channel
(
di
,
ch
,
0
);
isdn_slot_free
(
slot
,
0
);
isdn_slot_set_m_idx
(
slot
,
-
1
);
if
(
info
->
drv_index
>=
0
)
{
info
->
isdn_slot
=
-
1
;
dev
->
m_idx
[
info
->
drv_index
]
=
-
1
;
info
->
drv_index
=
-
1
;
}
}
}
/*
/*
...
@@ -812,11 +777,11 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m)
...
@@ -812,11 +777,11 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m)
printk
(
KERN_DEBUG
"Msusp ttyI%d
\n
"
,
info
->
line
);
printk
(
KERN_DEBUG
"Msusp ttyI%d
\n
"
,
info
->
line
);
#endif
#endif
l
=
strlen
(
id
);
l
=
strlen
(
id
);
if
((
info
->
isdn_
driver
>=
0
))
{
if
((
info
->
isdn_
slot
>=
0
))
{
cmd
.
parm
.
cmsg
.
Length
=
l
+
18
;
cmd
.
parm
.
cmsg
.
Length
=
l
+
18
;
cmd
.
parm
.
cmsg
.
Command
=
CAPI_FACILITY
;
cmd
.
parm
.
cmsg
.
Command
=
CAPI_FACILITY
;
cmd
.
parm
.
cmsg
.
Subcommand
=
CAPI_REQ
;
cmd
.
parm
.
cmsg
.
Subcommand
=
CAPI_REQ
;
cmd
.
parm
.
cmsg
.
adr
.
Controller
=
i
nfo
->
isdn_driver
+
1
;
cmd
.
parm
.
cmsg
.
adr
.
Controller
=
i
sdn_slot_driver
(
info
->
isdn_slot
)
+
1
;
cmd
.
parm
.
cmsg
.
para
[
0
]
=
3
;
/* 16 bit 0x0003 suplementary service */
cmd
.
parm
.
cmsg
.
para
[
0
]
=
3
;
/* 16 bit 0x0003 suplementary service */
cmd
.
parm
.
cmsg
.
para
[
1
]
=
0
;
cmd
.
parm
.
cmsg
.
para
[
1
]
=
0
;
cmd
.
parm
.
cmsg
.
para
[
2
]
=
l
+
3
;
cmd
.
parm
.
cmsg
.
para
[
2
]
=
l
+
3
;
...
@@ -824,10 +789,7 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m)
...
@@ -824,10 +789,7 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m)
cmd
.
parm
.
cmsg
.
para
[
4
]
=
0
;
cmd
.
parm
.
cmsg
.
para
[
4
]
=
0
;
cmd
.
parm
.
cmsg
.
para
[
5
]
=
l
;
cmd
.
parm
.
cmsg
.
para
[
5
]
=
l
;
strncpy
(
&
cmd
.
parm
.
cmsg
.
para
[
6
],
id
,
l
);
strncpy
(
&
cmd
.
parm
.
cmsg
.
para
[
6
],
id
,
l
);
cmd
.
command
=
CAPI_PUT_MESSAGE
;
isdn_slot_command
(
info
->
isdn_slot
,
CAPI_PUT_MESSAGE
,
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
isdn_command
(
&
cmd
);
}
}
}
}
...
@@ -871,43 +833,26 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m)
...
@@ -871,43 +833,26 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m)
m
->
mdmreg
[
REG_SI1I
]
=
si2bit
[
si
];
m
->
mdmreg
[
REG_SI1I
]
=
si2bit
[
si
];
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
i
=
isdn_get_free_
channel
(
usg
,
l2
,
m
->
mdmreg
[
REG_L3PROT
],
-
1
,
-
1
,
m
->
msn
);
i
=
isdn_get_free_
slot
(
usg
,
l2
,
m
->
mdmreg
[
REG_L3PROT
],
-
1
,
-
1
,
m
->
msn
);
if
(
i
<
0
)
{
if
(
i
<
0
)
{
restore_flags
(
flags
);
restore_flags
(
flags
);
isdn_tty_modem_result
(
RESULT_NO_DIALTONE
,
info
);
isdn_tty_modem_result
(
RESULT_NO_DIALTONE
,
info
);
}
else
{
}
else
{
info
->
isdn_driver
=
dev
->
drvmap
[
i
];
info
->
isdn_slot
=
i
;
info
->
isdn_channel
=
dev
->
chanmap
[
i
];
isdn_slot_set_m_idx
(
i
,
info
->
line
);
info
->
drv_index
=
i
;
isdn_slot_set_usage
(
i
,
isdn_slot_usage
(
i
)
|
ISDN_USAGE_OUTGOING
);
dev
->
m_idx
[
i
]
=
info
->
line
;
dev
->
usage
[
i
]
|=
ISDN_USAGE_OUTGOING
;
info
->
last_dir
=
1
;
info
->
last_dir
=
1
;
// strcpy(info->last_num, n);
// strcpy(info->last_num, n);
isdn_info_update
();
restore_flags
(
flags
);
restore_flags
(
flags
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_CLREAZ
;
isdn_command
(
&
cmd
);
strcpy
(
cmd
.
parm
.
num
,
isdn_map_eaz2msn
(
m
->
msn
,
info
->
isdn_driver
));
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETEAZ
;
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETL2
;
info
->
last_l2
=
l2
;
info
->
last_l2
=
l2
;
cmd
.
arg
=
info
->
isdn_channel
+
(
l2
<<
8
);
cmd
.
arg
=
l2
<<
8
;
isdn_command
(
&
cmd
);
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_SETL2
,
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
m
->
mdmreg
[
REG_L3PROT
]
<<
8
;
cmd
.
command
=
ISDN_CMD_SETL3
;
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_SETL3
,
&
cmd
);
cmd
.
arg
=
info
->
isdn_channel
+
(
m
->
mdmreg
[
REG_L3PROT
]
<<
8
);
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
parm
.
cmsg
.
Length
=
l
+
18
;
cmd
.
parm
.
cmsg
.
Length
=
l
+
18
;
cmd
.
parm
.
cmsg
.
Command
=
CAPI_FACILITY
;
cmd
.
parm
.
cmsg
.
Command
=
CAPI_FACILITY
;
cmd
.
parm
.
cmsg
.
Subcommand
=
CAPI_REQ
;
cmd
.
parm
.
cmsg
.
Subcommand
=
CAPI_REQ
;
cmd
.
parm
.
cmsg
.
adr
.
Controller
=
i
nfo
->
isdn_driver
+
1
;
cmd
.
parm
.
cmsg
.
adr
.
Controller
=
i
sdn_slot_driver
(
info
->
isdn_slot
)
+
1
;
cmd
.
parm
.
cmsg
.
para
[
0
]
=
3
;
/* 16 bit 0x0003 suplementary service */
cmd
.
parm
.
cmsg
.
para
[
0
]
=
3
;
/* 16 bit 0x0003 suplementary service */
cmd
.
parm
.
cmsg
.
para
[
1
]
=
0
;
cmd
.
parm
.
cmsg
.
para
[
1
]
=
0
;
cmd
.
parm
.
cmsg
.
para
[
2
]
=
l
+
3
;
cmd
.
parm
.
cmsg
.
para
[
2
]
=
l
+
3
;
...
@@ -915,11 +860,10 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m)
...
@@ -915,11 +860,10 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m)
cmd
.
parm
.
cmsg
.
para
[
4
]
=
0
;
cmd
.
parm
.
cmsg
.
para
[
4
]
=
0
;
cmd
.
parm
.
cmsg
.
para
[
5
]
=
l
;
cmd
.
parm
.
cmsg
.
para
[
5
]
=
l
;
strncpy
(
&
cmd
.
parm
.
cmsg
.
para
[
6
],
id
,
l
);
strncpy
(
&
cmd
.
parm
.
cmsg
.
para
[
6
],
id
,
l
);
cmd
.
command
=
CAPI_PUT_MESSAGE
;
info
->
dialing
=
1
;
info
->
dialing
=
1
;
// strcpy(dev->num[i], n);
// strcpy(dev->num[i], n);
isdn_info_update
();
isdn_info_update
();
isdn_
command
(
&
cmd
);
isdn_
slot_command
(
info
->
isdn_slot
,
CAPI_PUT_MESSAGE
,
&
cmd
);
isdn_timer_ctrl
(
ISDN_TIMER_CARRIER
,
1
);
isdn_timer_ctrl
(
ISDN_TIMER_CARRIER
,
1
);
}
}
}
}
...
@@ -965,51 +909,33 @@ isdn_tty_send_msg(modem_info * info, atemu * m, char *msg)
...
@@ -965,51 +909,33 @@ isdn_tty_send_msg(modem_info * info, atemu * m, char *msg)
m
->
mdmreg
[
REG_SI1I
]
=
si2bit
[
si
];
m
->
mdmreg
[
REG_SI1I
]
=
si2bit
[
si
];
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
i
=
isdn_get_free_
channel
(
usg
,
l2
,
m
->
mdmreg
[
REG_L3PROT
],
-
1
,
-
1
,
m
->
msn
);
i
=
isdn_get_free_
slot
(
usg
,
l2
,
m
->
mdmreg
[
REG_L3PROT
],
-
1
,
-
1
,
m
->
msn
);
if
(
i
<
0
)
{
if
(
i
<
0
)
{
restore_flags
(
flags
);
restore_flags
(
flags
);
isdn_tty_modem_result
(
RESULT_NO_DIALTONE
,
info
);
isdn_tty_modem_result
(
RESULT_NO_DIALTONE
,
info
);
}
else
{
}
else
{
info
->
isdn_driver
=
dev
->
drvmap
[
i
];
info
->
isdn_slot
=
i
;
info
->
isdn_channel
=
dev
->
chanmap
[
i
];
isdn_slot_set_m_idx
(
i
,
info
->
line
);
info
->
drv_index
=
i
;
isdn_slot_set_usage
(
i
,
isdn_slot_usage
(
i
)
|
ISDN_USAGE_OUTGOING
);
dev
->
m_idx
[
i
]
=
info
->
line
;
dev
->
usage
[
i
]
|=
ISDN_USAGE_OUTGOING
;
info
->
last_dir
=
1
;
info
->
last_dir
=
1
;
isdn_info_update
();
restore_flags
(
flags
);
restore_flags
(
flags
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_CLREAZ
;
isdn_command
(
&
cmd
);
strcpy
(
cmd
.
parm
.
num
,
isdn_map_eaz2msn
(
m
->
msn
,
info
->
isdn_driver
));
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETEAZ
;
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
command
=
ISDN_CMD_SETL2
;
info
->
last_l2
=
l2
;
info
->
last_l2
=
l2
;
cmd
.
arg
=
info
->
isdn_channel
+
(
l2
<<
8
);
cmd
.
arg
=
l2
<<
8
;
isdn_command
(
&
cmd
);
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_SETL2
,
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
m
->
mdmreg
[
REG_L3PROT
]
<<
8
;
cmd
.
command
=
ISDN_CMD_SETL3
;
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_SETL3
,
&
cmd
);
cmd
.
arg
=
info
->
isdn_channel
+
(
m
->
mdmreg
[
REG_L3PROT
]
<<
8
);
isdn_command
(
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
parm
.
cmsg
.
Length
=
l
+
14
;
cmd
.
parm
.
cmsg
.
Length
=
l
+
14
;
cmd
.
parm
.
cmsg
.
Command
=
CAPI_MANUFACTURER
;
cmd
.
parm
.
cmsg
.
Command
=
CAPI_MANUFACTURER
;
cmd
.
parm
.
cmsg
.
Subcommand
=
CAPI_REQ
;
cmd
.
parm
.
cmsg
.
Subcommand
=
CAPI_REQ
;
cmd
.
parm
.
cmsg
.
adr
.
Controller
=
i
nfo
->
isdn_driver
+
1
;
cmd
.
parm
.
cmsg
.
adr
.
Controller
=
i
sdn_slot_driver
(
info
->
isdn_slot
)
+
1
;
cmd
.
parm
.
cmsg
.
para
[
0
]
=
l
+
1
;
cmd
.
parm
.
cmsg
.
para
[
0
]
=
l
+
1
;
strncpy
(
&
cmd
.
parm
.
cmsg
.
para
[
1
],
msg
,
l
);
strncpy
(
&
cmd
.
parm
.
cmsg
.
para
[
1
],
msg
,
l
);
cmd
.
parm
.
cmsg
.
para
[
l
+
1
]
=
0xd
;
cmd
.
parm
.
cmsg
.
para
[
l
+
1
]
=
0xd
;
cmd
.
command
=
CAPI_PUT_MESSAGE
;
/* info->dialing = 1;
/* info->dialing = 1;
strcpy(dev->num[i], n);
strcpy(dev->num[i], n);
isdn_info_update();
isdn_info_update();
*/
*/
isdn_
command
(
&
cmd
);
isdn_
slot_command
(
info
->
isdn_slot
,
CAPI_PUT_MESSAGE
,
&
cmd
);
}
}
}
}
...
@@ -1173,6 +1099,7 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
...
@@ -1173,6 +1099,7 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
{
{
int
c
;
int
c
;
int
total
=
0
;
int
total
=
0
;
int
di
;
modem_info
*
info
=
(
modem_info
*
)
tty
->
driver_data
;
modem_info
*
info
=
(
modem_info
*
)
tty
->
driver_data
;
atemu
*
m
=
&
info
->
emu
;
atemu
*
m
=
&
info
->
emu
;
...
@@ -1186,8 +1113,9 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
...
@@ -1186,8 +1113,9 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
c
=
count
;
c
=
count
;
if
(
c
>
info
->
xmit_size
-
info
->
xmit_count
)
if
(
c
>
info
->
xmit_size
-
info
->
xmit_count
)
c
=
info
->
xmit_size
-
info
->
xmit_count
;
c
=
info
->
xmit_size
-
info
->
xmit_count
;
if
(
info
->
isdn_driver
>=
0
&&
c
>
dev
->
drv
[
info
->
isdn_driver
]
->
maxbufsize
)
di
=
isdn_slot_driver
(
info
->
isdn_slot
);
c
=
dev
->
drv
[
info
->
isdn_driver
]
->
maxbufsize
;
if
(
di
>=
0
&&
c
>
dev
->
drv
[
di
]
->
maxbufsize
)
c
=
dev
->
drv
[
di
]
->
maxbufsize
;
if
(
c
<=
0
)
if
(
c
<=
0
)
break
;
break
;
if
((
info
->
online
>
1
)
if
((
info
->
online
>
1
)
...
@@ -1247,12 +1175,9 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
...
@@ -1247,12 +1175,9 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
if
(
info
->
vonline
&
4
)
{
/* ETX seen */
if
(
info
->
vonline
&
4
)
{
/* ETX seen */
isdn_ctrl
c
;
isdn_ctrl
c
;
c
.
command
=
ISDN_CMD_FAXCMD
;
c
.
driver
=
info
->
isdn_driver
;
c
.
arg
=
info
->
isdn_channel
;
c
.
parm
.
aux
.
cmd
=
ISDN_FAX_CLASS1_CTRL
;
c
.
parm
.
aux
.
cmd
=
ISDN_FAX_CLASS1_CTRL
;
c
.
parm
.
aux
.
subcmd
=
ETX
;
c
.
parm
.
aux
.
subcmd
=
ETX
;
isdn_
command
(
&
c
);
isdn_
slot_command
(
info
->
isdn_slot
,
ISDN_CMD_FAXCMD
,
&
c
);
}
}
info
->
vonline
=
0
;
info
->
vonline
=
0
;
#ifdef ISDN_DEBUG_MODEM_VOICE
#ifdef ISDN_DEBUG_MODEM_VOICE
...
@@ -2015,10 +1940,10 @@ modem_write_profile(atemu * m)
...
@@ -2015,10 +1940,10 @@ modem_write_profile(atemu * m)
}
}
int
int
isdn_tty_
modem_
init
(
void
)
isdn_tty_init
(
void
)
{
{
modem
*
m
;
modem
*
m
;
int
i
;
int
i
,
retval
;
modem_info
*
info
;
modem_info
*
info
;
m
=
&
dev
->
mdm
;
m
=
&
dev
->
mdm
;
...
@@ -2063,13 +1988,15 @@ isdn_tty_modem_init(void)
...
@@ -2063,13 +1988,15 @@ isdn_tty_modem_init(void)
m
->
tty_modem
.
minor_start
=
0
;
m
->
tty_modem
.
minor_start
=
0
;
m
->
cua_modem
.
subtype
=
ISDN_SERIAL_TYPE_CALLOUT
;
m
->
cua_modem
.
subtype
=
ISDN_SERIAL_TYPE_CALLOUT
;
if
(
tty_register_driver
(
&
m
->
tty_modem
))
{
retval
=
tty_register_driver
(
&
m
->
tty_modem
);
if
(
retval
)
{
printk
(
KERN_WARNING
"isdn_tty: Couldn't register modem-device
\n
"
);
printk
(
KERN_WARNING
"isdn_tty: Couldn't register modem-device
\n
"
);
return
-
1
;
goto
err
;
}
}
if
(
tty_register_driver
(
&
m
->
cua_modem
))
{
retval
=
tty_register_driver
(
&
m
->
cua_modem
);
if
(
retval
)
{
printk
(
KERN_WARNING
"isdn_tty: Couldn't register modem-callout-device
\n
"
);
printk
(
KERN_WARNING
"isdn_tty: Couldn't register modem-callout-device
\n
"
);
return
-
2
;
goto
err_unregister_tty
;
}
}
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
info
=
&
m
->
info
[
i
];
info
=
&
m
->
info
[
i
];
...
@@ -2098,24 +2025,58 @@ isdn_tty_modem_init(void)
...
@@ -2098,24 +2025,58 @@ isdn_tty_modem_init(void)
info
->
normal_termios
=
m
->
tty_modem
.
init_termios
;
info
->
normal_termios
=
m
->
tty_modem
.
init_termios
;
init_waitqueue_head
(
&
info
->
open_wait
);
init_waitqueue_head
(
&
info
->
open_wait
);
init_waitqueue_head
(
&
info
->
close_wait
);
init_waitqueue_head
(
&
info
->
close_wait
);
info
->
isdn_driver
=
-
1
;
info
->
isdn_slot
=
-
1
;
info
->
isdn_channel
=
-
1
;
info
->
drv_index
=
-
1
;
info
->
xmit_size
=
ISDN_SERIAL_XMIT_SIZE
;
info
->
xmit_size
=
ISDN_SERIAL_XMIT_SIZE
;
skb_queue_head_init
(
&
info
->
xmit_queue
);
skb_queue_head_init
(
&
info
->
xmit_queue
);
#ifdef CONFIG_ISDN_AUDIO
#ifdef CONFIG_ISDN_AUDIO
skb_queue_head_init
(
&
info
->
dtmf_queue
);
skb_queue_head_init
(
&
info
->
dtmf_queue
);
#endif
#endif
if
(
!
(
info
->
xmit_buf
=
kmalloc
(
ISDN_SERIAL_XMIT_MAX
+
5
,
GFP_KERNEL
)))
{
info
->
xmit_buf
=
kmalloc
(
ISDN_SERIAL_XMIT_MAX
+
5
,
GFP_KERNEL
);
if
(
!
info
->
xmit_buf
)
{
printk
(
KERN_ERR
"Could not allocate modem xmit-buffer
\n
"
);
printk
(
KERN_ERR
"Could not allocate modem xmit-buffer
\n
"
);
return
-
3
;
#ifdef CONFIG_ISDN_TTY_FAX
kfree
(
info
->
fax
);
#endif
goto
err_unregister_cua
;
}
}
/* Make room for T.70 header */
/* Make room for T.70 header */
info
->
xmit_buf
+=
4
;
info
->
xmit_buf
+=
4
;
}
}
return
0
;
return
0
;
err_unregister_cua:
for
(
i
--
;
i
>=
0
;
i
--
)
{
info
=
&
m
->
info
[
i
];
#ifdef CONFIG_ISDN_TTY_FAX
kfree
(
info
->
fax
);
#endif
kfree
(
info
->
xmit_buf
-
4
);
}
tty_unregister_driver
(
&
dev
->
mdm
.
cua_modem
);
err_unregister_tty:
tty_unregister_driver
(
&
dev
->
mdm
.
tty_modem
);
err:
return
retval
;
}
}
void
isdn_tty_exit
(
void
)
{
modem
*
m
=
&
dev
->
mdm
;
modem_info
*
info
;
int
i
;
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
info
=
&
m
->
info
[
i
];
isdn_tty_cleanup_xmit
(
info
);
#ifdef CONFIG_ISDN_TTY_FAX
kfree
(
info
->
fax
);
#endif
kfree
(
info
->
xmit_buf
-
4
);
}
tty_unregister_driver
(
&
dev
->
mdm
.
cua_modem
);
tty_unregister_driver
(
&
dev
->
mdm
.
tty_modem
);
}
/*
/*
* isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx)
* isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx)
...
@@ -2227,26 +2188,21 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup)
...
@@ -2227,26 +2188,21 @@ isdn_tty_find_icall(int di, int ch, setup_parm *setup)
#ifndef FIX_FILE_TRANSFER
#ifndef FIX_FILE_TRANSFER
(
info
->
flags
&
ISDN_ASYNC_NORMAL_ACTIVE
)
&&
(
info
->
flags
&
ISDN_ASYNC_NORMAL_ACTIVE
)
&&
#endif
#endif
(
info
->
isdn_driver
==
-
1
)
&&
(
info
->
isdn_slot
==
-
1
)
&&
(
info
->
isdn_channel
==
-
1
)
&&
(
USG_NONE
(
isdn_slot_usage
(
idx
))))
{
(
USG_NONE
(
dev
->
usage
[
idx
])))
{
int
matchret
;
int
matchret
;
if
((
matchret
=
isdn_tty_match_icall
(
eaz
,
&
info
->
emu
,
di
))
>
wret
)
if
((
matchret
=
isdn_tty_match_icall
(
eaz
,
&
info
->
emu
,
di
))
>
wret
)
wret
=
matchret
;
wret
=
matchret
;
if
(
!
matchret
)
{
/* EAZ is matching */
if
(
!
matchret
)
{
/* EAZ is matching */
info
->
isdn_driver
=
di
;
info
->
isdn_slot
=
idx
;
info
->
isdn_channel
=
ch
;
isdn_slot_set_m_idx
(
idx
,
info
->
line
);
info
->
drv_index
=
idx
;
strcpy
(
isdn_slot_num
(
idx
),
nr
);
dev
->
m_idx
[
idx
]
=
info
->
line
;
dev
->
usage
[
idx
]
&=
ISDN_USAGE_EXCLUSIVE
;
dev
->
usage
[
idx
]
|=
isdn_calc_usage
(
si1
,
info
->
emu
.
mdmreg
[
REG_L2PROT
]);
strcpy
(
dev
->
num
[
idx
],
nr
);
strcpy
(
info
->
emu
.
cpn
,
eaz
);
strcpy
(
info
->
emu
.
cpn
,
eaz
);
info
->
emu
.
mdmreg
[
REG_SI1I
]
=
si2bit
[
si1
];
info
->
emu
.
mdmreg
[
REG_SI1I
]
=
si2bit
[
si1
];
info
->
emu
.
mdmreg
[
REG_PLAN
]
=
setup
->
plan
;
info
->
emu
.
mdmreg
[
REG_PLAN
]
=
setup
->
plan
;
info
->
emu
.
mdmreg
[
REG_SCREEN
]
=
setup
->
screen
;
info
->
emu
.
mdmreg
[
REG_SCREEN
]
=
setup
->
screen
;
isdn_
info_update
(
);
isdn_
slot_set_usage
(
idx
,
(
isdn_slot_usage
(
idx
)
&
ISDN_USAGE_EXCLUSIVE
)
|
isdn_calc_usage
(
si1
,
info
->
emu
.
mdmreg
[
REG_L2PROT
])
);
restore_flags
(
flags
);
restore_flags
(
flags
);
printk
(
KERN_INFO
"isdn_tty: call from %s, -> RING on ttyI%d
\n
"
,
nr
,
printk
(
KERN_INFO
"isdn_tty: call from %s, -> RING on ttyI%d
\n
"
,
nr
,
info
->
line
);
info
->
line
);
...
@@ -2276,7 +2232,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
...
@@ -2276,7 +2232,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
if
(
i
<
0
)
if
(
i
<
0
)
return
0
;
return
0
;
if
((
mi
=
dev
->
m_idx
[
i
]
)
>=
0
)
{
if
((
mi
=
isdn_slot_m_idx
(
i
)
)
>=
0
)
{
info
=
&
dev
->
mdm
.
info
[
mi
];
info
=
&
dev
->
mdm
.
info
[
mi
];
switch
(
c
->
command
)
{
switch
(
c
->
command
)
{
case
ISDN_STAT_CINF
:
case
ISDN_STAT_CINF
:
...
@@ -2290,8 +2246,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
...
@@ -2290,8 +2246,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
#ifdef ISDN_TTY_STAT_DEBUG
#ifdef ISDN_TTY_STAT_DEBUG
printk
(
KERN_DEBUG
"tty_STAT_BSENT ttyI%d
\n
"
,
info
->
line
);
printk
(
KERN_DEBUG
"tty_STAT_BSENT ttyI%d
\n
"
,
info
->
line
);
#endif
#endif
if
((
info
->
isdn_driver
==
c
->
driver
)
&&
if
((
info
->
isdn_slot
==
isdn_dc2minor
(
c
->
driver
,
c
->
arg
)))
{
(
info
->
isdn_channel
==
c
->
arg
))
{
info
->
msr
|=
UART_MSR_CTS
;
info
->
msr
|=
UART_MSR_CTS
;
if
(
info
->
send_outstanding
)
if
(
info
->
send_outstanding
)
if
(
!
(
--
info
->
send_outstanding
))
if
(
!
(
--
info
->
send_outstanding
))
...
@@ -2375,14 +2330,14 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
...
@@ -2375,14 +2330,14 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
info
->
last_dir
=
0
;
info
->
last_dir
=
0
;
info
->
dialing
=
0
;
info
->
dialing
=
0
;
info
->
rcvsched
=
1
;
info
->
rcvsched
=
1
;
if
(
USG_MODEM
(
dev
->
usage
[
i
]
))
{
if
(
USG_MODEM
(
isdn_slot_usage
(
i
)
))
{
if
(
info
->
emu
.
mdmreg
[
REG_L2PROT
]
==
ISDN_PROTO_L2_MODEM
)
{
if
(
info
->
emu
.
mdmreg
[
REG_L2PROT
]
==
ISDN_PROTO_L2_MODEM
)
{
strcpy
(
info
->
emu
.
connmsg
,
c
->
parm
.
num
);
strcpy
(
info
->
emu
.
connmsg
,
c
->
parm
.
num
);
isdn_tty_modem_result
(
RESULT_CONNECT
,
info
);
isdn_tty_modem_result
(
RESULT_CONNECT
,
info
);
}
else
}
else
isdn_tty_modem_result
(
RESULT_CONNECT64000
,
info
);
isdn_tty_modem_result
(
RESULT_CONNECT64000
,
info
);
}
}
if
(
USG_VOICE
(
dev
->
usage
[
i
]
))
if
(
USG_VOICE
(
isdn_slot_usage
(
i
)
))
isdn_tty_modem_result
(
RESULT_VCON
,
info
);
isdn_tty_modem_result
(
RESULT_VCON
,
info
);
return
1
;
return
1
;
}
}
...
@@ -2421,7 +2376,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
...
@@ -2421,7 +2376,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
#endif
#endif
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
{
info
=
&
dev
->
mdm
.
info
[
i
];
info
=
&
dev
->
mdm
.
info
[
i
];
if
(
i
nfo
->
isdn_driver
==
c
->
driver
)
{
if
(
i
sdn_slot_driver
(
info
->
isdn_slot
)
==
c
->
driver
)
{
if
(
info
->
online
)
if
(
info
->
online
)
isdn_tty_modem_hup
(
info
,
1
);
isdn_tty_modem_hup
(
info
,
1
);
}
}
...
@@ -2473,6 +2428,7 @@ isdn_tty_at_cout(char *msg, modem_info * info)
...
@@ -2473,6 +2428,7 @@ isdn_tty_at_cout(char *msg, modem_info * info)
ulong
flags
;
ulong
flags
;
struct
sk_buff
*
skb
=
0
;
struct
sk_buff
*
skb
=
0
;
char
*
sp
=
0
;
char
*
sp
=
0
;
int
di
,
ch
;
if
(
!
msg
)
{
if
(
!
msg
)
{
printk
(
KERN_WARNING
"isdn_tty: Null-Message in isdn_tty_at_cout
\n
"
);
printk
(
KERN_WARNING
"isdn_tty: Null-Message in isdn_tty_at_cout
\n
"
);
...
@@ -2488,8 +2444,9 @@ isdn_tty_at_cout(char *msg, modem_info * info)
...
@@ -2488,8 +2444,9 @@ isdn_tty_at_cout(char *msg, modem_info * info)
/* use queue instead of direct flip, if online and */
/* use queue instead of direct flip, if online and */
/* data is in queue or flip buffer is full */
/* data is in queue or flip buffer is full */
di
=
isdn_slot_driver
(
info
->
isdn_slot
);
ch
=
isdn_slot_channel
(
info
->
isdn_slot
);
if
((
info
->
online
)
&&
(((
tty
->
flip
.
count
+
strlen
(
msg
))
>=
TTY_FLIPBUF_SIZE
)
||
if
((
info
->
online
)
&&
(((
tty
->
flip
.
count
+
strlen
(
msg
))
>=
TTY_FLIPBUF_SIZE
)
||
(
!
skb_queue_empty
(
&
dev
->
drv
[
info
->
isdn_driver
]
->
rpqueue
[
info
->
isdn_channel
]))))
{
(
!
skb_queue_empty
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
]))))
{
skb
=
alloc_skb
(
strlen
(
msg
)
skb
=
alloc_skb
(
strlen
(
msg
)
#ifdef CONFIG_ISDN_AUDIO
#ifdef CONFIG_ISDN_AUDIO
+
sizeof
(
isdn_audio_skb
)
+
sizeof
(
isdn_audio_skb
)
...
@@ -2532,8 +2489,8 @@ isdn_tty_at_cout(char *msg, modem_info * info)
...
@@ -2532,8 +2489,8 @@ isdn_tty_at_cout(char *msg, modem_info * info)
}
}
}
}
if
(
skb
)
{
if
(
skb
)
{
__skb_queue_tail
(
&
dev
->
drv
[
info
->
isdn_driver
]
->
rpqueue
[
info
->
isdn_channel
],
skb
);
__skb_queue_tail
(
&
dev
->
drv
[
di
]
->
rpqueue
[
ch
],
skb
);
dev
->
drv
[
info
->
isdn_driver
]
->
rcvcount
[
info
->
isdn_channel
]
+=
skb
->
len
;
dev
->
drv
[
di
]
->
rcvcount
[
ch
]
+=
skb
->
len
;
restore_flags
(
flags
);
restore_flags
(
flags
);
/* Schedule dequeuing */
/* Schedule dequeuing */
if
((
dev
->
modempoll
)
&&
(
info
->
rcvsched
))
if
((
dev
->
modempoll
)
&&
(
info
->
rcvsched
))
...
@@ -2551,7 +2508,7 @@ isdn_tty_at_cout(char *msg, modem_info * info)
...
@@ -2551,7 +2508,7 @@ isdn_tty_at_cout(char *msg, modem_info * info)
static
void
static
void
isdn_tty_on_hook
(
modem_info
*
info
)
isdn_tty_on_hook
(
modem_info
*
info
)
{
{
if
(
info
->
isdn_
channel
>=
0
)
{
if
(
info
->
isdn_
slot
>=
0
)
{
#ifdef ISDN_DEBUG_MODEM_HUP
#ifdef ISDN_DEBUG_MODEM_HUP
printk
(
KERN_DEBUG
"Mhup in isdn_tty_on_hook
\n
"
);
printk
(
KERN_DEBUG
"Mhup in isdn_tty_on_hook
\n
"
);
#endif
#endif
...
@@ -2711,7 +2668,7 @@ isdn_tty_modem_result(int code, modem_info * info)
...
@@ -2711,7 +2668,7 @@ isdn_tty_modem_result(int code, modem_info * info)
/* print CID, _before_ _every_ ring */
/* print CID, _before_ _every_ ring */
if
(
!
(
m
->
mdmreg
[
REG_CIDONCE
]
&
BIT_CIDONCE
))
{
if
(
!
(
m
->
mdmreg
[
REG_CIDONCE
]
&
BIT_CIDONCE
))
{
isdn_tty_at_cout
(
"
\r\n
CALLER NUMBER: "
,
info
);
isdn_tty_at_cout
(
"
\r\n
CALLER NUMBER: "
,
info
);
isdn_tty_at_cout
(
dev
->
num
[
info
->
drv_index
]
,
info
);
isdn_tty_at_cout
(
isdn_slot_num
(
info
->
isdn_slot
)
,
info
);
if
(
m
->
mdmreg
[
REG_CDN
]
&
BIT_CDN
)
{
if
(
m
->
mdmreg
[
REG_CDN
]
&
BIT_CDN
)
{
isdn_tty_at_cout
(
"
\r\n
CALLED NUMBER: "
,
info
);
isdn_tty_at_cout
(
"
\r\n
CALLED NUMBER: "
,
info
);
isdn_tty_at_cout
(
info
->
emu
.
cpn
,
info
);
isdn_tty_at_cout
(
info
->
emu
.
cpn
,
info
);
...
@@ -2740,7 +2697,7 @@ isdn_tty_modem_result(int code, modem_info * info)
...
@@ -2740,7 +2697,7 @@ isdn_tty_modem_result(int code, modem_info * info)
(
m
->
mdmreg
[
REG_RINGCNT
]
==
1
))
{
(
m
->
mdmreg
[
REG_RINGCNT
]
==
1
))
{
isdn_tty_at_cout
(
"
\r\n
"
,
info
);
isdn_tty_at_cout
(
"
\r\n
"
,
info
);
isdn_tty_at_cout
(
"CALLER NUMBER: "
,
info
);
isdn_tty_at_cout
(
"CALLER NUMBER: "
,
info
);
isdn_tty_at_cout
(
dev
->
num
[
info
->
drv_index
]
,
info
);
isdn_tty_at_cout
(
isdn_slot_num
(
info
->
isdn_slot
)
,
info
);
if
(
m
->
mdmreg
[
REG_CDN
]
&
BIT_CDN
)
{
if
(
m
->
mdmreg
[
REG_CDN
]
&
BIT_CDN
)
{
isdn_tty_at_cout
(
"
\r\n
CALLED NUMBER: "
,
info
);
isdn_tty_at_cout
(
"
\r\n
CALLED NUMBER: "
,
info
);
isdn_tty_at_cout
(
info
->
emu
.
cpn
,
info
);
isdn_tty_at_cout
(
info
->
emu
.
cpn
,
info
);
...
@@ -3252,7 +3209,7 @@ isdn_tty_cmd_ATA(modem_info * info)
...
@@ -3252,7 +3209,7 @@ isdn_tty_cmd_ATA(modem_info * info)
if
(
info
->
msr
&
UART_MSR_RI
)
{
if
(
info
->
msr
&
UART_MSR_RI
)
{
/* Accept incoming call */
/* Accept incoming call */
info
->
last_dir
=
0
;
info
->
last_dir
=
0
;
strcpy
(
info
->
last_num
,
dev
->
num
[
info
->
drv_index
]
);
strcpy
(
info
->
last_num
,
isdn_slot_num
(
info
->
isdn_slot
)
);
m
->
mdmreg
[
REG_RINGCNT
]
=
0
;
m
->
mdmreg
[
REG_RINGCNT
]
=
0
;
info
->
msr
&=
~
UART_MSR_RI
;
info
->
msr
&=
~
UART_MSR_RI
;
l2
=
m
->
mdmreg
[
REG_L2PROT
];
l2
=
m
->
mdmreg
[
REG_L2PROT
];
...
@@ -3266,27 +3223,20 @@ isdn_tty_cmd_ATA(modem_info * info)
...
@@ -3266,27 +3223,20 @@ isdn_tty_cmd_ATA(modem_info * info)
l2
=
ISDN_PROTO_L2_X75I
;
l2
=
ISDN_PROTO_L2_X75I
;
}
}
#endif
#endif
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
l2
<<
8
;
cmd
.
command
=
ISDN_CMD_SETL2
;
cmd
.
arg
=
info
->
isdn_channel
+
(
l2
<<
8
);
info
->
last_l2
=
l2
;
info
->
last_l2
=
l2
;
isdn_command
(
&
cmd
);
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_SETL2
,
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
m
->
mdmreg
[
REG_L3PROT
]
<<
8
;
cmd
.
command
=
ISDN_CMD_SETL3
;
cmd
.
arg
=
info
->
isdn_channel
+
(
m
->
mdmreg
[
REG_L3PROT
]
<<
8
);
#ifdef CONFIG_ISDN_TTY_FAX
#ifdef CONFIG_ISDN_TTY_FAX
if
(
l2
==
ISDN_PROTO_L2_FAX
)
{
if
(
l2
==
ISDN_PROTO_L2_FAX
)
{
cmd
.
parm
.
fax
=
info
->
fax
;
cmd
.
parm
.
fax
=
info
->
fax
;
info
->
fax
->
direction
=
ISDN_TTY_FAX_CONN_IN
;
info
->
fax
->
direction
=
ISDN_TTY_FAX_CONN_IN
;
}
}
#endif
#endif
isdn_command
(
&
cmd
);
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_SETL3
,
&
cmd
);
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_ACCEPTD
;
info
->
dialing
=
16
;
info
->
dialing
=
16
;
info
->
emu
.
carrierwait
=
0
;
info
->
emu
.
carrierwait
=
0
;
isdn_
command
(
&
cmd
);
isdn_
slot_command
(
info
->
isdn_slot
,
ISDN_CMD_ACCEPTD
,
&
cmd
);
isdn_timer_ctrl
(
ISDN_TIMER_CARRIER
,
1
);
isdn_timer_ctrl
(
ISDN_TIMER_CARRIER
,
1
);
}
else
}
else
isdn_tty_modem_result
(
RESULT_NO_ANSWER
,
info
);
isdn_tty_modem_result
(
RESULT_NO_ANSWER
,
info
);
...
@@ -3642,12 +3592,10 @@ isdn_tty_cmd_PLUSV(char **p, modem_info * info)
...
@@ -3642,12 +3592,10 @@ isdn_tty_cmd_PLUSV(char **p, modem_info * info)
PARSE_ERROR1
;
PARSE_ERROR1
;
m
->
vpar
[
4
]
=
par1
;
m
->
vpar
[
4
]
=
par1
;
m
->
vpar
[
5
]
=
par2
;
m
->
vpar
[
5
]
=
par2
;
cmd
.
driver
=
info
->
isdn_driver
;
cmd
.
arg
=
ISDN_AUDIO_SETDD
<<
8
;
cmd
.
command
=
ISDN_CMD_AUDIO
;
cmd
.
arg
=
info
->
isdn_channel
+
(
ISDN_AUDIO_SETDD
<<
8
);
cmd
.
parm
.
num
[
0
]
=
par1
;
cmd
.
parm
.
num
[
0
]
=
par1
;
cmd
.
parm
.
num
[
1
]
=
par2
;
cmd
.
parm
.
num
[
1
]
=
par2
;
isdn_
command
(
&
cmd
);
isdn_
slot_command
(
info
->
isdn_slot
,
ISDN_CMD_AUDIO
,
&
cmd
);
break
;
break
;
}
else
}
else
if
(
*
p
[
0
]
==
'?'
)
{
if
(
*
p
[
0
]
==
'?'
)
{
...
@@ -3973,8 +3921,8 @@ isdn_tty_modem_escape(void)
...
@@ -3973,8 +3921,8 @@ isdn_tty_modem_escape(void)
int
midx
;
int
midx
;
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
for
(
i
=
0
;
i
<
ISDN_MAX_CHANNELS
;
i
++
)
if
(
USG_MODEM
(
dev
->
usage
[
i
]
))
if
(
USG_MODEM
(
isdn_slot_usage
(
i
)
))
if
((
midx
=
dev
->
m_idx
[
i
]
)
>=
0
)
{
if
((
midx
=
isdn_slot_m_idx
(
i
)
)
>=
0
)
{
modem_info
*
info
=
&
dev
->
mdm
.
info
[
midx
];
modem_info
*
info
=
&
dev
->
mdm
.
info
[
midx
];
if
(
info
->
online
)
{
if
(
info
->
online
)
{
ton
=
1
;
ton
=
1
;
...
...
drivers/isdn/i4l/isdn_tty.h
View file @
b14ebcfc
...
@@ -105,7 +105,7 @@ extern void isdn_tty_modem_escape(void);
...
@@ -105,7 +105,7 @@ extern void isdn_tty_modem_escape(void);
extern
void
isdn_tty_modem_ring
(
void
);
extern
void
isdn_tty_modem_ring
(
void
);
extern
void
isdn_tty_carrier_timeout
(
void
);
extern
void
isdn_tty_carrier_timeout
(
void
);
extern
void
isdn_tty_modem_xmit
(
void
);
extern
void
isdn_tty_modem_xmit
(
void
);
extern
int
isdn_tty_
modem_
init
(
void
);
extern
int
isdn_tty_init
(
void
);
extern
void
isdn_tty_readmodem
(
void
);
extern
void
isdn_tty_readmodem
(
void
);
extern
int
isdn_tty_find_icall
(
int
,
int
,
setup_parm
*
);
extern
int
isdn_tty_find_icall
(
int
,
int
,
setup_parm
*
);
extern
void
isdn_tty_cleanup_xmit
(
modem_info
*
);
extern
void
isdn_tty_cleanup_xmit
(
modem_info
*
);
...
@@ -119,3 +119,6 @@ extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
...
@@ -119,3 +119,6 @@ extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
extern
int
isdn_tty_fax_command
(
modem_info
*
,
isdn_ctrl
*
);
extern
int
isdn_tty_fax_command
(
modem_info
*
,
isdn_ctrl
*
);
extern
void
isdn_tty_fax_bitorder
(
modem_info
*
,
struct
sk_buff
*
);
extern
void
isdn_tty_fax_bitorder
(
modem_info
*
,
struct
sk_buff
*
);
#endif
#endif
extern
int
isdn_tty_init
(
void
);
extern
void
isdn_tty_exit
(
void
);
drivers/isdn/i4l/isdn_ttyfax.c
View file @
b14ebcfc
...
@@ -74,7 +74,7 @@ isdn_tty_fax_modem_result(int code, modem_info * info)
...
@@ -74,7 +74,7 @@ isdn_tty_fax_modem_result(int code, modem_info * info)
case
2
:
/* +FCON */
case
2
:
/* +FCON */
/* Append CPN, if enabled */
/* Append CPN, if enabled */
if
((
m
->
mdmreg
[
REG_CPNFCON
]
&
BIT_CPNFCON
)
&&
if
((
m
->
mdmreg
[
REG_CPNFCON
]
&
BIT_CPNFCON
)
&&
(
!
(
dev
->
usage
[
info
->
isdn_channel
]
&
ISDN_USAGE_OUTGOING
)))
{
(
!
(
isdn_slot_usage
(
info
->
isdn_slot
)
&
ISDN_USAGE_OUTGOING
)))
{
sprintf
(
rs
,
"/%s"
,
m
->
cpn
);
sprintf
(
rs
,
"/%s"
,
m
->
cpn
);
isdn_tty_at_cout
(
rs
,
info
);
isdn_tty_at_cout
(
rs
,
info
);
}
}
...
@@ -360,12 +360,11 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
...
@@ -360,12 +360,11 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
default:
default:
PARSE_ERROR1
;
PARSE_ERROR1
;
}
}
c
.
command
=
ISDN_CMD_FAXCMD
;
#ifdef ISDN_TTY_FAX_CMD_DEBUG
#ifdef ISDN_TTY_FAX_CMD_DEBUG
printk
(
KERN_DEBUG
"isdn_tty_cmd_FCLASS1 %d/%d/%d)
\n
"
,
printk
(
KERN_DEBUG
"isdn_tty_cmd_FCLASS1 %d/%d/%d)
\n
"
,
c
.
parm
.
aux
.
cmd
,
c
.
parm
.
aux
.
subcmd
,
c
.
parm
.
aux
.
para
[
0
]);
c
.
parm
.
aux
.
cmd
,
c
.
parm
.
aux
.
subcmd
,
c
.
parm
.
aux
.
para
[
0
]);
#endif
#endif
if
(
info
->
isdn_
driver
<
0
)
{
if
(
info
->
isdn_
slot
<
0
)
{
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
if
((
c
.
parm
.
aux
.
subcmd
==
AT_EQ_VALUE
)
||
if
((
c
.
parm
.
aux
.
subcmd
==
AT_EQ_VALUE
)
||
...
@@ -374,32 +373,21 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
...
@@ -374,32 +373,21 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
PARSE_ERROR1
;
PARSE_ERROR1
;
}
}
/* get a temporary connection to the first free fax driver */
/* get a temporary connection to the first free fax driver */
i
=
isdn_get_free_
channel
(
ISDN_USAGE_FAX
,
ISDN_PROTO_L2_FAX
,
i
=
isdn_get_free_
slot
(
ISDN_USAGE_FAX
,
ISDN_PROTO_L2_FAX
,
ISDN_PROTO_L3_FCLASS1
,
-
1
,
-
1
,
"00"
);
ISDN_PROTO_L3_FCLASS1
,
-
1
,
-
1
,
"00"
);
if
(
i
<
0
)
{
if
(
i
<
0
)
{
restore_flags
(
flags
);
restore_flags
(
flags
);
PARSE_ERROR1
;
PARSE_ERROR1
;
}
}
info
->
isdn_driver
=
dev
->
drvmap
[
i
];
info
->
isdn_slot
=
i
;
info
->
isdn_channel
=
dev
->
chanmap
[
i
];
isdn_slot_set_m_idx
(
i
,
info
->
line
);
info
->
drv_index
=
i
;
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_FAXCMD
,
&
c
);
dev
->
m_idx
[
i
]
=
info
->
line
;
isdn_slot_free
(
info
->
isdn_slot
,
ISDN_USAGE_FAX
);
c
.
driver
=
info
->
isdn_driver
;
isdn_slot_set_m_idx
(
i
,
-
1
);
c
.
arg
=
info
->
isdn_channel
;
info
->
isdn_slot
=
-
1
;
isdn_command
(
&
c
);
isdn_free_channel
(
info
->
isdn_driver
,
info
->
isdn_channel
,
ISDN_USAGE_FAX
);
info
->
isdn_driver
=
-
1
;
info
->
isdn_channel
=
-
1
;
if
(
info
->
drv_index
>=
0
)
{
dev
->
m_idx
[
info
->
drv_index
]
=
-
1
;
info
->
drv_index
=
-
1
;
}
restore_flags
(
flags
);
restore_flags
(
flags
);
}
else
{
}
else
{
c
.
driver
=
info
->
isdn_driver
;
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_FAXCMD
,
&
c
);
c
.
arg
=
info
->
isdn_channel
;
isdn_command
(
&
c
);
}
}
return
1
;
return
1
;
}
}
...
@@ -800,10 +788,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
...
@@ -800,10 +788,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
printk
(
KERN_DEBUG
"isdn_tty: Fax FDR
\n
"
);
printk
(
KERN_DEBUG
"isdn_tty: Fax FDR
\n
"
);
#endif
#endif
f
->
code
=
ISDN_TTY_FAX_DR
;
f
->
code
=
ISDN_TTY_FAX_DR
;
cmd
.
driver
=
info
->
isdn_driver
;
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_FAXCMD
,
&
cmd
);
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_FAXCMD
;
isdn_command
(
&
cmd
);
if
(
f
->
phase
==
ISDN_FAX_PHASE_B
)
{
if
(
f
->
phase
==
ISDN_FAX_PHASE_B
)
{
f
->
phase
=
ISDN_FAX_PHASE_C
;
f
->
phase
=
ISDN_FAX_PHASE_C
;
}
else
if
(
f
->
phase
==
ISDN_FAX_PHASE_D
)
{
}
else
if
(
f
->
phase
==
ISDN_FAX_PHASE_D
)
{
...
@@ -855,10 +840,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
...
@@ -855,10 +840,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
#endif
#endif
if
((
f
->
phase
==
ISDN_FAX_PHASE_B
)
||
(
f
->
phase
==
ISDN_FAX_PHASE_D
))
{
if
((
f
->
phase
==
ISDN_FAX_PHASE_B
)
||
(
f
->
phase
==
ISDN_FAX_PHASE_D
))
{
f
->
code
=
ISDN_TTY_FAX_DT
;
f
->
code
=
ISDN_TTY_FAX_DT
;
cmd
.
driver
=
info
->
isdn_driver
;
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_FAXCMD
,
&
cmd
);
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_FAXCMD
;
isdn_command
(
&
cmd
);
if
(
f
->
phase
==
ISDN_FAX_PHASE_D
)
{
if
(
f
->
phase
==
ISDN_FAX_PHASE_D
)
{
f
->
phase
=
ISDN_FAX_PHASE_C
;
f
->
phase
=
ISDN_FAX_PHASE_C
;
isdn_tty_fax_modem_result
(
7
,
info
);
/* CONNECT */
isdn_tty_fax_modem_result
(
7
,
info
);
/* CONNECT */
...
@@ -913,10 +895,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
...
@@ -913,10 +895,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
PARSE_ERROR1
;
PARSE_ERROR1
;
f
->
fet
=
par
;
f
->
fet
=
par
;
f
->
code
=
ISDN_TTY_FAX_ET
;
f
->
code
=
ISDN_TTY_FAX_ET
;
cmd
.
driver
=
info
->
isdn_driver
;
isdn_slot_command
(
info
->
isdn_slot
,
ISDN_CMD_FAXCMD
,
&
cmd
);
cmd
.
arg
=
info
->
isdn_channel
;
cmd
.
command
=
ISDN_CMD_FAXCMD
;
isdn_command
(
&
cmd
);
#ifdef ISDN_TTY_FAX_STAT_DEBUG
#ifdef ISDN_TTY_FAX_STAT_DEBUG
printk
(
KERN_DEBUG
"isdn_tty: Fax FET=%d
\n
"
,
par
);
printk
(
KERN_DEBUG
"isdn_tty: Fax FET=%d
\n
"
,
par
);
#endif
#endif
...
...
drivers/isdn/i4l/isdn_v110.c
View file @
b14ebcfc
...
@@ -515,14 +515,12 @@ isdn_v110_encode(isdn_v110_stream * v, struct sk_buff *skb)
...
@@ -515,14 +515,12 @@ isdn_v110_encode(isdn_v110_stream * v, struct sk_buff *skb)
}
}
int
int
isdn_v110_stat_callback
(
int
idx
,
isdn_ctrl
*
c
)
isdn_v110_stat_callback
(
struct
isdn_v110
*
iv110
,
isdn_ctrl
*
c
)
{
{
isdn_v110_stream
*
v
=
NULL
;
isdn_v110_stream
*
v
=
NULL
;
int
i
;
int
i
;
int
ret
;
int
ret
;
if
(
idx
<
0
)
return
0
;
switch
(
c
->
command
)
{
switch
(
c
->
command
)
{
case
ISDN_STAT_BSENT
:
case
ISDN_STAT_BSENT
:
/* Keep the send-queue of the driver filled
/* Keep the send-queue of the driver filled
...
@@ -531,9 +529,9 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
...
@@ -531,9 +529,9 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
* send down an Idle-Frame (or an Sync-Frame, if
* send down an Idle-Frame (or an Sync-Frame, if
* v->SyncInit != 0).
* v->SyncInit != 0).
*/
*/
if
(
!
(
v
=
dev
->
v110
[
idx
]
))
if
(
!
(
v
=
iv110
->
v110
))
return
0
;
return
0
;
atomic_inc
(
&
dev
->
v110use
[
idx
]
);
atomic_inc
(
&
iv110
->
v110use
);
if
(
v
->
skbidle
>
0
)
{
if
(
v
->
skbidle
>
0
)
{
v
->
skbidle
--
;
v
->
skbidle
--
;
ret
=
1
;
ret
=
1
;
...
@@ -560,38 +558,38 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
...
@@ -560,38 +558,38 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
}
else
}
else
break
;
break
;
}
}
atomic_dec
(
&
dev
->
v110use
[
idx
]
);
atomic_dec
(
&
iv110
->
v110use
);
return
ret
;
return
ret
;
case
ISDN_STAT_DHUP
:
case
ISDN_STAT_DHUP
:
case
ISDN_STAT_BHUP
:
case
ISDN_STAT_BHUP
:
while
(
1
)
{
while
(
1
)
{
atomic_inc
(
&
dev
->
v110use
[
idx
]
);
atomic_inc
(
&
iv110
->
v110use
);
if
(
atomic_dec_and_test
(
&
dev
->
v110use
[
idx
]
))
{
if
(
atomic_dec_and_test
(
&
iv110
->
v110use
))
{
isdn_v110_close
(
dev
->
v110
[
idx
]
);
isdn_v110_close
(
iv110
->
v110
);
dev
->
v110
[
idx
]
=
NULL
;
iv110
->
v110
=
NULL
;
break
;
break
;
}
}
sti
();
sti
();
}
}
break
;
break
;
case
ISDN_STAT_BCONN
:
case
ISDN_STAT_BCONN
:
if
(
dev
->
v110emu
[
idx
]
&&
(
dev
->
v110
[
idx
]
==
NULL
))
{
if
(
iv110
->
v110emu
&&
(
iv110
->
v110
==
NULL
))
{
int
hdrlen
=
dev
->
drv
[
c
->
driver
]
->
interface
->
hl_hdrlen
;
int
hdrlen
=
dev
->
drv
[
c
->
driver
]
->
interface
->
hl_hdrlen
;
int
maxsize
=
dev
->
drv
[
c
->
driver
]
->
interface
->
maxbufsize
;
int
maxsize
=
dev
->
drv
[
c
->
driver
]
->
interface
->
maxbufsize
;
atomic_inc
(
&
dev
->
v110use
[
idx
]
);
atomic_inc
(
&
iv110
->
v110use
);
switch
(
dev
->
v110emu
[
idx
]
)
{
switch
(
iv110
->
v110emu
)
{
case
ISDN_PROTO_L2_V11096
:
case
ISDN_PROTO_L2_V11096
:
dev
->
v110
[
idx
]
=
isdn_v110_open
(
V110_9600
,
hdrlen
,
maxsize
);
iv110
->
v110
=
isdn_v110_open
(
V110_9600
,
hdrlen
,
maxsize
);
break
;
break
;
case
ISDN_PROTO_L2_V11019
:
case
ISDN_PROTO_L2_V11019
:
dev
->
v110
[
idx
]
=
isdn_v110_open
(
V110_19200
,
hdrlen
,
maxsize
);
iv110
->
v110
=
isdn_v110_open
(
V110_19200
,
hdrlen
,
maxsize
);
break
;
break
;
case
ISDN_PROTO_L2_V11038
:
case
ISDN_PROTO_L2_V11038
:
dev
->
v110
[
idx
]
=
isdn_v110_open
(
V110_38400
,
hdrlen
,
maxsize
);
iv110
->
v110
=
isdn_v110_open
(
V110_38400
,
hdrlen
,
maxsize
);
break
;
break
;
default:
;
default:
;
}
}
if
((
v
=
dev
->
v110
[
idx
]
))
{
if
((
v
=
iv110
->
v110
))
{
while
(
v
->
SyncInit
)
{
while
(
v
->
SyncInit
)
{
struct
sk_buff
*
skb
=
isdn_v110_sync
(
v
);
struct
sk_buff
*
skb
=
isdn_v110_sync
(
v
);
if
(
dev
->
drv
[
c
->
driver
]
->
interface
->
writebuf_skb
(
c
->
driver
,
c
->
arg
,
1
,
skb
)
<=
0
)
{
if
(
dev
->
drv
[
c
->
driver
]
->
interface
->
writebuf_skb
(
c
->
driver
,
c
->
arg
,
1
,
skb
)
<=
0
)
{
...
@@ -603,8 +601,8 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
...
@@ -603,8 +601,8 @@ isdn_v110_stat_callback(int idx, isdn_ctrl * c)
v
->
skbidle
++
;
v
->
skbidle
++
;
}
}
}
else
}
else
printk
(
KERN_WARNING
"isdn_v110: Couldn't open stream
for chan %d
\n
"
,
idx
);
printk
(
KERN_WARNING
"isdn_v110: Couldn't open stream
\n
"
);
atomic_dec
(
&
dev
->
v110use
[
idx
]
);
atomic_dec
(
&
iv110
->
v110use
);
}
}
break
;
break
;
default:
default:
...
...
drivers/isdn/i4l/isdn_v110.h
View file @
b14ebcfc
...
@@ -9,8 +9,14 @@
...
@@ -9,8 +9,14 @@
*
*
*/
*/
#ifndef _isdn_v110_h_
#ifndef ISDN_V110_H
#define _isdn_v110_h_
#define ISDN_V110_H
struct
isdn_v110
{
int
v110emu
;
/* V.110 emulator-mode 0=none */
atomic_t
v110use
;
/* Usage-Semaphore for stream */
isdn_v110_stream
*
v110
;
/* V.110 private data */
};
/*
/*
* isdn_v110_encode will take raw data and encode it using V.110
* isdn_v110_encode will take raw data and encode it using V.110
...
@@ -23,7 +29,7 @@ extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *);
...
@@ -23,7 +29,7 @@ extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *);
*/
*/
extern
struct
sk_buff
*
isdn_v110_decode
(
isdn_v110_stream
*
,
struct
sk_buff
*
);
extern
struct
sk_buff
*
isdn_v110_decode
(
isdn_v110_stream
*
,
struct
sk_buff
*
);
extern
int
isdn_v110_stat_callback
(
int
,
isdn_ctrl
*
);
extern
int
isdn_v110_stat_callback
(
struct
isdn_v110
*
v110
,
isdn_ctrl
*
);
extern
void
isdn_v110_close
(
isdn_v110_stream
*
v
);
extern
void
isdn_v110_close
(
isdn_v110_stream
*
v
);
#endif
#endif
drivers/isdn/isdnloop/isdnloop.c
View file @
b14ebcfc
...
@@ -757,6 +757,10 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller)
...
@@ -757,6 +757,10 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller)
int
i
;
int
i
;
static
char
nphone
[
30
];
static
char
nphone
[
30
];
if
(
!
card
)
{
printk
(
"BUG!!!
\n
"
);
return
""
;
}
switch
(
card
->
ptype
)
{
switch
(
card
->
ptype
)
{
case
ISDN_PTYPE_EURO
:
case
ISDN_PTYPE_EURO
:
if
(
caller
)
{
if
(
caller
)
{
...
@@ -775,7 +779,7 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller)
...
@@ -775,7 +779,7 @@ isdnloop_vstphone(isdnloop_card * card, char *phone, int caller)
return
(
&
phone
[
strlen
(
phone
)
-
1
]);
return
(
&
phone
[
strlen
(
phone
)
-
1
]);
break
;
break
;
}
}
return
(
"
\0
"
)
;
return
""
;
}
}
/*
/*
...
@@ -882,7 +886,7 @@ isdnloop_parse_cmd(isdnloop_card * card)
...
@@ -882,7 +886,7 @@ isdnloop_parse_cmd(isdnloop_card * card)
isdnloop_vstphone
(
card
,
cmd
.
parm
.
setup
.
eazmsn
,
1
),
isdnloop_vstphone
(
card
,
cmd
.
parm
.
setup
.
eazmsn
,
1
),
cmd
.
parm
.
setup
.
si1
,
cmd
.
parm
.
setup
.
si1
,
cmd
.
parm
.
setup
.
si2
,
cmd
.
parm
.
setup
.
si2
,
isdnloop_vstphone
(
card
->
rcard
[
ch
],
isdnloop_vstphone
(
card
->
rcard
[
ch
-
1
],
cmd
.
parm
.
setup
.
phone
,
0
));
cmd
.
parm
.
setup
.
phone
,
0
));
isdnloop_fake
(
card
->
rcard
[
ch
-
1
],
buf
,
card
->
rch
[
ch
-
1
]
+
1
);
isdnloop_fake
(
card
->
rcard
[
ch
-
1
],
buf
,
card
->
rch
[
ch
-
1
]
+
1
);
/* Fall through */
/* Fall through */
...
...
fs/ntfs/ChangeLog
View file @
b14ebcfc
...
@@ -2,6 +2,36 @@ ToDo:
...
@@ -2,6 +2,36 @@ ToDo:
- Find and fix bugs.
- Find and fix bugs.
- Enable NFS exporting of NTFS.
- Enable NFS exporting of NTFS.
2.0.24 - Cleanups.
- Treat BUG_ON() as ASSERT() not VERIFY(), i.e. do not use side effects
inside BUG_ON(). (Adam J. Richter)
- Split logical OR expressions inside BUG_ON() into individual BUG_ON()
calls for improved debugging. (Adam J. Richter)
- Add errors flag to the ntfs volume state, accessed via
NVol{,Set,Clear}Errors(vol).
- Do not allow read-write remounts of read-only volumes with errors.
- Clarify comment for ntfs file operation sendfile which was added by
Christoph Hellwig a while ago (just using generic_file_sendfile())
to say that ntfs ->sendfile is only used for the case where the
source data is on the ntfs partition and the destination is
somewhere else, i.e. nothing we need to concern ourselves with.
- Add generic_file_write() as our ntfs file write operation.
2.0.23 - Major bug fixes (races, deadlocks, non-i386 architectures).
- Massive internal locking changes to mft record locking. Fixes lock
recursion and replaces the mrec_lock read/write semaphore with a
mutex. Also removes the now superfluous mft_count. This fixes several
race conditions and deadlocks, especially in the future write code.
- Fix ntfs over loopback for compressed files by adding an
optimization barrier. (gcc was screwing up otherwise ?)
- Miscellaneous cleanups all over the code and a fix or two in error
handling code paths.
Thanks go to Christoph Hellwig for pointing out the following two:
- Remove now unused function fs/ntfs/malloc.h::vmalloc_nofs().
- Fix ntfs_free() for ia64 and parisc by checking for VMALLOC_END, too.
2.0.22 - Cleanups, mainly to ntfs_readdir(), and use C99 initializers.
2.0.22 - Cleanups, mainly to ntfs_readdir(), and use C99 initializers.
- Change fs/ntfs/dir.c::ntfs_reddir() to only read/write ->f_pos once
- Change fs/ntfs/dir.c::ntfs_reddir() to only read/write ->f_pos once
...
...
fs/ntfs/Makefile
View file @
b14ebcfc
...
@@ -5,7 +5,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o
...
@@ -5,7 +5,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o
ntfs-objs
:=
aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o
\
ntfs-objs
:=
aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o
\
mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o
mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.0.2
2
\"
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.0.2
4
\"
ifeq
($(CONFIG_NTFS_DEBUG),y)
ifeq
($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS
+=
-DDEBUG
EXTRA_CFLAGS
+=
-DDEBUG
...
...
fs/ntfs/aops.c
View file @
b14ebcfc
...
@@ -106,8 +106,6 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
...
@@ -106,8 +106,6 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
if
(
!
NInoMstProtected
(
ni
))
{
if
(
!
NInoMstProtected
(
ni
))
{
if
(
likely
(
page_uptodate
&&
!
PageError
(
page
)))
if
(
likely
(
page_uptodate
&&
!
PageError
(
page
)))
SetPageUptodate
(
page
);
SetPageUptodate
(
page
);
unlock_page
(
page
);
return
;
}
else
{
}
else
{
char
*
addr
;
char
*
addr
;
unsigned
int
i
,
recs
,
nr_err
;
unsigned
int
i
,
recs
,
nr_err
;
...
@@ -332,6 +330,8 @@ static int ntfs_read_block(struct page *page)
...
@@ -332,6 +330,8 @@ static int ntfs_read_block(struct page *page)
* for it to be read in before we can do the copy.
* for it to be read in before we can do the copy.
*
*
* Return 0 on success and -errno on error.
* Return 0 on success and -errno on error.
*
* WARNING: Do not make this function static! It is used by mft.c!
*/
*/
int
ntfs_readpage
(
struct
file
*
file
,
struct
page
*
page
)
int
ntfs_readpage
(
struct
file
*
file
,
struct
page
*
page
)
{
{
...
@@ -372,8 +372,8 @@ int ntfs_readpage(struct file *file, struct page *page)
...
@@ -372,8 +372,8 @@ int ntfs_readpage(struct file *file, struct page *page)
else
else
base_ni
=
ni
->
_INE
(
base_ntfs_ino
);
base_ni
=
ni
->
_INE
(
base_ntfs_ino
);
/* Map, pin and lock the mft record
for reading
. */
/* Map, pin and lock the mft record. */
mrec
=
map_mft_record
(
READ
,
base_ni
);
mrec
=
map_mft_record
(
base_ni
);
if
(
unlikely
(
IS_ERR
(
mrec
)))
{
if
(
unlikely
(
IS_ERR
(
mrec
)))
{
err
=
PTR_ERR
(
mrec
);
err
=
PTR_ERR
(
mrec
);
goto
err_out
;
goto
err_out
;
...
@@ -416,7 +416,7 @@ int ntfs_readpage(struct file *file, struct page *page)
...
@@ -416,7 +416,7 @@ int ntfs_readpage(struct file *file, struct page *page)
put_unm_err_out:
put_unm_err_out:
put_attr_search_ctx
(
ctx
);
put_attr_search_ctx
(
ctx
);
unm_err_out:
unm_err_out:
unmap_mft_record
(
READ
,
base_ni
);
unmap_mft_record
(
base_ni
);
err_out:
err_out:
unlock_page
(
page
);
unlock_page
(
page
);
return
err
;
return
err
;
...
...
fs/ntfs/attrib.c
View file @
b14ebcfc
...
@@ -110,7 +110,8 @@ static inline run_list_element *ntfs_rl_realloc(run_list_element *rl,
...
@@ -110,7 +110,8 @@ static inline run_list_element *ntfs_rl_realloc(run_list_element *rl,
static
inline
BOOL
ntfs_are_rl_mergeable
(
run_list_element
*
dst
,
static
inline
BOOL
ntfs_are_rl_mergeable
(
run_list_element
*
dst
,
run_list_element
*
src
)
run_list_element
*
src
)
{
{
BUG_ON
(
!
dst
||
!
src
);
BUG_ON
(
!
dst
);
BUG_ON
(
!
src
);
if
((
dst
->
lcn
<
0
)
||
(
src
->
lcn
<
0
))
/* Are we merging holes? */
if
((
dst
->
lcn
<
0
)
||
(
src
->
lcn
<
0
))
/* Are we merging holes? */
return
FALSE
;
return
FALSE
;
...
@@ -192,7 +193,8 @@ static inline run_list_element *ntfs_rl_append(run_list_element *dst,
...
@@ -192,7 +193,8 @@ static inline run_list_element *ntfs_rl_append(run_list_element *dst,
BOOL
right
;
BOOL
right
;
int
magic
;
int
magic
;
BUG_ON
(
!
dst
||
!
src
);
BUG_ON
(
!
dst
);
BUG_ON
(
!
src
);
/* First, check if the right hand end needs merging. */
/* First, check if the right hand end needs merging. */
right
=
ntfs_are_rl_mergeable
(
src
+
ssize
-
1
,
dst
+
loc
+
1
);
right
=
ntfs_are_rl_mergeable
(
src
+
ssize
-
1
,
dst
+
loc
+
1
);
...
@@ -258,7 +260,8 @@ static inline run_list_element *ntfs_rl_insert(run_list_element *dst,
...
@@ -258,7 +260,8 @@ static inline run_list_element *ntfs_rl_insert(run_list_element *dst,
BOOL
hole
=
FALSE
;
/* Following a hole */
BOOL
hole
=
FALSE
;
/* Following a hole */
int
magic
;
int
magic
;
BUG_ON
(
!
dst
||
!
src
);
BUG_ON
(
!
dst
);
BUG_ON
(
!
src
);
/* disc => Discontinuity between the end of @dst and the start of @src.
/* disc => Discontinuity between the end of @dst and the start of @src.
* This means we might need to insert a hole.
* This means we might need to insert a hole.
...
@@ -362,7 +365,8 @@ static inline run_list_element *ntfs_rl_replace(run_list_element *dst,
...
@@ -362,7 +365,8 @@ static inline run_list_element *ntfs_rl_replace(run_list_element *dst,
BOOL
right
;
BOOL
right
;
int
magic
;
int
magic
;
BUG_ON
(
!
dst
||
!
src
);
BUG_ON
(
!
dst
);
BUG_ON
(
!
src
);
/* First, merge the left and right ends, if necessary. */
/* First, merge the left and right ends, if necessary. */
right
=
ntfs_are_rl_mergeable
(
src
+
ssize
-
1
,
dst
+
loc
+
1
);
right
=
ntfs_are_rl_mergeable
(
src
+
ssize
-
1
,
dst
+
loc
+
1
);
...
@@ -423,7 +427,8 @@ static inline run_list_element *ntfs_rl_replace(run_list_element *dst,
...
@@ -423,7 +427,8 @@ static inline run_list_element *ntfs_rl_replace(run_list_element *dst,
static
inline
run_list_element
*
ntfs_rl_split
(
run_list_element
*
dst
,
int
dsize
,
static
inline
run_list_element
*
ntfs_rl_split
(
run_list_element
*
dst
,
int
dsize
,
run_list_element
*
src
,
int
ssize
,
int
loc
)
run_list_element
*
src
,
int
ssize
,
int
loc
)
{
{
BUG_ON
(
!
dst
||
!
src
);
BUG_ON
(
!
dst
);
BUG_ON
(
!
src
);
/* Space required: @dst size + @src size + one new hole. */
/* Space required: @dst size + @src size + one new hole. */
dst
=
ntfs_rl_realloc
(
dst
,
dsize
,
dsize
+
ssize
+
1
);
dst
=
ntfs_rl_realloc
(
dst
,
dsize
,
dsize
+
ssize
+
1
);
...
@@ -948,7 +953,7 @@ int map_run_list(ntfs_inode *ni, VCN vcn)
...
@@ -948,7 +953,7 @@ int map_run_list(ntfs_inode *ni, VCN vcn)
else
else
base_ni
=
ni
->
_INE
(
base_ntfs_ino
);
base_ni
=
ni
->
_INE
(
base_ntfs_ino
);
mrec
=
map_mft_record
(
READ
,
base_ni
);
mrec
=
map_mft_record
(
base_ni
);
if
(
IS_ERR
(
mrec
))
if
(
IS_ERR
(
mrec
))
return
PTR_ERR
(
mrec
);
return
PTR_ERR
(
mrec
);
ctx
=
get_attr_search_ctx
(
base_ni
,
mrec
);
ctx
=
get_attr_search_ctx
(
base_ni
,
mrec
);
...
@@ -979,7 +984,7 @@ int map_run_list(ntfs_inode *ni, VCN vcn)
...
@@ -979,7 +984,7 @@ int map_run_list(ntfs_inode *ni, VCN vcn)
put_attr_search_ctx
(
ctx
);
put_attr_search_ctx
(
ctx
);
err_out:
err_out:
unmap_mft_record
(
READ
,
base_ni
);
unmap_mft_record
(
base_ni
);
return
err
;
return
err
;
}
}
...
@@ -1671,7 +1676,7 @@ void reinit_attr_search_ctx(attr_search_context *ctx)
...
@@ -1671,7 +1676,7 @@ void reinit_attr_search_ctx(attr_search_context *ctx)
return
;
return
;
}
/* Attribute list. */
}
/* Attribute list. */
if
(
ctx
->
ntfs_ino
!=
ctx
->
base_ntfs_ino
)
if
(
ctx
->
ntfs_ino
!=
ctx
->
base_ntfs_ino
)
unmap_mft_record
(
READ
,
ctx
->
ntfs_ino
);
unmap_mft_record
(
ctx
->
ntfs_ino
);
init_attr_search_ctx
(
ctx
,
ctx
->
base_ntfs_ino
,
ctx
->
base_mrec
);
init_attr_search_ctx
(
ctx
,
ctx
->
base_ntfs_ino
,
ctx
->
base_mrec
);
return
;
return
;
}
}
...
@@ -1704,7 +1709,7 @@ attr_search_context *get_attr_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
...
@@ -1704,7 +1709,7 @@ attr_search_context *get_attr_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
void
put_attr_search_ctx
(
attr_search_context
*
ctx
)
void
put_attr_search_ctx
(
attr_search_context
*
ctx
)
{
{
if
(
ctx
->
base_ntfs_ino
&&
ctx
->
ntfs_ino
!=
ctx
->
base_ntfs_ino
)
if
(
ctx
->
base_ntfs_ino
&&
ctx
->
ntfs_ino
!=
ctx
->
base_ntfs_ino
)
unmap_mft_record
(
READ
,
ctx
->
ntfs_ino
);
unmap_mft_record
(
ctx
->
ntfs_ino
);
kmem_cache_free
(
ntfs_attr_ctx_cache
,
ctx
);
kmem_cache_free
(
ntfs_attr_ctx_cache
,
ctx
);
return
;
return
;
}
}
...
...
fs/ntfs/compress.c
View file @
b14ebcfc
...
@@ -467,7 +467,8 @@ int ntfs_read_compressed_block(struct page *page)
...
@@ -467,7 +467,8 @@ int ntfs_read_compressed_block(struct page *page)
* Bad things happen if we get here for anything that is not an
* Bad things happen if we get here for anything that is not an
* unnamed $DATA attribute.
* unnamed $DATA attribute.
*/
*/
BUG_ON
(
ni
->
type
!=
AT_DATA
||
ni
->
name_len
);
BUG_ON
(
ni
->
type
!=
AT_DATA
);
BUG_ON
(
ni
->
name_len
);
pages
=
kmalloc
(
nr_pages
*
sizeof
(
struct
page
*
),
GFP_NOFS
);
pages
=
kmalloc
(
nr_pages
*
sizeof
(
struct
page
*
),
GFP_NOFS
);
...
@@ -608,8 +609,27 @@ int ntfs_read_compressed_block(struct page *page)
...
@@ -608,8 +609,27 @@ int ntfs_read_compressed_block(struct page *page)
if
(
buffer_uptodate
(
tbh
))
if
(
buffer_uptodate
(
tbh
))
continue
;
continue
;
wait_on_buffer
(
tbh
);
wait_on_buffer
(
tbh
);
if
(
unlikely
(
!
buffer_uptodate
(
tbh
)))
/*
goto
read_err
;
* We need an optimization barrier here, otherwise we start
* hitting the below fixup code when accessing a loopback
* mounted ntfs partition. This indicates either there is a
* race condition in the loop driver or, more likely, gcc
* overoptimises the code without the barrier and it doesn't
* do the Right Thing(TM).
*/
barrier
();
if
(
unlikely
(
!
buffer_uptodate
(
tbh
)))
{
ntfs_warning
(
vol
->
sb
,
"Buffer is unlocked but not "
"uptodate! Unplugging the disk queue "
"and rescheduling."
);
get_bh
(
tbh
);
blk_run_queues
();
schedule
();
put_bh
(
tbh
);
if
(
unlikely
(
!
buffer_uptodate
(
tbh
)))
goto
read_err
;
ntfs_warning
(
vol
->
sb
,
"Buffer is now uptodate. Good."
);
}
}
}
/*
/*
...
...
fs/ntfs/dir.c
View file @
b14ebcfc
...
@@ -76,7 +76,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -76,7 +76,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
u8
*
index_end
;
u8
*
index_end
;
u64
mref
;
u64
mref
;
attr_search_context
*
ctx
;
attr_search_context
*
ctx
;
int
err
=
0
,
rc
;
int
err
,
rc
;
VCN
vcn
,
old_vcn
;
VCN
vcn
,
old_vcn
;
struct
address_space
*
ia_mapping
;
struct
address_space
*
ia_mapping
;
struct
page
*
page
;
struct
page
*
page
;
...
@@ -84,23 +84,24 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -84,23 +84,24 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
ntfs_name
*
name
=
NULL
;
ntfs_name
*
name
=
NULL
;
/* Get hold of the mft record for the directory. */
/* Get hold of the mft record for the directory. */
m
=
map_mft_record
(
READ
,
dir_ni
);
m
=
map_mft_record
(
dir_ni
);
if
(
IS_ERR
(
m
))
if
(
unlikely
(
IS_ERR
(
m
)))
{
goto
map_err_out
;
ntfs_error
(
sb
,
"map_mft_record() failed with error code %ld."
,
-
PTR_ERR
(
m
));
return
ERR_MREF
(
PTR_ERR
(
m
));
}
ctx
=
get_attr_search_ctx
(
dir_ni
,
m
);
ctx
=
get_attr_search_ctx
(
dir_ni
,
m
);
if
(
!
ctx
)
{
if
(
unlikely
(
!
ctx
)
)
{
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
unm_
err_out
;
goto
err_out
;
}
}
/* Find the index root attribute in the mft record. */
/* Find the index root attribute in the mft record. */
if
(
!
lookup_attr
(
AT_INDEX_ROOT
,
I30
,
4
,
CASE_SENSITIVE
,
0
,
NULL
,
0
,
if
(
!
lookup_attr
(
AT_INDEX_ROOT
,
I30
,
4
,
CASE_SENSITIVE
,
0
,
NULL
,
0
,
ctx
))
{
ctx
))
{
ntfs_error
(
sb
,
"Index root attribute missing in directory "
ntfs_error
(
sb
,
"Index root attribute missing in directory "
"inode 0x%lx."
,
dir_ni
->
mft_no
);
"inode 0x%lx."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
err
=
-
EIO
;
goto
put_unm_
err_out
;
goto
err_out
;
}
}
/* Get to the index root value (it's been verified in read_inode). */
/* Get to the index root value (it's been verified in read_inode). */
ir
=
(
INDEX_ROOT
*
)((
u8
*
)
ctx
->
attr
+
ir
=
(
INDEX_ROOT
*
)((
u8
*
)
ctx
->
attr
+
...
@@ -154,7 +155,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -154,7 +155,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
GFP_NOFS
);
GFP_NOFS
);
if
(
!
name
)
{
if
(
!
name
)
{
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
put_unm_
err_out
;
goto
err_out
;
}
}
}
}
name
->
mref
=
le64_to_cpu
(
name
->
mref
=
le64_to_cpu
(
...
@@ -169,7 +170,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -169,7 +170,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
}
}
mref
=
le64_to_cpu
(
ie
->
_IIF
(
indexed_file
));
mref
=
le64_to_cpu
(
ie
->
_IIF
(
indexed_file
));
put_attr_search_ctx
(
ctx
);
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
dir_ni
);
unmap_mft_record
(
dir_ni
);
return
mref
;
return
mref
;
}
}
/*
/*
...
@@ -208,7 +209,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -208,7 +209,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
name
=
kmalloc
(
name_size
,
GFP_NOFS
);
name
=
kmalloc
(
name_size
,
GFP_NOFS
);
if
(
!
name
)
{
if
(
!
name
)
{
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
put_unm_
err_out
;
goto
err_out
;
}
}
name
->
mref
=
le64_to_cpu
(
ie
->
_IIF
(
indexed_file
));
name
->
mref
=
le64_to_cpu
(
ie
->
_IIF
(
indexed_file
));
name
->
type
=
type
;
name
->
type
=
type
;
...
@@ -267,12 +268,12 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -267,12 +268,12 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
if
(
!
(
ie
->
_IEH
(
flags
)
&
INDEX_ENTRY_NODE
))
{
if
(
!
(
ie
->
_IEH
(
flags
)
&
INDEX_ENTRY_NODE
))
{
if
(
name
)
{
if
(
name
)
{
put_attr_search_ctx
(
ctx
);
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
dir_ni
);
unmap_mft_record
(
dir_ni
);
return
name
->
mref
;
return
name
->
mref
;
}
}
ntfs_debug
(
"Entry not found."
);
ntfs_debug
(
"Entry not found."
);
err
=
-
ENOENT
;
err
=
-
ENOENT
;
goto
put_unm_
err_out
;
goto
err_out
;
}
/* Child node present, descend into it. */
}
/* Child node present, descend into it. */
/* Consistency check: Verify that an index allocation exists. */
/* Consistency check: Verify that an index allocation exists. */
if
(
!
NInoIndexAllocPresent
(
dir_ni
))
{
if
(
!
NInoIndexAllocPresent
(
dir_ni
))
{
...
@@ -280,11 +281,19 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -280,11 +281,19 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"requires one. Directory inode 0x%lx is "
"requires one. Directory inode 0x%lx is "
"corrupt or driver bug."
,
dir_ni
->
mft_no
);
"corrupt or driver bug."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
err
=
-
EIO
;
goto
put_unm_
err_out
;
goto
err_out
;
}
}
/* Get the starting vcn of the index_block holding the child node. */
/* Get the starting vcn of the index_block holding the child node. */
vcn
=
sle64_to_cpup
((
u8
*
)
ie
+
le16_to_cpu
(
ie
->
_IEH
(
length
))
-
8
);
vcn
=
sle64_to_cpup
((
u8
*
)
ie
+
le16_to_cpu
(
ie
->
_IEH
(
length
))
-
8
);
ia_mapping
=
VFS_I
(
dir_ni
)
->
i_mapping
;
ia_mapping
=
VFS_I
(
dir_ni
)
->
i_mapping
;
/*
* We are done with the index root and the mft record. Release them,
* otherwise we deadlock with ntfs_map_page().
*/
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
dir_ni
);
m
=
NULL
;
ctx
=
NULL
;
descend_into_child_node:
descend_into_child_node:
/*
/*
* Convert vcn to index into the index allocation attribute in units
* Convert vcn to index into the index allocation attribute in units
...
@@ -296,7 +305,8 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -296,7 +305,8 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
if
(
IS_ERR
(
page
))
{
if
(
IS_ERR
(
page
))
{
ntfs_error
(
sb
,
"Failed to map directory index page, error %ld."
,
ntfs_error
(
sb
,
"Failed to map directory index page, error %ld."
,
-
PTR_ERR
(
page
));
-
PTR_ERR
(
page
));
goto
put_unm_err_out
;
err
=
PTR_ERR
(
page
);
goto
err_out
;
}
}
kaddr
=
(
u8
*
)
page_address
(
page
);
kaddr
=
(
u8
*
)
page_address
(
page
);
fast_descend_into_child_node:
fast_descend_into_child_node:
...
@@ -308,7 +318,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -308,7 +318,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
ntfs_error
(
sb
,
"Out of bounds check failed. Corrupt directory "
ntfs_error
(
sb
,
"Out of bounds check failed. Corrupt directory "
"inode 0x%lx or driver bug."
,
dir_ni
->
mft_no
);
"inode 0x%lx or driver bug."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
}
if
(
sle64_to_cpu
(
ia
->
index_block_vcn
)
!=
vcn
)
{
if
(
sle64_to_cpu
(
ia
->
index_block_vcn
)
!=
vcn
)
{
ntfs_error
(
sb
,
"Actual VCN (0x%Lx) of index buffer is "
ntfs_error
(
sb
,
"Actual VCN (0x%Lx) of index buffer is "
...
@@ -318,7 +328,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -318,7 +328,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
(
long
long
)
sle64_to_cpu
(
ia
->
index_block_vcn
),
(
long
long
)
sle64_to_cpu
(
ia
->
index_block_vcn
),
(
long
long
)
vcn
,
dir_ni
->
mft_no
);
(
long
long
)
vcn
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
}
if
(
le32_to_cpu
(
ia
->
index
.
allocated_size
)
+
0x18
!=
if
(
le32_to_cpu
(
ia
->
index
.
allocated_size
)
+
0x18
!=
dir_ni
->
_IDM
(
index_block_size
))
{
dir_ni
->
_IDM
(
index_block_size
))
{
...
@@ -330,7 +340,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -330,7 +340,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
le32_to_cpu
(
ia
->
index
.
allocated_size
)
+
0x18
,
le32_to_cpu
(
ia
->
index
.
allocated_size
)
+
0x18
,
dir_ni
->
_IDM
(
index_block_size
));
dir_ni
->
_IDM
(
index_block_size
));
err
=
-
EIO
;
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
}
index_end
=
(
u8
*
)
ia
+
dir_ni
->
_IDM
(
index_block_size
);
index_end
=
(
u8
*
)
ia
+
dir_ni
->
_IDM
(
index_block_size
);
if
(
index_end
>
kaddr
+
PAGE_CACHE_SIZE
)
{
if
(
index_end
>
kaddr
+
PAGE_CACHE_SIZE
)
{
...
@@ -339,7 +349,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -339,7 +349,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"Cannot access! This is probably a bug in the "
"Cannot access! This is probably a bug in the "
"driver."
,
(
long
long
)
vcn
,
dir_ni
->
mft_no
);
"driver."
,
(
long
long
)
vcn
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
}
index_end
=
(
u8
*
)
&
ia
->
index
+
le32_to_cpu
(
ia
->
index
.
index_length
);
index_end
=
(
u8
*
)
&
ia
->
index
+
le32_to_cpu
(
ia
->
index
.
index_length
);
if
(
index_end
>
(
u8
*
)
ia
+
dir_ni
->
_IDM
(
index_block_size
))
{
if
(
index_end
>
(
u8
*
)
ia
+
dir_ni
->
_IDM
(
index_block_size
))
{
...
@@ -347,7 +357,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -347,7 +357,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"inode 0x%lx exceeds maximum size."
,
"inode 0x%lx exceeds maximum size."
,
(
long
long
)
vcn
,
dir_ni
->
mft_no
);
(
long
long
)
vcn
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
}
/* The first index entry. */
/* The first index entry. */
ie
=
(
INDEX_ENTRY
*
)((
u8
*
)
&
ia
->
index
+
ie
=
(
INDEX_ENTRY
*
)((
u8
*
)
&
ia
->
index
+
...
@@ -367,7 +377,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -367,7 +377,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"directory inode 0x%lx."
,
"directory inode 0x%lx."
,
dir_ni
->
mft_no
);
dir_ni
->
mft_no
);
err
=
-
EIO
;
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
}
/*
/*
* The last entry cannot contain a name. It can however contain
* The last entry cannot contain a name. It can however contain
...
@@ -403,7 +413,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -403,7 +413,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
GFP_NOFS
);
GFP_NOFS
);
if
(
!
name
)
{
if
(
!
name
)
{
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
}
}
}
name
->
mref
=
le64_to_cpu
(
name
->
mref
=
le64_to_cpu
(
...
@@ -418,8 +428,6 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -418,8 +428,6 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
}
}
mref
=
le64_to_cpu
(
ie
->
_IIF
(
indexed_file
));
mref
=
le64_to_cpu
(
ie
->
_IIF
(
indexed_file
));
ntfs_unmap_page
(
page
);
ntfs_unmap_page
(
page
);
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
dir_ni
);
return
mref
;
return
mref
;
}
}
/*
/*
...
@@ -459,7 +467,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -459,7 +467,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
name
=
kmalloc
(
name_size
,
GFP_NOFS
);
name
=
kmalloc
(
name_size
,
GFP_NOFS
);
if
(
!
name
)
{
if
(
!
name
)
{
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
put_
unm_err_out
;
goto
unm_err_out
;
}
}
name
->
mref
=
le64_to_cpu
(
ie
->
_IIF
(
indexed_file
));
name
->
mref
=
le64_to_cpu
(
ie
->
_IIF
(
indexed_file
));
name
->
type
=
type
;
name
->
type
=
type
;
...
@@ -519,7 +527,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -519,7 +527,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"a leaf node in directory inode 0x%lx."
,
"a leaf node in directory inode 0x%lx."
,
dir_ni
->
mft_no
);
dir_ni
->
mft_no
);
err
=
-
EIO
;
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
}
/* Child node present, descend into it. */
/* Child node present, descend into it. */
old_vcn
=
vcn
;
old_vcn
=
vcn
;
...
@@ -539,7 +547,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -539,7 +547,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
ntfs_error
(
sb
,
"Negative child node vcn in directory inode "
ntfs_error
(
sb
,
"Negative child node vcn in directory inode "
"0x%lx."
,
dir_ni
->
mft_no
);
"0x%lx."
,
dir_ni
->
mft_no
);
err
=
-
EIO
;
err
=
-
EIO
;
goto
unm_
unm_
err_out
;
goto
unm_err_out
;
}
}
/*
/*
* No child node present, return -ENOENT, unless we have got a matching
* No child node present, return -ENOENT, unless we have got a matching
...
@@ -548,31 +556,26 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -548,31 +556,26 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
*/
*/
if
(
name
)
{
if
(
name
)
{
ntfs_unmap_page
(
page
);
ntfs_unmap_page
(
page
);
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
dir_ni
);
return
name
->
mref
;
return
name
->
mref
;
}
}
ntfs_debug
(
"Entry not found."
);
ntfs_debug
(
"Entry not found."
);
err
=
-
ENOENT
;
err
=
-
ENOENT
;
unm_unm_err_out:
ntfs_unmap_page
(
page
);
put_unm_err_out:
put_attr_search_ctx
(
ctx
);
unm_err_out:
unm_err_out:
unmap_mft_record
(
READ
,
dir_ni
);
ntfs_unmap_page
(
page
);
err_out:
if
(
ctx
)
put_attr_search_ctx
(
ctx
);
if
(
m
)
unmap_mft_record
(
dir_ni
);
if
(
name
)
{
if
(
name
)
{
kfree
(
name
);
kfree
(
name
);
*
res
=
NULL
;
*
res
=
NULL
;
}
}
return
ERR_MREF
(
err
);
return
ERR_MREF
(
err
);
map_err_out:
ntfs_error
(
sb
,
"map_mft_record(READ) failed with error code %ld."
,
-
PTR_ERR
(
m
));
return
ERR_MREF
(
PTR_ERR
(
m
));
dir_err_out:
dir_err_out:
ntfs_error
(
sb
,
"Corrupt directory. Aborting lookup."
);
ntfs_error
(
sb
,
"Corrupt directory. Aborting lookup."
);
err
=
-
EIO
;
err
=
-
EIO
;
goto
put_unm_
err_out
;
goto
err_out
;
}
}
#if 0
#if 0
...
@@ -614,7 +617,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -614,7 +617,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
u8 *index_end;
u8 *index_end;
u64 mref;
u64 mref;
attr_search_context *ctx;
attr_search_context *ctx;
int err
= 0
, rc;
int err, rc;
IGNORE_CASE_BOOL ic;
IGNORE_CASE_BOOL ic;
VCN vcn, old_vcn;
VCN vcn, old_vcn;
struct address_space *ia_mapping;
struct address_space *ia_mapping;
...
@@ -622,23 +625,24 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -622,23 +625,24 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
u8 *kaddr;
u8 *kaddr;
/* Get hold of the mft record for the directory. */
/* Get hold of the mft record for the directory. */
m = map_mft_record(READ, dir_ni);
m = map_mft_record(dir_ni);
if (IS_ERR(m))
if (IS_ERR(m)) {
goto map_err_out;
ntfs_error(sb, "map_mft_record() failed with error code %ld.",
-PTR_ERR(m));
return ERR_MREF(PTR_ERR(m));
}
ctx = get_attr_search_ctx(dir_ni, m);
ctx = get_attr_search_ctx(dir_ni, m);
if (!ctx) {
if (!ctx) {
err = -ENOMEM;
err = -ENOMEM;
goto
unm_
err_out;
goto err_out;
}
}
/* Find the index root attribute in the mft record. */
/* Find the index root attribute in the mft record. */
if (!lookup_attr(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, 0,
if (!lookup_attr(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, 0,
ctx)) {
ctx)) {
ntfs_error(sb, "Index root attribute missing in directory "
ntfs_error(sb, "Index root attribute missing in directory "
"inode 0x%lx.", dir_ni->mft_no);
"inode 0x%lx.", dir_ni->mft_no);
err = -EIO;
err = -EIO;
goto
put_unm_
err_out;
goto err_out;
}
}
/* Get to the index root value (it's been verified in read_inode). */
/* Get to the index root value (it's been verified in read_inode). */
ir = (INDEX_ROOT*)((u8*)ctx->attr +
ir = (INDEX_ROOT*)((u8*)ctx->attr +
...
@@ -689,7 +693,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -689,7 +693,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
found_it:
found_it:
mref = le64_to_cpu(ie->_IIF(indexed_file));
mref = le64_to_cpu(ie->_IIF(indexed_file));
put_attr_search_ctx(ctx);
put_attr_search_ctx(ctx);
unmap_mft_record(
READ,
dir_ni);
unmap_mft_record(dir_ni);
return mref;
return mref;
}
}
/*
/*
...
@@ -737,7 +741,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -737,7 +741,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
if (!(ie->_IEH(flags) & INDEX_ENTRY_NODE)) {
if (!(ie->_IEH(flags) & INDEX_ENTRY_NODE)) {
/* No child node, return -ENOENT. */
/* No child node, return -ENOENT. */
err = -ENOENT;
err = -ENOENT;
goto
put_unm_
err_out;
goto err_out;
} /* Child node present, descend into it. */
} /* Child node present, descend into it. */
/* Consistency check: Verify that an index allocation exists. */
/* Consistency check: Verify that an index allocation exists. */
if (!NInoIndexAllocPresent(dir_ni)) {
if (!NInoIndexAllocPresent(dir_ni)) {
...
@@ -745,11 +749,19 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -745,11 +749,19 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"requires one. Directory inode 0x%lx is "
"requires one. Directory inode 0x%lx is "
"corrupt or driver bug.", dir_ni->mft_no);
"corrupt or driver bug.", dir_ni->mft_no);
err = -EIO;
err = -EIO;
goto
put_unm_
err_out;
goto err_out;
}
}
/* Get the starting vcn of the index_block holding the child node. */
/* Get the starting vcn of the index_block holding the child node. */
vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->_IEH(length)) - 8);
vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->_IEH(length)) - 8);
ia_mapping = VFS_I(dir_ni)->i_mapping;
ia_mapping = VFS_I(dir_ni)->i_mapping;
/*
* We are done with the index root and the mft record. Release them,
* otherwise we deadlock with ntfs_map_page().
*/
put_attr_search_ctx(ctx);
unmap_mft_record(dir_ni);
m = NULL;
ctx = NULL;
descend_into_child_node:
descend_into_child_node:
/*
/*
* Convert vcn to index into the index allocation attribute in units
* Convert vcn to index into the index allocation attribute in units
...
@@ -761,7 +773,8 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -761,7 +773,8 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
if (IS_ERR(page)) {
if (IS_ERR(page)) {
ntfs_error(sb, "Failed to map directory index page, error %ld.",
ntfs_error(sb, "Failed to map directory index page, error %ld.",
-PTR_ERR(page));
-PTR_ERR(page));
goto put_unm_err_out;
err = PTR_ERR(page);
goto err_out;
}
}
kaddr = (u8*)page_address(page);
kaddr = (u8*)page_address(page);
fast_descend_into_child_node:
fast_descend_into_child_node:
...
@@ -773,7 +786,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -773,7 +786,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
ntfs_error(sb, "Out of bounds check failed. Corrupt directory "
ntfs_error(sb, "Out of bounds check failed. Corrupt directory "
"inode 0x%lx or driver bug.", dir_ni->mft_no);
"inode 0x%lx or driver bug.", dir_ni->mft_no);
err = -EIO;
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
}
if (sle64_to_cpu(ia->index_block_vcn) != vcn) {
if (sle64_to_cpu(ia->index_block_vcn) != vcn) {
ntfs_error(sb, "Actual VCN (0x%Lx) of index buffer is "
ntfs_error(sb, "Actual VCN (0x%Lx) of index buffer is "
...
@@ -783,7 +796,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -783,7 +796,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
(long long)sle64_to_cpu(ia->index_block_vcn),
(long long)sle64_to_cpu(ia->index_block_vcn),
(long long)vcn, dir_ni->mft_no);
(long long)vcn, dir_ni->mft_no);
err = -EIO;
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
}
if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
dir_ni->_IDM(index_block_size)) {
dir_ni->_IDM(index_block_size)) {
...
@@ -795,7 +808,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -795,7 +808,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
le32_to_cpu(ia->index.allocated_size) + 0x18,
le32_to_cpu(ia->index.allocated_size) + 0x18,
dir_ni->_IDM(index_block_size));
dir_ni->_IDM(index_block_size));
err = -EIO;
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
}
index_end = (u8*)ia + dir_ni->_IDM(index_block_size);
index_end = (u8*)ia + dir_ni->_IDM(index_block_size);
if (index_end > kaddr + PAGE_CACHE_SIZE) {
if (index_end > kaddr + PAGE_CACHE_SIZE) {
...
@@ -804,7 +817,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -804,7 +817,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"Cannot access! This is probably a bug in the "
"Cannot access! This is probably a bug in the "
"driver.", (long long)vcn, dir_ni->mft_no);
"driver.", (long long)vcn, dir_ni->mft_no);
err = -EIO;
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
}
index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
if (index_end > (u8*)ia + dir_ni->_IDM(index_block_size)) {
if (index_end > (u8*)ia + dir_ni->_IDM(index_block_size)) {
...
@@ -812,7 +825,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -812,7 +825,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"inode 0x%lx exceeds maximum size.",
"inode 0x%lx exceeds maximum size.",
(long long)vcn, dir_ni->mft_no);
(long long)vcn, dir_ni->mft_no);
err = -EIO;
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
}
/* The first index entry. */
/* The first index entry. */
ie = (INDEX_ENTRY*)((u8*)&ia->index +
ie = (INDEX_ENTRY*)((u8*)&ia->index +
...
@@ -832,7 +845,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -832,7 +845,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"directory inode 0x%lx.",
"directory inode 0x%lx.",
dir_ni->mft_no);
dir_ni->mft_no);
err = -EIO;
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
}
/*
/*
* The last entry cannot contain a name. It can however contain
* The last entry cannot contain a name. It can however contain
...
@@ -865,8 +878,6 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -865,8 +878,6 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
found_it2:
found_it2:
mref = le64_to_cpu(ie->_IIF(indexed_file));
mref = le64_to_cpu(ie->_IIF(indexed_file));
ntfs_unmap_page(page);
ntfs_unmap_page(page);
put_attr_search_ctx(ctx);
unmap_mft_record(READ, dir_ni);
return mref;
return mref;
}
}
/*
/*
...
@@ -917,7 +928,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -917,7 +928,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"a leaf node in directory inode 0x%lx.",
"a leaf node in directory inode 0x%lx.",
dir_ni->mft_no);
dir_ni->mft_no);
err = -EIO;
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
}
/* Child node present, descend into it. */
/* Child node present, descend into it. */
old_vcn = vcn;
old_vcn = vcn;
...
@@ -937,26 +948,23 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -937,26 +948,23 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
ntfs_error(sb, "Negative child node vcn in directory inode "
ntfs_error(sb, "Negative child node vcn in directory inode "
"0x%lx.", dir_ni->mft_no);
"0x%lx.", dir_ni->mft_no);
err = -EIO;
err = -EIO;
goto unm_
unm_
err_out;
goto unm_err_out;
}
}
/* No child node, return -ENOENT. */
/* No child node, return -ENOENT. */
ntfs_debug("Entry not found.");
ntfs_debug("Entry not found.");
err = -ENOENT;
err = -ENOENT;
unm_unm_err_out:
ntfs_unmap_page(page);
put_unm_err_out:
put_attr_search_ctx(ctx);
unm_err_out:
unm_err_out:
unmap_mft_record(READ, dir_ni);
ntfs_unmap_page(page);
err_out:
if (ctx)
put_attr_search_ctx(ctx);
if (m)
unmap_mft_record(dir_ni);
return ERR_MREF(err);
return ERR_MREF(err);
map_err_out:
ntfs_error(sb, "map_mft_record(READ) failed with error code %ld.",
-PTR_ERR(m));
return ERR_MREF(PTR_ERR(m));
dir_err_out:
dir_err_out:
ntfs_error(sb, "Corrupt directory. Aborting lookup.");
ntfs_error(sb, "Corrupt directory. Aborting lookup.");
err = -EIO;
err = -EIO;
goto
put_unm_
err_out;
goto err_out;
}
}
#endif
#endif
...
@@ -1095,22 +1103,8 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
...
@@ -1095,22 +1103,8 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto
done
;
goto
done
;
fpos
++
;
fpos
++
;
}
}
m
=
NULL
;
/* Get hold of the mft record for the directory. */
ctx
=
NULL
;
m
=
map_mft_record
(
READ
,
ndir
);
if
(
unlikely
(
IS_ERR
(
m
)))
{
err
=
PTR_ERR
(
m
);
m
=
NULL
;
ctx
=
NULL
;
goto
err_out
;
}
ctx
=
get_attr_search_ctx
(
ndir
,
m
);
if
(
unlikely
(
!
ctx
))
{
err
=
-
ENOMEM
;
goto
err_out
;
}
/*
/*
* Allocate a buffer to store the current name being processed
* Allocate a buffer to store the current name being processed
* converted to format determined by current NLS.
* converted to format determined by current NLS.
...
@@ -1124,6 +1118,18 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
...
@@ -1124,6 +1118,18 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* Are we jumping straight into the index allocation attribute? */
/* Are we jumping straight into the index allocation attribute? */
if
(
fpos
>=
vol
->
mft_record_size
)
if
(
fpos
>=
vol
->
mft_record_size
)
goto
skip_index_root
;
goto
skip_index_root
;
/* Get hold of the mft record for the directory. */
m
=
map_mft_record
(
ndir
);
if
(
unlikely
(
IS_ERR
(
m
)))
{
err
=
PTR_ERR
(
m
);
m
=
NULL
;
goto
err_out
;
}
ctx
=
get_attr_search_ctx
(
ndir
,
m
);
if
(
unlikely
(
!
ctx
))
{
err
=
-
ENOMEM
;
goto
err_out
;
}
/* Get the offset into the index root attribute. */
/* Get the offset into the index root attribute. */
ir_pos
=
(
s64
)
fpos
;
ir_pos
=
(
s64
)
fpos
;
/* Find the index root attribute in the mft record. */
/* Find the index root attribute in the mft record. */
...
@@ -1162,9 +1168,21 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
...
@@ -1162,9 +1168,21 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* Submit the name to the filldir callback. */
/* Submit the name to the filldir callback. */
rc
=
ntfs_filldir
(
vol
,
&
fpos
,
ndir
,
INDEX_TYPE_ROOT
,
ir
,
ie
,
rc
=
ntfs_filldir
(
vol
,
&
fpos
,
ndir
,
INDEX_TYPE_ROOT
,
ir
,
ie
,
name
,
dirent
,
filldir
);
name
,
dirent
,
filldir
);
if
(
rc
)
if
(
rc
)
{
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
ndir
);
goto
abort
;
goto
abort
;
}
}
}
/*
* We are done with the index root and the mft record for that matter.
* We need to release it, otherwise we deadlock on ntfs_attr_iget()
* and/or ntfs_read_page().
*/
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
ndir
);
m
=
NULL
;
ctx
=
NULL
;
/* If there is no index allocation attribute we are finished. */
/* If there is no index allocation attribute we are finished. */
if
(
!
NInoIndexAllocPresent
(
ndir
))
if
(
!
NInoIndexAllocPresent
(
ndir
))
goto
EOD
;
goto
EOD
;
...
@@ -1197,7 +1215,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
...
@@ -1197,7 +1215,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
}
/* Get the starting bit position in the current bitmap page. */
/* Get the starting bit position in the current bitmap page. */
cur_bmp_pos
=
bmp_pos
&
((
PAGE_CACHE_SIZE
*
8
)
-
1
);
cur_bmp_pos
=
bmp_pos
&
((
PAGE_CACHE_SIZE
*
8
)
-
1
);
bmp_pos
&=
~
((
PAGE_CACHE_SIZE
*
8
)
-
1
);
bmp_pos
&=
~
(
u64
)(
(
PAGE_CACHE_SIZE
*
8
)
-
1
);
get_next_bmp_page:
get_next_bmp_page:
ntfs_debug
(
"Reading bitmap with page index 0x%Lx, bit ofs 0x%Lx"
,
ntfs_debug
(
"Reading bitmap with page index 0x%Lx, bit ofs 0x%Lx"
,
(
long
long
)
bmp_pos
>>
(
3
+
PAGE_CACHE_SHIFT
),
(
long
long
)
bmp_pos
>>
(
3
+
PAGE_CACHE_SHIFT
),
...
@@ -1343,8 +1361,6 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
...
@@ -1343,8 +1361,6 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* We are finished, set fpos to EOD. */
/* We are finished, set fpos to EOD. */
fpos
=
vdir
->
i_size
+
vol
->
mft_record_size
;
fpos
=
vdir
->
i_size
+
vol
->
mft_record_size
;
abort:
abort:
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
ndir
);
kfree
(
name
);
kfree
(
name
);
done:
done:
#ifdef DEBUG
#ifdef DEBUG
...
@@ -1366,7 +1382,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
...
@@ -1366,7 +1382,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if
(
ctx
)
if
(
ctx
)
put_attr_search_ctx
(
ctx
);
put_attr_search_ctx
(
ctx
);
if
(
m
)
if
(
m
)
unmap_mft_record
(
READ
,
ndir
);
unmap_mft_record
(
ndir
);
if
(
!
err
)
if
(
!
err
)
err
=
-
EIO
;
err
=
-
EIO
;
ntfs_debug
(
"Failed. Returning error code %i."
,
-
err
);
ntfs_debug
(
"Failed. Returning error code %i."
,
-
err
);
...
...
fs/ntfs/file.c
View file @
b14ebcfc
...
@@ -51,8 +51,15 @@ static int ntfs_file_open(struct inode *vi, struct file *filp)
...
@@ -51,8 +51,15 @@ static int ntfs_file_open(struct inode *vi, struct file *filp)
struct
file_operations
ntfs_file_ops
=
{
struct
file_operations
ntfs_file_ops
=
{
.
llseek
=
generic_file_llseek
,
/* Seek inside file. */
.
llseek
=
generic_file_llseek
,
/* Seek inside file. */
.
read
=
generic_file_read
,
/* Read from file. */
.
read
=
generic_file_read
,
/* Read from file. */
#ifdef NTFS_RW
.
write
=
generic_file_write
,
/* Write to a file. */
#endif
.
mmap
=
generic_file_mmap
,
/* Mmap file. */
.
mmap
=
generic_file_mmap
,
/* Mmap file. */
.
sendfile
=
generic_file_sendfile
,
/* Zero-copy data send. */
.
sendfile
=
generic_file_sendfile
,
/* Zero-copy data send with the
data source being on the
ntfs partition. We don't
need to care about the data
destination. */
.
open
=
ntfs_file_open
,
/* Open file. */
.
open
=
ntfs_file_open
,
/* Open file. */
};
};
...
...
fs/ntfs/inode.c
View file @
b14ebcfc
...
@@ -278,7 +278,9 @@ void ntfs_destroy_big_inode(struct inode *inode)
...
@@ -278,7 +278,9 @@ void ntfs_destroy_big_inode(struct inode *inode)
ntfs_inode
*
ni
=
NTFS_I
(
inode
);
ntfs_inode
*
ni
=
NTFS_I
(
inode
);
ntfs_debug
(
"Entering."
);
ntfs_debug
(
"Entering."
);
BUG_ON
(
atomic_read
(
&
ni
->
mft_count
)
||
!
atomic_dec_and_test
(
&
ni
->
count
));
BUG_ON
(
ni
->
page
);
if
(
!
atomic_dec_and_test
(
&
ni
->
count
))
BUG
();
kmem_cache_free
(
ntfs_big_inode_cache
,
NTFS_I
(
inode
));
kmem_cache_free
(
ntfs_big_inode_cache
,
NTFS_I
(
inode
));
}
}
...
@@ -299,7 +301,9 @@ static inline ntfs_inode *ntfs_alloc_extent_inode(void)
...
@@ -299,7 +301,9 @@ static inline ntfs_inode *ntfs_alloc_extent_inode(void)
void
ntfs_destroy_extent_inode
(
ntfs_inode
*
ni
)
void
ntfs_destroy_extent_inode
(
ntfs_inode
*
ni
)
{
{
ntfs_debug
(
"Entering."
);
ntfs_debug
(
"Entering."
);
BUG_ON
(
atomic_read
(
&
ni
->
mft_count
)
||
!
atomic_dec_and_test
(
&
ni
->
count
));
BUG_ON
(
ni
->
page
);
if
(
!
atomic_dec_and_test
(
&
ni
->
count
))
BUG
();
kmem_cache_free
(
ntfs_inode_cache
,
ni
);
kmem_cache_free
(
ntfs_inode_cache
,
ni
);
}
}
...
@@ -323,8 +327,7 @@ static void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni)
...
@@ -323,8 +327,7 @@ static void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni)
atomic_set
(
&
ni
->
count
,
1
);
atomic_set
(
&
ni
->
count
,
1
);
ni
->
vol
=
NTFS_SB
(
sb
);
ni
->
vol
=
NTFS_SB
(
sb
);
init_run_list
(
&
ni
->
run_list
);
init_run_list
(
&
ni
->
run_list
);
init_rwsem
(
&
ni
->
mrec_lock
);
init_MUTEX
(
&
ni
->
mrec_lock
);
atomic_set
(
&
ni
->
mft_count
,
0
);
ni
->
page
=
NULL
;
ni
->
page
=
NULL
;
ni
->
page_ofs
=
0
;
ni
->
page_ofs
=
0
;
ni
->
attr_list_size
=
0
;
ni
->
attr_list_size
=
0
;
...
@@ -504,7 +507,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
...
@@ -504,7 +507,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
ntfs_init_big_inode
(
vi
);
ntfs_init_big_inode
(
vi
);
ni
=
NTFS_I
(
vi
);
ni
=
NTFS_I
(
vi
);
m
=
map_mft_record
(
READ
,
ni
);
m
=
map_mft_record
(
ni
);
if
(
IS_ERR
(
m
))
{
if
(
IS_ERR
(
m
))
{
err
=
PTR_ERR
(
m
);
err
=
PTR_ERR
(
m
);
goto
err_out
;
goto
err_out
;
...
@@ -790,6 +793,11 @@ static int ntfs_read_locked_inode(struct inode *vi)
...
@@ -790,6 +793,11 @@ static int ntfs_read_locked_inode(struct inode *vi)
/* No index allocation. */
/* No index allocation. */
vi
->
i_size
=
ni
->
initialized_size
=
vi
->
i_size
=
ni
->
initialized_size
=
ni
->
allocated_size
=
0
;
ni
->
allocated_size
=
0
;
/* We are done with the mft record, so we release it. */
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
ni
);
m
=
NULL
;
ctx
=
NULL
;
goto
skip_large_dir_stuff
;
goto
skip_large_dir_stuff
;
}
/* LARGE_INDEX: Index allocation present. Setup state. */
}
/* LARGE_INDEX: Index allocation present. Setup state. */
NInoSetIndexAllocPresent
(
ni
);
NInoSetIndexAllocPresent
(
ni
);
...
@@ -834,7 +842,14 @@ static int ntfs_read_locked_inode(struct inode *vi)
...
@@ -834,7 +842,14 @@ static int ntfs_read_locked_inode(struct inode *vi)
ctx
->
attr
->
_ANR
(
initialized_size
));
ctx
->
attr
->
_ANR
(
initialized_size
));
ni
->
allocated_size
=
sle64_to_cpu
(
ni
->
allocated_size
=
sle64_to_cpu
(
ctx
->
attr
->
_ANR
(
allocated_size
));
ctx
->
attr
->
_ANR
(
allocated_size
));
/*
* We are done with the mft record, so we release it. Otherwise
*
*/
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
ni
);
m
=
NULL
;
ctx
=
NULL
;
/* Get the index bitmap attribute inode. */
/* Get the index bitmap attribute inode. */
bvi
=
ntfs_attr_iget
(
vi
,
AT_BITMAP
,
I30
,
4
);
bvi
=
ntfs_attr_iget
(
vi
,
AT_BITMAP
,
I30
,
4
);
if
(
unlikely
(
IS_ERR
(
bvi
)))
{
if
(
unlikely
(
IS_ERR
(
bvi
)))
{
...
@@ -858,7 +873,6 @@ static int ntfs_read_locked_inode(struct inode *vi)
...
@@ -858,7 +873,6 @@ static int ntfs_read_locked_inode(struct inode *vi)
bvi
->
i_size
<<
3
,
vi
->
i_size
);
bvi
->
i_size
<<
3
,
vi
->
i_size
);
goto
unm_err_out
;
goto
unm_err_out
;
}
}
skip_large_dir_stuff:
skip_large_dir_stuff:
/* Everyone gets read and scan permissions. */
/* Everyone gets read and scan permissions. */
vi
->
i_mode
|=
S_IRUGO
|
S_IXUGO
;
vi
->
i_mode
|=
S_IRUGO
|
S_IXUGO
;
...
@@ -998,6 +1012,11 @@ static int ntfs_read_locked_inode(struct inode *vi)
...
@@ -998,6 +1012,11 @@ static int ntfs_read_locked_inode(struct inode *vi)
le32_to_cpu
(
ctx
->
attr
->
_ARA
(
value_length
));
le32_to_cpu
(
ctx
->
attr
->
_ARA
(
value_length
));
}
}
no_data_attr_special_case:
no_data_attr_special_case:
/* We are done with the mft record, so we release it. */
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
ni
);
m
=
NULL
;
ctx
=
NULL
;
/* Everyone gets all permissions. */
/* Everyone gets all permissions. */
vi
->
i_mode
|=
S_IRWXUGO
;
vi
->
i_mode
|=
S_IRWXUGO
;
/* If read-only, noone gets write permissions. */
/* If read-only, noone gets write permissions. */
...
@@ -1026,9 +1045,6 @@ static int ntfs_read_locked_inode(struct inode *vi)
...
@@ -1026,9 +1045,6 @@ static int ntfs_read_locked_inode(struct inode *vi)
else
else
vi
->
i_blocks
=
ni
->
_ICF
(
compressed_size
)
>>
9
;
vi
->
i_blocks
=
ni
->
_ICF
(
compressed_size
)
>>
9
;
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
ni
);
ntfs_debug
(
"Done."
);
ntfs_debug
(
"Done."
);
return
0
;
return
0
;
...
@@ -1037,7 +1053,8 @@ static int ntfs_read_locked_inode(struct inode *vi)
...
@@ -1037,7 +1053,8 @@ static int ntfs_read_locked_inode(struct inode *vi)
err
=
-
EIO
;
err
=
-
EIO
;
if
(
ctx
)
if
(
ctx
)
put_attr_search_ctx
(
ctx
);
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
ni
);
if
(
m
)
unmap_mft_record
(
ni
);
err_out:
err_out:
ntfs_error
(
vi
->
i_sb
,
"Failed with error code %i. Marking inode 0x%lx "
ntfs_error
(
vi
->
i_sb
,
"Failed with error code %i. Marking inode 0x%lx "
"as bad."
,
-
err
,
vi
->
i_ino
);
"as bad."
,
-
err
,
vi
->
i_ino
);
...
@@ -1091,7 +1108,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
...
@@ -1091,7 +1108,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
/* Set inode type to zero but preserve permissions. */
/* Set inode type to zero but preserve permissions. */
vi
->
i_mode
=
base_vi
->
i_mode
&
~
S_IFMT
;
vi
->
i_mode
=
base_vi
->
i_mode
&
~
S_IFMT
;
m
=
map_mft_record
(
READ
,
base_ni
);
m
=
map_mft_record
(
base_ni
);
if
(
IS_ERR
(
m
))
{
if
(
IS_ERR
(
m
))
{
err
=
PTR_ERR
(
m
);
err
=
PTR_ERR
(
m
);
goto
err_out
;
goto
err_out
;
...
@@ -1265,7 +1282,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
...
@@ -1265,7 +1282,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
ni
->
nr_extents
=
-
1
;
ni
->
nr_extents
=
-
1
;
put_attr_search_ctx
(
ctx
);
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
base_ni
);
unmap_mft_record
(
base_ni
);
ntfs_debug
(
"Done."
);
ntfs_debug
(
"Done."
);
return
0
;
return
0
;
...
@@ -1275,7 +1292,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
...
@@ -1275,7 +1292,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
err
=
-
EIO
;
err
=
-
EIO
;
if
(
ctx
)
if
(
ctx
)
put_attr_search_ctx
(
ctx
);
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
base_ni
);
unmap_mft_record
(
base_ni
);
err_out:
err_out:
ntfs_error
(
vi
->
i_sb
,
"Failed with error code %i while reading "
ntfs_error
(
vi
->
i_sb
,
"Failed with error code %i while reading "
"attribute inode (mft_no 0x%lx, type 0x%x, name_len "
"attribute inode (mft_no 0x%lx, type 0x%x, name_len "
...
@@ -1398,7 +1415,7 @@ void ntfs_read_inode_mount(struct inode *vi)
...
@@ -1398,7 +1415,7 @@ void ntfs_read_inode_mount(struct inode *vi)
/* Need this to sanity check attribute list references to $MFT. */
/* Need this to sanity check attribute list references to $MFT. */
ni
->
seq_no
=
le16_to_cpu
(
m
->
sequence_number
);
ni
->
seq_no
=
le16_to_cpu
(
m
->
sequence_number
);
/* Provides readpage() and sync_page() for map_mft_record(
READ
). */
/* Provides readpage() and sync_page() for map_mft_record(). */
vi
->
i_mapping
->
a_ops
=
&
ntfs_mft_aops
;
vi
->
i_mapping
->
a_ops
=
&
ntfs_mft_aops
;
ctx
=
get_attr_search_ctx
(
ni
,
m
);
ctx
=
get_attr_search_ctx
(
ni
,
m
);
...
@@ -1795,8 +1812,8 @@ void __ntfs_clear_inode(ntfs_inode *ni)
...
@@ -1795,8 +1812,8 @@ void __ntfs_clear_inode(ntfs_inode *ni)
}
}
}
}
/* Synchronize with ntfs_commit_inode(). */
/* Synchronize with ntfs_commit_inode(). */
down
_write
(
&
ni
->
mrec_lock
);
down
(
&
ni
->
mrec_lock
);
up
_write
(
&
ni
->
mrec_lock
);
up
(
&
ni
->
mrec_lock
);
if
(
NInoDirty
(
ni
))
{
if
(
NInoDirty
(
ni
))
{
ntfs_error
(
ni
->
vol
->
sb
,
"Failed to commit dirty inode "
ntfs_error
(
ni
->
vol
->
sb
,
"Failed to commit dirty inode "
"asynchronously."
);
"asynchronously."
);
...
...
fs/ntfs/inode.h
View file @
b14ebcfc
...
@@ -72,9 +72,8 @@ struct _ntfs_inode {
...
@@ -72,9 +72,8 @@ struct _ntfs_inode {
* The following fields are only valid for real inodes and extent
* The following fields are only valid for real inodes and extent
* inodes.
* inodes.
*/
*/
struct
rw_semaphore
mrec_lock
;
/* Lock for serializing access to the
struct
semaphore
mrec_lock
;
/* Lock for serializing access to the
mft record belonging to this inode. */
mft record belonging to this inode. */
atomic_t
mft_count
;
/* Mapping reference count for book keeping. */
struct
page
*
page
;
/* The page containing the mft record of the
struct
page
*
page
;
/* The page containing the mft record of the
inode. This should only be touched by the
inode. This should only be touched by the
(un)map_mft_record*() functions. */
(un)map_mft_record*() functions. */
...
...
fs/ntfs/malloc.h
View file @
b14ebcfc
...
@@ -25,20 +25,6 @@
...
@@ -25,20 +25,6 @@
#include <linux/vmalloc.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/slab.h>
/**
* vmalloc_nofs - allocate any pages but don't allow calls into fs layer
* @size: number of bytes to allocate
*
* Allocate any pages but don't allow calls into fs layer. Return allocated
* memory or NULL if insufficient memory.
*/
static
inline
void
*
vmalloc_nofs
(
unsigned
long
size
)
{
if
(
likely
(
size
>>
PAGE_SHIFT
<
num_physpages
))
return
__vmalloc
(
size
,
GFP_NOFS
|
__GFP_HIGHMEM
,
PAGE_KERNEL
);
return
NULL
;
}
/**
/**
* ntfs_malloc_nofs - allocate memory in multiples of pages
* ntfs_malloc_nofs - allocate memory in multiples of pages
* @size number of bytes to allocate
* @size number of bytes to allocate
...
@@ -66,7 +52,8 @@ static inline void *ntfs_malloc_nofs(unsigned long size)
...
@@ -66,7 +52,8 @@ static inline void *ntfs_malloc_nofs(unsigned long size)
static
inline
void
ntfs_free
(
void
*
addr
)
static
inline
void
ntfs_free
(
void
*
addr
)
{
{
if
(
likely
((
unsigned
long
)
addr
<
VMALLOC_START
))
{
if
(
likely
(((
unsigned
long
)
addr
<
VMALLOC_START
)
||
((
unsigned
long
)
addr
>=
VMALLOC_END
)))
{
return
kfree
(
addr
);
return
kfree
(
addr
);
/* return free_page((unsigned long)addr); */
/* return free_page((unsigned long)addr); */
}
}
...
...
fs/ntfs/mft.c
View file @
b14ebcfc
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project.
* mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project.
*
*
* Copyright (c) 2001,2002 Anton Altaparmakov.
* Copyright (c) 2001,2002 Anton Altaparmakov.
* Copyright (
C
) 2002 Richard Russon.
* Copyright (
c
) 2002 Richard Russon.
*
*
* This program/include file is free software; you can redistribute it and/or
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* modify it under the terms of the GNU General Public License as published
...
@@ -85,13 +85,15 @@ int format_mft_record(ntfs_inode *ni, MFT_RECORD *mft_rec)
...
@@ -85,13 +85,15 @@ int format_mft_record(ntfs_inode *ni, MFT_RECORD *mft_rec)
if
(
mft_rec
)
if
(
mft_rec
)
m
=
mft_rec
;
m
=
mft_rec
;
else
{
else
{
m
=
map_mft_record
(
WRITE
,
ni
);
m
=
map_mft_record
(
ni
);
if
(
IS_ERR
(
m
))
if
(
IS_ERR
(
m
))
return
PTR_ERR
(
m
);
return
PTR_ERR
(
m
);
}
}
__format_mft_record
(
m
,
ni
->
vol
->
mft_record_size
,
ni
->
mft_no
);
__format_mft_record
(
m
,
ni
->
vol
->
mft_record_size
,
ni
->
mft_no
);
if
(
!
mft_rec
)
if
(
!
mft_rec
)
{
unmap_mft_record
(
WRITE
,
ni
);
// FIXME: Need to set the mft record dirty!
unmap_mft_record
(
ni
);
}
return
0
;
return
0
;
}
}
...
@@ -132,7 +134,7 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni)
...
@@ -132,7 +134,7 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni)
struct
page
*
page
;
struct
page
*
page
;
unsigned
long
index
,
ofs
,
end_index
;
unsigned
long
index
,
ofs
,
end_index
;
BUG_ON
(
atomic_read
(
&
ni
->
mft_count
)
||
ni
->
page
);
BUG_ON
(
ni
->
page
);
/*
/*
* The index into the page cache and the offset within the page cache
* The index into the page cache and the offset within the page cache
* page of the wanted mft record. FIXME: We need to check for
* page of the wanted mft record. FIXME: We need to check for
...
@@ -146,70 +148,36 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni)
...
@@ -146,70 +148,36 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni)
end_index
=
mft_vi
->
i_size
>>
PAGE_CACHE_SHIFT
;
end_index
=
mft_vi
->
i_size
>>
PAGE_CACHE_SHIFT
;
/* If the wanted index is out of bounds the mft record doesn't exist. */
/* If the wanted index is out of bounds the mft record doesn't exist. */
if
(
index
>=
end_index
)
{
if
(
unlikely
(
index
>=
end_index
)
)
{
if
(
index
>
end_index
||
(
mft_vi
->
i_size
&
~
PAGE_CACHE_MASK
)
<
if
(
index
>
end_index
||
(
mft_vi
->
i_size
&
~
PAGE_CACHE_MASK
)
<
ofs
+
vol
->
mft_record_size
)
{
ofs
+
vol
->
mft_record_size
)
{
page
=
ERR_PTR
(
-
ENOENT
);
page
=
ERR_PTR
(
-
ENOENT
);
goto
up_
err_out
;
goto
err_out
;
}
}
}
}
/* Read, map, and pin the page. */
/* Read, map, and pin the page. */
page
=
ntfs_map_page
(
mft_vi
->
i_mapping
,
index
);
page
=
ntfs_map_page
(
mft_vi
->
i_mapping
,
index
);
if
(
!
IS_ERR
(
page
))
{
if
(
likely
(
!
IS_ERR
(
page
)))
{
/* Pin the mft record mapping in the ntfs_inode. */
atomic_inc
(
&
ni
->
mft_count
);
/* Setup the references in the ntfs_inode. */
ni
->
page
=
page
;
ni
->
page
=
page
;
ni
->
page_ofs
=
ofs
;
ni
->
page_ofs
=
ofs
;
return
page_address
(
page
)
+
ofs
;
return
page_address
(
page
)
+
ofs
;
}
}
up_err_out:
err_out:
/* Just in case... */
ni
->
page
=
NULL
;
ni
->
page
=
NULL
;
ni
->
page_ofs
=
0
;
ni
->
page_ofs
=
0
;
ntfs_error
(
vol
->
sb
,
"Failed with error code %lu."
,
-
PTR_ERR
(
page
));
ntfs_error
(
vol
->
sb
,
"Failed with error code %lu."
,
-
PTR_ERR
(
page
));
return
(
void
*
)
page
;
return
(
void
*
)
page
;
}
}
/**
* unmap_mft_record_page - unmap the page in which a specific mft record resides
* @ni: ntfs inode whose mft record page to unmap
*
* This unmaps the page in which the mft record of the ntfs inode @ni is
* situated and returns. This is a NOOP if highmem is not configured.
*
* The unmap happens via ntfs_unmap_page() which in turn decrements the use
* count on the page thus releasing it from the pinned state.
*
* We do not actually unmap the page from memory of course, as that will be
* done by the page cache code itself when memory pressure increases or
* whatever.
*/
static
inline
void
unmap_mft_record_page
(
ntfs_inode
*
ni
)
{
BUG_ON
(
atomic_read
(
&
ni
->
mft_count
)
||
!
ni
->
page
);
// TODO: If dirty, blah...
ntfs_unmap_page
(
ni
->
page
);
ni
->
page
=
NULL
;
ni
->
page_ofs
=
0
;
return
;
}
/**
/**
* map_mft_record - map, pin and lock an mft record
* map_mft_record - map, pin and lock an mft record
* @rw: map for read (rw = READ) or write (rw = WRITE)
* @ni: ntfs inode whose MFT record to map
* @ni: ntfs inode whose MFT record to map
*
*
* First, take the mrec_lock semaphore for reading or writing, depending on
* First, take the mrec_lock semaphore. We might now be sleeping, while waiting
* the value or @rw. We might now be sleeping, while waiting for the semaphore
* for the semaphore if it was already locked by someone else.
* if it was already locked by someone else.
*
*
* Then increment the map reference count and return the mft. If this is the
* The page of the record is first mapped using map_mft_record_page() before
* first invocation, the page of the record is first mapped using
* being returned to the caller.
* map_mft_record_page().
*
*
* This in turn uses ntfs_map_page() to get the page containing the wanted mft
* This in turn uses ntfs_map_page() to get the page containing the wanted mft
* record (it in turn calls read_cache_page() which reads it in from disk if
* record (it in turn calls read_cache_page() which reads it in from disk if
...
@@ -234,11 +202,11 @@ static inline void unmap_mft_record_page(ntfs_inode *ni)
...
@@ -234,11 +202,11 @@ static inline void unmap_mft_record_page(ntfs_inode *ni)
* locking problem then is them locking the page while we are accessing it.
* locking problem then is them locking the page while we are accessing it.
*
*
* So that code will end up having to own the mrec_lock of all mft
* So that code will end up having to own the mrec_lock of all mft
* records/inodes present in the page before I/O can proceed.
Grr. In that
* records/inodes present in the page before I/O can proceed.
In that case we
*
case we wouldn't need need to bother with PG_locked and PG_uptodate as
*
wouldn't need to bother with PG_locked and PG_uptodate as nobody will be
*
nobody will be accessing anything without owning the mrec_lock semaphore.
*
accessing anything without owning the mrec_lock semaphore. But we do need
*
But we do need to use them because of the read_cache_page() invokation and
*
to use them because of the read_cache_page() invokation and the code becomes
*
the code becomes
so much simpler this way that it is well worth it.
* so much simpler this way that it is well worth it.
*
*
* The mft record is now ours and we return a pointer to it. You need to check
* The mft record is now ours and we return a pointer to it. You need to check
* the returned pointer with IS_ERR() and if that is true, PTR_ERR() will return
* the returned pointer with IS_ERR() and if that is true, PTR_ERR() will return
...
@@ -251,89 +219,75 @@ static inline void unmap_mft_record_page(ntfs_inode *ni)
...
@@ -251,89 +219,75 @@ static inline void unmap_mft_record_page(ntfs_inode *ni)
* A: No, the inode ones mean we want to change the mft record, not we want to
* A: No, the inode ones mean we want to change the mft record, not we want to
* write it out.
* write it out.
*/
*/
MFT_RECORD
*
map_mft_record
(
const
int
rw
,
ntfs_inode
*
ni
)
MFT_RECORD
*
map_mft_record
(
ntfs_inode
*
ni
)
{
{
MFT_RECORD
*
m
;
MFT_RECORD
*
m
;
ntfs_debug
(
"Entering for mft_no 0x%lx, mapping for %s."
,
ni
->
mft_no
,
ntfs_debug
(
"Entering for mft_no 0x%lx."
,
ni
->
mft_no
);
rw
==
READ
?
"READ"
:
"WRITE"
);
/* Make sure the ntfs inode doesn't go away. */
/* Make sure the ntfs inode doesn't go away. */
atomic_inc
(
&
ni
->
count
);
atomic_inc
(
&
ni
->
count
);
/* Serialize access to this mft record. */
/* Serialize access to this mft record. */
if
(
rw
==
READ
)
down
(
&
ni
->
mrec_lock
);
down_read
(
&
ni
->
mrec_lock
);
else
down_write
(
&
ni
->
mrec_lock
);
/* If already mapped, bump reference count and return the mft record. */
if
(
atomic_read
(
&
ni
->
mft_count
))
{
BUG_ON
(
!
ni
->
page
);
atomic_inc
(
&
ni
->
mft_count
);
return
page_address
(
ni
->
page
)
+
ni
->
page_ofs
;
}
/* Wasn't mapped. Map it now and return it if all was ok. */
m
=
map_mft_record_page
(
ni
);
m
=
map_mft_record_page
(
ni
);
if
(
!
IS_ERR
(
m
))
if
(
likely
(
!
IS_ERR
(
m
)
))
return
m
;
return
m
;
/* Mapping failed. Release the mft record lock. */
up
(
&
ni
->
mrec_lock
);
if
(
rw
==
READ
)
up_read
(
&
ni
->
mrec_lock
);
else
up_write
(
&
ni
->
mrec_lock
);
ntfs_error
(
ni
->
vol
->
sb
,
"Failed with error code %lu."
,
-
PTR_ERR
(
m
));
/* Release the ntfs inode and return the error code. */
atomic_dec
(
&
ni
->
count
);
atomic_dec
(
&
ni
->
count
);
ntfs_error
(
ni
->
vol
->
sb
,
"Failed with error code %lu."
,
-
PTR_ERR
(
m
));
return
m
;
return
m
;
}
}
/**
/**
* unmap_mft_record - release a mapped mft record
* unmap_mft_record_page - unmap the page in which a specific mft record resides
* @rw: unmap from read (@rw = READ) or write (@rw = WRITE)
* @ni: ntfs inode whose mft record page to unmap
* @ni: ntfs inode whose MFT record to unmap
*
* First, decrement the mapping count and when it reaches zero unmap the mft
* record.
*
*
* Second, release the mrec_lock semaphore.
* This unmaps the page in which the mft record of the ntfs inode @ni is
* situated and returns. This is a NOOP if highmem is not configured.
*
*
* The mft record is now released for others to get hold of.
* The unmap happens via ntfs_unmap_page() which in turn decrements the use
* count on the page thus releasing it from the pinned state.
*
*
* Finally, release the ntfs inode by decreasing the ntfs inode reference count.
* We do not actually unmap the page from memory of course, as that will be
* done by the page cache code itself when memory pressure increases or
* whatever.
*/
static
inline
void
unmap_mft_record_page
(
ntfs_inode
*
ni
)
{
BUG_ON
(
!
ni
->
page
);
// TODO: If dirty, blah...
ntfs_unmap_page
(
ni
->
page
);
ni
->
page
=
NULL
;
ni
->
page_ofs
=
0
;
return
;
}
/**
* unmap_mft_record - release a mapped mft record
* @ni: ntfs inode whose MFT record to unmap
*
*
* NOTE: If caller had the mft record mapped for write and has modified it, it
* We release the page mapping and the mrec_lock mutex which unmaps the mft
* is imperative to set the mft record dirty BEFORE calling unmap_mft_record().
* record and releases it for others to get hold of. We also release the ntfs
* inode by decrementing the ntfs inode reference count.
*
*
* NOTE:
This has to be done both for 'normal' mft records, and for extent
mft
* NOTE:
If caller has modified the mft record, it is imperative to set the
mft
* record
s
.
* record
dirty BEFORE calling unmap_mft_record()
.
*/
*/
void
unmap_mft_record
(
const
int
rw
,
ntfs_inode
*
ni
)
void
unmap_mft_record
(
ntfs_inode
*
ni
)
{
{
struct
page
*
page
=
ni
->
page
;
struct
page
*
page
=
ni
->
page
;
BUG_ON
(
!
atomic_read
(
&
ni
->
mft_count
)
||
!
page
);
BUG_ON
(
!
page
);
ntfs_debug
(
"Entering for mft_no 0x%lx, unmapping from %s."
,
ni
->
mft_no
,
rw
==
READ
?
"READ"
:
"WRITE"
);
/* Only release the actual page mapping if this is the last one. */
ntfs_debug
(
"Entering for mft_no 0x%lx."
,
ni
->
mft_no
);
if
(
atomic_dec_and_test
(
&
ni
->
mft_count
))
unmap_mft_record_page
(
ni
);
/* Release the semaphore. */
unmap_mft_record_page
(
ni
);
if
(
rw
==
READ
)
up
(
&
ni
->
mrec_lock
);
up_read
(
&
ni
->
mrec_lock
);
else
up_write
(
&
ni
->
mrec_lock
);
/* Release the ntfs inode. */
atomic_dec
(
&
ni
->
count
);
atomic_dec
(
&
ni
->
count
);
/*
/*
* If pure ntfs_inode, i.e. no vfs inode attached, we leave it to
* If pure ntfs_inode, i.e. no vfs inode attached, we leave it to
* ntfs_clear_extent_inode() in the extent inode case, and to the
* ntfs_clear_extent_inode() in the extent inode case, and to the
...
@@ -355,11 +309,6 @@ void unmap_mft_record(const int rw, ntfs_inode *ni)
...
@@ -355,11 +309,6 @@ void unmap_mft_record(const int rw, ntfs_inode *ni)
*
*
* On successful return, @ntfs_ino contains a pointer to the ntfs_inode
* On successful return, @ntfs_ino contains a pointer to the ntfs_inode
* structure of the mapped extent inode.
* structure of the mapped extent inode.
*
* Note, we always map for READ. We consider this lock as irrelevant because
* the base inode will be write locked in all cases when we want to write to
* an extent inode which already gurantees that there is no-one else accessing
* the extent inode.
*/
*/
MFT_RECORD
*
map_extent_mft_record
(
ntfs_inode
*
base_ni
,
MFT_REF
mref
,
MFT_RECORD
*
map_extent_mft_record
(
ntfs_inode
*
base_ni
,
MFT_REF
mref
,
ntfs_inode
**
ntfs_ino
)
ntfs_inode
**
ntfs_ino
)
...
@@ -393,21 +342,21 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
...
@@ -393,21 +342,21 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
break
;
break
;
}
}
}
}
if
(
ni
)
{
if
(
likely
(
ni
!=
NULL
)
)
{
up
(
&
base_ni
->
extent_lock
);
up
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
atomic_dec
(
&
base_ni
->
count
);
/* We found the record; just have to map and return it. */
/* We found the record; just have to map and return it. */
m
=
map_mft_record
(
READ
,
ni
);
m
=
map_mft_record
(
ni
);
/*
Map mft record increments
this on success. */
/*
map_mft_record() has incremented
this on success. */
atomic_dec
(
&
ni
->
count
);
atomic_dec
(
&
ni
->
count
);
if
(
!
IS_ERR
(
m
))
{
if
(
likely
(
!
IS_ERR
(
m
)
))
{
/* Verify the sequence number. */
/* Verify the sequence number. */
if
(
l
e16_to_cpu
(
m
->
sequence_number
)
==
seq_no
)
{
if
(
l
ikely
(
le16_to_cpu
(
m
->
sequence_number
)
==
seq_no
)
)
{
ntfs_debug
(
"Done 1."
);
ntfs_debug
(
"Done 1."
);
*
ntfs_ino
=
ni
;
*
ntfs_ino
=
ni
;
return
m
;
return
m
;
}
}
unmap_mft_record
(
READ
,
ni
);
unmap_mft_record
(
ni
);
ntfs_error
(
base_ni
->
vol
->
sb
,
"Found stale extent mft "
ntfs_error
(
base_ni
->
vol
->
sb
,
"Found stale extent mft "
"reference! Corrupt file system. "
"reference! Corrupt file system. "
"Run chkdsk."
);
"Run chkdsk."
);
...
@@ -420,7 +369,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
...
@@ -420,7 +369,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
}
}
/* Record wasn't there. Get a new ntfs inode and initialize it. */
/* Record wasn't there. Get a new ntfs inode and initialize it. */
ni
=
ntfs_new_extent_inode
(
base_ni
->
vol
->
sb
,
mft_no
);
ni
=
ntfs_new_extent_inode
(
base_ni
->
vol
->
sb
,
mft_no
);
if
(
!
ni
)
{
if
(
unlikely
(
!
ni
)
)
{
up
(
&
base_ni
->
extent_lock
);
up
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
atomic_dec
(
&
base_ni
->
count
);
return
ERR_PTR
(
-
ENOMEM
);
return
ERR_PTR
(
-
ENOMEM
);
...
@@ -430,15 +379,15 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
...
@@ -430,15 +379,15 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
ni
->
nr_extents
=
-
1
;
ni
->
nr_extents
=
-
1
;
ni
->
_INE
(
base_ntfs_ino
)
=
base_ni
;
ni
->
_INE
(
base_ntfs_ino
)
=
base_ni
;
/* Now map the record. */
/* Now map the record. */
m
=
map_mft_record
(
READ
,
ni
);
m
=
map_mft_record
(
ni
);
if
(
IS_ERR
(
m
))
{
if
(
unlikely
(
IS_ERR
(
m
)
))
{
up
(
&
base_ni
->
extent_lock
);
up
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
atomic_dec
(
&
base_ni
->
count
);
ntfs_clear_extent_inode
(
ni
);
ntfs_clear_extent_inode
(
ni
);
goto
map_err_out
;
goto
map_err_out
;
}
}
/* Verify the sequence number. */
/* Verify the sequence number. */
if
(
le16_to_cpu
(
m
->
sequence_number
)
!=
seq_no
)
{
if
(
unlikely
(
le16_to_cpu
(
m
->
sequence_number
)
!=
seq_no
)
)
{
ntfs_error
(
base_ni
->
vol
->
sb
,
"Found stale extent mft "
ntfs_error
(
base_ni
->
vol
->
sb
,
"Found stale extent mft "
"reference! Corrupt file system. Run chkdsk."
);
"reference! Corrupt file system. Run chkdsk."
);
destroy_ni
=
TRUE
;
destroy_ni
=
TRUE
;
...
@@ -451,7 +400,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
...
@@ -451,7 +400,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
int
new_size
=
(
base_ni
->
nr_extents
+
4
)
*
sizeof
(
ntfs_inode
*
);
int
new_size
=
(
base_ni
->
nr_extents
+
4
)
*
sizeof
(
ntfs_inode
*
);
tmp
=
(
ntfs_inode
**
)
kmalloc
(
new_size
,
GFP_NOFS
);
tmp
=
(
ntfs_inode
**
)
kmalloc
(
new_size
,
GFP_NOFS
);
if
(
!
tmp
)
{
if
(
unlikely
(
!
tmp
)
)
{
ntfs_error
(
base_ni
->
vol
->
sb
,
"Failed to allocate "
ntfs_error
(
base_ni
->
vol
->
sb
,
"Failed to allocate "
"internal buffer."
);
"internal buffer."
);
destroy_ni
=
TRUE
;
destroy_ni
=
TRUE
;
...
@@ -472,7 +421,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
...
@@ -472,7 +421,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
*
ntfs_ino
=
ni
;
*
ntfs_ino
=
ni
;
return
m
;
return
m
;
unm_err_out:
unm_err_out:
unmap_mft_record
(
READ
,
ni
);
unmap_mft_record
(
ni
);
up
(
&
base_ni
->
extent_lock
);
up
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
atomic_dec
(
&
base_ni
->
count
);
/*
/*
...
...
fs/ntfs/mft.h
View file @
b14ebcfc
...
@@ -31,15 +31,15 @@ extern int format_mft_record(ntfs_inode *ni, MFT_RECORD *m);
...
@@ -31,15 +31,15 @@ extern int format_mft_record(ntfs_inode *ni, MFT_RECORD *m);
//extern int format_mft_record2(struct super_block *vfs_sb,
//extern int format_mft_record2(struct super_block *vfs_sb,
// const unsigned long inum, MFT_RECORD *m);
// const unsigned long inum, MFT_RECORD *m);
extern
MFT_RECORD
*
map_mft_record
(
const
int
rw
,
ntfs_inode
*
ni
);
extern
MFT_RECORD
*
map_mft_record
(
ntfs_inode
*
ni
);
extern
void
unmap_mft_record
(
const
int
rw
,
ntfs_inode
*
ni
);
extern
void
unmap_mft_record
(
ntfs_inode
*
ni
);
extern
MFT_RECORD
*
map_extent_mft_record
(
ntfs_inode
*
base_ni
,
MFT_REF
mref
,
extern
MFT_RECORD
*
map_extent_mft_record
(
ntfs_inode
*
base_ni
,
MFT_REF
mref
,
ntfs_inode
**
ntfs_ino
);
ntfs_inode
**
ntfs_ino
);
static
inline
void
unmap_extent_mft_record
(
ntfs_inode
*
ni
)
static
inline
void
unmap_extent_mft_record
(
ntfs_inode
*
ni
)
{
{
unmap_mft_record
(
READ
,
ni
);
unmap_mft_record
(
ni
);
return
;
return
;
}
}
...
...
fs/ntfs/namei.c
View file @
b14ebcfc
...
@@ -162,6 +162,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
...
@@ -162,6 +162,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
handle_name:
handle_name:
{
{
struct
dentry
*
real_dent
;
struct
dentry
*
real_dent
;
MFT_RECORD
*
m
;
attr_search_context
*
ctx
;
attr_search_context
*
ctx
;
ntfs_inode
*
ni
=
NTFS_I
(
dent_inode
);
ntfs_inode
*
ni
=
NTFS_I
(
dent_inode
);
int
err
;
int
err
;
...
@@ -175,22 +176,23 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
...
@@ -175,22 +176,23 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
name
->
len
*
3
+
1
);
name
->
len
*
3
+
1
);
kfree
(
name
);
kfree
(
name
);
}
else
/* if (name->type == FILE_NAME_DOS) */
{
/* Case 3. */
}
else
/* if (name->type == FILE_NAME_DOS) */
{
/* Case 3. */
MFT_RECORD
*
m
;
FILE_NAME_ATTR
*
fn
;
FILE_NAME_ATTR
*
fn
;
kfree
(
name
);
kfree
(
name
);
/* Find the WIN32 name corresponding to the matched DOS name. */
/* Find the WIN32 name corresponding to the matched DOS name. */
ni
=
NTFS_I
(
dent_inode
);
ni
=
NTFS_I
(
dent_inode
);
m
=
map_mft_record
(
READ
,
ni
);
m
=
map_mft_record
(
ni
);
if
(
IS_ERR
(
m
))
{
if
(
IS_ERR
(
m
))
{
err
=
PTR_ERR
(
m
);
err
=
PTR_ERR
(
m
);
goto
name_err_out
;
m
=
NULL
;
ctx
=
NULL
;
goto
err_out
;
}
}
ctx
=
get_attr_search_ctx
(
ni
,
m
);
ctx
=
get_attr_search_ctx
(
ni
,
m
);
if
(
!
ctx
)
{
if
(
!
ctx
)
{
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
unm_
err_out
;
goto
err_out
;
}
}
do
{
do
{
ATTR_RECORD
*
a
;
ATTR_RECORD
*
a
;
...
@@ -202,21 +204,21 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
...
@@ -202,21 +204,21 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
"namespace counterpart to DOS "
"namespace counterpart to DOS "
"file name. Run chkdsk."
);
"file name. Run chkdsk."
);
err
=
-
EIO
;
err
=
-
EIO
;
goto
put_unm_
err_out
;
goto
err_out
;
}
}
/* Consistency checks. */
/* Consistency checks. */
a
=
ctx
->
attr
;
a
=
ctx
->
attr
;
if
(
a
->
non_resident
||
a
->
flags
)
if
(
a
->
non_resident
||
a
->
flags
)
goto
eio_
put_unm_
err_out
;
goto
eio_err_out
;
val_len
=
le32_to_cpu
(
a
->
_ARA
(
value_length
));
val_len
=
le32_to_cpu
(
a
->
_ARA
(
value_length
));
if
(
le16_to_cpu
(
a
->
_ARA
(
value_offset
))
+
val_len
>
if
(
le16_to_cpu
(
a
->
_ARA
(
value_offset
))
+
val_len
>
le32_to_cpu
(
a
->
length
))
le32_to_cpu
(
a
->
length
))
goto
eio_
put_unm_
err_out
;
goto
eio_err_out
;
fn
=
(
FILE_NAME_ATTR
*
)((
u8
*
)
ctx
->
attr
+
le16_to_cpu
(
fn
=
(
FILE_NAME_ATTR
*
)((
u8
*
)
ctx
->
attr
+
le16_to_cpu
(
ctx
->
attr
->
_ARA
(
value_offset
)));
ctx
->
attr
->
_ARA
(
value_offset
)));
if
((
u32
)(
fn
->
file_name_length
*
sizeof
(
uchar_t
)
+
if
((
u32
)(
fn
->
file_name_length
*
sizeof
(
uchar_t
)
+
sizeof
(
FILE_NAME_ATTR
))
>
val_len
)
sizeof
(
FILE_NAME_ATTR
))
>
val_len
)
goto
eio_
put_unm_
err_out
;
goto
eio_err_out
;
}
while
(
fn
->
file_name_type
!=
FILE_NAME_WIN32
);
}
while
(
fn
->
file_name_type
!=
FILE_NAME_WIN32
);
/* Convert the found WIN32 name to current NLS code page. */
/* Convert the found WIN32 name to current NLS code page. */
...
@@ -226,13 +228,15 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
...
@@ -226,13 +228,15 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
fn
->
file_name_length
*
3
+
1
);
fn
->
file_name_length
*
3
+
1
);
put_attr_search_ctx
(
ctx
);
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
ni
);
unmap_mft_record
(
ni
);
}
}
m
=
NULL
;
ctx
=
NULL
;
/* Check if a conversion error occured. */
/* Check if a conversion error occured. */
if
((
signed
)
nls_name
.
len
<
0
)
{
if
((
signed
)
nls_name
.
len
<
0
)
{
err
=
(
signed
)
nls_name
.
len
;
err
=
(
signed
)
nls_name
.
len
;
goto
name_
err_out
;
goto
err_out
;
}
}
nls_name
.
hash
=
full_name_hash
(
nls_name
.
name
,
nls_name
.
len
);
nls_name
.
hash
=
full_name_hash
(
nls_name
.
name
,
nls_name
.
len
);
...
@@ -248,7 +252,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
...
@@ -248,7 +252,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
kfree
(
nls_name
.
name
);
kfree
(
nls_name
.
name
);
if
(
!
real_dent
)
{
if
(
!
real_dent
)
{
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
name_
err_out
;
goto
err_out
;
}
}
d_add
(
real_dent
,
dent_inode
);
d_add
(
real_dent
,
dent_inode
);
return
real_dent
;
return
real_dent
;
...
@@ -269,14 +273,14 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
...
@@ -269,14 +273,14 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
d_instantiate
(
real_dent
,
dent_inode
);
d_instantiate
(
real_dent
,
dent_inode
);
return
real_dent
;
return
real_dent
;
eio_
put_unm_
err_out:
eio_err_out:
ntfs_error
(
vol
->
sb
,
"Illegal file name attribute. Run chkdsk."
);
ntfs_error
(
vol
->
sb
,
"Illegal file name attribute. Run chkdsk."
);
err
=
-
EIO
;
err
=
-
EIO
;
put_unm_
err_out:
err_out:
put_attr_search_ctx
(
ctx
);
if
(
ctx
)
unm_err_out:
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
ni
);
if
(
m
)
name_err_out:
unmap_mft_record
(
ni
);
iput
(
dent_inode
);
iput
(
dent_inode
);
return
ERR_PTR
(
err
);
return
ERR_PTR
(
err
);
}
}
...
...
fs/ntfs/super.c
View file @
b14ebcfc
...
@@ -307,6 +307,23 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
...
@@ -307,6 +307,23 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
ntfs_debug
(
"Entering with remount options string: %s"
,
opt
);
ntfs_debug
(
"Entering with remount options string: %s"
,
opt
);
#ifndef NTFS_RW
/* For read-only compiled driver, enforce all read-only flags. */
*
flags
|=
MS_RDONLY
|
MS_NOATIME
|
MS_NODIRATIME
;
#else
/*
* For the read-write compiled driver, if we are remounting read-write,
* make sure there aren't any volume errors.
*/
if
((
sb
->
s_flags
&
MS_RDONLY
)
&&
!
(
*
flags
&
MS_RDONLY
))
{
if
(
NVolErrors
(
vol
))
{
ntfs_error
(
sb
,
"Volume has errors and is read-only."
"Cannot remount read-write."
);
return
-
EROFS
;
}
}
#endif
// FIXME/TODO: If left like this we will have problems with rw->ro and
// FIXME/TODO: If left like this we will have problems with rw->ro and
// ro->rw, as well as with sync->async and vice versa remounts.
// ro->rw, as well as with sync->async and vice versa remounts.
// Note: The VFS already checks that there are no pending deletes and
// Note: The VFS already checks that there are no pending deletes and
...
@@ -324,10 +341,6 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
...
@@ -324,10 +341,6 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
if
(
!
parse_options
(
vol
,
opt
))
if
(
!
parse_options
(
vol
,
opt
))
return
-
EINVAL
;
return
-
EINVAL
;
#ifndef NTFS_RW
*
flags
|=
MS_RDONLY
|
MS_NOATIME
|
MS_NODIRATIME
;
#endif
return
0
;
return
0
;
}
}
...
@@ -852,7 +865,7 @@ static BOOL load_system_files(ntfs_volume *vol)
...
@@ -852,7 +865,7 @@ static BOOL load_system_files(ntfs_volume *vol)
ntfs_error
(
sb
,
"Failed to load $Volume."
);
ntfs_error
(
sb
,
"Failed to load $Volume."
);
goto
iput_lcnbmp_err_out
;
goto
iput_lcnbmp_err_out
;
}
}
m
=
map_mft_record
(
READ
,
NTFS_I
(
vol
->
vol_ino
));
m
=
map_mft_record
(
NTFS_I
(
vol
->
vol_ino
));
if
(
IS_ERR
(
m
))
{
if
(
IS_ERR
(
m
))
{
iput_volume_failed:
iput_volume_failed:
iput
(
vol
->
vol_ino
);
iput
(
vol
->
vol_ino
);
...
@@ -867,7 +880,7 @@ static BOOL load_system_files(ntfs_volume *vol)
...
@@ -867,7 +880,7 @@ static BOOL load_system_files(ntfs_volume *vol)
err_put_vol:
err_put_vol:
put_attr_search_ctx
(
ctx
);
put_attr_search_ctx
(
ctx
);
get_ctx_vol_failed:
get_ctx_vol_failed:
unmap_mft_record
(
READ
,
NTFS_I
(
vol
->
vol_ino
));
unmap_mft_record
(
NTFS_I
(
vol
->
vol_ino
));
goto
iput_volume_failed
;
goto
iput_volume_failed
;
}
}
vi
=
(
VOLUME_INFORMATION
*
)((
char
*
)
ctx
->
attr
+
vi
=
(
VOLUME_INFORMATION
*
)((
char
*
)
ctx
->
attr
+
...
@@ -882,7 +895,7 @@ static BOOL load_system_files(ntfs_volume *vol)
...
@@ -882,7 +895,7 @@ static BOOL load_system_files(ntfs_volume *vol)
vol
->
major_ver
=
vi
->
major_ver
;
vol
->
major_ver
=
vi
->
major_ver
;
vol
->
minor_ver
=
vi
->
minor_ver
;
vol
->
minor_ver
=
vi
->
minor_ver
;
put_attr_search_ctx
(
ctx
);
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
READ
,
NTFS_I
(
vol
->
vol_ino
));
unmap_mft_record
(
NTFS_I
(
vol
->
vol_ino
));
printk
(
KERN_INFO
"NTFS volume version %i.%i.
\n
"
,
vol
->
major_ver
,
printk
(
KERN_INFO
"NTFS volume version %i.%i.
\n
"
,
vol
->
major_ver
,
vol
->
minor_ver
);
vol
->
minor_ver
);
/*
/*
...
...
fs/ntfs/volume.h
View file @
b14ebcfc
...
@@ -101,6 +101,7 @@ typedef struct {
...
@@ -101,6 +101,7 @@ typedef struct {
* Defined bits for the flags field in the ntfs_volume structure.
* Defined bits for the flags field in the ntfs_volume structure.
*/
*/
typedef
enum
{
typedef
enum
{
NV_Errors
,
/* 1: Volume has errors, prevent remount rw. */
NV_ShowSystemFiles
,
/* 1: Return system files in ntfs_readdir(). */
NV_ShowSystemFiles
,
/* 1: Return system files in ntfs_readdir(). */
NV_CaseSensitive
,
/* 1: Treat file names as case sensitive and
NV_CaseSensitive
,
/* 1: Treat file names as case sensitive and
create filenames in the POSIX namespace.
create filenames in the POSIX namespace.
...
@@ -127,6 +128,7 @@ static inline void NVolClear##flag(ntfs_volume *vol) \
...
@@ -127,6 +128,7 @@ static inline void NVolClear##flag(ntfs_volume *vol) \
}
}
/* Emit the ntfs volume bitops functions. */
/* Emit the ntfs volume bitops functions. */
NVOL_FNS
(
Errors
)
NVOL_FNS
(
ShowSystemFiles
)
NVOL_FNS
(
ShowSystemFiles
)
NVOL_FNS
(
CaseSensitive
)
NVOL_FNS
(
CaseSensitive
)
...
...
include/linux/isdn.h
View file @
b14ebcfc
...
@@ -245,18 +245,12 @@ typedef struct {
...
@@ -245,18 +245,12 @@ typedef struct {
#define ISDN_TIMER_MODEMPLUS 2
#define ISDN_TIMER_MODEMPLUS 2
#define ISDN_TIMER_MODEMRING 4
#define ISDN_TIMER_MODEMRING 4
#define ISDN_TIMER_MODEMXMIT 8
#define ISDN_TIMER_MODEMXMIT 8
#define ISDN_TIMER_NETDIAL 16
#define ISDN_TIMER_NETHANGUP 32
#define ISDN_TIMER_NETHANGUP 32
#define ISDN_TIMER_CARRIER 256
/* Wait for Carrier */
#define ISDN_TIMER_CARRIER 256
/* Wait for Carrier */
#define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \
#define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \
ISDN_TIMER_MODEMXMIT)
ISDN_TIMER_MODEMXMIT)
#define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \
#define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \
ISDN_TIMER_NETDIAL | ISDN_TIMER_CARRIER)
ISDN_TIMER_CARRIER)
/* Timeout-Values for isdn_net_dial() */
#define ISDN_TIMER_DTIMEOUT10 (10*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
#define ISDN_TIMER_DTIMEOUT15 (15*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
#define ISDN_TIMER_DTIMEOUT60 (60*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
/* GLOBAL_FLAGS */
/* GLOBAL_FLAGS */
#define ISDN_GLOBAL_STOPPED 1
#define ISDN_GLOBAL_STOPPED 1
...
@@ -291,9 +285,10 @@ typedef struct {
...
@@ -291,9 +285,10 @@ typedef struct {
typedef
struct
isdn_net_local_s
{
typedef
struct
isdn_net_local_s
{
ulong
magic
;
ulong
magic
;
char
name
[
10
];
/* Name of device */
char
name
[
10
];
/* Name of device */
struct
timer_list
dial_timer
;
/* dial timeout */
int
dial_event
;
/* event in case of timer expiry */
struct
net_device_stats
stats
;
/* Ethernet Statistics */
struct
net_device_stats
stats
;
/* Ethernet Statistics */
int
isdn_device
;
/* Index to isdn-device */
int
isdn_slot
;
/* Index to isdn device/channel */
int
isdn_channel
;
/* Index to isdn-channel */
int
ppp_slot
;
/* PPPD device slot number */
int
ppp_slot
;
/* PPPD device slot number */
int
pre_device
;
/* Preselected isdn-device */
int
pre_device
;
/* Preselected isdn-device */
int
pre_channel
;
/* Preselected isdn-channel */
int
pre_channel
;
/* Preselected isdn-channel */
...
@@ -302,7 +297,6 @@ typedef struct isdn_net_local_s {
...
@@ -302,7 +297,6 @@ typedef struct isdn_net_local_s {
int
dialretry
;
/* Counter for Dialout-retries */
int
dialretry
;
/* Counter for Dialout-retries */
int
dialmax
;
/* Max. Number of Dial-retries */
int
dialmax
;
/* Max. Number of Dial-retries */
int
cbdelay
;
/* Delay before Callback starts */
int
cbdelay
;
/* Delay before Callback starts */
int
dtimer
;
/* Timeout-counter for dialing */
char
msn
[
ISDN_MSNLEN
];
/* MSNs/EAZs for this interface */
char
msn
[
ISDN_MSNLEN
];
/* MSNs/EAZs for this interface */
u_char
cbhup
;
/* Flag: Reject Call before Callback*/
u_char
cbhup
;
/* Flag: Reject Call before Callback*/
u_char
dialstate
;
/* State for dialing */
u_char
dialstate
;
/* State for dialing */
...
@@ -387,12 +381,12 @@ typedef struct isdn_net_local_s {
...
@@ -387,12 +381,12 @@ typedef struct isdn_net_local_s {
/* the interface itself */
/* the interface itself */
typedef
struct
isdn_net_dev_s
{
typedef
struct
isdn_net_dev_s
{
isdn_net_local
*
local
;
isdn_net_local
local
;
isdn_net_local
*
queue
;
/* circular list of all bundled
isdn_net_local
*
queue
;
/* circular list of all bundled
channels, which are currently
channels, which are currently
online */
online */
spinlock_t
queue_lock
;
/* lock to protect queue */
spinlock_t
queue_lock
;
/* lock to protect queue */
void
*
next
;
/* Pointer to next isdn-interface
*/
struct
list_head
global_list
;
/* global list of all isdn_net_devs
*/
struct
net_device
dev
;
/* interface to upper levels */
struct
net_device
dev
;
/* interface to upper levels */
#ifdef CONFIG_ISDN_PPP
#ifdef CONFIG_ISDN_PPP
ippp_bundle
*
pb
;
/* pointer to the common bundle structure
ippp_bundle
*
pb
;
/* pointer to the common bundle structure
...
@@ -480,9 +474,7 @@ typedef struct modem_info {
...
@@ -480,9 +474,7 @@ typedef struct modem_info {
/* 2 = B-Channel is up, deliver d.*/
/* 2 = B-Channel is up, deliver d.*/
int
dialing
;
/* Dial in progress or ATA */
int
dialing
;
/* Dial in progress or ATA */
int
rcvsched
;
/* Receive needs schedule */
int
rcvsched
;
/* Receive needs schedule */
int
isdn_driver
;
/* Index to isdn-driver */
int
isdn_slot
;
/* Index to isdn-driver/channel */
int
isdn_channel
;
/* Index to isdn-channel */
int
drv_index
;
/* Index to dev->usage */
int
ncarrier
;
/* Flag: schedule NO CARRIER */
int
ncarrier
;
/* Flag: schedule NO CARRIER */
unsigned
char
last_cause
[
8
];
/* Last cause message */
unsigned
char
last_cause
[
8
];
/* Last cause message */
unsigned
char
last_num
[
ISDN_MSNLEN
];
unsigned
char
last_num
[
ISDN_MSNLEN
];
...
@@ -608,24 +600,10 @@ typedef struct isdn_devt {
...
@@ -608,24 +600,10 @@ typedef struct isdn_devt {
infostruct
*
infochain
;
/* List of open info-devs. */
infostruct
*
infochain
;
/* List of open info-devs. */
wait_queue_head_t
info_waitq
;
/* Wait-Queue for isdninfo */
wait_queue_head_t
info_waitq
;
/* Wait-Queue for isdninfo */
struct
timer_list
timer
;
/* Misc.-function Timer */
struct
timer_list
timer
;
/* Misc.-function Timer */
int
chanmap
[
ISDN_MAX_CHANNELS
];
/* Map minor->device-channel */
int
drvmap
[
ISDN_MAX_CHANNELS
];
/* Map minor->driver-index */
int
usage
[
ISDN_MAX_CHANNELS
];
/* Used by tty/ip/voice */
char
num
[
ISDN_MAX_CHANNELS
][
ISDN_MSNLEN
];
/* Remote number of active ch.*/
int
m_idx
[
ISDN_MAX_CHANNELS
];
/* Index for mdm.... */
driver
*
drv
[
ISDN_MAX_DRIVERS
];
/* Array of drivers */
driver
*
drv
[
ISDN_MAX_DRIVERS
];
/* Array of drivers */
isdn_net_dev
*
netdev
;
/* Linked list of net-if's */
char
drvid
[
ISDN_MAX_DRIVERS
][
20
];
/* Driver-ID */
char
drvid
[
ISDN_MAX_DRIVERS
][
20
];
/* Driver-ID */
struct
task_struct
*
profd
;
/* For iprofd */
struct
task_struct
*
profd
;
/* For iprofd */
modem
mdm
;
/* tty-driver-data */
modem
mdm
;
/* tty-driver-data */
isdn_net_dev
*
rx_netdev
[
ISDN_MAX_CHANNELS
];
/* rx netdev-pointers */
isdn_net_dev
*
st_netdev
[
ISDN_MAX_CHANNELS
];
/* stat netdev-pointers */
ulong
ibytes
[
ISDN_MAX_CHANNELS
];
/* Statistics incoming bytes */
ulong
obytes
[
ISDN_MAX_CHANNELS
];
/* Statistics outgoing bytes */
int
v110emu
[
ISDN_MAX_CHANNELS
];
/* V.110 emulator-mode 0=none */
atomic_t
v110use
[
ISDN_MAX_CHANNELS
];
/* Usage-Semaphore for stream */
isdn_v110_stream
*
v110
[
ISDN_MAX_CHANNELS
];
/* V.110 private data */
struct
semaphore
sem
;
/* serialize list access*/
struct
semaphore
sem
;
/* serialize list access*/
unsigned
long
global_features
;
unsigned
long
global_features
;
#ifdef CONFIG_DEVFS_FS
#ifdef CONFIG_DEVFS_FS
...
...
include/linux/isdnif.h
View file @
b14ebcfc
...
@@ -418,9 +418,7 @@ typedef struct {
...
@@ -418,9 +418,7 @@ typedef struct {
char
display
[
85
];
/* display message data */
char
display
[
85
];
/* display message data */
isdn_cmd_stat
isdn_io
;
/* ISDN IO-parameter/result */
isdn_cmd_stat
isdn_io
;
/* ISDN IO-parameter/result */
aux_s
aux
;
/* for modem commands/indications */
aux_s
aux
;
/* for modem commands/indications */
#ifdef CONFIG_ISDN_TTY_FAX
T30_s
*
fax
;
/* Pointer to ttys fax struct */
T30_s
*
fax
;
/* Pointer to ttys fax struct */
#endif
ulong
userdata
;
/* User Data */
ulong
userdata
;
/* User Data */
}
parm
;
}
parm
;
}
isdn_ctrl
;
}
isdn_ctrl
;
...
...
mm/mmap.c
View file @
b14ebcfc
...
@@ -422,6 +422,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
...
@@ -422,6 +422,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
{
{
struct
mm_struct
*
mm
=
current
->
mm
;
struct
mm_struct
*
mm
=
current
->
mm
;
struct
vm_area_struct
*
vma
,
*
prev
;
struct
vm_area_struct
*
vma
,
*
prev
;
struct
inode
*
inode
=
NULL
;
unsigned
int
vm_flags
;
unsigned
int
vm_flags
;
int
correct_wcount
=
0
;
int
correct_wcount
=
0
;
int
error
;
int
error
;
...
@@ -469,17 +470,18 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
...
@@ -469,17 +470,18 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
}
}
if
(
file
)
{
if
(
file
)
{
inode
=
file
->
f_dentry
->
d_inode
;
switch
(
flags
&
MAP_TYPE
)
{
switch
(
flags
&
MAP_TYPE
)
{
case
MAP_SHARED
:
case
MAP_SHARED
:
if
((
prot
&
PROT_WRITE
)
&&
!
(
file
->
f_mode
&
FMODE_WRITE
))
if
((
prot
&
PROT_WRITE
)
&&
!
(
file
->
f_mode
&
FMODE_WRITE
))
return
-
EACCES
;
return
-
EACCES
;
/* Make sure we don't allow writing to an append-only file.. */
/* Make sure we don't allow writing to an append-only file.. */
if
(
IS_APPEND
(
file
->
f_dentry
->
d_
inode
)
&&
(
file
->
f_mode
&
FMODE_WRITE
))
if
(
IS_APPEND
(
inode
)
&&
(
file
->
f_mode
&
FMODE_WRITE
))
return
-
EACCES
;
return
-
EACCES
;
/* make sure there are no mandatory locks on the file. */
/* make sure there are no mandatory locks on the file. */
if
(
locks_verify_locked
(
file
->
f_dentry
->
d_
inode
))
if
(
locks_verify_locked
(
inode
))
return
-
EAGAIN
;
return
-
EAGAIN
;
vm_flags
|=
VM_SHARED
|
VM_MAYSHARE
;
vm_flags
|=
VM_SHARED
|
VM_MAYSHARE
;
...
@@ -603,7 +605,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
...
@@ -603,7 +605,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
vma_link
(
mm
,
vma
,
prev
,
rb_link
,
rb_parent
);
vma_link
(
mm
,
vma
,
prev
,
rb_link
,
rb_parent
);
if
(
correct_wcount
)
if
(
correct_wcount
)
atomic_inc
(
&
file
->
f_dentry
->
d_
inode
->
i_writecount
);
atomic_inc
(
&
inode
->
i_writecount
);
out:
out:
mm
->
total_vm
+=
len
>>
PAGE_SHIFT
;
mm
->
total_vm
+=
len
>>
PAGE_SHIFT
;
...
@@ -615,7 +617,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
...
@@ -615,7 +617,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
unmap_and_free_vma:
unmap_and_free_vma:
if
(
correct_wcount
)
if
(
correct_wcount
)
atomic_inc
(
&
file
->
f_dentry
->
d_
inode
->
i_writecount
);
atomic_inc
(
&
inode
->
i_writecount
);
vma
->
vm_file
=
NULL
;
vma
->
vm_file
=
NULL
;
fput
(
file
);
fput
(
file
);
...
@@ -755,38 +757,41 @@ struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr,
...
@@ -755,38 +757,41 @@ struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr,
return
prev
?
prev
->
vm_next
:
vma
;
return
prev
?
prev
->
vm_next
:
vma
;
}
}
#ifdef ARCH_STACK_GROWSUP
/*
/*
* vma is the first one with address < vma->vm_end,
* vma is the first one with address > vma->vm_end. Have to extend vma.
* and even address < vma->vm_start. Have to extend vma.
*/
*/
int
expand_stack
(
struct
vm_area_struct
*
vma
,
unsigned
long
address
)
int
expand_stack
(
struct
vm_area_struct
*
vma
,
unsigned
long
address
)
{
{
unsigned
long
grow
;
unsigned
long
grow
;
if
(
!
(
vma
->
vm_flags
&
VM_GROWSUP
))
return
-
EFAULT
;
/*
/*
* vma->vm_start/vm_end cannot change under us because the caller
* vma->vm_start/vm_end cannot change under us because the caller
* is required to hold the mmap_sem in
write
mode. We need to get
* is required to hold the mmap_sem in
read
mode. We need to get
* the spinlock only before relocating the vma range ourself.
* the spinlock only before relocating the vma range ourself.
*/
*/
address
+=
4
+
PAGE_SIZE
-
1
;
address
&=
PAGE_MASK
;
address
&=
PAGE_MASK
;
spin_lock
(
&
vma
->
vm_mm
->
page_table_lock
);
spin_lock
(
&
vma
->
vm_mm
->
page_table_lock
);
grow
=
(
vma
->
vm_start
-
address
)
>>
PAGE_SHIFT
;
grow
=
(
address
-
vma
->
vm_end
)
>>
PAGE_SHIFT
;
/* Overcommit.. */
/* Overcommit.. */
if
(
!
vm_enough_memory
(
grow
))
{
if
(
!
vm_enough_memory
(
grow
))
{
spin_unlock
(
&
vma
->
vm_mm
->
page_table_lock
);
spin_unlock
(
&
vma
->
vm_mm
->
page_table_lock
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
if
(
vma
->
vm_end
-
address
>
current
->
rlim
[
RLIMIT_STACK
].
rlim_cur
||
if
(
address
-
vma
->
vm_start
>
current
->
rlim
[
RLIMIT_STACK
].
rlim_cur
||
((
vma
->
vm_mm
->
total_vm
+
grow
)
<<
PAGE_SHIFT
)
>
((
vma
->
vm_mm
->
total_vm
+
grow
)
<<
PAGE_SHIFT
)
>
current
->
rlim
[
RLIMIT_AS
].
rlim_cur
)
{
current
->
rlim
[
RLIMIT_AS
].
rlim_cur
)
{
spin_unlock
(
&
vma
->
vm_mm
->
page_table_lock
);
spin_unlock
(
&
vma
->
vm_mm
->
page_table_lock
);
vm_unacct_memory
(
grow
);
vm_unacct_memory
(
grow
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
vma
->
vm_start
=
address
;
vma
->
vm_end
=
address
;
vma
->
vm_pgoff
-=
grow
;
vma
->
vm_mm
->
total_vm
+=
grow
;
vma
->
vm_mm
->
total_vm
+=
grow
;
if
(
vma
->
vm_flags
&
VM_LOCKED
)
if
(
vma
->
vm_flags
&
VM_LOCKED
)
vma
->
vm_mm
->
locked_vm
+=
grow
;
vma
->
vm_mm
->
locked_vm
+=
grow
;
...
@@ -794,7 +799,6 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address)
...
@@ -794,7 +799,6 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address)
return
0
;
return
0
;
}
}
#ifdef ARCH_STACK_GROWSUP
struct
vm_area_struct
*
find_extend_vma
(
struct
mm_struct
*
mm
,
unsigned
long
addr
)
struct
vm_area_struct
*
find_extend_vma
(
struct
mm_struct
*
mm
,
unsigned
long
addr
)
{
{
struct
vm_area_struct
*
vma
,
*
prev
;
struct
vm_area_struct
*
vma
,
*
prev
;
...
@@ -811,6 +815,44 @@ struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long add
...
@@ -811,6 +815,44 @@ struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long add
return
prev
;
return
prev
;
}
}
#else
#else
/*
* vma is the first one with address < vma->vm_start. Have to extend vma.
*/
int
expand_stack
(
struct
vm_area_struct
*
vma
,
unsigned
long
address
)
{
unsigned
long
grow
;
/*
* vma->vm_start/vm_end cannot change under us because the caller
* is required to hold the mmap_sem in read mode. We need to get
* the spinlock only before relocating the vma range ourself.
*/
address
&=
PAGE_MASK
;
spin_lock
(
&
vma
->
vm_mm
->
page_table_lock
);
grow
=
(
vma
->
vm_start
-
address
)
>>
PAGE_SHIFT
;
/* Overcommit.. */
if
(
!
vm_enough_memory
(
grow
))
{
spin_unlock
(
&
vma
->
vm_mm
->
page_table_lock
);
return
-
ENOMEM
;
}
if
(
vma
->
vm_end
-
address
>
current
->
rlim
[
RLIMIT_STACK
].
rlim_cur
||
((
vma
->
vm_mm
->
total_vm
+
grow
)
<<
PAGE_SHIFT
)
>
current
->
rlim
[
RLIMIT_AS
].
rlim_cur
)
{
spin_unlock
(
&
vma
->
vm_mm
->
page_table_lock
);
vm_unacct_memory
(
grow
);
return
-
ENOMEM
;
}
vma
->
vm_start
=
address
;
vma
->
vm_pgoff
-=
grow
;
vma
->
vm_mm
->
total_vm
+=
grow
;
if
(
vma
->
vm_flags
&
VM_LOCKED
)
vma
->
vm_mm
->
locked_vm
+=
grow
;
spin_unlock
(
&
vma
->
vm_mm
->
page_table_lock
);
return
0
;
}
struct
vm_area_struct
*
find_extend_vma
(
struct
mm_struct
*
mm
,
unsigned
long
addr
)
struct
vm_area_struct
*
find_extend_vma
(
struct
mm_struct
*
mm
,
unsigned
long
addr
)
{
{
struct
vm_area_struct
*
vma
;
struct
vm_area_struct
*
vma
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment