diff options
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 53 |
1 files changed, 23 insertions, 30 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index d72c37f03e50..0c0dacba1f51 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -431,17 +431,13 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, | |||
431 | static int bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid) | 431 | static int bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid) |
432 | { | 432 | { |
433 | struct bonding *bond = netdev_priv(bond_dev); | 433 | struct bonding *bond = netdev_priv(bond_dev); |
434 | struct slave *slave; | 434 | struct slave *slave, *stop_at; |
435 | int i, res; | 435 | int i, res; |
436 | 436 | ||
437 | bond_for_each_slave(bond, slave, i) { | 437 | bond_for_each_slave(bond, slave, i) { |
438 | struct net_device *slave_dev = slave->dev; | 438 | res = vlan_vid_add(slave->dev, vid); |
439 | const struct net_device_ops *slave_ops = slave_dev->netdev_ops; | 439 | if (res) |
440 | 440 | goto unwind; | |
441 | if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) && | ||
442 | slave_ops->ndo_vlan_rx_add_vid) { | ||
443 | slave_ops->ndo_vlan_rx_add_vid(slave_dev, vid); | ||
444 | } | ||
445 | } | 441 | } |
446 | 442 | ||
447 | res = bond_add_vlan(bond, vid); | 443 | res = bond_add_vlan(bond, vid); |
@@ -452,6 +448,14 @@ static int bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid) | |||
452 | } | 448 | } |
453 | 449 | ||
454 | return 0; | 450 | return 0; |
451 | |||
452 | unwind: | ||
453 | /* unwind from head to the slave that failed */ | ||
454 | stop_at = slave; | ||
455 | bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) | ||
456 | vlan_vid_del(slave->dev, vid); | ||
457 | |||
458 | return res; | ||
455 | } | 459 | } |
456 | 460 | ||
457 | /** | 461 | /** |
@@ -465,15 +469,8 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid) | |||
465 | struct slave *slave; | 469 | struct slave *slave; |
466 | int i, res; | 470 | int i, res; |
467 | 471 | ||
468 | bond_for_each_slave(bond, slave, i) { | 472 | bond_for_each_slave(bond, slave, i) |
469 | struct net_device *slave_dev = slave->dev; | 473 | vlan_vid_del(slave->dev, vid); |
470 | const struct net_device_ops *slave_ops = slave_dev->netdev_ops; | ||
471 | |||
472 | if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) && | ||
473 | slave_ops->ndo_vlan_rx_kill_vid) { | ||
474 | slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vid); | ||
475 | } | ||
476 | } | ||
477 | 474 | ||
478 | res = bond_del_vlan(bond, vid); | 475 | res = bond_del_vlan(bond, vid); |
479 | if (res) { | 476 | if (res) { |
@@ -488,30 +485,26 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid) | |||
488 | static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *slave_dev) | 485 | static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *slave_dev) |
489 | { | 486 | { |
490 | struct vlan_entry *vlan; | 487 | struct vlan_entry *vlan; |
491 | const struct net_device_ops *slave_ops = slave_dev->netdev_ops; | 488 | int res; |
492 | |||
493 | if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) || | ||
494 | !(slave_ops->ndo_vlan_rx_add_vid)) | ||
495 | return; | ||
496 | 489 | ||
497 | list_for_each_entry(vlan, &bond->vlan_list, vlan_list) | 490 | list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { |
498 | slave_ops->ndo_vlan_rx_add_vid(slave_dev, vlan->vlan_id); | 491 | res = vlan_vid_add(slave_dev, vlan->vlan_id); |
492 | if (res) | ||
493 | pr_warning("%s: Failed to add vlan id %d to device %s\n", | ||
494 | bond->dev->name, vlan->vlan_id, | ||
495 | slave_dev->name); | ||
496 | } | ||
499 | } | 497 | } |
500 | 498 | ||
501 | static void bond_del_vlans_from_slave(struct bonding *bond, | 499 | static void bond_del_vlans_from_slave(struct bonding *bond, |
502 | struct net_device *slave_dev) | 500 | struct net_device *slave_dev) |
503 | { | 501 | { |
504 | const struct net_device_ops *slave_ops = slave_dev->netdev_ops; | ||
505 | struct vlan_entry *vlan; | 502 | struct vlan_entry *vlan; |
506 | 503 | ||
507 | if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) || | ||
508 | !(slave_ops->ndo_vlan_rx_kill_vid)) | ||
509 | return; | ||
510 | |||
511 | list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { | 504 | list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { |
512 | if (!vlan->vlan_id) | 505 | if (!vlan->vlan_id) |
513 | continue; | 506 | continue; |
514 | slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vlan->vlan_id); | 507 | vlan_vid_del(slave_dev, vlan->vlan_id); |
515 | } | 508 | } |
516 | } | 509 | } |
517 | 510 | ||