/* According to comments in the declaration of struct net_device, this function * is "Called from unregister, can be used to call free_netdev". Ok then... */ static void hsr_dev_destroy(struct net_device *hsr_dev) { struct hsr_priv *hsr; struct hsr_port *port; hsr = netdev_priv(hsr_dev); rtnl_lock(); hsr_for_each_port(hsr, port) hsr_del_port(port); rtnl_unlock(); del_timer_sync(&hsr->prune_timer); del_timer_sync(&hsr->announce_timer); synchronize_rcu(); }
int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], unsigned char multicast_spec, u8 protocol_version) { struct hsr_priv *hsr; struct hsr_port *port; int res; hsr = netdev_priv(hsr_dev); INIT_LIST_HEAD(&hsr->ports); INIT_LIST_HEAD(&hsr->node_db); INIT_LIST_HEAD(&hsr->self_node_db); ether_addr_copy(hsr_dev->dev_addr, slave[0]->dev_addr); /* Make sure we recognize frames from ourselves in hsr_rcv() */ res = hsr_create_self_node(&hsr->self_node_db, hsr_dev->dev_addr, slave[1]->dev_addr); if (res < 0) return res; spin_lock_init(&hsr->seqnr_lock); /* Overflow soon to find bugs easier: */ hsr->sequence_nr = HSR_SEQNR_START; hsr->sup_sequence_nr = HSR_SUP_SEQNR_START; init_timer(&hsr->announce_timer); hsr->announce_timer.function = hsr_announce; hsr->announce_timer.data = (unsigned long) hsr; init_timer(&hsr->prune_timer); hsr->prune_timer.function = hsr_prune_nodes; hsr->prune_timer.data = (unsigned long) hsr; ether_addr_copy(hsr->sup_multicast_addr, def_multicast_addr); hsr->sup_multicast_addr[ETH_ALEN - 1] = multicast_spec; hsr->protVersion = protocol_version; /* FIXME: should I modify the value of these? * * - hsr_dev->flags - i.e. * IFF_MASTER/SLAVE? * - hsr_dev->priv_flags - i.e. * IFF_EBRIDGE? * IFF_TX_SKB_SHARING? * IFF_HSR_MASTER/SLAVE? */ /* Make sure the 1st call to netif_carrier_on() gets through */ netif_carrier_off(hsr_dev); res = hsr_add_port(hsr, hsr_dev, HSR_PT_MASTER); if (res) return res; res = register_netdevice(hsr_dev); if (res) goto fail; res = hsr_add_port(hsr, slave[0], HSR_PT_SLAVE_A); if (res) goto fail; res = hsr_add_port(hsr, slave[1], HSR_PT_SLAVE_B); if (res) goto fail; hsr->prune_timer.expires = jiffies + msecs_to_jiffies(PRUNE_PERIOD); add_timer(&hsr->prune_timer); return 0; fail: hsr_for_each_port(hsr, port) hsr_del_port(port); return res; }