net/hsr: Implemented .ndo_fix_features (better device features handling).
Signed-off-by: Arvid Brodin <arvid.brodin@alten.se> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c5a7591172
commit
1cc1eb5273
|
@ -198,6 +198,39 @@ static int hsr_dev_close(struct net_device *dev)
|
|||
}
|
||||
|
||||
|
||||
static netdev_features_t hsr_features_recompute(struct hsr_priv *hsr,
|
||||
netdev_features_t features)
|
||||
{
|
||||
netdev_features_t mask;
|
||||
struct hsr_port *port;
|
||||
|
||||
mask = features;
|
||||
|
||||
/* Mask out all features that, if supported by one device, should be
|
||||
* enabled for all devices (see NETIF_F_ONE_FOR_ALL).
|
||||
*
|
||||
* Anything that's off in mask will not be enabled - so only things
|
||||
* that were in features originally, and also is in NETIF_F_ONE_FOR_ALL,
|
||||
* may become enabled.
|
||||
*/
|
||||
features &= ~NETIF_F_ONE_FOR_ALL;
|
||||
hsr_for_each_port(hsr, port)
|
||||
features = netdev_increment_features(features,
|
||||
port->dev->features,
|
||||
mask);
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
static netdev_features_t hsr_fix_features(struct net_device *dev,
|
||||
netdev_features_t features)
|
||||
{
|
||||
struct hsr_priv *hsr = netdev_priv(dev);
|
||||
|
||||
return hsr_features_recompute(hsr, features);
|
||||
}
|
||||
|
||||
|
||||
static void hsr_fill_tag(struct hsr_ethhdr *hsr_ethhdr, struct hsr_priv *hsr)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
|
@ -465,6 +498,7 @@ static const struct net_device_ops hsr_device_ops = {
|
|||
.ndo_open = hsr_dev_open,
|
||||
.ndo_stop = hsr_dev_close,
|
||||
.ndo_start_xmit = hsr_dev_xmit,
|
||||
.ndo_fix_features = hsr_fix_features,
|
||||
};
|
||||
|
||||
|
||||
|
@ -478,6 +512,19 @@ void hsr_dev_setup(struct net_device *dev)
|
|||
dev->tx_queue_len = 0;
|
||||
|
||||
dev->destructor = hsr_dev_destroy;
|
||||
|
||||
dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
|
||||
NETIF_F_GSO_MASK | NETIF_F_HW_CSUM |
|
||||
NETIF_F_HW_VLAN_CTAG_TX;
|
||||
|
||||
dev->features = dev->hw_features;
|
||||
|
||||
/* Prevent recursive tx locking */
|
||||
dev->features |= NETIF_F_LLTX;
|
||||
/* VLAN on top of HSR needs testing and probably some work on
|
||||
* hsr_header_create() etc.
|
||||
*/
|
||||
dev->features |= NETIF_F_VLAN_CHALLENGED;
|
||||
}
|
||||
|
||||
|
||||
|
@ -513,14 +560,6 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
|
|||
if (res < 0)
|
||||
return res;
|
||||
|
||||
hsr_dev->features = slave[0]->features & slave[1]->features;
|
||||
/* Prevent recursive tx locking */
|
||||
hsr_dev->features |= NETIF_F_LLTX;
|
||||
/* VLAN on top of HSR needs testing and probably some work on
|
||||
* hsr_header_create() etc.
|
||||
*/
|
||||
hsr_dev->features |= NETIF_F_VLAN_CHALLENGED;
|
||||
|
||||
spin_lock_init(&hsr->seqnr_lock);
|
||||
/* Overflow soon to find bugs easier: */
|
||||
hsr->sequence_nr = USHRT_MAX - 1024;
|
||||
|
|
|
@ -344,6 +344,7 @@ int hsr_add_port(struct hsr_priv *hsr, struct net_device *dev,
|
|||
if (dev->hard_header_len + HSR_HLEN > master->dev->hard_header_len)
|
||||
master->dev->hard_header_len = dev->hard_header_len + HSR_HLEN;
|
||||
|
||||
netdev_update_features(master->dev);
|
||||
dev_set_mtu(master->dev, hsr_get_max_mtu(hsr));
|
||||
|
||||
return 0;
|
||||
|
@ -363,6 +364,7 @@ void hsr_del_port(struct hsr_port *port)
|
|||
list_del_rcu(&port->port_list);
|
||||
|
||||
if (port != master) {
|
||||
netdev_update_features(master->dev);
|
||||
dev_set_mtu(master->dev, hsr_get_max_mtu(hsr));
|
||||
netdev_rx_handler_unregister(port->dev);
|
||||
dev_set_promiscuity(port->dev, -1);
|
||||
|
|
Loading…
Reference in New Issue