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
4e700bcd
Commit
4e700bcd
authored
Mar 30, 2011
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
parents
6aba74f2
a84b50ce
Changes
25
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
531 additions
and
216 deletions
+531
-216
drivers/atm/solos-pci.c
drivers/atm/solos-pci.c
+11
-28
drivers/connector/cn_queue.c
drivers/connector/cn_queue.c
+17
-41
drivers/connector/connector.c
drivers/connector/connector.c
+12
-35
drivers/net/atlx/atl2.c
drivers/net/atlx/atl2.c
+14
-8
drivers/net/irda/via-ircc.c
drivers/net/irda/via-ircc.c
+21
-73
drivers/net/phy/phy_device.c
drivers/net/phy/phy_device.c
+6
-2
drivers/net/usb/Kconfig
drivers/net/usb/Kconfig
+15
-0
drivers/net/usb/Makefile
drivers/net/usb/Makefile
+1
-0
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_ether.c
+15
-6
drivers/net/usb/lg-vl600.c
drivers/net/usb/lg-vl600.c
+346
-0
drivers/net/usb/usbnet.c
drivers/net/usb/usbnet.c
+7
-3
include/linux/atmdev.h
include/linux/atmdev.h
+1
-0
include/linux/connector.h
include/linux/connector.h
+3
-13
include/linux/skbuff.h
include/linux/skbuff.h
+1
-1
include/linux/usb/usbnet.h
include/linux/usb/usbnet.h
+3
-0
include/net/if_inet6.h
include/net/if_inet6.h
+16
-0
include/net/ip.h
include/net/ip.h
+8
-0
net/atm/common.c
net/atm/common.c
+1
-0
net/bridge/br_multicast.c
net/bridge/br_multicast.c
+1
-1
net/bridge/br_stp_if.c
net/bridge/br_stp_if.c
+1
-1
net/core/dev.c
net/core/dev.c
+22
-2
net/ipv4/arp.c
net/ipv4/arp.c
+3
-0
net/ipv4/fib_frontend.c
net/ipv4/fib_frontend.c
+2
-0
net/ipv6/ndisc.c
net/ipv6/ndisc.c
+2
-0
net/sctp/protocol.c
net/sctp/protocol.c
+2
-2
No files found.
drivers/atm/solos-pci.c
View file @
4e700bcd
...
@@ -165,7 +165,6 @@ static uint32_t fpga_tx(struct solos_card *);
...
@@ -165,7 +165,6 @@ static uint32_t fpga_tx(struct solos_card *);
static
irqreturn_t
solos_irq
(
int
irq
,
void
*
dev_id
);
static
irqreturn_t
solos_irq
(
int
irq
,
void
*
dev_id
);
static
struct
atm_vcc
*
find_vcc
(
struct
atm_dev
*
dev
,
short
vpi
,
int
vci
);
static
struct
atm_vcc
*
find_vcc
(
struct
atm_dev
*
dev
,
short
vpi
,
int
vci
);
static
int
list_vccs
(
int
vci
);
static
int
list_vccs
(
int
vci
);
static
void
release_vccs
(
struct
atm_dev
*
dev
);
static
int
atm_init
(
struct
solos_card
*
,
struct
device
*
);
static
int
atm_init
(
struct
solos_card
*
,
struct
device
*
);
static
void
atm_remove
(
struct
solos_card
*
);
static
void
atm_remove
(
struct
solos_card
*
);
static
int
send_command
(
struct
solos_card
*
card
,
int
dev
,
const
char
*
buf
,
size_t
size
);
static
int
send_command
(
struct
solos_card
*
card
,
int
dev
,
const
char
*
buf
,
size_t
size
);
...
@@ -384,7 +383,6 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb
...
@@ -384,7 +383,6 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb
/* Anything but 'Showtime' is down */
/* Anything but 'Showtime' is down */
if
(
strcmp
(
state_str
,
"Showtime"
))
{
if
(
strcmp
(
state_str
,
"Showtime"
))
{
atm_dev_signal_change
(
card
->
atmdev
[
port
],
ATM_PHY_SIG_LOST
);
atm_dev_signal_change
(
card
->
atmdev
[
port
],
ATM_PHY_SIG_LOST
);
release_vccs
(
card
->
atmdev
[
port
]);
dev_info
(
&
card
->
dev
->
dev
,
"Port %d: %s
\n
"
,
port
,
state_str
);
dev_info
(
&
card
->
dev
->
dev
,
"Port %d: %s
\n
"
,
port
,
state_str
);
return
0
;
return
0
;
}
}
...
@@ -697,7 +695,7 @@ void solos_bh(unsigned long card_arg)
...
@@ -697,7 +695,7 @@ void solos_bh(unsigned long card_arg)
size
);
size
);
}
}
if
(
atmdebug
)
{
if
(
atmdebug
)
{
dev_info
(
&
card
->
dev
->
dev
,
"Received:
device
%d
\n
"
,
port
);
dev_info
(
&
card
->
dev
->
dev
,
"Received:
port
%d
\n
"
,
port
);
dev_info
(
&
card
->
dev
->
dev
,
"size: %d VPI: %d VCI: %d
\n
"
,
dev_info
(
&
card
->
dev
->
dev
,
"size: %d VPI: %d VCI: %d
\n
"
,
size
,
le16_to_cpu
(
header
->
vpi
),
size
,
le16_to_cpu
(
header
->
vpi
),
le16_to_cpu
(
header
->
vci
));
le16_to_cpu
(
header
->
vci
));
...
@@ -710,8 +708,8 @@ void solos_bh(unsigned long card_arg)
...
@@ -710,8 +708,8 @@ void solos_bh(unsigned long card_arg)
le16_to_cpu
(
header
->
vci
));
le16_to_cpu
(
header
->
vci
));
if
(
!
vcc
)
{
if
(
!
vcc
)
{
if
(
net_ratelimit
())
if
(
net_ratelimit
())
dev_warn
(
&
card
->
dev
->
dev
,
"Received packet for unknown V
CI.VP
I %d.%d on port %d
\n
"
,
dev_warn
(
&
card
->
dev
->
dev
,
"Received packet for unknown V
PI.VC
I %d.%d on port %d
\n
"
,
le16_to_cpu
(
header
->
v
ci
),
le16_to_cpu
(
header
->
vp
i
),
le16_to_cpu
(
header
->
v
pi
),
le16_to_cpu
(
header
->
vc
i
),
port
);
port
);
continue
;
continue
;
}
}
...
@@ -830,28 +828,6 @@ static int list_vccs(int vci)
...
@@ -830,28 +828,6 @@ static int list_vccs(int vci)
return
num_found
;
return
num_found
;
}
}
static
void
release_vccs
(
struct
atm_dev
*
dev
)
{
int
i
;
write_lock_irq
(
&
vcc_sklist_lock
);
for
(
i
=
0
;
i
<
VCC_HTABLE_SIZE
;
i
++
)
{
struct
hlist_head
*
head
=
&
vcc_hash
[
i
];
struct
hlist_node
*
node
,
*
tmp
;
struct
sock
*
s
;
struct
atm_vcc
*
vcc
;
sk_for_each_safe
(
s
,
node
,
tmp
,
head
)
{
vcc
=
atm_sk
(
s
);
if
(
vcc
->
dev
==
dev
)
{
vcc_release_async
(
vcc
,
-
EPIPE
);
sk_del_node_init
(
s
);
}
}
}
write_unlock_irq
(
&
vcc_sklist_lock
);
}
static
int
popen
(
struct
atm_vcc
*
vcc
)
static
int
popen
(
struct
atm_vcc
*
vcc
)
{
{
...
@@ -1018,8 +994,15 @@ static uint32_t fpga_tx(struct solos_card *card)
...
@@ -1018,8 +994,15 @@ static uint32_t fpga_tx(struct solos_card *card)
/* Clean up and free oldskb now it's gone */
/* Clean up and free oldskb now it's gone */
if
(
atmdebug
)
{
if
(
atmdebug
)
{
struct
pkt_hdr
*
header
=
(
void
*
)
oldskb
->
data
;
int
size
=
le16_to_cpu
(
header
->
size
);
skb_pull
(
oldskb
,
sizeof
(
*
header
));
dev_info
(
&
card
->
dev
->
dev
,
"Transmitted: port %d
\n
"
,
dev_info
(
&
card
->
dev
->
dev
,
"Transmitted: port %d
\n
"
,
port
);
port
);
dev_info
(
&
card
->
dev
->
dev
,
"size: %d VPI: %d VCI: %d
\n
"
,
size
,
le16_to_cpu
(
header
->
vpi
),
le16_to_cpu
(
header
->
vci
));
print_buffer
(
oldskb
);
print_buffer
(
oldskb
);
}
}
...
@@ -1262,7 +1245,7 @@ static int atm_init(struct solos_card *card, struct device *parent)
...
@@ -1262,7 +1245,7 @@ static int atm_init(struct solos_card *card, struct device *parent)
card
->
atmdev
[
i
]
->
ci_range
.
vci_bits
=
16
;
card
->
atmdev
[
i
]
->
ci_range
.
vci_bits
=
16
;
card
->
atmdev
[
i
]
->
dev_data
=
card
;
card
->
atmdev
[
i
]
->
dev_data
=
card
;
card
->
atmdev
[
i
]
->
phy_data
=
(
void
*
)(
unsigned
long
)
i
;
card
->
atmdev
[
i
]
->
phy_data
=
(
void
*
)(
unsigned
long
)
i
;
atm_dev_signal_change
(
card
->
atmdev
[
i
],
ATM_PHY_SIG_
UNKNOWN
);
atm_dev_signal_change
(
card
->
atmdev
[
i
],
ATM_PHY_SIG_
FOUND
);
skb
=
alloc_skb
(
sizeof
(
*
header
),
GFP_ATOMIC
);
skb
=
alloc_skb
(
sizeof
(
*
header
),
GFP_ATOMIC
);
if
(
!
skb
)
{
if
(
!
skb
)
{
...
...
drivers/connector/cn_queue.c
View file @
4e700bcd
...
@@ -31,24 +31,9 @@
...
@@ -31,24 +31,9 @@
#include <linux/connector.h>
#include <linux/connector.h>
#include <linux/delay.h>
#include <linux/delay.h>
void
cn_queue_wrapper
(
struct
work_struct
*
work
)
{
struct
cn_callback_entry
*
cbq
=
container_of
(
work
,
struct
cn_callback_entry
,
work
);
struct
cn_callback_data
*
d
=
&
cbq
->
data
;
struct
cn_msg
*
msg
=
NLMSG_DATA
(
nlmsg_hdr
(
d
->
skb
));
struct
netlink_skb_parms
*
nsp
=
&
NETLINK_CB
(
d
->
skb
);
d
->
callback
(
msg
,
nsp
);
kfree_skb
(
d
->
skb
);
d
->
skb
=
NULL
;
kfree
(
d
->
free
);
}
static
struct
cn_callback_entry
*
static
struct
cn_callback_entry
*
cn_queue_alloc_callback_entry
(
const
char
*
name
,
struct
cb_id
*
id
,
cn_queue_alloc_callback_entry
(
struct
cn_queue_dev
*
dev
,
const
char
*
name
,
struct
cb_id
*
id
,
void
(
*
callback
)(
struct
cn_msg
*
,
struct
netlink_skb_parms
*
))
void
(
*
callback
)(
struct
cn_msg
*
,
struct
netlink_skb_parms
*
))
{
{
struct
cn_callback_entry
*
cbq
;
struct
cn_callback_entry
*
cbq
;
...
@@ -59,17 +44,23 @@ cn_queue_alloc_callback_entry(const char *name, struct cb_id *id,
...
@@ -59,17 +44,23 @@ cn_queue_alloc_callback_entry(const char *name, struct cb_id *id,
return
NULL
;
return
NULL
;
}
}
atomic_set
(
&
cbq
->
refcnt
,
1
);
atomic_inc
(
&
dev
->
refcnt
);
cbq
->
pdev
=
dev
;
snprintf
(
cbq
->
id
.
name
,
sizeof
(
cbq
->
id
.
name
),
"%s"
,
name
);
snprintf
(
cbq
->
id
.
name
,
sizeof
(
cbq
->
id
.
name
),
"%s"
,
name
);
memcpy
(
&
cbq
->
id
.
id
,
id
,
sizeof
(
struct
cb_id
));
memcpy
(
&
cbq
->
id
.
id
,
id
,
sizeof
(
struct
cb_id
));
cbq
->
data
.
callback
=
callback
;
cbq
->
callback
=
callback
;
INIT_WORK
(
&
cbq
->
work
,
&
cn_queue_wrapper
);
return
cbq
;
return
cbq
;
}
}
static
void
cn_queue_fre
e_callback
(
struct
cn_callback_entry
*
cbq
)
void
cn_queue_releas
e_callback
(
struct
cn_callback_entry
*
cbq
)
{
{
flush_workqueue
(
cbq
->
pdev
->
cn_queue
);
if
(
!
atomic_dec_and_test
(
&
cbq
->
refcnt
))
return
;
atomic_dec
(
&
cbq
->
pdev
->
refcnt
);
kfree
(
cbq
);
kfree
(
cbq
);
}
}
...
@@ -85,13 +76,10 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name,
...
@@ -85,13 +76,10 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name,
struct
cn_callback_entry
*
cbq
,
*
__cbq
;
struct
cn_callback_entry
*
cbq
,
*
__cbq
;
int
found
=
0
;
int
found
=
0
;
cbq
=
cn_queue_alloc_callback_entry
(
name
,
id
,
callback
);
cbq
=
cn_queue_alloc_callback_entry
(
dev
,
name
,
id
,
callback
);
if
(
!
cbq
)
if
(
!
cbq
)
return
-
ENOMEM
;
return
-
ENOMEM
;
atomic_inc
(
&
dev
->
refcnt
);
cbq
->
pdev
=
dev
;
spin_lock_bh
(
&
dev
->
queue_lock
);
spin_lock_bh
(
&
dev
->
queue_lock
);
list_for_each_entry
(
__cbq
,
&
dev
->
queue_list
,
callback_entry
)
{
list_for_each_entry
(
__cbq
,
&
dev
->
queue_list
,
callback_entry
)
{
if
(
cn_cb_equal
(
&
__cbq
->
id
.
id
,
id
))
{
if
(
cn_cb_equal
(
&
__cbq
->
id
.
id
,
id
))
{
...
@@ -104,8 +92,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name,
...
@@ -104,8 +92,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name,
spin_unlock_bh
(
&
dev
->
queue_lock
);
spin_unlock_bh
(
&
dev
->
queue_lock
);
if
(
found
)
{
if
(
found
)
{
cn_queue_free_callback
(
cbq
);
cn_queue_release_callback
(
cbq
);
atomic_dec
(
&
dev
->
refcnt
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
...
@@ -130,10 +117,8 @@ void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id)
...
@@ -130,10 +117,8 @@ void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id)
}
}
spin_unlock_bh
(
&
dev
->
queue_lock
);
spin_unlock_bh
(
&
dev
->
queue_lock
);
if
(
found
)
{
if
(
found
)
cn_queue_free_callback
(
cbq
);
cn_queue_release_callback
(
cbq
);
atomic_dec
(
&
dev
->
refcnt
);
}
}
}
struct
cn_queue_dev
*
cn_queue_alloc_dev
(
const
char
*
name
,
struct
sock
*
nls
)
struct
cn_queue_dev
*
cn_queue_alloc_dev
(
const
char
*
name
,
struct
sock
*
nls
)
...
@@ -151,12 +136,6 @@ struct cn_queue_dev *cn_queue_alloc_dev(const char *name, struct sock *nls)
...
@@ -151,12 +136,6 @@ struct cn_queue_dev *cn_queue_alloc_dev(const char *name, struct sock *nls)
dev
->
nls
=
nls
;
dev
->
nls
=
nls
;
dev
->
cn_queue
=
alloc_ordered_workqueue
(
dev
->
name
,
0
);
if
(
!
dev
->
cn_queue
)
{
kfree
(
dev
);
return
NULL
;
}
return
dev
;
return
dev
;
}
}
...
@@ -164,9 +143,6 @@ void cn_queue_free_dev(struct cn_queue_dev *dev)
...
@@ -164,9 +143,6 @@ void cn_queue_free_dev(struct cn_queue_dev *dev)
{
{
struct
cn_callback_entry
*
cbq
,
*
n
;
struct
cn_callback_entry
*
cbq
,
*
n
;
flush_workqueue
(
dev
->
cn_queue
);
destroy_workqueue
(
dev
->
cn_queue
);
spin_lock_bh
(
&
dev
->
queue_lock
);
spin_lock_bh
(
&
dev
->
queue_lock
);
list_for_each_entry_safe
(
cbq
,
n
,
&
dev
->
queue_list
,
callback_entry
)
list_for_each_entry_safe
(
cbq
,
n
,
&
dev
->
queue_list
,
callback_entry
)
list_del
(
&
cbq
->
callback_entry
);
list_del
(
&
cbq
->
callback_entry
);
...
...
drivers/connector/connector.c
View file @
4e700bcd
...
@@ -122,51 +122,28 @@ EXPORT_SYMBOL_GPL(cn_netlink_send);
...
@@ -122,51 +122,28 @@ EXPORT_SYMBOL_GPL(cn_netlink_send);
*/
*/
static
int
cn_call_callback
(
struct
sk_buff
*
skb
)
static
int
cn_call_callback
(
struct
sk_buff
*
skb
)
{
{
struct
cn_callback_entry
*
__cbq
,
*
__new_cbq
;
struct
cn_callback_entry
*
i
,
*
cbq
=
NULL
;
struct
cn_dev
*
dev
=
&
cdev
;
struct
cn_dev
*
dev
=
&
cdev
;
struct
cn_msg
*
msg
=
NLMSG_DATA
(
nlmsg_hdr
(
skb
));
struct
cn_msg
*
msg
=
NLMSG_DATA
(
nlmsg_hdr
(
skb
));
struct
netlink_skb_parms
*
nsp
=
&
NETLINK_CB
(
skb
);
int
err
=
-
ENODEV
;
int
err
=
-
ENODEV
;
spin_lock_bh
(
&
dev
->
cbdev
->
queue_lock
);
spin_lock_bh
(
&
dev
->
cbdev
->
queue_lock
);
list_for_each_entry
(
__cbq
,
&
dev
->
cbdev
->
queue_list
,
callback_entry
)
{
list_for_each_entry
(
i
,
&
dev
->
cbdev
->
queue_list
,
callback_entry
)
{
if
(
cn_cb_equal
(
&
__cbq
->
id
.
id
,
&
msg
->
id
))
{
if
(
cn_cb_equal
(
&
i
->
id
.
id
,
&
msg
->
id
))
{
if
(
likely
(
!
work_pending
(
&
__cbq
->
work
)
&&
atomic_inc
(
&
i
->
refcnt
);
__cbq
->
data
.
skb
==
NULL
))
{
cbq
=
i
;
__cbq
->
data
.
skb
=
skb
;
if
(
queue_work
(
dev
->
cbdev
->
cn_queue
,
&
__cbq
->
work
))
err
=
0
;
else
err
=
-
EINVAL
;
}
else
{
struct
cn_callback_data
*
d
;
err
=
-
ENOMEM
;
__new_cbq
=
kzalloc
(
sizeof
(
struct
cn_callback_entry
),
GFP_ATOMIC
);
if
(
__new_cbq
)
{
d
=
&
__new_cbq
->
data
;
d
->
skb
=
skb
;
d
->
callback
=
__cbq
->
data
.
callback
;
d
->
free
=
__new_cbq
;
INIT_WORK
(
&
__new_cbq
->
work
,
&
cn_queue_wrapper
);
if
(
queue_work
(
dev
->
cbdev
->
cn_queue
,
&
__new_cbq
->
work
))
err
=
0
;
else
{
kfree
(
__new_cbq
);
err
=
-
EINVAL
;
}
}
}
break
;
break
;
}
}
}
}
spin_unlock_bh
(
&
dev
->
cbdev
->
queue_lock
);
spin_unlock_bh
(
&
dev
->
cbdev
->
queue_lock
);
if
(
cbq
!=
NULL
)
{
cbq
->
callback
(
msg
,
nsp
);
kfree_skb
(
skb
);
cn_queue_release_callback
(
cbq
);
}
return
err
;
return
err
;
}
}
...
...
drivers/net/atlx/atl2.c
View file @
4e700bcd
...
@@ -1996,13 +1996,15 @@ static int atl2_set_eeprom(struct net_device *netdev,
...
@@ -1996,13 +1996,15 @@ static int atl2_set_eeprom(struct net_device *netdev,
if
(
!
eeprom_buff
)
if
(
!
eeprom_buff
)
return
-
ENOMEM
;
return
-
ENOMEM
;
ptr
=
(
u32
*
)
eeprom_buff
;
ptr
=
eeprom_buff
;
if
(
eeprom
->
offset
&
3
)
{
if
(
eeprom
->
offset
&
3
)
{
/* need read/modify/write of first changed EEPROM word */
/* need read/modify/write of first changed EEPROM word */
/* only the second byte of the word is being modified */
/* only the second byte of the word is being modified */
if
(
!
atl2_read_eeprom
(
hw
,
first_dword
*
4
,
&
(
eeprom_buff
[
0
])))
if
(
!
atl2_read_eeprom
(
hw
,
first_dword
*
4
,
&
(
eeprom_buff
[
0
])))
{
return
-
EIO
;
ret_val
=
-
EIO
;
goto
out
;
}
ptr
++
;
ptr
++
;
}
}
if
(((
eeprom
->
offset
+
eeprom
->
len
)
&
3
))
{
if
(((
eeprom
->
offset
+
eeprom
->
len
)
&
3
))
{
...
@@ -2011,18 +2013,22 @@ static int atl2_set_eeprom(struct net_device *netdev,
...
@@ -2011,18 +2013,22 @@ static int atl2_set_eeprom(struct net_device *netdev,
* only the first byte of the word is being modified
* only the first byte of the word is being modified
*/
*/
if
(
!
atl2_read_eeprom
(
hw
,
last_dword
*
4
,
if
(
!
atl2_read_eeprom
(
hw
,
last_dword
*
4
,
&
(
eeprom_buff
[
last_dword
-
first_dword
])))
&
(
eeprom_buff
[
last_dword
-
first_dword
])))
{
return
-
EIO
;
ret_val
=
-
EIO
;
goto
out
;
}
}
}
/* Device's eeprom is always little-endian, word addressable */
/* Device's eeprom is always little-endian, word addressable */
memcpy
(
ptr
,
bytes
,
eeprom
->
len
);
memcpy
(
ptr
,
bytes
,
eeprom
->
len
);
for
(
i
=
0
;
i
<
last_dword
-
first_dword
+
1
;
i
++
)
{
for
(
i
=
0
;
i
<
last_dword
-
first_dword
+
1
;
i
++
)
{
if
(
!
atl2_write_eeprom
(
hw
,
((
first_dword
+
i
)
*
4
),
eeprom_buff
[
i
]))
if
(
!
atl2_write_eeprom
(
hw
,
((
first_dword
+
i
)
*
4
),
eeprom_buff
[
i
]))
{
return
-
EIO
;
ret_val
=
-
EIO
;
goto
out
;
}
}
}
out:
kfree
(
eeprom_buff
);
kfree
(
eeprom_buff
);
return
ret_val
;
return
ret_val
;
}
}
...
...
drivers/net/irda/via-ircc.c
View file @
4e700bcd
...
@@ -75,15 +75,9 @@ static int dongle_id = 0; /* default: probe */
...
@@ -75,15 +75,9 @@ static int dongle_id = 0; /* default: probe */
/* We can't guess the type of connected dongle, user *must* supply it. */
/* We can't guess the type of connected dongle, user *must* supply it. */
module_param
(
dongle_id
,
int
,
0
);
module_param
(
dongle_id
,
int
,
0
);
/* FIXME : we should not need this, because instances should be automatically
* managed by the PCI layer. Especially that we seem to only be using the
* first entry. Jean II */
/* Max 4 instances for now */
static
struct
via_ircc_cb
*
dev_self
[]
=
{
NULL
,
NULL
,
NULL
,
NULL
};
/* Some prototypes */
/* Some prototypes */
static
int
via_ircc_open
(
int
i
,
chipio_t
*
info
,
unsigned
int
id
);
static
int
via_ircc_open
(
struct
pci_dev
*
pdev
,
chipio_t
*
info
,
static
int
via_ircc_close
(
struct
via_ircc_cb
*
self
);
unsigned
int
id
);
static
int
via_ircc_dma_receive
(
struct
via_ircc_cb
*
self
);
static
int
via_ircc_dma_receive
(
struct
via_ircc_cb
*
self
);
static
int
via_ircc_dma_receive_complete
(
struct
via_ircc_cb
*
self
,
static
int
via_ircc_dma_receive_complete
(
struct
via_ircc_cb
*
self
,
int
iobase
);
int
iobase
);
...
@@ -215,7 +209,7 @@ static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_devi
...
@@ -215,7 +209,7 @@ static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_devi
pci_write_config_byte
(
pcidev
,
0x42
,(
bTmp
|
0xf0
));
pci_write_config_byte
(
pcidev
,
0x42
,(
bTmp
|
0xf0
));
pci_write_config_byte
(
pcidev
,
0x5a
,
0xc0
);
pci_write_config_byte
(
pcidev
,
0x5a
,
0xc0
);
WriteLPCReg
(
0x28
,
0x70
);
WriteLPCReg
(
0x28
,
0x70
);
if
(
via_ircc_open
(
0
,
&
info
,
0x3076
)
==
0
)
if
(
via_ircc_open
(
pcidev
,
&
info
,
0x3076
)
==
0
)
rc
=
0
;
rc
=
0
;
}
else
}
else
rc
=
-
ENODEV
;
//IR not turn on
rc
=
-
ENODEV
;
//IR not turn on
...
@@ -254,7 +248,7 @@ static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_devi
...
@@ -254,7 +248,7 @@ static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_devi
info
.
irq
=
FirIRQ
;
info
.
irq
=
FirIRQ
;
info
.
dma
=
FirDRQ1
;
info
.
dma
=
FirDRQ1
;
info
.
dma2
=
FirDRQ0
;
info
.
dma2
=
FirDRQ0
;
if
(
via_ircc_open
(
0
,
&
info
,
0x3096
)
==
0
)
if
(
via_ircc_open
(
pcidev
,
&
info
,
0x3096
)
==
0
)
rc
=
0
;
rc
=
0
;
}
else
}
else
rc
=
-
ENODEV
;
//IR not turn on !!!!!
rc
=
-
ENODEV
;
//IR not turn on !!!!!
...
@@ -264,48 +258,10 @@ static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_devi
...
@@ -264,48 +258,10 @@ static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_devi
return
rc
;
return
rc
;
}
}
/*
* Function via_ircc_clean ()
*
* Close all configured chips
*
*/
static
void
via_ircc_clean
(
void
)
{
int
i
;
IRDA_DEBUG
(
3
,
"%s()
\n
"
,
__func__
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
dev_self
);
i
++
)
{
if
(
dev_self
[
i
])
via_ircc_close
(
dev_self
[
i
]);
}
}
static
void
__devexit
via_remove_one
(
struct
pci_dev
*
pdev
)
{
IRDA_DEBUG
(
3
,
"%s()
\n
"
,
__func__
);
/* FIXME : This is ugly. We should use pci_get_drvdata(pdev);
* to get our driver instance and call directly via_ircc_close().
* See vlsi_ir for details...
* Jean II */
via_ircc_clean
();
/* FIXME : This should be in via_ircc_close(), because here we may
* theoritically disable still configured devices :-( - Jean II */
pci_disable_device
(
pdev
);
}
static
void
__exit
via_ircc_cleanup
(
void
)
static
void
__exit
via_ircc_cleanup
(
void
)
{
{
IRDA_DEBUG
(
3
,
"%s()
\n
"
,
__func__
);
IRDA_DEBUG
(
3
,
"%s()
\n
"
,
__func__
);
/* FIXME : This should be redundant, as pci_unregister_driver()
* should call via_remove_one() on each device.
* Jean II */
via_ircc_clean
();
/* Cleanup all instances of the driver */
/* Cleanup all instances of the driver */
pci_unregister_driver
(
&
via_driver
);
pci_unregister_driver
(
&
via_driver
);
}
}
...
@@ -324,12 +280,13 @@ static const struct net_device_ops via_ircc_fir_ops = {
...
@@ -324,12 +280,13 @@ static const struct net_device_ops via_ircc_fir_ops = {
};
};
/*
/*
* Function via_ircc_open
(
iobase, irq)
* Function via_ircc_open
(pdev,
iobase, irq)
*
*
* Open driver instance
* Open driver instance
*
*
*/
*/
static
__devinit
int
via_ircc_open
(
int
i
,
chipio_t
*
info
,
unsigned
int
id
)
static
__devinit
int
via_ircc_open
(
struct
pci_dev
*
pdev
,
chipio_t
*
info
,
unsigned
int
id
)
{
{
struct
net_device
*
dev
;
struct
net_device
*
dev
;
struct
via_ircc_cb
*
self
;
struct
via_ircc_cb
*
self
;
...
@@ -337,9 +294,6 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
...
@@ -337,9 +294,6 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
IRDA_DEBUG
(
3
,
"%s()
\n
"
,
__func__
);
IRDA_DEBUG
(
3
,
"%s()
\n
"
,
__func__
);
if
(
i
>=
ARRAY_SIZE
(
dev_self
))
return
-
ENOMEM
;
/* Allocate new instance of the driver */
/* Allocate new instance of the driver */
dev
=
alloc_irdadev
(
sizeof
(
struct
via_ircc_cb
));
dev
=
alloc_irdadev
(
sizeof
(
struct
via_ircc_cb
));
if
(
dev
==
NULL
)
if
(
dev
==
NULL
)
...
@@ -349,13 +303,8 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
...
@@ -349,13 +303,8 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
self
->
netdev
=
dev
;
self
->
netdev
=
dev
;
spin_lock_init
(
&
self
->
lock
);
spin_lock_init
(
&
self
->
lock
);
/* FIXME : We should store our driver instance in the PCI layer,
pci_set_drvdata
(
pdev
,
self
);
* using pci_set_drvdata(), not in this array.
* See vlsi_ir for details... - Jean II */
/* FIXME : 'i' is always 0 (see via_init_one()) :-( - Jean II */
/* Need to store self somewhere */
dev_self
[
i
]
=
self
;
self
->
index
=
i
;
/* Initialize Resource */
/* Initialize Resource */
self
->
io
.
cfg_base
=
info
->
cfg_base
;
self
->
io
.
cfg_base
=
info
->
cfg_base
;
self
->
io
.
fir_base
=
info
->
fir_base
;
self
->
io
.
fir_base
=
info
->
fir_base
;
...
@@ -414,7 +363,7 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
...
@@ -414,7 +363,7 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
/* Allocate memory if needed */
/* Allocate memory if needed */
self
->
rx_buff
.
head
=
self
->
rx_buff
.
head
=
dma_alloc_coherent
(
NULL
,
self
->
rx_buff
.
truesize
,
dma_alloc_coherent
(
&
pdev
->
dev
,
self
->
rx_buff
.
truesize
,
&
self
->
rx_buff_dma
,
GFP_KERNEL
);
&
self
->
rx_buff_dma
,
GFP_KERNEL
);
if
(
self
->
rx_buff
.
head
==
NULL
)
{
if
(
self
->
rx_buff
.
head
==
NULL
)
{
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
...
@@ -423,7 +372,7 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
...
@@ -423,7 +372,7 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
memset
(
self
->
rx_buff
.
head
,
0
,
self
->
rx_buff
.
truesize
);
memset
(
self
->
rx_buff
.
head
,
0
,
self
->
rx_buff
.
truesize
);
self
->
tx_buff
.
head
=
self
->
tx_buff
.
head
=
dma_alloc_coherent
(
NULL
,
self
->
tx_buff
.
truesize
,
dma_alloc_coherent
(
&
pdev
->
dev
,
self
->
tx_buff
.
truesize
,
&
self
->
tx_buff_dma
,
GFP_KERNEL
);
&
self
->
tx_buff_dma
,
GFP_KERNEL
);
if
(
self
->
tx_buff
.
head
==
NULL
)
{
if
(
self
->
tx_buff
.
head
==
NULL
)
{
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
...
@@ -455,33 +404,32 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
...
@@ -455,33 +404,32 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
via_hw_init
(
self
);
via_hw_init
(
self
);
return
0
;
return
0
;
err_out4:
err_out4:
dma_free_coherent
(
NULL
,
self
->
tx_buff
.
truesize
,
dma_free_coherent
(
&
pdev
->
dev
,
self
->
tx_buff
.
truesize
,
self
->
tx_buff
.
head
,
self
->
tx_buff_dma
);
self
->
tx_buff
.
head
,
self
->
tx_buff_dma
);
err_out3:
err_out3:
dma_free_coherent
(
NULL
,
self
->
rx_buff
.
truesize
,
dma_free_coherent
(
&
pdev
->
dev
,
self
->
rx_buff
.
truesize
,
self
->
rx_buff
.
head
,
self
->
rx_buff_dma
);
self
->
rx_buff
.
head
,
self
->
rx_buff_dma
);
err_out2:
err_out2:
release_region
(
self
->
io
.
fir_base
,
self
->
io
.
fir_ext
);
release_region
(
self
->
io
.
fir_base
,
self
->
io
.
fir_ext
);
err_out1:
err_out1:
pci_set_drvdata
(
pdev
,
NULL
);
free_netdev
(
dev
);
free_netdev
(
dev
);
dev_self
[
i
]
=
NULL
;
return
err
;
return
err
;
}
}
/*
/*
* Function via_
ircc_close (self
)
* Function via_
remove_one(pdev
)
*
*
* Close driver instance
* Close driver instance
*
*
*/
*/
static
int
via_ircc_close
(
struct
via_ircc_cb
*
self
)
static
void
__devexit
via_remove_one
(
struct
pci_dev
*
pdev
)
{
{
struct
via_ircc_cb
*
self
=
pci_get_drvdata
(
pdev
);
int
iobase
;
int
iobase
;
IRDA_DEBUG
(
3
,
"%s()
\n
"
,
__func__
);
IRDA_DEBUG
(
3
,
"%s()
\n
"
,
__func__
);
IRDA_ASSERT
(
self
!=
NULL
,
return
-
1
;);
iobase
=
self
->
io
.
fir_base
;
iobase
=
self
->
io
.
fir_base
;
ResetChip
(
iobase
,
5
);
//hardware reset.
ResetChip
(
iobase
,
5
);
//hardware reset.
...
@@ -493,16 +441,16 @@ static int via_ircc_close(struct via_ircc_cb *self)
...
@@ -493,16 +441,16 @@ static int via_ircc_close(struct via_ircc_cb *self)
__func__
,
self
->
io
.
fir_base
);
__func__
,
self
->
io
.
fir_base
);
release_region
(
self
->
io
.
fir_base
,
self
->
io
.
fir_ext
);
release_region
(
self
->
io
.
fir_base
,
self
->
io
.
fir_ext
);
if
(
self
->
tx_buff
.
head
)
if
(
self
->
tx_buff
.
head
)
dma_free_coherent
(
NULL
,
self
->
tx_buff
.
truesize
,
dma_free_coherent
(
&
pdev
->
dev
,
self
->
tx_buff
.
truesize
,
self
->
tx_buff
.
head
,
self
->
tx_buff_dma
);
self
->
tx_buff
.
head
,
self
->
tx_buff_dma
);
if
(
self
->
rx_buff
.
head
)
if
(
self
->
rx_buff
.
head
)
dma_free_coherent
(
NULL
,
self
->
rx_buff
.
truesize
,
dma_free_coherent
(
&
pdev
->
dev
,
self
->
rx_buff
.
truesize
,
self
->
rx_buff
.
head
,
self
->
rx_buff_dma
);
self
->
rx_buff
.
head
,
self
->
rx_buff_dma
);
dev_self
[
self
->
index
]
=
NULL
;
pci_set_drvdata
(
pdev
,
NULL
)
;
free_netdev
(
self
->
netdev
);
free_netdev
(
self
->
netdev
);
return
0
;
pci_disable_device
(
pdev
)
;
}
}
/*
/*
...
...
drivers/net/phy/phy_device.c
View file @
4e700bcd
...
@@ -442,11 +442,11 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
...
@@ -442,11 +442,11 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
u32
flags
,
phy_interface_t
interface
)
u32
flags
,
phy_interface_t
interface
)
{
{
struct
device
*
d
=
&
phydev
->
dev
;
struct
device
*
d
=
&
phydev
->
dev
;
int
err
;
/* Assume that if there is no driver, that it doesn't
/* Assume that if there is no driver, that it doesn't
* exist, and we should use the genphy driver. */
* exist, and we should use the genphy driver. */
if
(
NULL
==
d
->
driver
)
{
if
(
NULL
==
d
->
driver
)
{
int
err
;
d
->
driver
=
&
genphy_driver
.
driver
;
d
->
driver
=
&
genphy_driver
.
driver
;
err
=
d
->
driver
->
probe
(
d
);
err
=
d
->
driver
->
probe
(
d
);
...
@@ -474,7 +474,11 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
...
@@ -474,7 +474,11 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
/* Do initial configuration here, now that
/* Do initial configuration here, now that
* we have certain key parameters
* we have certain key parameters
* (dev_flags and interface) */
* (dev_flags and interface) */
return
phy_init_hw
(
phydev
);
err
=
phy_init_hw
(
phydev
);
if
(
err
)
phy_detach
(
phydev
);
return
err
;
}
}
/**
/**
...
...
drivers/net/usb/Kconfig
View file @
4e700bcd
...
@@ -433,4 +433,19 @@ config USB_SIERRA_NET
...
@@ -433,4 +433,19 @@ config USB_SIERRA_NET
To compile this driver as a module, choose M here: the
To compile this driver as a module, choose M here: the
module will be called sierra_net.
module will be called sierra_net.
config USB_VL600
tristate "LG VL600 modem dongle"
depends on USB_NET_CDCETHER
select USB_ACM
help
Select this if you want to use an LG Electronics 4G/LTE usb modem
called VL600. This driver only handles the ethernet
interface exposed by the modem firmware. To establish a connection
you will first need a userspace program that sends the right
command to the modem through its CDC ACM port, and most
likely also a DHCP client. See this thread about using the
4G modem from Verizon:
http://ubuntuforums.org/showpost.php?p=10589647&postcount=17
endmenu
endmenu
drivers/net/usb/Makefile
View file @
4e700bcd
...
@@ -27,4 +27,5 @@ obj-$(CONFIG_USB_IPHETH) += ipheth.o
...
@@ -27,4 +27,5 @@ obj-$(CONFIG_USB_IPHETH) += ipheth.o
obj-$(CONFIG_USB_SIERRA_NET)
+=
sierra_net.o
obj-$(CONFIG_USB_SIERRA_NET)
+=
sierra_net.o
obj-$(CONFIG_USB_NET_CX82310_ETH)
+=
cx82310_eth.o
obj-$(CONFIG_USB_NET_CX82310_ETH)
+=
cx82310_eth.o
obj-$(CONFIG_USB_NET_CDC_NCM)
+=
cdc_ncm.o
obj-$(CONFIG_USB_NET_CDC_NCM)
+=
cdc_ncm.o
obj-$(CONFIG_USB_VL600)
+=
lg-vl600.o
drivers/net/usb/cdc_ether.c
View file @
4e700bcd
...
@@ -378,7 +378,7 @@ static void dumpspeed(struct usbnet *dev, __le32 *speeds)
...
@@ -378,7 +378,7 @@ static void dumpspeed(struct usbnet *dev, __le32 *speeds)
__le32_to_cpu
(
speeds
[
1
])
/
1000
);
__le32_to_cpu
(
speeds
[
1
])
/
1000
);
}
}
static
void
cdc_status
(
struct
usbnet
*
dev
,
struct
urb
*
urb
)
void
usbnet_
cdc_status
(
struct
usbnet
*
dev
,
struct
urb
*
urb
)
{
{
struct
usb_cdc_notification
*
event
;
struct
usb_cdc_notification
*
event
;
...
@@ -418,8 +418,9 @@ static void cdc_status(struct usbnet *dev, struct urb *urb)
...
@@ -418,8 +418,9 @@ static void cdc_status(struct usbnet *dev, struct urb *urb)
break
;
break
;
}
}
}
}
EXPORT_SYMBOL_GPL
(
usbnet_cdc_status
);
static
int
cdc_bind
(
struct
usbnet
*
dev
,
struct
usb_interface
*
intf
)
int
usbnet_
cdc_bind
(
struct
usbnet
*
dev
,
struct
usb_interface
*
intf
)
{
{
int
status
;
int
status
;
struct
cdc_state
*
info
=
(
void
*
)
&
dev
->
data
;
struct
cdc_state
*
info
=
(
void
*
)
&
dev
->
data
;
...
@@ -441,6 +442,7 @@ static int cdc_bind(struct usbnet *dev, struct usb_interface *intf)
...
@@ -441,6 +442,7 @@ static int cdc_bind(struct usbnet *dev, struct usb_interface *intf)
*/
*/
return
0
;
return
0
;
}
}
EXPORT_SYMBOL_GPL
(
usbnet_cdc_bind
);
static
int
cdc_manage_power
(
struct
usbnet
*
dev
,
int
on
)
static
int
cdc_manage_power
(
struct
usbnet
*
dev
,
int
on
)
{
{
...
@@ -452,18 +454,18 @@ static const struct driver_info cdc_info = {
...
@@ -452,18 +454,18 @@ static const struct driver_info cdc_info = {
.
description
=
"CDC Ethernet Device"
,
.
description
=
"CDC Ethernet Device"
,
.
flags
=
FLAG_ETHER
,
.
flags
=
FLAG_ETHER
,
// .check_connect = cdc_check_connect,
// .check_connect = cdc_check_connect,
.
bind
=
cdc_bind
,
.
bind
=
usbnet_
cdc_bind
,
.
unbind
=
usbnet_cdc_unbind
,
.
unbind
=
usbnet_cdc_unbind
,
.
status
=
cdc_status
,
.
status
=
usbnet_
cdc_status
,
.
manage_power
=
cdc_manage_power
,
.
manage_power
=
cdc_manage_power
,
};
};
static
const
struct
driver_info
mbm_info
=
{
static
const
struct
driver_info
mbm_info
=
{
.
description
=
"Mobile Broadband Network Device"
,
.
description
=
"Mobile Broadband Network Device"
,
.
flags
=
FLAG_WWAN
,
.
flags
=
FLAG_WWAN
,
.
bind
=
cdc_bind
,
.
bind
=
usbnet_
cdc_bind
,
.
unbind
=
usbnet_cdc_unbind
,
.
unbind
=
usbnet_cdc_unbind
,
.
status
=
cdc_status
,
.
status
=
usbnet_
cdc_status
,
.
manage_power
=
cdc_manage_power
,
.
manage_power
=
cdc_manage_power
,
};
};
...
@@ -560,6 +562,13 @@ static const struct usb_device_id products [] = {
...
@@ -560,6 +562,13 @@ static const struct usb_device_id products [] = {
.
driver_info
=
0
,
.
driver_info
=
0
,
},
},
/* LG Electronics VL600 wants additional headers on every frame */
{
USB_DEVICE_AND_INTERFACE_INFO
(
0x1004
,
0x61aa
,
USB_CLASS_COMM
,
USB_CDC_SUBCLASS_ETHERNET
,
USB_CDC_PROTO_NONE
),
.
driver_info
=
0
,
},
/*
/*
* WHITELIST!!!
* WHITELIST!!!
*
*
...
...
drivers/net/usb/lg-vl600.c
0 → 100644
View file @
4e700bcd
/*
* Ethernet interface part of the LG VL600 LTE modem (4G dongle)
*
* Copyright (C) 2011 Intel Corporation
* Author: Andrzej Zaborowski <balrogg@gmail.com>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/usb/cdc.h>
#include <linux/usb/usbnet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/inetdevice.h>
/*
* The device has a CDC ACM port for modem control (it claims to be
* CDC ACM anyway) and a CDC Ethernet port for actual network data.
* It will however ignore data on both ports that is not encapsulated
* in a specific way, any data returned is also encapsulated the same
* way. The headers don't seem to follow any popular standard.
*
* This driver adds and strips these headers from the ethernet frames
* sent/received from the CDC Ethernet port. The proprietary header
* replaces the standard ethernet header in a packet so only actual
* ethernet frames are allowed. The headers allow some form of
* multiplexing by using non standard values of the .h_proto field.
* Windows/Mac drivers do send a couple of such frames to the device
* during initialisation, with protocol set to 0x0906 or 0x0b06 and (what
* seems to be) a flag in the .dummy_flags. This doesn't seem necessary
* for modem operation but can possibly be used for GPS or other funcitons.
*/
struct
vl600_frame_hdr
{
__le32
len
;
__le32
serial
;
__le32
pkt_cnt
;
__le32
dummy_flags
;
__le32
dummy
;
__le32
magic
;
}
__attribute__
((
packed
));
struct
vl600_pkt_hdr
{
__le32
dummy
[
2
];
__le32
len
;
__be16
h_proto
;
}
__attribute__
((
packed
));
struct
vl600_state
{
struct
sk_buff
*
current_rx_buf
;
};
static
int
vl600_bind
(
struct
usbnet
*
dev
,
struct
usb_interface
*
intf
)
{
int
ret
;
struct
vl600_state
*
s
=
kzalloc
(
sizeof
(
struct
vl600_state
),
GFP_KERNEL
);
if
(
!
s
)
return
-
ENOMEM
;
ret
=
usbnet_cdc_bind
(
dev
,
intf
);
if
(
ret
)
{
kfree
(
s
);
return
ret
;
}
dev
->
driver_priv
=
s
;
/* ARP packets don't go through, but they're also of no use. The
* subnet has only two hosts anyway: us and the gateway / DHCP
* server (probably simulated by modem firmware or network operator)
* whose address changes everytime we connect to the intarwebz and
* who doesn't bother answering ARP requests either. So hardware
* addresses have no meaning, the destination and the source of every
* packet depend only on whether it is on the IN or OUT endpoint. */
dev
->
net
->
flags
|=
IFF_NOARP
;
return
ret
;
}
static
void
vl600_unbind
(
struct
usbnet
*
dev
,
struct
usb_interface
*
intf
)
{
struct
vl600_state
*
s
=
dev
->
driver_priv
;
if
(
s
->
current_rx_buf
)
dev_kfree_skb
(
s
->
current_rx_buf
);
kfree
(
s
);
return
usbnet_cdc_unbind
(
dev
,
intf
);
}
static
int
vl600_rx_fixup
(
struct
usbnet
*
dev
,
struct
sk_buff
*
skb
)
{
struct
vl600_frame_hdr
*
frame
;
struct
vl600_pkt_hdr
*
packet
;
struct
ethhdr
*
ethhdr
;
int
packet_len
,
count
;
struct
sk_buff
*
buf
=
skb
;
struct
sk_buff
*
clone
;
struct
vl600_state
*
s
=
dev
->
driver_priv
;
/* Frame lengths are generally 4B multiplies but every couple of
* hours there's an odd number of bytes sized yet correct frame,
* so don't require this. */
/* Allow a packet (or multiple packets batched together) to be
* split across many frames. We don't allow a new batch to
* begin in the same frame another one is ending however, and no
* leading or trailing pad bytes. */
if
(
s
->
current_rx_buf
)
{
frame
=
(
struct
vl600_frame_hdr
*
)
s
->
current_rx_buf
->
data
;
if
(
skb
->
len
+
s
->
current_rx_buf
->
len
>
le32_to_cpup
(
&
frame
->
len
))
{
netif_err
(
dev
,
ifup
,
dev
->
net
,
"Fragment too long
\n
"
);
dev
->
net
->
stats
.
rx_length_errors
++
;
goto
error
;
}
buf
=
s
->
current_rx_buf
;
memcpy
(
skb_put
(
buf
,
skb
->
len
),
skb
->
data
,
skb
->
len
);
}
else
if
(
skb
->
len
<
4
)
{
netif_err
(
dev
,
ifup
,
dev
->
net
,
"Frame too short
\n
"
);
dev
->
net
->
stats
.
rx_length_errors
++
;
goto
error
;
}
frame
=
(
struct
vl600_frame_hdr
*
)
buf
->
data
;
/* NOTE: Should check that frame->magic == 0x53544448?
* Otherwise if we receive garbage at the beginning of the frame
* we may end up allocating a huge buffer and saving all the
* future incoming data into it. */
if
(
buf
->
len
<
sizeof
(
*
frame
)
||
buf
->
len
!=
le32_to_cpup
(
&
frame
->
len
))
{
/* Save this fragment for later assembly */
if
(
s
->
current_rx_buf
)
return
0
;
s
->
current_rx_buf
=
skb_copy_expand
(
skb
,
0
,
le32_to_cpup
(
&
frame
->
len
),
GFP_ATOMIC
);
if
(
!
s
->
current_rx_buf
)
{
netif_err
(
dev
,
ifup
,
dev
->
net
,
"Reserving %i bytes "
"for packet assembly failed.
\n
"
,
le32_to_cpup
(
&
frame
->
len
));
dev
->
net
->
stats
.
rx_errors
++
;
}
return
0
;
}
count
=
le32_to_cpup
(
&
frame
->
pkt_cnt
);
skb_pull
(
buf
,
sizeof
(
*
frame
));
while
(
count
--
)
{
if
(
buf
->
len
<
sizeof
(
*
packet
))
{
netif_err
(
dev
,
ifup
,
dev
->
net
,
"Packet too short
\n
"
);
goto
error
;
}
packet
=
(
struct
vl600_pkt_hdr
*
)
buf
->
data
;
packet_len
=
sizeof
(
*
packet
)
+
le32_to_cpup
(
&
packet
->
len
);
if
(
packet_len
>
buf
->
len
)
{
netif_err
(
dev
,
ifup
,
dev
->
net
,
"Bad packet length stored in header
\n
"
);
goto
error
;
}
/* Packet header is same size as the ethernet header
* (sizeof(*packet) == sizeof(*ethhdr)), additionally
* the h_proto field is in the same place so we just leave it
* alone and fill in the remaining fields.
*/
ethhdr
=
(
struct
ethhdr
*
)
skb
->
data
;
if
(
be16_to_cpup
(
&
ethhdr
->
h_proto
)
==
ETH_P_ARP
&&
buf
->
len
>
0x26
)
{
/* Copy the addresses from packet contents */
memcpy
(
ethhdr
->
h_source
,
&
buf
->
data
[
sizeof
(
*
ethhdr
)
+
0x8
],
ETH_ALEN
);
memcpy
(
ethhdr
->
h_dest
,
&
buf
->
data
[
sizeof
(
*
ethhdr
)
+
0x12
],
ETH_ALEN
);
}
else
{
memset
(
ethhdr
->
h_source
,
0
,
ETH_ALEN
);
memcpy
(
ethhdr
->
h_dest
,
dev
->
net
->
dev_addr
,
ETH_ALEN
);
}
if
(
count
)
{
/* Not the last packet in this batch */
clone
=
skb_clone
(
buf
,
GFP_ATOMIC
);
if
(
!
clone
)
goto
error
;
skb_trim
(
clone
,
packet_len
);
usbnet_skb_return
(
dev
,
clone
);
skb_pull
(
buf
,
(
packet_len
+
3
)
&
~
3
);
}
else
{
skb_trim
(
buf
,
packet_len
);
if
(
s
->
current_rx_buf
)
{
usbnet_skb_return
(
dev
,
buf
);
s
->
current_rx_buf
=
NULL
;
return
0
;
}
return
1
;
}
}
error:
if
(
s
->
current_rx_buf
)
{
dev_kfree_skb_any
(
s
->
current_rx_buf
);
s
->
current_rx_buf
=
NULL
;
}
dev
->
net
->
stats
.
rx_errors
++
;
return
0
;
}
static
struct
sk_buff
*
vl600_tx_fixup
(
struct
usbnet
*
dev
,
struct
sk_buff
*
skb
,
gfp_t
flags
)
{
struct
sk_buff
*
ret
;
struct
vl600_frame_hdr
*
frame
;
struct
vl600_pkt_hdr
*
packet
;
static
uint32_t
serial
=
1
;
int
orig_len
=
skb
->
len
-
sizeof
(
struct
ethhdr
);
int
full_len
=
(
skb
->
len
+
sizeof
(
struct
vl600_frame_hdr
)
+
3
)
&
~
3
;
frame
=
(
struct
vl600_frame_hdr
*
)
skb
->
data
;
if
(
skb
->
len
>
sizeof
(
*
frame
)
&&
skb
->
len
==
le32_to_cpup
(
&
frame
->
len
))
return
skb
;
/* Already encapsulated? */
if
(
skb
->
len
<
sizeof
(
struct
ethhdr
))
/* Drop, device can only deal with ethernet packets */
return
NULL
;
if
(
!
skb_cloned
(
skb
))
{
int
headroom
=
skb_headroom
(
skb
);
int
tailroom
=
skb_tailroom
(
skb
);
if
(
tailroom
>=
full_len
-
skb
->
len
-
sizeof
(
*
frame
)
&&
headroom
>=
sizeof
(
*
frame
))
/* There's enough head and tail room */
goto
encapsulate
;
if
(
headroom
+
tailroom
+
skb
->
len
>=
full_len
)
{
/* There's enough total room, just readjust */
skb
->
data
=
memmove
(
skb
->
head
+
sizeof
(
*
frame
),
skb
->
data
,
skb
->
len
);
skb_set_tail_pointer
(
skb
,
skb
->
len
);
goto
encapsulate
;
}
}
/* Alloc a new skb with the required size */
ret
=
skb_copy_expand
(
skb
,
sizeof
(
struct
vl600_frame_hdr
),
full_len
-
skb
->
len
-
sizeof
(
struct
vl600_frame_hdr
),
flags
);
dev_kfree_skb_any
(
skb
);
if
(
!
ret
)
return
ret
;
skb
=
ret
;
encapsulate:
/* Packet header is same size as ethernet packet header
* (sizeof(*packet) == sizeof(struct ethhdr)), additionally the
* h_proto field is in the same place so we just leave it alone and
* overwrite the remaining fields.
*/
packet
=
(
struct
vl600_pkt_hdr
*
)
skb
->
data
;
memset
(
&
packet
->
dummy
,
0
,
sizeof
(
packet
->
dummy
));
packet
->
len
=
cpu_to_le32
(
orig_len
);
frame
=
(
struct
vl600_frame_hdr
*
)
skb_push
(
skb
,
sizeof
(
*
frame
));
memset
(
frame
,
0
,
sizeof
(
*
frame
));
frame
->
len
=
cpu_to_le32
(
full_len
);
frame
->
serial
=
cpu_to_le32
(
serial
++
);
frame
->
pkt_cnt
=
cpu_to_le32
(
1
);
if
(
skb
->
len
<
full_len
)
/* Pad */
skb_put
(
skb
,
full_len
-
skb
->
len
);
return
skb
;
}
static
const
struct
driver_info
vl600_info
=
{
.
description
=
"LG VL600 modem"
,
.
flags
=
FLAG_ETHER
|
FLAG_RX_ASSEMBLE
,
.
bind
=
vl600_bind
,
.
unbind
=
vl600_unbind
,
.
status
=
usbnet_cdc_status
,
.
rx_fixup
=
vl600_rx_fixup
,
.
tx_fixup
=
vl600_tx_fixup
,
};
static
const
struct
usb_device_id
products
[]
=
{
{
USB_DEVICE_AND_INTERFACE_INFO
(
0x1004
,
0x61aa
,
USB_CLASS_COMM
,
USB_CDC_SUBCLASS_ETHERNET
,
USB_CDC_PROTO_NONE
),
.
driver_info
=
(
unsigned
long
)
&
vl600_info
,
},
{},
/* End */
};
MODULE_DEVICE_TABLE
(
usb
,
products
);
static
struct
usb_driver
lg_vl600_driver
=
{
.
name
=
"lg-vl600"
,
.
id_table
=
products
,
.
probe
=
usbnet_probe
,
.
disconnect
=
usbnet_disconnect
,
.
suspend
=
usbnet_suspend
,
.
resume
=
usbnet_resume
,
};
static
int
__init
vl600_init
(
void
)
{
return
usb_register
(
&
lg_vl600_driver
);
}
module_init
(
vl600_init
);
static
void
__exit
vl600_exit
(
void
)
{
usb_deregister
(
&
lg_vl600_driver
);
}
module_exit
(
vl600_exit
);
MODULE_AUTHOR
(
"Anrzej Zaborowski"
);
MODULE_DESCRIPTION
(
"LG-VL600 modem's ethernet link"
);
MODULE_LICENSE
(
"GPL"
);
drivers/net/usb/usbnet.c
View file @
4e700bcd
...
@@ -387,8 +387,12 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
...
@@ -387,8 +387,12 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
static
inline
void
rx_process
(
struct
usbnet
*
dev
,
struct
sk_buff
*
skb
)
static
inline
void
rx_process
(
struct
usbnet
*
dev
,
struct
sk_buff
*
skb
)
{
{
if
(
dev
->
driver_info
->
rx_fixup
&&
if
(
dev
->
driver_info
->
rx_fixup
&&
!
dev
->
driver_info
->
rx_fixup
(
dev
,
skb
))
!
dev
->
driver_info
->
rx_fixup
(
dev
,
skb
))
{
goto
error
;
/* With RX_ASSEMBLE, rx_fixup() must update counters */
if
(
!
(
dev
->
driver_info
->
flags
&
FLAG_RX_ASSEMBLE
))
dev
->
net
->
stats
.
rx_errors
++
;
goto
done
;
}
// else network stack removes extra byte if we forced a short packet
// else network stack removes extra byte if we forced a short packet
if
(
skb
->
len
)
{
if
(
skb
->
len
)
{
...
@@ -401,8 +405,8 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
...
@@ -401,8 +405,8 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
}
}
netif_dbg
(
dev
,
rx_err
,
dev
->
net
,
"drop
\n
"
);
netif_dbg
(
dev
,
rx_err
,
dev
->
net
,
"drop
\n
"
);
error:
dev
->
net
->
stats
.
rx_errors
++
;
dev
->
net
->
stats
.
rx_errors
++
;
done:
skb_queue_tail
(
&
dev
->
done
,
skb
);
skb_queue_tail
(
&
dev
->
done
,
skb
);
}
}
...
...
include/linux/atmdev.h
View file @
4e700bcd
...
@@ -443,6 +443,7 @@ void atm_dev_signal_change(struct atm_dev *dev, char signal);
...
@@ -443,6 +443,7 @@ void atm_dev_signal_change(struct atm_dev *dev, char signal);
void
vcc_insert_socket
(
struct
sock
*
sk
);
void
vcc_insert_socket
(
struct
sock
*
sk
);
void
atm_dev_release_vccs
(
struct
atm_dev
*
dev
);
/*
/*
* This is approximately the algorithm used by alloc_skb.
* This is approximately the algorithm used by alloc_skb.
...
...
include/linux/connector.h
View file @
4e700bcd
...
@@ -88,8 +88,6 @@ struct cn_queue_dev {
...
@@ -88,8 +88,6 @@ struct cn_queue_dev {
atomic_t
refcnt
;
atomic_t
refcnt
;
unsigned
char
name
[
CN_CBQ_NAMELEN
];
unsigned
char
name
[
CN_CBQ_NAMELEN
];
struct
workqueue_struct
*
cn_queue
;
struct
list_head
queue_list
;
struct
list_head
queue_list
;
spinlock_t
queue_lock
;
spinlock_t
queue_lock
;
...
@@ -101,20 +99,13 @@ struct cn_callback_id {
...
@@ -101,20 +99,13 @@ struct cn_callback_id {
struct
cb_id
id
;
struct
cb_id
id
;
};
};
struct
cn_callback_data
{
struct
sk_buff
*
skb
;
void
(
*
callback
)
(
struct
cn_msg
*
,
struct
netlink_skb_parms
*
);
void
*
free
;
};
struct
cn_callback_entry
{
struct
cn_callback_entry
{
struct
list_head
callback_entry
;
struct
list_head
callback_entry
;
struct
work_struct
work
;
atomic_t
refcnt
;
struct
cn_queue_dev
*
pdev
;
struct
cn_queue_dev
*
pdev
;
struct
cn_callback_id
id
;
struct
cn_callback_id
id
;
struct
cn_callback_data
data
;
void
(
*
callback
)
(
struct
cn_msg
*
,
struct
netlink_skb_parms
*
)
;
u32
seq
,
group
;
u32
seq
,
group
;
};
};
...
@@ -138,13 +129,12 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name,
...
@@ -138,13 +129,12 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name,
struct
cb_id
*
id
,
struct
cb_id
*
id
,
void
(
*
callback
)(
struct
cn_msg
*
,
struct
netlink_skb_parms
*
));
void
(
*
callback
)(
struct
cn_msg
*
,
struct
netlink_skb_parms
*
));
void
cn_queue_del_callback
(
struct
cn_queue_dev
*
dev
,
struct
cb_id
*
id
);
void
cn_queue_del_callback
(
struct
cn_queue_dev
*
dev
,
struct
cb_id
*
id
);
void
cn_queue_release_callback
(
struct
cn_callback_entry
*
);
struct
cn_queue_dev
*
cn_queue_alloc_dev
(
const
char
*
name
,
struct
sock
*
);
struct
cn_queue_dev
*
cn_queue_alloc_dev
(
const
char
*
name
,
struct
sock
*
);
void
cn_queue_free_dev
(
struct
cn_queue_dev
*
dev
);
void
cn_queue_free_dev
(
struct
cn_queue_dev
*
dev
);
int
cn_cb_equal
(
struct
cb_id
*
,
struct
cb_id
*
);
int
cn_cb_equal
(
struct
cb_id
*
,
struct
cb_id
*
);
void
cn_queue_wrapper
(
struct
work_struct
*
work
);
#endif
/* __KERNEL__ */
#endif
/* __KERNEL__ */
#endif
/* __CONNECTOR_H */
#endif
/* __CONNECTOR_H */
include/linux/skbuff.h
View file @
4e700bcd
...
@@ -126,7 +126,7 @@ struct sk_buff;
...
@@ -126,7 +126,7 @@ struct sk_buff;
* GRO uses frags we allocate at least 16 regardless of page size.
* GRO uses frags we allocate at least 16 regardless of page size.
*/
*/
#if (65536/PAGE_SIZE + 2) < 16
#if (65536/PAGE_SIZE + 2) < 16
#define MAX_SKB_FRAGS 16
#define MAX_SKB_FRAGS 16
UL
#else
#else
#define MAX_SKB_FRAGS (65536/PAGE_SIZE + 2)
#define MAX_SKB_FRAGS (65536/PAGE_SIZE + 2)
#endif
#endif
...
...
include/linux/usb/usbnet.h
View file @
4e700bcd
...
@@ -102,6 +102,7 @@ struct driver_info {
...
@@ -102,6 +102,7 @@ struct driver_info {
* Affects statistic (counters) and short packet handling.
* Affects statistic (counters) and short packet handling.
*/
*/
#define FLAG_MULTI_PACKET 0x1000
#define FLAG_MULTI_PACKET 0x1000
#define FLAG_RX_ASSEMBLE 0x2000
/* rx packets may span >1 frames */
/* init device ... can sleep, or cause probe() failure */
/* init device ... can sleep, or cause probe() failure */
int
(
*
bind
)(
struct
usbnet
*
,
struct
usb_interface
*
);
int
(
*
bind
)(
struct
usbnet
*
,
struct
usb_interface
*
);
...
@@ -172,7 +173,9 @@ struct cdc_state {
...
@@ -172,7 +173,9 @@ struct cdc_state {
};
};
extern
int
usbnet_generic_cdc_bind
(
struct
usbnet
*
,
struct
usb_interface
*
);
extern
int
usbnet_generic_cdc_bind
(
struct
usbnet
*
,
struct
usb_interface
*
);
extern
int
usbnet_cdc_bind
(
struct
usbnet
*
,
struct
usb_interface
*
);
extern
void
usbnet_cdc_unbind
(
struct
usbnet
*
,
struct
usb_interface
*
);
extern
void
usbnet_cdc_unbind
(
struct
usbnet
*
,
struct
usb_interface
*
);
extern
void
usbnet_cdc_status
(
struct
usbnet
*
,
struct
urb
*
);
/* CDC and RNDIS support the same host-chosen packet filters for IN transfers */
/* CDC and RNDIS support the same host-chosen packet filters for IN transfers */
#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
...
...
include/net/if_inet6.h
View file @
4e700bcd
...
@@ -286,5 +286,21 @@ static inline void ipv6_ib_mc_map(const struct in6_addr *addr,
...
@@ -286,5 +286,21 @@ static inline void ipv6_ib_mc_map(const struct in6_addr *addr,
buf
[
9
]
=
broadcast
[
9
];
buf
[
9
]
=
broadcast
[
9
];
memcpy
(
buf
+
10
,
addr
->
s6_addr
+
6
,
10
);
memcpy
(
buf
+
10
,
addr
->
s6_addr
+
6
,
10
);
}
}
static
inline
int
ipv6_ipgre_mc_map
(
const
struct
in6_addr
*
addr
,
const
unsigned
char
*
broadcast
,
char
*
buf
)
{
if
((
broadcast
[
0
]
|
broadcast
[
1
]
|
broadcast
[
2
]
|
broadcast
[
3
])
!=
0
)
{
memcpy
(
buf
,
broadcast
,
4
);
}
else
{
/* v4mapped? */
if
((
addr
->
s6_addr32
[
0
]
|
addr
->
s6_addr32
[
1
]
|
(
addr
->
s6_addr32
[
2
]
^
htonl
(
0x0000ffff
)))
!=
0
)
return
-
EINVAL
;
memcpy
(
buf
,
&
addr
->
s6_addr32
[
3
],
4
);
}
return
0
;
}
#endif
#endif
#endif
#endif
include/net/ip.h
View file @
4e700bcd
...
@@ -339,6 +339,14 @@ static inline void ip_ib_mc_map(__be32 naddr, const unsigned char *broadcast, ch
...
@@ -339,6 +339,14 @@ static inline void ip_ib_mc_map(__be32 naddr, const unsigned char *broadcast, ch
buf
[
16
]
=
addr
&
0x0f
;
buf
[
16
]
=
addr
&
0x0f
;
}
}
static
inline
void
ip_ipgre_mc_map
(
__be32
naddr
,
const
unsigned
char
*
broadcast
,
char
*
buf
)
{
if
((
broadcast
[
0
]
|
broadcast
[
1
]
|
broadcast
[
2
]
|
broadcast
[
3
])
!=
0
)
memcpy
(
buf
,
broadcast
,
4
);
else
memcpy
(
buf
,
&
naddr
,
sizeof
(
naddr
));
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#include <linux/ipv6.h>
#include <linux/ipv6.h>
#endif
#endif
...
...
net/atm/common.c
View file @
4e700bcd
...
@@ -252,6 +252,7 @@ void atm_dev_release_vccs(struct atm_dev *dev)
...
@@ -252,6 +252,7 @@ void atm_dev_release_vccs(struct atm_dev *dev)
}
}
write_unlock_irq
(
&
vcc_sklist_lock
);
write_unlock_irq
(
&
vcc_sklist_lock
);
}
}
EXPORT_SYMBOL
(
atm_dev_release_vccs
);
static
int
adjust_tp
(
struct
atm_trafprm
*
tp
,
unsigned
char
aal
)
static
int
adjust_tp
(
struct
atm_trafprm
*
tp
,
unsigned
char
aal
)
{
{
...
...
net/bridge/br_multicast.c
View file @
4e700bcd
...
@@ -1475,7 +1475,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
...
@@ -1475,7 +1475,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
ip6h
->
payload_len
==
0
)
ip6h
->
payload_len
==
0
)
return
0
;
return
0
;
len
=
ntohs
(
ip6h
->
payload_len
);
len
=
ntohs
(
ip6h
->
payload_len
)
+
sizeof
(
*
ip6h
)
;
if
(
skb
->
len
<
len
)
if
(
skb
->
len
<
len
)
return
-
EINVAL
;
return
-
EINVAL
;
...
...
net/bridge/br_stp_if.c
View file @
4e700bcd
...
@@ -213,7 +213,7 @@ bool br_stp_recalculate_bridge_id(struct net_bridge *br)
...
@@ -213,7 +213,7 @@ bool br_stp_recalculate_bridge_id(struct net_bridge *br)
/* user has chosen a value so keep it */
/* user has chosen a value so keep it */
if
(
br
->
flags
&
BR_SET_MAC_ADDR
)
if
(
br
->
flags
&
BR_SET_MAC_ADDR
)
return
;
return
false
;
list_for_each_entry
(
p
,
&
br
->
port_list
,
list
)
{
list_for_each_entry
(
p
,
&
br
->
port_list
,
list
)
{
if
(
addr
==
br_mac_zero
||
if
(
addr
==
br_mac_zero
||
...
...
net/core/dev.c
View file @
4e700bcd
...
@@ -1454,6 +1454,27 @@ static inline void net_timestamp_check(struct sk_buff *skb)
...
@@ -1454,6 +1454,27 @@ static inline void net_timestamp_check(struct sk_buff *skb)
__net_timestamp
(
skb
);
__net_timestamp
(
skb
);
}
}
static
inline
bool
is_skb_forwardable
(
struct
net_device
*
dev
,
struct
sk_buff
*
skb
)
{
unsigned
int
len
;
if
(
!
(
dev
->
flags
&
IFF_UP
))
return
false
;
len
=
dev
->
mtu
+
dev
->
hard_header_len
+
VLAN_HLEN
;
if
(
skb
->
len
<=
len
)
return
true
;
/* if TSO is enabled, we don't care about the length as the packet
* could be forwarded without being segmented before
*/
if
(
skb_is_gso
(
skb
))
return
true
;
return
false
;
}
/**
/**
* dev_forward_skb - loopback an skb to another netif
* dev_forward_skb - loopback an skb to another netif
*
*
...
@@ -1477,8 +1498,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
...
@@ -1477,8 +1498,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
skb_orphan
(
skb
);
skb_orphan
(
skb
);
nf_reset
(
skb
);
nf_reset
(
skb
);
if
(
unlikely
(
!
(
dev
->
flags
&
IFF_UP
)
||
if
(
unlikely
(
!
is_skb_forwardable
(
dev
,
skb
)))
{
(
skb
->
len
>
(
dev
->
mtu
+
dev
->
hard_header_len
+
VLAN_HLEN
))))
{
atomic_long_inc
(
&
dev
->
rx_dropped
);
atomic_long_inc
(
&
dev
->
rx_dropped
);
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
NET_RX_DROP
;
return
NET_RX_DROP
;
...
...
net/ipv4/arp.c
View file @
4e700bcd
...
@@ -215,6 +215,9 @@ int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir)
...
@@ -215,6 +215,9 @@ int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir)
case
ARPHRD_INFINIBAND
:
case
ARPHRD_INFINIBAND
:
ip_ib_mc_map
(
addr
,
dev
->
broadcast
,
haddr
);
ip_ib_mc_map
(
addr
,
dev
->
broadcast
,
haddr
);
return
0
;
return
0
;
case
ARPHRD_IPGRE
:
ip_ipgre_mc_map
(
addr
,
dev
->
broadcast
,
haddr
);
return
0
;
default:
default:
if
(
dir
)
{
if
(
dir
)
{
memcpy
(
haddr
,
dev
->
broadcast
,
dev
->
addr_len
);
memcpy
(
haddr
,
dev
->
broadcast
,
dev
->
addr_len
);
...
...
net/ipv4/fib_frontend.c
View file @
4e700bcd
...
@@ -1068,6 +1068,7 @@ static void ip_fib_net_exit(struct net *net)
...
@@ -1068,6 +1068,7 @@ static void ip_fib_net_exit(struct net *net)
fib4_rules_exit
(
net
);
fib4_rules_exit
(
net
);
#endif
#endif
rtnl_lock
();
for
(
i
=
0
;
i
<
FIB_TABLE_HASHSZ
;
i
++
)
{
for
(
i
=
0
;
i
<
FIB_TABLE_HASHSZ
;
i
++
)
{
struct
fib_table
*
tb
;
struct
fib_table
*
tb
;
struct
hlist_head
*
head
;
struct
hlist_head
*
head
;
...
@@ -1080,6 +1081,7 @@ static void ip_fib_net_exit(struct net *net)
...
@@ -1080,6 +1081,7 @@ static void ip_fib_net_exit(struct net *net)
fib_free_table
(
tb
);
fib_free_table
(
tb
);
}
}
}
}
rtnl_unlock
();
kfree
(
net
->
ipv4
.
fib_table_hash
);
kfree
(
net
->
ipv4
.
fib_table_hash
);
}
}
...
...
net/ipv6/ndisc.c
View file @
4e700bcd
...
@@ -341,6 +341,8 @@ int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int d
...
@@ -341,6 +341,8 @@ int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int d
case
ARPHRD_INFINIBAND
:
case
ARPHRD_INFINIBAND
:
ipv6_ib_mc_map
(
addr
,
dev
->
broadcast
,
buf
);
ipv6_ib_mc_map
(
addr
,
dev
->
broadcast
,
buf
);
return
0
;
return
0
;
case
ARPHRD_IPGRE
:
return
ipv6_ipgre_mc_map
(
addr
,
dev
->
broadcast
,
buf
);
default:
default:
if
(
dir
)
{
if
(
dir
)
{
memcpy
(
buf
,
dev
->
broadcast
,
dev
->
addr_len
);
memcpy
(
buf
,
dev
->
broadcast
,
dev
->
addr_len
);
...
...
net/sctp/protocol.c
View file @
4e700bcd
...
@@ -1205,7 +1205,7 @@ SCTP_STATIC __init int sctp_init(void)
...
@@ -1205,7 +1205,7 @@ SCTP_STATIC __init int sctp_init(void)
if
((
sctp_assoc_hashsize
>
(
64
*
1024
))
&&
order
>
0
)
if
((
sctp_assoc_hashsize
>
(
64
*
1024
))
&&
order
>
0
)
continue
;
continue
;
sctp_assoc_hashtable
=
(
struct
sctp_hashbucket
*
)
sctp_assoc_hashtable
=
(
struct
sctp_hashbucket
*
)
__get_free_pages
(
GFP_ATOMIC
,
order
);
__get_free_pages
(
GFP_ATOMIC
|
__GFP_NOWARN
,
order
);
}
while
(
!
sctp_assoc_hashtable
&&
--
order
>
0
);
}
while
(
!
sctp_assoc_hashtable
&&
--
order
>
0
);
if
(
!
sctp_assoc_hashtable
)
{
if
(
!
sctp_assoc_hashtable
)
{
pr_err
(
"Failed association hash alloc
\n
"
);
pr_err
(
"Failed association hash alloc
\n
"
);
...
@@ -1238,7 +1238,7 @@ SCTP_STATIC __init int sctp_init(void)
...
@@ -1238,7 +1238,7 @@ SCTP_STATIC __init int sctp_init(void)
if
((
sctp_port_hashsize
>
(
64
*
1024
))
&&
order
>
0
)
if
((
sctp_port_hashsize
>
(
64
*
1024
))
&&
order
>
0
)
continue
;
continue
;
sctp_port_hashtable
=
(
struct
sctp_bind_hashbucket
*
)
sctp_port_hashtable
=
(
struct
sctp_bind_hashbucket
*
)
__get_free_pages
(
GFP_ATOMIC
,
order
);
__get_free_pages
(
GFP_ATOMIC
|
__GFP_NOWARN
,
order
);
}
while
(
!
sctp_port_hashtable
&&
--
order
>
0
);
}
while
(
!
sctp_port_hashtable
&&
--
order
>
0
);
if
(
!
sctp_port_hashtable
)
{
if
(
!
sctp_port_hashtable
)
{
pr_err
(
"Failed bind hash alloc
\n
"
);
pr_err
(
"Failed bind hash alloc
\n
"
);
...
...
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