// SPDX-License-Identifier: GPL-2.0
/* Copyright 2011-2014 Autronica Fire and Security AS
 *
 * Author(s):
 *	2011-2014 Arvid Brodin, arvid.brodin@alten.se
 *
 * Event handling for HSR and PRP devices.
 */

#include <linux/netdevice.h>
#include <net/rtnetlink.h>
#include <linux/rculist.h>
#include <linux/timer.h>
#include <linux/etherdevice.h>
#include "hsr_main.h"
#include "hsr_device.h"
#include "hsr_netlink.h"
#include "hsr_framereg.h"
#include "hsr_slave.h"

static bool hsr_slave_empty(struct hsr_priv *hsr)
{
	struct hsr_port *port;

	hsr_for_each_port(hsr, port)
		if (port->type != HSR_PT_MASTER)
			return false;
	return true;
}

static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
			     void *ptr)
{
	struct hsr_port *port, *master;
	struct net_device *dev;
	struct hsr_priv *hsr;
	LIST_HEAD(list_kill);
	int mtu_max;
	int res;

	dev = netdev_notifier_info_to_dev(ptr);
	port = hsr_port_get_rtnl(dev);
	if (!port) {
		if (!is_hsr_master(dev))
			return NOTIFY_DONE;	/* Not an HSR device */
		hsr = netdev_priv(dev);
		port = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
		if (!port) {
			/* Resend of notification concerning removed device? */
			return NOTIFY_DONE;
		}
	} else {
		hsr = port->hsr;
	}

	switch (event) {
	case NETDEV_UP:		/* Administrative state DOWN */
	case NETDEV_DOWN:	/* Administrative state UP */
	case NETDEV_CHANGE:	/* Link (carrier) state changes */
		hsr_check_carrier_and_operstate(hsr);
		break;
	case NETDEV_CHANGENAME:
		if (is_hsr_master(dev))
			hsr_debugfs_rename(dev);
		break;
	case NETDEV_CHANGEADDR:
		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;
		}

		master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);

		if (port->type == HSR_PT_SLAVE_A) {
			eth_hw_addr_set(master->dev, dev->dev_addr);
			call_netdevice_notifiers(NETDEV_CHANGEADDR,
						 master->dev);
		}

		/* Make sure we recognize frames from ourselves in hsr_rcv() */
		port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B);
		res = hsr_create_self_node(hsr,
					   master->dev->dev_addr,
					   port ?
						port->dev->dev_addr :
						master->dev->dev_addr);
		if (res)
			netdev_warn(master->dev,
				    "Could not update HSR node address.\n");
		break;
	case NETDEV_CHANGEMTU:
		if (port->type == HSR_PT_MASTER)
			break; /* Handled in ndo_change_mtu() */
		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 (!is_hsr_master(dev)) {
			master = hsr_port_get_hsr(port->hsr, HSR_PT_MASTER);
			hsr_del_port(port);
			if (hsr_slave_empty(master->hsr)) {
				const struct rtnl_link_ops *ops;

				ops = master->dev->rtnl_link_ops;
				ops->dellink(master->dev, &list_kill);
				unregister_netdevice_many(&list_kill);
			}
		}
		break;
	case NETDEV_PRE_TYPE_CHANGE:
		/* HSR works only on Ethernet devices. Refuse slave to change
		 * its type.
		 */
		return NOTIFY_BAD;
	}

	return NOTIFY_DONE;
}

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;
}

int hsr_get_version(struct net_device *dev, enum hsr_version *ver)
{
	struct hsr_priv *hsr;

	hsr = netdev_priv(dev);
	*ver = hsr->prot_version;

	return 0;
}
EXPORT_SYMBOL(hsr_get_version);

static struct notifier_block hsr_nb = {
	.notifier_call = hsr_netdev_notify,	/* Slave event notifications */
};

static int __init hsr_init(void)
{
	int res;

	BUILD_BUG_ON(sizeof(struct hsr_tag) != HSR_HLEN);

	register_netdevice_notifier(&hsr_nb);
	res = hsr_netlink_init();

	return res;
}

static void __exit hsr_exit(void)
{
	hsr_netlink_exit();
	hsr_debugfs_remove_root();
	unregister_netdevice_notifier(&hsr_nb);
}

module_init(hsr_init);
module_exit(hsr_exit);
MODULE_LICENSE("GPL");
