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
nexedi
linux
Commits
aca25753
Commit
aca25753
authored
Jul 01, 2008
by
Krzysztof Hałasa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WAN: Port COSA driver to generic HDLC.
Signed-off-by:
Krzysztof Hałasa
<
khc@pm.waw.pl
>
parent
0bee8db8
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
130 additions
and
167 deletions
+130
-167
drivers/net/wan/Kconfig
drivers/net/wan/Kconfig
+1
-1
drivers/net/wan/Makefile
drivers/net/wan/Makefile
+1
-1
drivers/net/wan/cosa.c
drivers/net/wan/cosa.c
+128
-165
No files found.
drivers/net/wan/Kconfig
View file @
aca25753
...
...
@@ -37,7 +37,7 @@ config HOSTESS_SV11
# The COSA/SRP driver has not been tested as non-modular yet.
config COSA
tristate "COSA/SRP sync serial boards support"
depends on ISA && m && ISA_DMA_API
depends on ISA && m && ISA_DMA_API
&& HDLC
---help---
Driver for COSA and SRP synchronous serial boards.
...
...
drivers/net/wan/Makefile
View file @
aca25753
...
...
@@ -23,7 +23,7 @@ pc300-objs := $(pc300-y)
obj-$(CONFIG_HOSTESS_SV11)
+=
z85230.o syncppp.o hostess_sv11.o
obj-$(CONFIG_SEALEVEL_4021)
+=
z85230.o syncppp.o sealevel.o
obj-$(CONFIG_COSA)
+=
syncppp.o
cosa.o
obj-$(CONFIG_COSA)
+=
cosa.o
obj-$(CONFIG_FARSYNC)
+=
farsync.o
obj-$(CONFIG_DSCC4)
+=
dscc4.o
obj-$(CONFIG_LANMEDIA)
+=
syncppp.o
...
...
drivers/net/wan/cosa.c
View file @
aca25753
...
...
@@ -2,6 +2,7 @@
/*
* Copyright (C) 1995-1997 Jan "Yenya" Kasprzak <kas@fi.muni.cz>
* Generic HDLC port Copyright (C) 2008 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -54,7 +55,7 @@
*
* The Linux driver (unlike the present *BSD drivers :-) can work even
* for the COSA and SRP in one computer and allows each channel to work
* in one of the t
hree modes (character device, Cisco HDLC, Sync PPP
).
* in one of the t
wo modes (character or network device
).
*
* AUTHOR
*
...
...
@@ -72,12 +73,6 @@
* The Comtrol Hostess SV11 driver by Alan Cox
* The Sync PPP/Cisco HDLC layer (syncppp.c) ported to Linux by Alan Cox
*/
/*
* 5/25/1999 : Marcelo Tosatti <marcelo@conectiva.com.br>
* fixed a deadlock in cosa_sppp_open
*/
/* ---------- Headers, macros, data structures ---------- */
#include <linux/module.h>
#include <linux/kernel.h>
...
...
@@ -86,6 +81,7 @@
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/hdlc.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
...
...
@@ -93,14 +89,12 @@
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/smp_lock.h>
#undef COSA_SLOW_IO
/* for testing purposes only */
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/byteorder.h>
#include <net/syncppp.h>
#undef COSA_SLOW_IO
/* for testing purposes only */
#include "cosa.h"
/* Maximum length of the identification string. */
...
...
@@ -112,7 +106,6 @@
/* Per-channel data structure */
struct
channel_data
{
void
*
if_ptr
;
/* General purpose pointer (used by SPPP) */
int
usage
;
/* Usage count; >0 for chrdev, -1 for netdev */
int
num
;
/* Number of the channel */
struct
cosa_data
*
cosa
;
/* Pointer to the per-card structure */
...
...
@@ -136,10 +129,9 @@ struct channel_data {
wait_queue_head_t
txwaitq
,
rxwaitq
;
int
tx_status
,
rx_status
;
/*
SPPP/
HDLC device parts */
struct
ppp_device
ppp
dev
;
/*
generic
HDLC device parts */
struct
net_device
*
net
dev
;
struct
sk_buff
*
rx_skb
,
*
tx_skb
;
struct
net_device_stats
stats
;
};
/* cosa->firmware_status bits */
...
...
@@ -281,21 +273,19 @@ static int cosa_start_tx(struct channel_data *channel, char *buf, int size);
static
void
cosa_kick
(
struct
cosa_data
*
cosa
);
static
int
cosa_dma_able
(
struct
channel_data
*
chan
,
char
*
buf
,
int
data
);
/* SPPP/HDLC stuff */
static
void
sppp_channel_init
(
struct
channel_data
*
chan
);
static
void
sppp_channel_delete
(
struct
channel_data
*
chan
);
static
int
cosa_sppp_open
(
struct
net_device
*
d
);
static
int
cosa_sppp_close
(
struct
net_device
*
d
);
static
void
cosa_sppp_timeout
(
struct
net_device
*
d
);
static
int
cosa_sppp_tx
(
struct
sk_buff
*
skb
,
struct
net_device
*
d
);
static
char
*
sppp_setup_rx
(
struct
channel_data
*
channel
,
int
size
);
static
int
sppp_rx_done
(
struct
channel_data
*
channel
);
static
int
sppp_tx_done
(
struct
channel_data
*
channel
,
int
size
);
static
int
cosa_sppp_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
ifr
,
int
cmd
);
static
struct
net_device_stats
*
cosa_net_stats
(
struct
net_device
*
dev
);
/* Network device stuff */
static
int
cosa_net_attach
(
struct
net_device
*
dev
,
unsigned
short
encoding
,
unsigned
short
parity
);
static
int
cosa_net_open
(
struct
net_device
*
d
);
static
int
cosa_net_close
(
struct
net_device
*
d
);
static
void
cosa_net_timeout
(
struct
net_device
*
d
);
static
int
cosa_net_tx
(
struct
sk_buff
*
skb
,
struct
net_device
*
d
);
static
char
*
cosa_net_setup_rx
(
struct
channel_data
*
channel
,
int
size
);
static
int
cosa_net_rx_done
(
struct
channel_data
*
channel
);
static
int
cosa_net_tx_done
(
struct
channel_data
*
channel
,
int
size
);
static
int
cosa_net_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
ifr
,
int
cmd
);
/* Character device */
static
void
chardev_channel_init
(
struct
channel_data
*
chan
);
static
char
*
chrdev_setup_rx
(
struct
channel_data
*
channel
,
int
size
);
static
int
chrdev_rx_done
(
struct
channel_data
*
channel
);
static
int
chrdev_tx_done
(
struct
channel_data
*
channel
,
int
size
);
...
...
@@ -357,17 +347,17 @@ static void debug_status_in(struct cosa_data *cosa, int status);
static
void
debug_status_out
(
struct
cosa_data
*
cosa
,
int
status
);
#endif
static
inline
struct
channel_data
*
dev_to_chan
(
struct
net_device
*
dev
)
{
return
(
struct
channel_data
*
)
dev_to_hdlc
(
dev
)
->
priv
;
}
/* ---------- Initialization stuff ---------- */
static
int
__init
cosa_init
(
void
)
{
int
i
,
err
=
0
;
printk
(
KERN_INFO
"cosa v1.08 (c) 1997-2000 Jan Kasprzak <kas@fi.muni.cz>
\n
"
);
#ifdef CONFIG_SMP
printk
(
KERN_INFO
"cosa: SMP found. Please mail any success/failure reports to the author.
\n
"
);
#endif
if
(
cosa_major
>
0
)
{
if
(
register_chrdev
(
cosa_major
,
"cosa"
,
&
cosa_fops
))
{
printk
(
KERN_WARNING
"cosa: unable to get major %d
\n
"
,
...
...
@@ -402,7 +392,7 @@ static int __init cosa_init(void)
}
err
=
0
;
goto
out
;
out_chrdev:
unregister_chrdev
(
cosa_major
,
"cosa"
);
out:
...
...
@@ -414,43 +404,29 @@ static void __exit cosa_exit(void)
{
struct
cosa_data
*
cosa
;
int
i
;
printk
(
KERN_INFO
"Unloading the cosa module
\n
"
);
for
(
i
=
0
;
i
<
nr_cards
;
i
++
)
for
(
i
=
0
;
i
<
nr_cards
;
i
++
)
device_destroy
(
cosa_class
,
MKDEV
(
cosa_major
,
i
));
class_destroy
(
cosa_class
);
for
(
cosa
=
cosa_cards
;
nr_cards
--
;
cosa
++
)
{
for
(
cosa
=
cosa_cards
;
nr_cards
--
;
cosa
++
)
{
/* Clean up the per-channel data */
for
(
i
=
0
;
i
<
cosa
->
nchannels
;
i
++
)
{
for
(
i
=
0
;
i
<
cosa
->
nchannels
;
i
++
)
{
/* Chardev driver has no alloc'd per-channel data */
sppp_channel_delete
(
cosa
->
chan
+
i
);
unregister_hdlc_device
(
cosa
->
chan
[
i
].
netdev
);
free_netdev
(
cosa
->
chan
[
i
].
netdev
);
}
/* Clean up the per-card data */
kfree
(
cosa
->
chan
);
kfree
(
cosa
->
bouncebuf
);
free_irq
(
cosa
->
irq
,
cosa
);
free_dma
(
cosa
->
dma
);
release_region
(
cosa
->
datareg
,
is_8bit
(
cosa
)
?
2
:
4
);
release_region
(
cosa
->
datareg
,
is_8bit
(
cosa
)
?
2
:
4
);
}
unregister_chrdev
(
cosa_major
,
"cosa"
);
}
module_exit
(
cosa_exit
);
/*
* This function should register all the net devices needed for the
* single channel.
*/
static
__inline__
void
channel_init
(
struct
channel_data
*
chan
)
{
sprintf
(
chan
->
name
,
"cosa%dc%d"
,
chan
->
cosa
->
num
,
chan
->
num
);
/* Initialize the chardev data structures */
chardev_channel_init
(
chan
);
/* Register the sppp interface */
sppp_channel_init
(
chan
);
}
static
int
cosa_probe
(
int
base
,
int
irq
,
int
dma
)
{
struct
cosa_data
*
cosa
=
cosa_cards
+
nr_cards
;
...
...
@@ -576,13 +552,43 @@ static int cosa_probe(int base, int irq, int dma)
/* Initialize the per-channel data */
cosa
->
chan
=
kcalloc
(
cosa
->
nchannels
,
sizeof
(
struct
channel_data
),
GFP_KERNEL
);
if
(
!
cosa
->
chan
)
{
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
err_out3
;
}
for
(
i
=
0
;
i
<
cosa
->
nchannels
;
i
++
)
{
cosa
->
chan
[
i
].
cosa
=
cosa
;
cosa
->
chan
[
i
].
num
=
i
;
channel_init
(
cosa
->
chan
+
i
);
for
(
i
=
0
;
i
<
cosa
->
nchannels
;
i
++
)
{
struct
channel_data
*
chan
=
&
cosa
->
chan
[
i
];
chan
->
cosa
=
cosa
;
chan
->
num
=
i
;
sprintf
(
chan
->
name
,
"cosa%dc%d"
,
chan
->
cosa
->
num
,
i
);
/* Initialize the chardev data structures */
mutex_init
(
&
chan
->
rlock
);
init_MUTEX
(
&
chan
->
wsem
);
/* Register the network interface */
if
(
!
(
chan
->
netdev
=
alloc_hdlcdev
(
chan
)))
{
printk
(
KERN_WARNING
"%s: alloc_hdlcdev failed.
\n
"
,
chan
->
name
);
goto
err_hdlcdev
;
}
dev_to_hdlc
(
chan
->
netdev
)
->
attach
=
cosa_net_attach
;
dev_to_hdlc
(
chan
->
netdev
)
->
xmit
=
cosa_net_tx
;
chan
->
netdev
->
open
=
cosa_net_open
;
chan
->
netdev
->
stop
=
cosa_net_close
;
chan
->
netdev
->
do_ioctl
=
cosa_net_ioctl
;
chan
->
netdev
->
tx_timeout
=
cosa_net_timeout
;
chan
->
netdev
->
watchdog_timeo
=
TX_TIMEOUT
;
chan
->
netdev
->
base_addr
=
chan
->
cosa
->
datareg
;
chan
->
netdev
->
irq
=
chan
->
cosa
->
irq
;
chan
->
netdev
->
dma
=
chan
->
cosa
->
dma
;
if
(
register_hdlc_device
(
chan
->
netdev
))
{
printk
(
KERN_WARNING
"%s: register_hdlc_device()"
" failed.
\n
"
,
chan
->
netdev
->
name
);
free_netdev
(
chan
->
netdev
);
goto
err_hdlcdev
;
}
}
printk
(
KERN_INFO
"cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels
\n
"
,
...
...
@@ -590,13 +596,20 @@ static int cosa_probe(int base, int irq, int dma)
cosa
->
datareg
,
cosa
->
irq
,
cosa
->
dma
,
cosa
->
nchannels
);
return
nr_cards
++
;
err_hdlcdev:
while
(
i
--
>
0
)
{
unregister_hdlc_device
(
cosa
->
chan
[
i
].
netdev
);
free_netdev
(
cosa
->
chan
[
i
].
netdev
);
}
kfree
(
cosa
->
chan
);
err_out3:
kfree
(
cosa
->
bouncebuf
);
err_out2:
free_dma
(
cosa
->
dma
);
err_out1:
free_irq
(
cosa
->
irq
,
cosa
);
err_out:
err_out:
release_region
(
cosa
->
datareg
,
is_8bit
(
cosa
)
?
2
:
4
);
printk
(
KERN_NOTICE
"cosa%d: allocating resources failed
\n
"
,
cosa
->
num
);
...
...
@@ -604,54 +617,19 @@ static int cosa_probe(int base, int irq, int dma)
}
/*----------
SPPP/HDLC net
device ---------- */
/*----------
network
device ---------- */
static
void
cosa_setup
(
struct
net_device
*
d
)
static
int
cosa_net_attach
(
struct
net_device
*
dev
,
unsigned
short
encoding
,
unsigned
short
parity
)
{
d
->
open
=
cosa_sppp_open
;
d
->
stop
=
cosa_sppp_close
;
d
->
hard_start_xmit
=
cosa_sppp_tx
;
d
->
do_ioctl
=
cosa_sppp_ioctl
;
d
->
get_stats
=
cosa_net_stats
;
d
->
tx_timeout
=
cosa_sppp_timeout
;
d
->
watchdog_timeo
=
TX_TIMEOUT
;
}
static
void
sppp_channel_init
(
struct
channel_data
*
chan
)
{
struct
net_device
*
d
;
chan
->
if_ptr
=
&
chan
->
pppdev
;
d
=
alloc_netdev
(
0
,
chan
->
name
,
cosa_setup
);
if
(
!
d
)
{
printk
(
KERN_WARNING
"%s: alloc_netdev failed.
\n
"
,
chan
->
name
);
return
;
}
chan
->
pppdev
.
dev
=
d
;
d
->
base_addr
=
chan
->
cosa
->
datareg
;
d
->
irq
=
chan
->
cosa
->
irq
;
d
->
dma
=
chan
->
cosa
->
dma
;
d
->
ml_priv
=
chan
;
sppp_attach
(
&
chan
->
pppdev
);
if
(
register_netdev
(
d
))
{
printk
(
KERN_WARNING
"%s: register_netdev failed.
\n
"
,
d
->
name
);
sppp_detach
(
d
);
free_netdev
(
d
);
chan
->
pppdev
.
dev
=
NULL
;
return
;
}
}
static
void
sppp_channel_delete
(
struct
channel_data
*
chan
)
{
unregister_netdev
(
chan
->
pppdev
.
dev
);
sppp_detach
(
chan
->
pppdev
.
dev
);
free_netdev
(
chan
->
pppdev
.
dev
);
chan
->
pppdev
.
dev
=
NULL
;
if
(
encoding
==
ENCODING_NRZ
&&
parity
==
PARITY_CRC16_PR1_CCITT
)
return
0
;
return
-
EINVAL
;
}
static
int
cosa_
sppp_open
(
struct
net_device
*
d
)
static
int
cosa_
net_open
(
struct
net_device
*
dev
)
{
struct
channel_data
*
chan
=
d
->
ml_priv
;
struct
channel_data
*
chan
=
d
ev_to_chan
(
dev
)
;
int
err
;
unsigned
long
flags
;
...
...
@@ -662,36 +640,35 @@ static int cosa_sppp_open(struct net_device *d)
}
spin_lock_irqsave
(
&
chan
->
cosa
->
lock
,
flags
);
if
(
chan
->
usage
!=
0
)
{
printk
(
KERN_WARNING
"%s:
sppp_open called with usage count %d
\n
"
,
chan
->
name
,
chan
->
usage
);
printk
(
KERN_WARNING
"%s:
cosa_net_open called with usage count"
" %d
\n
"
,
chan
->
name
,
chan
->
usage
);
spin_unlock_irqrestore
(
&
chan
->
cosa
->
lock
,
flags
);
return
-
EBUSY
;
}
chan
->
setup_rx
=
sppp
_setup_rx
;
chan
->
tx_done
=
sppp
_tx_done
;
chan
->
rx_done
=
sppp
_rx_done
;
chan
->
usage
=
-
1
;
chan
->
setup_rx
=
cosa_net
_setup_rx
;
chan
->
tx_done
=
cosa_net
_tx_done
;
chan
->
rx_done
=
cosa_net
_rx_done
;
chan
->
usage
=
-
1
;
chan
->
cosa
->
usage
++
;
spin_unlock_irqrestore
(
&
chan
->
cosa
->
lock
,
flags
);
err
=
sppp_open
(
d
);
err
=
hdlc_open
(
dev
);
if
(
err
)
{
spin_lock_irqsave
(
&
chan
->
cosa
->
lock
,
flags
);
chan
->
usage
=
0
;
chan
->
usage
=
0
;
chan
->
cosa
->
usage
--
;
spin_unlock_irqrestore
(
&
chan
->
cosa
->
lock
,
flags
);
return
err
;
}
netif_start_queue
(
d
);
netif_start_queue
(
d
ev
);
cosa_enable_rx
(
chan
);
return
0
;
}
static
int
cosa_
sppp
_tx
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
static
int
cosa_
net
_tx
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
struct
channel_data
*
chan
=
dev
->
ml_priv
;
struct
channel_data
*
chan
=
dev
_to_chan
(
dev
)
;
netif_stop_queue
(
dev
);
...
...
@@ -700,16 +677,16 @@ static int cosa_sppp_tx(struct sk_buff *skb, struct net_device *dev)
return
0
;
}
static
void
cosa_
sppp
_timeout
(
struct
net_device
*
dev
)
static
void
cosa_
net
_timeout
(
struct
net_device
*
dev
)
{
struct
channel_data
*
chan
=
dev
->
ml_priv
;
struct
channel_data
*
chan
=
dev
_to_chan
(
dev
)
;
if
(
test_bit
(
RXBIT
,
&
chan
->
cosa
->
rxtx
))
{
chan
->
stats
.
rx_errors
++
;
chan
->
stats
.
rx_missed_errors
++
;
chan
->
netdev
->
stats
.
rx_errors
++
;
chan
->
netdev
->
stats
.
rx_missed_errors
++
;
}
else
{
chan
->
stats
.
tx_errors
++
;
chan
->
stats
.
tx_aborted_errors
++
;
chan
->
netdev
->
stats
.
tx_errors
++
;
chan
->
netdev
->
stats
.
tx_aborted_errors
++
;
}
cosa_kick
(
chan
->
cosa
);
if
(
chan
->
tx_skb
)
{
...
...
@@ -719,13 +696,13 @@ static void cosa_sppp_timeout(struct net_device *dev)
netif_wake_queue
(
dev
);
}
static
int
cosa_
sppp_close
(
struct
net_device
*
d
)
static
int
cosa_
net_close
(
struct
net_device
*
dev
)
{
struct
channel_data
*
chan
=
d
->
ml_priv
;
struct
channel_data
*
chan
=
d
ev_to_chan
(
dev
)
;
unsigned
long
flags
;
netif_stop_queue
(
d
);
sppp_close
(
d
);
netif_stop_queue
(
d
ev
);
hdlc_close
(
dev
);
cosa_disable_rx
(
chan
);
spin_lock_irqsave
(
&
chan
->
cosa
->
lock
,
flags
);
if
(
chan
->
rx_skb
)
{
...
...
@@ -736,13 +713,13 @@ static int cosa_sppp_close(struct net_device *d)
kfree_skb
(
chan
->
tx_skb
);
chan
->
tx_skb
=
NULL
;
}
chan
->
usage
=
0
;
chan
->
usage
=
0
;
chan
->
cosa
->
usage
--
;
spin_unlock_irqrestore
(
&
chan
->
cosa
->
lock
,
flags
);
return
0
;
}
static
char
*
sppp
_setup_rx
(
struct
channel_data
*
chan
,
int
size
)
static
char
*
cosa_net
_setup_rx
(
struct
channel_data
*
chan
,
int
size
)
{
/*
* We can safely fall back to non-dma-able memory, because we have
...
...
@@ -754,66 +731,53 @@ static char *sppp_setup_rx(struct channel_data *chan, int size)
if
(
chan
->
rx_skb
==
NULL
)
{
printk
(
KERN_NOTICE
"%s: Memory squeeze, dropping packet
\n
"
,
chan
->
name
);
chan
->
stats
.
rx_dropped
++
;
chan
->
netdev
->
stats
.
rx_dropped
++
;
return
NULL
;
}
chan
->
pppdev
.
dev
->
trans_start
=
jiffies
;
chan
->
net
dev
->
trans_start
=
jiffies
;
return
skb_put
(
chan
->
rx_skb
,
size
);
}
static
int
sppp
_rx_done
(
struct
channel_data
*
chan
)
static
int
cosa_net
_rx_done
(
struct
channel_data
*
chan
)
{
if
(
!
chan
->
rx_skb
)
{
printk
(
KERN_WARNING
"%s: rx_done with empty skb!
\n
"
,
chan
->
name
);
chan
->
stats
.
rx_errors
++
;
chan
->
stats
.
rx_frame_errors
++
;
chan
->
netdev
->
stats
.
rx_errors
++
;
chan
->
netdev
->
stats
.
rx_frame_errors
++
;
return
0
;
}
chan
->
rx_skb
->
protocol
=
h
tons
(
ETH_P_WAN_PPP
);
chan
->
rx_skb
->
dev
=
chan
->
pppdev
.
dev
;
chan
->
rx_skb
->
protocol
=
h
dlc_type_trans
(
chan
->
rx_skb
,
chan
->
netdev
);
chan
->
rx_skb
->
dev
=
chan
->
net
dev
;
skb_reset_mac_header
(
chan
->
rx_skb
);
chan
->
stats
.
rx_packets
++
;
chan
->
stats
.
rx_bytes
+=
chan
->
cosa
->
rxsize
;
chan
->
netdev
->
stats
.
rx_packets
++
;
chan
->
netdev
->
stats
.
rx_bytes
+=
chan
->
cosa
->
rxsize
;
netif_rx
(
chan
->
rx_skb
);
chan
->
rx_skb
=
NULL
;
chan
->
pppdev
.
dev
->
last_rx
=
jiffies
;
chan
->
net
dev
->
last_rx
=
jiffies
;
return
0
;
}
/* ARGSUSED */
static
int
sppp
_tx_done
(
struct
channel_data
*
chan
,
int
size
)
static
int
cosa_net
_tx_done
(
struct
channel_data
*
chan
,
int
size
)
{
if
(
!
chan
->
tx_skb
)
{
printk
(
KERN_WARNING
"%s: tx_done with empty skb!
\n
"
,
chan
->
name
);
chan
->
stats
.
tx_errors
++
;
chan
->
stats
.
tx_aborted_errors
++
;
chan
->
netdev
->
stats
.
tx_errors
++
;
chan
->
netdev
->
stats
.
tx_aborted_errors
++
;
return
1
;
}
dev_kfree_skb_irq
(
chan
->
tx_skb
);
chan
->
tx_skb
=
NULL
;
chan
->
stats
.
tx_packets
++
;
chan
->
stats
.
tx_bytes
+=
size
;
netif_wake_queue
(
chan
->
pppdev
.
dev
);
chan
->
netdev
->
stats
.
tx_packets
++
;
chan
->
netdev
->
stats
.
tx_bytes
+=
size
;
netif_wake_queue
(
chan
->
net
dev
);
return
1
;
}
static
struct
net_device_stats
*
cosa_net_stats
(
struct
net_device
*
dev
)
{
struct
channel_data
*
chan
=
dev
->
ml_priv
;
return
&
chan
->
stats
;
}
/*---------- Character device ---------- */
static
void
chardev_channel_init
(
struct
channel_data
*
chan
)
{
mutex_init
(
&
chan
->
rlock
);
init_MUTEX
(
&
chan
->
wsem
);
}
static
ssize_t
cosa_read
(
struct
file
*
file
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
...
...
@@ -1223,16 +1187,15 @@ static int cosa_ioctl_common(struct cosa_data *cosa,
return
-
ENOIOCTLCMD
;
}
static
int
cosa_sppp_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
ifr
,
int
cmd
)
static
int
cosa_net_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
ifr
,
int
cmd
)
{
int
rv
;
struct
channel_data
*
chan
=
dev
->
ml_priv
;
rv
=
cosa_ioctl_common
(
chan
->
cosa
,
chan
,
cmd
,
(
unsigned
long
)
ifr
->
ifr_data
);
if
(
rv
==
-
ENOIOCTLCMD
)
{
return
sppp_do_ioctl
(
dev
,
ifr
,
cmd
);
}
return
rv
;
struct
channel_data
*
chan
=
dev
_to_chan
(
dev
)
;
rv
=
cosa_ioctl_common
(
chan
->
cosa
,
chan
,
cmd
,
(
unsigned
long
)
ifr
->
ifr_data
);
if
(
rv
!=
-
ENOIOCTLCMD
)
return
rv
;
return
hdlc_ioctl
(
dev
,
ifr
,
cmd
)
;
}
static
int
cosa_chardev_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
...
...
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