aboutsummaryrefslogtreecommitdiffstats
path: root/net/dsa/slave.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-03-29 16:24:05 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-29 16:24:05 -0400
commit7836b16c0dd1d3039ccc35ceeff6d75401fbba8c (patch)
tree62f92afc09fc12f37e1048147ea0090e652921c8 /net/dsa/slave.c
parent5ce58c2f13eaa8ca6d7e1041175433bd8cc55756 (diff)
parentb2a6b93a0c5730dd96f224ed22ccd0662d06b3b0 (diff)
Merge branch 'dsa-hw-bridging'
Guenter Roeck says: ==================== net: dsa: HW bridging, EEE support Patch 1 to 7 of this series prepare the drivers using the mv88e6xxx code for HW bridging support, without adding the code itself. For the most part this factors out common port initialization code. There is no functional change except for patch 3, which disables the message port bit for the CPU port to prevent packet duplication if HW bridging is configured. Patch 8 adds the infrastructure for hardware bridging support to the mv88e6xxx code. Patch 9 wires the MV88E6352 driver to support hardware bridging. Patches 10 to 12 add support for ndo_fdb functions to the dsa subsystem, and wire up the MV88E6352 driver to support those functions. Patches 13 to 16 add EEE support and HW bridging support to the mv88e6171 driver. This set of patches is from Andrew, applied on top of the first set of patches. The series applies to net-next as of 3/24/2015. Thanks a lot to Andrew Lunn for testing and valuable feedback. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa/slave.c')
-rw-r--r--net/dsa/slave.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 39555f3f263b..3597724ec3d8 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -201,6 +201,105 @@ out:
201 return 0; 201 return 0;
202} 202}
203 203
204static int dsa_slave_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
205 struct net_device *dev,
206 const unsigned char *addr, u16 vid, u16 nlm_flags)
207{
208 struct dsa_slave_priv *p = netdev_priv(dev);
209 struct dsa_switch *ds = p->parent;
210 int ret = -EOPNOTSUPP;
211
212 if (ds->drv->fdb_add)
213 ret = ds->drv->fdb_add(ds, p->port, addr, vid);
214
215 return ret;
216}
217
218static int dsa_slave_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
219 struct net_device *dev,
220 const unsigned char *addr, u16 vid)
221{
222 struct dsa_slave_priv *p = netdev_priv(dev);
223 struct dsa_switch *ds = p->parent;
224 int ret = -EOPNOTSUPP;
225
226 if (ds->drv->fdb_del)
227 ret = ds->drv->fdb_del(ds, p->port, addr, vid);
228
229 return ret;
230}
231
232static int dsa_slave_fill_info(struct net_device *dev, struct sk_buff *skb,
233 const unsigned char *addr, u16 vid,
234 bool is_static,
235 u32 portid, u32 seq, int type,
236 unsigned int flags)
237{
238 struct nlmsghdr *nlh;
239 struct ndmsg *ndm;
240
241 nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags);
242 if (!nlh)
243 return -EMSGSIZE;
244
245 ndm = nlmsg_data(nlh);
246 ndm->ndm_family = AF_BRIDGE;
247 ndm->ndm_pad1 = 0;
248 ndm->ndm_pad2 = 0;
249 ndm->ndm_flags = NTF_EXT_LEARNED;
250 ndm->ndm_type = 0;
251 ndm->ndm_ifindex = dev->ifindex;
252 ndm->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
253
254 if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr))
255 goto nla_put_failure;
256
257 if (vid && nla_put_u16(skb, NDA_VLAN, vid))
258 goto nla_put_failure;
259
260 nlmsg_end(skb, nlh);
261 return 0;
262
263nla_put_failure:
264 nlmsg_cancel(skb, nlh);
265 return -EMSGSIZE;
266}
267
268/* Dump information about entries, in response to GETNEIGH */
269static int dsa_slave_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
270 struct net_device *dev,
271 struct net_device *filter_dev, int idx)
272{
273 struct dsa_slave_priv *p = netdev_priv(dev);
274 struct dsa_switch *ds = p->parent;
275 unsigned char addr[ETH_ALEN] = { 0 };
276 int ret;
277
278 if (!ds->drv->fdb_getnext)
279 return -EOPNOTSUPP;
280
281 for (; ; idx++) {
282 bool is_static;
283
284 ret = ds->drv->fdb_getnext(ds, p->port, addr, &is_static);
285 if (ret < 0)
286 break;
287
288 if (idx < cb->args[0])
289 continue;
290
291 ret = dsa_slave_fill_info(dev, skb, addr, 0,
292 is_static,
293 NETLINK_CB(cb->skb).portid,
294 cb->nlh->nlmsg_seq,
295 RTM_NEWNEIGH, NLM_F_MULTI);
296 if (ret < 0)
297 break;
298 }
299
300 return idx;
301}
302
204static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 303static int dsa_slave_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
205{ 304{
206 struct dsa_slave_priv *p = netdev_priv(dev); 305 struct dsa_slave_priv *p = netdev_priv(dev);
@@ -572,6 +671,9 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
572 .ndo_change_rx_flags = dsa_slave_change_rx_flags, 671 .ndo_change_rx_flags = dsa_slave_change_rx_flags,
573 .ndo_set_rx_mode = dsa_slave_set_rx_mode, 672 .ndo_set_rx_mode = dsa_slave_set_rx_mode,
574 .ndo_set_mac_address = dsa_slave_set_mac_address, 673 .ndo_set_mac_address = dsa_slave_set_mac_address,
674 .ndo_fdb_add = dsa_slave_fdb_add,
675 .ndo_fdb_del = dsa_slave_fdb_del,
676 .ndo_fdb_dump = dsa_slave_fdb_dump,
575 .ndo_do_ioctl = dsa_slave_ioctl, 677 .ndo_do_ioctl = dsa_slave_ioctl,
576}; 678};
577 679