Commit 1cc1eb52 authored by Arvid Brodin's avatar Arvid Brodin Committed by David S. Miller

net/hsr: Implemented .ndo_fix_features (better device features handling).

Signed-off-by: default avatarArvid Brodin <arvid.brodin@alten.se>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c5a75911
...@@ -198,6 +198,39 @@ static int hsr_dev_close(struct net_device *dev) ...@@ -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 = { ...@@ -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) ...@@ -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], ...@@ -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, ...@@ -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) ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment