From c5a7591172100269e426cf630da0f2dc8138a206 Mon Sep 17 00:00:00 2001 From: Arvid Brodin Date: Fri, 4 Jul 2014 23:38:05 +0200 Subject: net/hsr: Use list_head (and rcu) instead of array for slave devices. Signed-off-by: Arvid Brodin Signed-off-by: David S. Miller --- net/hsr/hsr_main.c | 128 +++++++++++++++++------------------------------------ 1 file changed, 40 insertions(+), 88 deletions(-) (limited to 'net/hsr/hsr_main.c') diff --git a/net/hsr/hsr_main.c b/net/hsr/hsr_main.c index b5abe26f7b4c..a06cab57ab68 100644 --- a/net/hsr/hsr_main.c +++ b/net/hsr/hsr_main.c @@ -39,76 +39,25 @@ void unregister_hsr_master(struct hsr_priv *hsr) } } -bool is_hsr_slave(struct net_device *dev) -{ - struct hsr_priv *hsr_it; - - list_for_each_entry_rcu(hsr_it, &hsr_list, hsr_list) { - if (dev == hsr_it->slave[0]) - return true; - if (dev == hsr_it->slave[1]) - return true; - } - - return false; -} - -/* If dev is a HSR slave device, return the virtual master device. Return NULL - * otherwise. - */ -struct hsr_priv *get_hsr_master(struct net_device *dev) -{ - struct hsr_priv *hsr; - - rcu_read_lock(); - list_for_each_entry_rcu(hsr, &hsr_list, hsr_list) - if ((dev == hsr->slave[0]) || - (dev == hsr->slave[1])) { - rcu_read_unlock(); - return hsr; - } - - rcu_read_unlock(); - return NULL; -} - -/* If dev is a HSR slave device, return the other slave device. Return NULL - * otherwise. - */ -struct net_device *get_other_slave(struct hsr_priv *hsr, - struct net_device *dev) -{ - if (dev == hsr->slave[0]) - return hsr->slave[1]; - if (dev == hsr->slave[1]) - return hsr->slave[0]; - - return NULL; -} - static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event, void *ptr) { - struct net_device *slave, *other_slave; + struct net_device *dev; + struct hsr_port *port, *master; struct hsr_priv *hsr; int mtu_max; int res; - struct net_device *dev; dev = netdev_notifier_info_to_dev(ptr); - - hsr = get_hsr_master(dev); - if (hsr) { - /* dev is a slave device */ - slave = dev; - other_slave = get_other_slave(hsr, slave); - } else { + port = hsr_port_get_rtnl(dev); + if (port == NULL) { if (!is_hsr_master(dev)) - return NOTIFY_DONE; + return NOTIFY_DONE; /* Not an HSR device */ hsr = netdev_priv(dev); - slave = hsr->slave[0]; - other_slave = hsr->slave[1]; + port = hsr_port_get_hsr(hsr, HSR_PT_MASTER); + } else { + hsr = port->hsr; } switch (event) { @@ -118,48 +67,41 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event, hsr_check_carrier_and_operstate(hsr); break; case NETDEV_CHANGEADDR: - - /* This should not happen since there's no ndo_set_mac_address() - * for HSR devices - i.e. not supported. - */ - if (dev == hsr->dev) + if (port->type == HSR_PT_MASTER) { + /* This should not happen since there's no + * ndo_set_mac_address() for HSR devices - i.e. not + * supported. + */ break; + } - if (dev == hsr->slave[0]) { - ether_addr_copy(hsr->dev->dev_addr, dev->dev_addr); - call_netdevice_notifiers(NETDEV_CHANGEADDR, hsr->dev); + master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); + + if (port->type == HSR_PT_SLAVE_A) { + ether_addr_copy(master->dev->dev_addr, dev->dev_addr); + call_netdevice_notifiers(NETDEV_CHANGEADDR, master->dev); } /* Make sure we recognize frames from ourselves in hsr_rcv() */ - other_slave = hsr->slave[1]; + port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B); res = hsr_create_self_node(&hsr->self_node_db, - hsr->dev->dev_addr, - other_slave ? - other_slave->dev_addr : - hsr->dev->dev_addr); + master->dev->dev_addr, + port ? + port->dev->dev_addr : + master->dev->dev_addr); if (res) - netdev_warn(hsr->dev, + netdev_warn(master->dev, "Could not update HSR node address.\n"); break; case NETDEV_CHANGEMTU: - if (dev == hsr->dev) + if (port->type == HSR_PT_MASTER) break; /* Handled in ndo_change_mtu() */ - mtu_max = hsr_get_max_mtu(hsr); - if (hsr->dev->mtu > mtu_max) - dev_set_mtu(hsr->dev, mtu_max); + mtu_max = hsr_get_max_mtu(port->hsr); + master = hsr_port_get_hsr(port->hsr, HSR_PT_MASTER); + master->dev->mtu = mtu_max; break; case NETDEV_UNREGISTER: - if (dev == hsr->slave[0]) { - hsr->slave[0] = NULL; - hsr_del_slave(hsr, 0); - } - if (dev == hsr->slave[1]) { - hsr->slave[1] = NULL; - hsr_del_slave(hsr, 1); - } - - /* There should really be a way to set a new slave device... */ - + hsr_del_port(port); break; case NETDEV_PRE_TYPE_CHANGE: /* HSR works only on Ethernet devices. Refuse slave to change @@ -172,6 +114,16 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event, } +struct hsr_port *hsr_port_get_hsr(struct hsr_priv *hsr, enum hsr_port_type pt) +{ + struct hsr_port *port; + + hsr_for_each_port(hsr, port) + if (port->type == pt) + return port; + return NULL; +} + static struct notifier_block hsr_nb = { .notifier_call = hsr_netdev_notify, /* Slave event notifications */ }; -- cgit v1.2.3