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;
}
Beispiel #2
0
int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
		     unsigned char multicast_spec)
{
	struct hsr_priv *hsr_priv;
	int i;
	int res;

	hsr_priv = netdev_priv(hsr_dev);
	hsr_priv->dev = hsr_dev;
	INIT_LIST_HEAD(&hsr_priv->node_db);
	INIT_LIST_HEAD(&hsr_priv->self_node_db);
	for (i = 0; i < HSR_MAX_SLAVE; i++)
		hsr_priv->slave[i] = slave[i];

	spin_lock_init(&hsr_priv->seqnr_lock);
	/* Overflow soon to find bugs easier: */
	hsr_priv->sequence_nr = USHRT_MAX - 1024;

	init_timer(&hsr_priv->announce_timer);
	hsr_priv->announce_timer.function = hsr_announce;
	hsr_priv->announce_timer.data = (unsigned long) hsr_priv;

	ether_addr_copy(hsr_priv->sup_multicast_addr, def_multicast_addr);
	hsr_priv->sup_multicast_addr[ETH_ALEN - 1] = multicast_spec;

/* 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?
 */

	for (i = 0; i < HSR_MAX_SLAVE; i++) {
		res = check_slave_ok(slave[i]);
		if (res)
			return res;
	}

	hsr_dev->features = slave[0]->features & slave[1]->features;
	/* Prevent recursive tx locking */
	hsr_dev->features |= NETIF_F_LLTX;
	/* VLAN on top of HSR needs testing and probably some work on
	 * hsr_header_create() etc.
	 */
	hsr_dev->features |= NETIF_F_VLAN_CHALLENGED;

	/* Set hsr_dev's MAC address to that of mac_slave1 */
	ether_addr_copy(hsr_dev->dev_addr, hsr_priv->slave[0]->dev_addr);

	/* Set required header length */
	for (i = 0; i < HSR_MAX_SLAVE; i++) {
		if (slave[i]->hard_header_len + HSR_TAGLEN >
						hsr_dev->hard_header_len)
			hsr_dev->hard_header_len =
					slave[i]->hard_header_len + HSR_TAGLEN;
	}

	/* MTU */
	for (i = 0; i < HSR_MAX_SLAVE; i++)
		if (slave[i]->mtu - HSR_TAGLEN < hsr_dev->mtu)
			hsr_dev->mtu = slave[i]->mtu - HSR_TAGLEN;

	/* Make sure the 1st call to netif_carrier_on() gets through */
	netif_carrier_off(hsr_dev);

	/* Promiscuity */
	for (i = 0; i < HSR_MAX_SLAVE; i++) {
		res = dev_set_promiscuity(slave[i], 1);
		if (res) {
			netdev_info(hsr_dev, "Cannot set slave promiscuity (%s, %d)\n",
				    slave[i]->name, res);
			goto fail;
		}
	}

	/* Make sure we recognize frames from ourselves in hsr_rcv() */
	res = hsr_create_self_node(&hsr_priv->self_node_db,
					hsr_dev->dev_addr,
					hsr_priv->slave[1]->dev_addr);
	if (res < 0)
		goto fail;

	res = register_netdevice(hsr_dev);
	if (res)
		goto fail;

	register_hsr_master(hsr_priv);

	return 0;

fail:
	restore_slaves(hsr_dev);
	return res;
}