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)
|
static void hsr_fill_tag(struct hsr_ethhdr *hsr_ethhdr, struct hsr_priv *hsr)
|
||||||
{
|
{
|
||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
|
@ -465,6 +498,7 @@ static const struct net_device_ops hsr_device_ops = {
|
||||||
.ndo_open = hsr_dev_open,
|
.ndo_open = hsr_dev_open,
|
||||||
.ndo_stop = hsr_dev_close,
|
.ndo_stop = hsr_dev_close,
|
||||||
.ndo_start_xmit = hsr_dev_xmit,
|
.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->tx_queue_len = 0;
|
||||||
|
|
||||||
dev->destructor = hsr_dev_destroy;
|
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)
|
if (res < 0)
|
||||||
return res;
|
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);
|
spin_lock_init(&hsr->seqnr_lock);
|
||||||
/* Overflow soon to find bugs easier: */
|
/* Overflow soon to find bugs easier: */
|
||||||
hsr->sequence_nr = USHRT_MAX - 1024;
|
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)
|
if (dev->hard_header_len + HSR_HLEN > master->dev->hard_header_len)
|
||||||
master->dev->hard_header_len = dev->hard_header_len + HSR_HLEN;
|
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));
|
dev_set_mtu(master->dev, hsr_get_max_mtu(hsr));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -363,6 +364,7 @@ void hsr_del_port(struct hsr_port *port)
|
||||||
list_del_rcu(&port->port_list);
|
list_del_rcu(&port->port_list);
|
||||||
|
|
||||||
if (port != master) {
|
if (port != master) {
|
||||||
|
netdev_update_features(master->dev);
|
||||||
dev_set_mtu(master->dev, hsr_get_max_mtu(hsr));
|
dev_set_mtu(master->dev, hsr_get_max_mtu(hsr));
|
||||||
netdev_rx_handler_unregister(port->dev);
|
netdev_rx_handler_unregister(port->dev);
|
||||||
dev_set_promiscuity(port->dev, -1);
|
dev_set_promiscuity(port->dev, -1);
|
||||||
|
|
Loading…
Reference in New Issue