aboutsummaryrefslogtreecommitdiffstats
path: root/net/hsr
diff options
context:
space:
mode:
authorArvid Brodin <arvid.brodin@alten.se>2014-07-04 17:38:57 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-08 14:35:31 -0400
commit1cc1eb52734bfd2fc57c7b3337a11198e713580d (patch)
tree91d62f13216f866ccc2015c21a0d8962691f049c /net/hsr
parentc5a7591172100269e426cf630da0f2dc8138a206 (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.c55
-rw-r--r--net/hsr/hsr_slave.c2
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
201static 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
225static 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
201static void hsr_fill_tag(struct hsr_ethhdr *hsr_ethhdr, struct hsr_priv *hsr) 234static 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);