diff options
Diffstat (limited to 'net/hsr/hsr_slave.c')
-rw-r--r-- | net/hsr/hsr_slave.c | 63 |
1 files changed, 31 insertions, 32 deletions
diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c index a9104d42aafb..f4b9f7a3ce51 100644 --- a/net/hsr/hsr_slave.c +++ b/net/hsr/hsr_slave.c @@ -25,7 +25,6 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb) return RX_HANDLER_PASS; } - rcu_read_lock(); /* hsr->node_db, hsr->ports */ port = hsr_port_get_rcu(skb->dev); if (!port) goto finish_pass; @@ -45,11 +44,9 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb) hsr_forward_skb(skb, port); finish_consume: - rcu_read_unlock(); /* hsr->node_db, hsr->ports */ return RX_HANDLER_CONSUMED; finish_pass: - rcu_read_unlock(); /* hsr->node_db, hsr->ports */ return RX_HANDLER_PASS; } @@ -58,33 +55,37 @@ bool hsr_port_exists(const struct net_device *dev) return rcu_access_pointer(dev->rx_handler) == hsr_handle_frame; } -static int hsr_check_dev_ok(struct net_device *dev) +static int hsr_check_dev_ok(struct net_device *dev, + struct netlink_ext_ack *extack) { /* Don't allow HSR on non-ethernet like devices */ if ((dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN) { - netdev_info(dev, "Cannot use loopback or non-ethernet device as HSR slave.\n"); + NL_SET_ERR_MSG_MOD(extack, "Cannot use loopback or non-ethernet device as HSR slave."); return -EINVAL; } /* Don't allow enslaving hsr devices */ if (is_hsr_master(dev)) { - netdev_info(dev, "Cannot create trees of HSR devices.\n"); + NL_SET_ERR_MSG_MOD(extack, + "Cannot create trees of HSR devices."); return -EINVAL; } if (hsr_port_exists(dev)) { - netdev_info(dev, "This device is already a HSR slave.\n"); + NL_SET_ERR_MSG_MOD(extack, + "This device is already a HSR slave."); return -EINVAL; } if (is_vlan_dev(dev)) { - netdev_info(dev, "HSR on top of VLAN is not yet supported in this driver.\n"); + NL_SET_ERR_MSG_MOD(extack, "HSR on top of VLAN is not yet supported in this driver."); return -EINVAL; } if (dev->priv_flags & IFF_DONT_BRIDGE) { - netdev_info(dev, "This device does not support bridging.\n"); + NL_SET_ERR_MSG_MOD(extack, + "This device does not support bridging."); return -EOPNOTSUPP; } @@ -96,19 +97,25 @@ static int hsr_check_dev_ok(struct net_device *dev) } /* Setup device to be added to the HSR bridge. */ -static int hsr_portdev_setup(struct net_device *dev, struct hsr_port *port) +static int hsr_portdev_setup(struct hsr_priv *hsr, struct net_device *dev, + struct hsr_port *port, + struct netlink_ext_ack *extack) + { + struct net_device *hsr_dev; + struct hsr_port *master; int res; - dev_hold(dev); res = dev_set_promiscuity(dev, 1); if (res) - goto fail_promiscuity; + return res; - /* FIXME: - * What does net device "adjacency" mean? Should we do - * res = netdev_master_upper_dev_link(port->dev, port->hsr->dev); ? - */ + master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); + hsr_dev = master->dev; + + res = netdev_upper_dev_link(dev, hsr_dev, extack); + if (res) + goto fail_upper_dev_link; res = netdev_rx_handler_register(dev, hsr_handle_frame, port); if (res) @@ -118,21 +125,20 @@ static int hsr_portdev_setup(struct net_device *dev, struct hsr_port *port) return 0; fail_rx_handler: + netdev_upper_dev_unlink(dev, hsr_dev); +fail_upper_dev_link: dev_set_promiscuity(dev, -1); -fail_promiscuity: - dev_put(dev); - return res; } int hsr_add_port(struct hsr_priv *hsr, struct net_device *dev, - enum hsr_port_type type) + enum hsr_port_type type, struct netlink_ext_ack *extack) { struct hsr_port *port, *master; int res; if (type != HSR_PT_MASTER) { - res = hsr_check_dev_ok(dev); + res = hsr_check_dev_ok(dev, extack); if (res) return res; } @@ -150,7 +156,7 @@ int hsr_add_port(struct hsr_priv *hsr, struct net_device *dev, port->type = type; if (type != HSR_PT_MASTER) { - res = hsr_portdev_setup(dev, port); + res = hsr_portdev_setup(hsr, dev, port, extack); if (res) goto fail_dev_setup; } @@ -179,21 +185,14 @@ void hsr_del_port(struct hsr_port *port) list_del_rcu(&port->port_list); if (port != master) { - if (master) { - netdev_update_features(master->dev); - dev_set_mtu(master->dev, hsr_get_max_mtu(hsr)); - } + 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); + netdev_upper_dev_unlink(port->dev, master->dev); } - /* FIXME? - * netdev_upper_dev_unlink(port->dev, port->hsr->dev); - */ - synchronize_rcu(); - if (port != master) - dev_put(port->dev); kfree(port); } |