diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 58 | ||||
-rw-r--r-- | drivers/net/bonding/bonding.h | 3 |
2 files changed, 60 insertions, 1 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2c930da90a85..94c9f68dd16b 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -1604,6 +1604,44 @@ static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_ | |||
1604 | return 0; | 1604 | return 0; |
1605 | } | 1605 | } |
1606 | 1606 | ||
1607 | #define BOND_INTERSECT_FEATURES \ | ||
1608 | (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) | ||
1609 | |||
1610 | /* | ||
1611 | * Compute the features available to the bonding device by | ||
1612 | * intersection of all of the slave devices' BOND_INTERSECT_FEATURES. | ||
1613 | * Call this after attaching or detaching a slave to update the | ||
1614 | * bond's features. | ||
1615 | */ | ||
1616 | static int bond_compute_features(struct bonding *bond) | ||
1617 | { | ||
1618 | int i; | ||
1619 | struct slave *slave; | ||
1620 | struct net_device *bond_dev = bond->dev; | ||
1621 | int features = bond->bond_features; | ||
1622 | |||
1623 | bond_for_each_slave(bond, slave, i) { | ||
1624 | struct net_device * slave_dev = slave->dev; | ||
1625 | if (i == 0) { | ||
1626 | features |= BOND_INTERSECT_FEATURES; | ||
1627 | } | ||
1628 | features &= | ||
1629 | ~(~slave_dev->features & BOND_INTERSECT_FEATURES); | ||
1630 | } | ||
1631 | |||
1632 | /* turn off NETIF_F_SG if we need a csum and h/w can't do it */ | ||
1633 | if ((features & NETIF_F_SG) && | ||
1634 | !(features & (NETIF_F_IP_CSUM | | ||
1635 | NETIF_F_NO_CSUM | | ||
1636 | NETIF_F_HW_CSUM))) { | ||
1637 | features &= ~NETIF_F_SG; | ||
1638 | } | ||
1639 | |||
1640 | bond_dev->features = features; | ||
1641 | |||
1642 | return 0; | ||
1643 | } | ||
1644 | |||
1607 | /* enslave device <slave> to bond device <master> */ | 1645 | /* enslave device <slave> to bond device <master> */ |
1608 | static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | 1646 | static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) |
1609 | { | 1647 | { |
@@ -1811,6 +1849,8 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de | |||
1811 | new_slave->delay = 0; | 1849 | new_slave->delay = 0; |
1812 | new_slave->link_failure_count = 0; | 1850 | new_slave->link_failure_count = 0; |
1813 | 1851 | ||
1852 | bond_compute_features(bond); | ||
1853 | |||
1814 | if (bond->params.miimon && !bond->params.use_carrier) { | 1854 | if (bond->params.miimon && !bond->params.use_carrier) { |
1815 | link_reporting = bond_check_dev_link(bond, slave_dev, 1); | 1855 | link_reporting = bond_check_dev_link(bond, slave_dev, 1); |
1816 | 1856 | ||
@@ -2015,7 +2055,7 @@ err_free: | |||
2015 | 2055 | ||
2016 | err_undo_flags: | 2056 | err_undo_flags: |
2017 | bond_dev->features = old_features; | 2057 | bond_dev->features = old_features; |
2018 | 2058 | ||
2019 | return res; | 2059 | return res; |
2020 | } | 2060 | } |
2021 | 2061 | ||
@@ -2100,6 +2140,8 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de | |||
2100 | /* release the slave from its bond */ | 2140 | /* release the slave from its bond */ |
2101 | bond_detach_slave(bond, slave); | 2141 | bond_detach_slave(bond, slave); |
2102 | 2142 | ||
2143 | bond_compute_features(bond); | ||
2144 | |||
2103 | if (bond->primary_slave == slave) { | 2145 | if (bond->primary_slave == slave) { |
2104 | bond->primary_slave = NULL; | 2146 | bond->primary_slave = NULL; |
2105 | } | 2147 | } |
@@ -2243,6 +2285,8 @@ static int bond_release_all(struct net_device *bond_dev) | |||
2243 | bond_alb_deinit_slave(bond, slave); | 2285 | bond_alb_deinit_slave(bond, slave); |
2244 | } | 2286 | } |
2245 | 2287 | ||
2288 | bond_compute_features(bond); | ||
2289 | |||
2246 | /* now that the slave is detached, unlock and perform | 2290 | /* now that the slave is detached, unlock and perform |
2247 | * all the undo steps that should not be called from | 2291 | * all the undo steps that should not be called from |
2248 | * within a lock. | 2292 | * within a lock. |
@@ -3588,6 +3632,7 @@ static int bond_master_netdev_event(unsigned long event, struct net_device *bond | |||
3588 | static int bond_slave_netdev_event(unsigned long event, struct net_device *slave_dev) | 3632 | static int bond_slave_netdev_event(unsigned long event, struct net_device *slave_dev) |
3589 | { | 3633 | { |
3590 | struct net_device *bond_dev = slave_dev->master; | 3634 | struct net_device *bond_dev = slave_dev->master; |
3635 | struct bonding *bond = bond_dev->priv; | ||
3591 | 3636 | ||
3592 | switch (event) { | 3637 | switch (event) { |
3593 | case NETDEV_UNREGISTER: | 3638 | case NETDEV_UNREGISTER: |
@@ -3626,6 +3671,9 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave | |||
3626 | * TODO: handle changing the primary's name | 3671 | * TODO: handle changing the primary's name |
3627 | */ | 3672 | */ |
3628 | break; | 3673 | break; |
3674 | case NETDEV_FEAT_CHANGE: | ||
3675 | bond_compute_features(bond); | ||
3676 | break; | ||
3629 | default: | 3677 | default: |
3630 | break; | 3678 | break; |
3631 | } | 3679 | } |
@@ -4526,6 +4574,11 @@ static inline void bond_set_mode_ops(struct bonding *bond, int mode) | |||
4526 | } | 4574 | } |
4527 | } | 4575 | } |
4528 | 4576 | ||
4577 | static struct ethtool_ops bond_ethtool_ops = { | ||
4578 | .get_tx_csum = ethtool_op_get_tx_csum, | ||
4579 | .get_sg = ethtool_op_get_sg, | ||
4580 | }; | ||
4581 | |||
4529 | /* | 4582 | /* |
4530 | * Does not allocate but creates a /proc entry. | 4583 | * Does not allocate but creates a /proc entry. |
4531 | * Allowed to fail. | 4584 | * Allowed to fail. |
@@ -4555,6 +4608,7 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par | |||
4555 | bond_dev->stop = bond_close; | 4608 | bond_dev->stop = bond_close; |
4556 | bond_dev->get_stats = bond_get_stats; | 4609 | bond_dev->get_stats = bond_get_stats; |
4557 | bond_dev->do_ioctl = bond_do_ioctl; | 4610 | bond_dev->do_ioctl = bond_do_ioctl; |
4611 | bond_dev->ethtool_ops = &bond_ethtool_ops; | ||
4558 | bond_dev->set_multicast_list = bond_set_multicast_list; | 4612 | bond_dev->set_multicast_list = bond_set_multicast_list; |
4559 | bond_dev->change_mtu = bond_change_mtu; | 4613 | bond_dev->change_mtu = bond_change_mtu; |
4560 | bond_dev->set_mac_address = bond_set_mac_address; | 4614 | bond_dev->set_mac_address = bond_set_mac_address; |
@@ -4591,6 +4645,8 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par | |||
4591 | NETIF_F_HW_VLAN_RX | | 4645 | NETIF_F_HW_VLAN_RX | |
4592 | NETIF_F_HW_VLAN_FILTER); | 4646 | NETIF_F_HW_VLAN_FILTER); |
4593 | 4647 | ||
4648 | bond->bond_features = bond_dev->features; | ||
4649 | |||
4594 | #ifdef CONFIG_PROC_FS | 4650 | #ifdef CONFIG_PROC_FS |
4595 | bond_create_proc_entry(bond); | 4651 | bond_create_proc_entry(bond); |
4596 | #endif | 4652 | #endif |
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index d27f377b3eeb..388196980862 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h | |||
@@ -211,6 +211,9 @@ struct bonding { | |||
211 | struct bond_params params; | 211 | struct bond_params params; |
212 | struct list_head vlan_list; | 212 | struct list_head vlan_list; |
213 | struct vlan_group *vlgrp; | 213 | struct vlan_group *vlgrp; |
214 | /* the features the bonding device supports, independently | ||
215 | * of any slaves */ | ||
216 | int bond_features; | ||
214 | }; | 217 | }; |
215 | 218 | ||
216 | /** | 219 | /** |