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
028ebff2
Commit
028ebff2
authored
Jul 20, 2007
by
David S. Miller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SPARC64]: Add proper multicast support to VNET driver.
Signed-off-by:
David S. Miller
<
davem@davemloft.net
>
parent
5fc98610
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
146 additions
and
2 deletions
+146
-2
drivers/net/sunvnet.c
drivers/net/sunvnet.c
+135
-2
drivers/net/sunvnet.h
drivers/net/sunvnet.h
+11
-0
No files found.
drivers/net/sunvnet.c
View file @
028ebff2
...
...
@@ -459,6 +459,22 @@ static int vnet_nack(struct vnet_port *port, void *msgbuf)
return
0
;
}
static
int
handle_mcast
(
struct
vnet_port
*
port
,
void
*
msgbuf
)
{
struct
vio_net_mcast_info
*
pkt
=
msgbuf
;
if
(
pkt
->
tag
.
stype
!=
VIO_SUBTYPE_ACK
)
printk
(
KERN_ERR
PFX
"%s: Got unexpected MCAST reply "
"[%02x:%02x:%04x:%08x]
\n
"
,
port
->
vp
->
dev
->
name
,
pkt
->
tag
.
type
,
pkt
->
tag
.
stype
,
pkt
->
tag
.
stype_env
,
pkt
->
tag
.
sid
);
return
0
;
}
static
void
maybe_tx_wakeup
(
struct
vnet
*
vp
)
{
struct
net_device
*
dev
=
vp
->
dev
;
...
...
@@ -544,7 +560,10 @@ static void vnet_event(void *arg, int event)
err
=
vnet_nack
(
port
,
&
msgbuf
);
}
}
else
if
(
msgbuf
.
tag
.
type
==
VIO_TYPE_CTRL
)
{
err
=
vio_control_pkt_engine
(
vio
,
&
msgbuf
);
if
(
msgbuf
.
tag
.
stype_env
==
VNET_MCAST_INFO
)
err
=
handle_mcast
(
port
,
&
msgbuf
);
else
err
=
vio_control_pkt_engine
(
vio
,
&
msgbuf
);
if
(
err
)
break
;
}
else
{
...
...
@@ -731,9 +750,122 @@ static int vnet_close(struct net_device *dev)
return
0
;
}
static
struct
vnet_mcast_entry
*
__vnet_mc_find
(
struct
vnet
*
vp
,
u8
*
addr
)
{
struct
vnet_mcast_entry
*
m
;
for
(
m
=
vp
->
mcast_list
;
m
;
m
=
m
->
next
)
{
if
(
!
memcmp
(
m
->
addr
,
addr
,
ETH_ALEN
))
return
m
;
}
return
NULL
;
}
static
void
__update_mc_list
(
struct
vnet
*
vp
,
struct
net_device
*
dev
)
{
struct
dev_addr_list
*
p
;
for
(
p
=
dev
->
mc_list
;
p
;
p
=
p
->
next
)
{
struct
vnet_mcast_entry
*
m
;
m
=
__vnet_mc_find
(
vp
,
p
->
dmi_addr
);
if
(
m
)
{
m
->
hit
=
1
;
continue
;
}
if
(
!
m
)
{
m
=
kzalloc
(
sizeof
(
*
m
),
GFP_ATOMIC
);
if
(
!
m
)
continue
;
memcpy
(
m
->
addr
,
p
->
dmi_addr
,
ETH_ALEN
);
m
->
hit
=
1
;
m
->
next
=
vp
->
mcast_list
;
vp
->
mcast_list
=
m
;
}
}
}
static
void
__send_mc_list
(
struct
vnet
*
vp
,
struct
vnet_port
*
port
)
{
struct
vio_net_mcast_info
info
;
struct
vnet_mcast_entry
*
m
,
**
pp
;
int
n_addrs
;
memset
(
&
info
,
0
,
sizeof
(
info
));
info
.
tag
.
type
=
VIO_TYPE_CTRL
;
info
.
tag
.
stype
=
VIO_SUBTYPE_INFO
;
info
.
tag
.
stype_env
=
VNET_MCAST_INFO
;
info
.
tag
.
sid
=
vio_send_sid
(
&
port
->
vio
);
info
.
set
=
1
;
n_addrs
=
0
;
for
(
m
=
vp
->
mcast_list
;
m
;
m
=
m
->
next
)
{
if
(
m
->
sent
)
continue
;
m
->
sent
=
1
;
memcpy
(
&
info
.
mcast_addr
[
n_addrs
*
ETH_ALEN
],
m
->
addr
,
ETH_ALEN
);
if
(
++
n_addrs
==
VNET_NUM_MCAST
)
{
info
.
count
=
n_addrs
;
(
void
)
vio_ldc_send
(
&
port
->
vio
,
&
info
,
sizeof
(
info
));
n_addrs
=
0
;
}
}
if
(
n_addrs
)
{
info
.
count
=
n_addrs
;
(
void
)
vio_ldc_send
(
&
port
->
vio
,
&
info
,
sizeof
(
info
));
}
info
.
set
=
0
;
n_addrs
=
0
;
pp
=
&
vp
->
mcast_list
;
while
((
m
=
*
pp
)
!=
NULL
)
{
if
(
m
->
hit
)
{
m
->
hit
=
0
;
pp
=
&
m
->
next
;
continue
;
}
memcpy
(
&
info
.
mcast_addr
[
n_addrs
*
ETH_ALEN
],
m
->
addr
,
ETH_ALEN
);
if
(
++
n_addrs
==
VNET_NUM_MCAST
)
{
info
.
count
=
n_addrs
;
(
void
)
vio_ldc_send
(
&
port
->
vio
,
&
info
,
sizeof
(
info
));
n_addrs
=
0
;
}
*
pp
=
m
->
next
;
kfree
(
m
);
}
if
(
n_addrs
)
{
info
.
count
=
n_addrs
;
(
void
)
vio_ldc_send
(
&
port
->
vio
,
&
info
,
sizeof
(
info
));
}
}
static
void
vnet_set_rx_mode
(
struct
net_device
*
dev
)
{
/* XXX Implement multicast support XXX */
struct
vnet
*
vp
=
netdev_priv
(
dev
);
struct
vnet_port
*
port
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
vp
->
lock
,
flags
);
if
(
!
list_empty
(
&
vp
->
port_list
))
{
port
=
list_entry
(
vp
->
port_list
.
next
,
struct
vnet_port
,
list
);
if
(
port
->
switch_port
)
{
__update_mc_list
(
vp
,
dev
);
__send_mc_list
(
vp
,
port
);
}
}
spin_unlock_irqrestore
(
&
vp
->
lock
,
flags
);
}
static
int
vnet_change_mtu
(
struct
net_device
*
dev
,
int
new_mtu
)
...
...
@@ -1070,6 +1202,7 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev,
switch_port
=
0
;
if
(
mdesc_get_property
(
hp
,
vdev
->
mp
,
"switch-port"
,
NULL
)
!=
NULL
)
switch_port
=
1
;
port
->
switch_port
=
switch_port
;
spin_lock_irqsave
(
&
vp
->
lock
,
flags
);
if
(
switch_port
)
...
...
drivers/net/sunvnet.h
View file @
028ebff2
...
...
@@ -30,6 +30,8 @@ struct vnet_port {
struct
hlist_node
hash
;
u8
raddr
[
ETH_ALEN
];
u8
switch_port
;
u8
__pad
;
struct
vnet
*
vp
;
...
...
@@ -53,6 +55,13 @@ static inline unsigned int vnet_hashfn(u8 *mac)
return
val
&
(
VNET_PORT_HASH_MASK
);
}
struct
vnet_mcast_entry
{
u8
addr
[
ETH_ALEN
];
u8
sent
;
u8
hit
;
struct
vnet_mcast_entry
*
next
;
};
struct
vnet
{
/* Protects port_list and port_hash. */
spinlock_t
lock
;
...
...
@@ -65,6 +74,8 @@ struct vnet {
struct
hlist_head
port_hash
[
VNET_PORT_HASH_SIZE
];
struct
vnet_mcast_entry
*
mcast_list
;
struct
list_head
list
;
u64
local_mac
;
};
...
...
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