aboutsummaryrefslogtreecommitdiffstats
path: root/net/dsa/slave.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-11-11 12:20:29 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-11-11 12:20:29 -0500
commit0a4cf2c8786219b4871c37240ab9787a61d843ee (patch)
treea126516733f3a757711754bbac189417c79d8bcb /net/dsa/slave.c
parent4694516d1987303dd83bfd0efdd36fa5b65d701b (diff)
parentdf02c6ff2e3937379b31ea161b53229134fe92f7 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: dsa: fix master interface allmulti/promisc handling dsa: fix skb->pkt_type when mac address of slave interface differs net: fix setting of skb->tail in skb_recycle_check() net: fix /proc/net/snmp as memory corruptor mac80211: fix a buffer overrun in station debug code netfilter: payload_len is be16, add size of struct rather than size of pointer ipv6: fix ip6_mr_init error path [4/4] dca: fixup initialization dependency [3/4] I/OAT: fix async_tx.callback checking [2/4] I/OAT: fix dma_pin_iovec_pages() error handling [1/4] I/OAT: fix channel resources free for not allocated channels ssb: Fix DMA-API compilation for non-PCI systems SSB: hide empty sub menu vlan: Fix typos in proc output string [netdrvr] usb/hso: Cleanup rfkill error handling sfc: Correct address of gPXE boot configuration in EEPROM el3_common_init() should be __devinit, not __init hso: rfkill type should be WWAN mlx4_en: Start port error flow bug fix af_key: mark policy as dead before destroying
Diffstat (limited to 'net/dsa/slave.c')
-rw-r--r--net/dsa/slave.c72
1 files changed, 70 insertions, 2 deletions
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 37616884b8a9..1af5a79309e9 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -10,6 +10,7 @@
10 10
11#include <linux/list.h> 11#include <linux/list.h>
12#include <linux/netdevice.h> 12#include <linux/netdevice.h>
13#include <linux/etherdevice.h>
13#include <linux/phy.h> 14#include <linux/phy.h>
14#include "dsa_priv.h" 15#include "dsa_priv.h"
15 16
@@ -49,11 +50,57 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds)
49/* slave device handling ****************************************************/ 50/* slave device handling ****************************************************/
50static int dsa_slave_open(struct net_device *dev) 51static int dsa_slave_open(struct net_device *dev)
51{ 52{
53 struct dsa_slave_priv *p = netdev_priv(dev);
54 struct net_device *master = p->parent->master_netdev;
55 int err;
56
57 if (!(master->flags & IFF_UP))
58 return -ENETDOWN;
59
60 if (compare_ether_addr(dev->dev_addr, master->dev_addr)) {
61 err = dev_unicast_add(master, dev->dev_addr, ETH_ALEN);
62 if (err < 0)
63 goto out;
64 }
65
66 if (dev->flags & IFF_ALLMULTI) {
67 err = dev_set_allmulti(master, 1);
68 if (err < 0)
69 goto del_unicast;
70 }
71 if (dev->flags & IFF_PROMISC) {
72 err = dev_set_promiscuity(master, 1);
73 if (err < 0)
74 goto clear_allmulti;
75 }
76
52 return 0; 77 return 0;
78
79clear_allmulti:
80 if (dev->flags & IFF_ALLMULTI)
81 dev_set_allmulti(master, -1);
82del_unicast:
83 if (compare_ether_addr(dev->dev_addr, master->dev_addr))
84 dev_unicast_delete(master, dev->dev_addr, ETH_ALEN);
85out:
86 return err;
53} 87}
54 88
55static int dsa_slave_close(struct net_device *dev) 89static int dsa_slave_close(struct net_device *dev)
56{ 90{
91 struct dsa_slave_priv *p = netdev_priv(dev);
92 struct net_device *master = p->parent->master_netdev;
93
94 dev_mc_unsync(master, dev);
95 dev_unicast_unsync(master, dev);
96 if (dev->flags & IFF_ALLMULTI)
97 dev_set_allmulti(master, -1);
98 if (dev->flags & IFF_PROMISC)
99 dev_set_promiscuity(master, -1);
100
101 if (compare_ether_addr(dev->dev_addr, master->dev_addr))
102 dev_unicast_delete(master, dev->dev_addr, ETH_ALEN);
103
57 return 0; 104 return 0;
58} 105}
59 106
@@ -77,9 +124,30 @@ static void dsa_slave_set_rx_mode(struct net_device *dev)
77 dev_unicast_sync(master, dev); 124 dev_unicast_sync(master, dev);
78} 125}
79 126
80static int dsa_slave_set_mac_address(struct net_device *dev, void *addr) 127static int dsa_slave_set_mac_address(struct net_device *dev, void *a)
81{ 128{
82 memcpy(dev->dev_addr, addr + 2, 6); 129 struct dsa_slave_priv *p = netdev_priv(dev);
130 struct net_device *master = p->parent->master_netdev;
131 struct sockaddr *addr = a;
132 int err;
133
134 if (!is_valid_ether_addr(addr->sa_data))
135 return -EADDRNOTAVAIL;
136
137 if (!(dev->flags & IFF_UP))
138 goto out;
139
140 if (compare_ether_addr(addr->sa_data, master->dev_addr)) {
141 err = dev_unicast_add(master, addr->sa_data, ETH_ALEN);
142 if (err < 0)
143 return err;
144 }
145
146 if (compare_ether_addr(dev->dev_addr, master->dev_addr))
147 dev_unicast_delete(master, dev->dev_addr, ETH_ALEN);
148
149out:
150 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
83 151
84 return 0; 152 return 0;
85} 153}