diff options
author | Arvid Brodin <arvid.brodin@alten.se> | 2014-07-04 17:38:57 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-08 14:35:31 -0400 |
commit | 1cc1eb52734bfd2fc57c7b3337a11198e713580d (patch) | |
tree | 91d62f13216f866ccc2015c21a0d8962691f049c /net/hsr | |
parent | c5a7591172100269e426cf630da0f2dc8138a206 (diff) |
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>
Diffstat (limited to 'net/hsr')
-rw-r--r-- | net/hsr/hsr_device.c | 55 | ||||
-rw-r--r-- | net/hsr/hsr_slave.c | 2 |
2 files changed, 49 insertions, 8 deletions
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index 1fc4ea20752e..c489aed98df4 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c | |||
@@ -198,6 +198,39 @@ static int hsr_dev_close(struct net_device *dev) | |||
198 | } | 198 | } |
199 | 199 | ||
200 | 200 | ||
201 | static netdev_features_t hsr_features_recompute(struct hsr_priv *hsr, | ||
202 | netdev_features_t features) | ||
203 | { | ||
204 | netdev_features_t mask; | ||
205 | struct hsr_port *port; | ||
206 | |||
207 | mask = features; | ||
208 | |||
209 | /* Mask out all features that, if supported by one device, should be | ||
210 | * enabled for all devices (see NETIF_F_ONE_FOR_ALL). | ||
211 | * | ||
212 | * Anything that's off in mask will not be enabled - so only things | ||
213 | * that were in features originally, and also is in NETIF_F_ONE_FOR_ALL, | ||
214 | * may become enabled. | ||
215 | */ | ||
216 | features &= ~NETIF_F_ONE_FOR_ALL; | ||
217 | hsr_for_each_port(hsr, port) | ||
218 | features = netdev_increment_features(features, | ||
219 | port->dev->features, | ||
220 | mask); | ||
221 | |||
222 | return features; | ||
223 | } | ||
224 | |||
225 | static netdev_features_t hsr_fix_features(struct net_device *dev, | ||
226 | netdev_features_t features) | ||
227 | { | ||
228 | struct hsr_priv *hsr = netdev_priv(dev); | ||
229 | |||
230 | return hsr_features_recompute(hsr, features); | ||
231 | } | ||
232 | |||
233 | |||
201 | static void hsr_fill_tag(struct hsr_ethhdr *hsr_ethhdr, struct hsr_priv *hsr) | 234 | static void hsr_fill_tag(struct hsr_ethhdr *hsr_ethhdr, struct hsr_priv *hsr) |
202 | { | 235 | { |
203 | unsigned long irqflags; | 236 | unsigned long irqflags; |
@@ -465,6 +498,7 @@ static const struct net_device_ops hsr_device_ops = { | |||
465 | .ndo_open = hsr_dev_open, | 498 | .ndo_open = hsr_dev_open, |
466 | .ndo_stop = hsr_dev_close, | 499 | .ndo_stop = hsr_dev_close, |
467 | .ndo_start_xmit = hsr_dev_xmit, | 500 | .ndo_start_xmit = hsr_dev_xmit, |
501 | .ndo_fix_features = hsr_fix_features, | ||
468 | }; | 502 | }; |
469 | 503 | ||
470 | 504 | ||
@@ -478,6 +512,19 @@ void hsr_dev_setup(struct net_device *dev) | |||
478 | dev->tx_queue_len = 0; | 512 | dev->tx_queue_len = 0; |
479 | 513 | ||
480 | dev->destructor = hsr_dev_destroy; | 514 | dev->destructor = hsr_dev_destroy; |
515 | |||
516 | dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | | ||
517 | NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | | ||
518 | NETIF_F_HW_VLAN_CTAG_TX; | ||
519 | |||
520 | dev->features = dev->hw_features; | ||
521 | |||
522 | /* Prevent recursive tx locking */ | ||
523 | dev->features |= NETIF_F_LLTX; | ||
524 | /* VLAN on top of HSR needs testing and probably some work on | ||
525 | * hsr_header_create() etc. | ||
526 | */ | ||
527 | dev->features |= NETIF_F_VLAN_CHALLENGED; | ||
481 | } | 528 | } |
482 | 529 | ||
483 | 530 | ||
@@ -513,14 +560,6 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], | |||
513 | if (res < 0) | 560 | if (res < 0) |
514 | return res; | 561 | return res; |
515 | 562 | ||
516 | hsr_dev->features = slave[0]->features & slave[1]->features; | ||
517 | /* Prevent recursive tx locking */ | ||
518 | hsr_dev->features |= NETIF_F_LLTX; | ||
519 | /* VLAN on top of HSR needs testing and probably some work on | ||
520 | * hsr_header_create() etc. | ||
521 | */ | ||
522 | hsr_dev->features |= NETIF_F_VLAN_CHALLENGED; | ||
523 | |||
524 | spin_lock_init(&hsr->seqnr_lock); | 563 | spin_lock_init(&hsr->seqnr_lock); |
525 | /* Overflow soon to find bugs easier: */ | 564 | /* Overflow soon to find bugs easier: */ |
526 | hsr->sequence_nr = USHRT_MAX - 1024; | 565 | hsr->sequence_nr = USHRT_MAX - 1024; |
diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c index fffd69297c3e..23817d0b765b 100644 --- a/net/hsr/hsr_slave.c +++ b/net/hsr/hsr_slave.c | |||
@@ -344,6 +344,7 @@ int hsr_add_port(struct hsr_priv *hsr, struct net_device *dev, | |||
344 | if (dev->hard_header_len + HSR_HLEN > master->dev->hard_header_len) | 344 | if (dev->hard_header_len + HSR_HLEN > master->dev->hard_header_len) |
345 | master->dev->hard_header_len = dev->hard_header_len + HSR_HLEN; | 345 | master->dev->hard_header_len = dev->hard_header_len + HSR_HLEN; |
346 | 346 | ||
347 | netdev_update_features(master->dev); | ||
347 | dev_set_mtu(master->dev, hsr_get_max_mtu(hsr)); | 348 | dev_set_mtu(master->dev, hsr_get_max_mtu(hsr)); |
348 | 349 | ||
349 | return 0; | 350 | return 0; |
@@ -363,6 +364,7 @@ void hsr_del_port(struct hsr_port *port) | |||
363 | list_del_rcu(&port->port_list); | 364 | list_del_rcu(&port->port_list); |
364 | 365 | ||
365 | if (port != master) { | 366 | if (port != master) { |
367 | netdev_update_features(master->dev); | ||
366 | dev_set_mtu(master->dev, hsr_get_max_mtu(hsr)); | 368 | dev_set_mtu(master->dev, hsr_get_max_mtu(hsr)); |
367 | netdev_rx_handler_unregister(port->dev); | 369 | netdev_rx_handler_unregister(port->dev); |
368 | dev_set_promiscuity(port->dev, -1); | 370 | dev_set_promiscuity(port->dev, -1); |