/*
 * Networking AIM - Networking Application Interface Module for MostCore
 *
 * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * This file is licensed under GPLv2.
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/wait.h>
#include <linux/kobject.h>
#include "mostcore.h"
#include "networking.h"

#define MEP_HDR_LEN 8
#define MDP_HDR_LEN 16
#define MAMAC_DATA_LEN (1024 - MDP_HDR_LEN)

#define PMHL 5

#define PMS_TELID_UNSEGM_MAMAC	0x0A
#define PMS_FIFONO_MDP		0x01
#define PMS_FIFONO_MEP		0x04
#define PMS_MSGTYPE_DATA	0x04
#define PMS_DEF_PRIO		0
#define MEP_DEF_RETRY		15

#define PMS_FIFONO_MASK		0x07
#define PMS_FIFONO_SHIFT	3
#define PMS_RETRY_SHIFT		4
#define PMS_TELID_MASK		0x0F
#define PMS_TELID_SHIFT		4

#define HB(value)		((u8)((u16)(value) >> 8))
#define LB(value)		((u8)(value))

#define EXTRACT_BIT_SET(bitset_name, value) \
	(((value) >> bitset_name##_SHIFT) & bitset_name##_MASK)

#define PMS_IS_MEP(buf, len) \
	((len) > MEP_HDR_LEN && \
	 EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MEP)

#define PMS_IS_MAMAC(buf, len) \
	((len) > MDP_HDR_LEN && \
	 EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MDP && \
	 EXTRACT_BIT_SET(PMS_TELID, (buf)[14]) == PMS_TELID_UNSEGM_MAMAC)

struct net_dev_channel {
	bool linked;
	int ch_id;
};

struct net_dev_context {
	struct most_interface *iface;
	bool channels_opened;
	bool is_mamac;
	unsigned char link_stat;
	struct net_device *dev;
	struct net_dev_channel rx;
	struct net_dev_channel tx;
	struct list_head list;
};

static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
static struct spinlock list_lock;
static struct most_aim aim;

static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo)
{
	u8 *buff = mbo->virt_address;
	const u8 broadcast[] = { 0x03, 0xFF };
	const u8 *dest_addr = skb->data + 4;
	const u8 *eth_type = skb->data + 12;
	unsigned int payload_len = skb->len - ETH_HLEN;
	unsigned int mdp_len = payload_len + MDP_HDR_LEN;

	if (mbo->buffer_length < mdp_len) {
		pr_err("drop: too small buffer! (%d for %d)\n",
		       mbo->buffer_length, mdp_len);
		return -EINVAL;
	}

	if (skb->len < ETH_HLEN) {
		pr_err("drop: too small packet! (%d)\n", skb->len);
		return -EINVAL;
	}

	if (dest_addr[0] == 0xFF && dest_addr[1] == 0xFF)
		dest_addr = broadcast;

	*buff++ = HB(mdp_len - 2);
	*buff++ = LB(mdp_len - 2);

	*buff++ = PMHL;
	*buff++ = (PMS_FIFONO_MDP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
	*buff++ = PMS_DEF_PRIO;
	*buff++ = dest_addr[0];
	*buff++ = dest_addr[1];
	*buff++ = 0x00;

	*buff++ = HB(payload_len + 6);
	*buff++ = LB(payload_len + 6);

	/* end of FPH here */

	*buff++ = eth_type[0];
	*buff++ = eth_type[1];
	*buff++ = 0;
	*buff++ = 0;

	*buff++ = PMS_TELID_UNSEGM_MAMAC << 4 | HB(payload_len);
	*buff++ = LB(payload_len);

	memcpy(buff, skb->data + ETH_HLEN, payload_len);
	mbo->buffer_length = mdp_len;
	return 0;
}

static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo)
{
	u8 *buff = mbo->virt_address;
	unsigned int mep_len = skb->len + MEP_HDR_LEN;

	if (mbo->buffer_length < mep_len) {
		pr_err("drop: too small buffer! (%d for %d)\n",
		       mbo->buffer_length, mep_len);
		return -EINVAL;
	}

	*buff++ = HB(mep_len - 2);
	*buff++ = LB(mep_len - 2);

	*buff++ = PMHL;
	*buff++ = (PMS_FIFONO_MEP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
	*buff++ = (MEP_DEF_RETRY << PMS_RETRY_SHIFT) | PMS_DEF_PRIO;
	*buff++ = 0;
	*buff++ = 0;
	*buff++ = 0;

	memcpy(buff, skb->data, skb->len);
	mbo->buffer_length = mep_len;
	return 0;
}

static int most_nd_set_mac_address(struct net_device *dev, void *p)
{
	struct net_dev_context *nd = dev->ml_priv;
	int err = eth_mac_addr(dev, p);

	if (err)
		return err;

	BUG_ON(nd->dev != dev);

	nd->is_mamac =
		(dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0 &&
		 dev->dev_addr[2] == 0 && dev->dev_addr[3] == 0);

	/*
	 * Set default MTU for the given packet type.
	 * It is still possible to change MTU using ip tools afterwards.
	 */
	dev->mtu = nd->is_mamac ? MAMAC_DATA_LEN : ETH_DATA_LEN;

	return 0;
}

static int most_nd_open(struct net_device *dev)
{
	struct net_dev_context *nd = dev->ml_priv;

	netdev_info(dev, "open net device\n");

	BUG_ON(nd->dev != dev);

	if (nd->channels_opened)
		return -EFAULT;

	BUG_ON(!nd->tx.linked || !nd->rx.linked);

	if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) {
		netdev_err(dev, "most_start_channel() failed\n");
		return -EBUSY;
	}

	if (most_start_channel(nd->iface, nd->tx.ch_id, &aim)) {
		netdev_err(dev, "most_start_channel() failed\n");
		most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
		return -EBUSY;
	}

	nd->channels_opened = true;

	if (nd->is_mamac) {
		nd->link_stat = 1;
		netif_wake_queue(dev);
	} else {
		nd->iface->request_netinfo(nd->iface, nd->tx.ch_id);
	}

	return 0;
}

static int most_nd_stop(struct net_device *dev)
{
	struct net_dev_context *nd = dev->ml_priv;

	netdev_info(dev, "stop net device\n");

	BUG_ON(nd->dev != dev);
	netif_stop_queue(dev);

	if (nd->channels_opened) {
		most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
		most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
		nd->channels_opened = false;
	}

	return 0;
}

static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb,
				      struct net_device *dev)
{
	struct net_dev_context *nd = dev->ml_priv;
	struct mbo *mbo;
	int ret;

	BUG_ON(nd->dev != dev);

	mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &aim);

	if (!mbo) {
		netif_stop_queue(dev);
		dev->stats.tx_fifo_errors++;
		return NETDEV_TX_BUSY;
	}

	if (nd->is_mamac)
		ret = skb_to_mamac(skb, mbo);
	else
		ret = skb_to_mep(skb, mbo);

	if (ret) {
		most_put_mbo(mbo);
		dev->stats.tx_dropped++;
		kfree_skb(skb);
		return NETDEV_TX_OK;
	}

	most_submit_mbo(mbo);
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += skb->len;
	kfree_skb(skb);
	return NETDEV_TX_OK;
}

static const struct net_device_ops most_nd_ops = {
	.ndo_open = most_nd_open,
	.ndo_stop = most_nd_stop,
	.ndo_start_xmit = most_nd_start_xmit,
	.ndo_set_mac_address = most_nd_set_mac_address,
};

static void most_nd_setup(struct net_device *dev)
{
	netdev_info(dev, "setup net device\n");
	ether_setup(dev);
	dev->netdev_ops = &most_nd_ops;
}

static void most_net_rm_netdev_safe(struct net_dev_context *nd)
{
	if (!nd->dev)
		return;

	pr_info("remove net device %p\n", nd->dev);

	unregister_netdev(nd->dev);
	free_netdev(nd->dev);
	nd->dev = NULL;
}

static struct net_dev_context *get_net_dev_context(
	struct most_interface *iface)
{
	struct net_dev_context *nd, *tmp;

	spin_lock(&list_lock);
	list_for_each_entry_safe(nd, tmp, &net_devices, list) {
		if (nd->iface == iface) {
			spin_unlock(&list_lock);
			return nd;
		}
	}
	spin_unlock(&list_lock);
	return NULL;
}

static int aim_probe_channel(struct most_interface *iface, int channel_idx,
			     struct most_channel_config *ccfg,
			     struct kobject *parent, char *name)
{
	struct net_dev_context *nd;
	struct net_dev_channel *ch;

	if (!iface)
		return -EINVAL;

	if (ccfg->data_type != MOST_CH_ASYNC)
		return -EINVAL;

	nd = get_net_dev_context(iface);

	if (!nd) {
		nd = kzalloc(sizeof(*nd), GFP_KERNEL);
		if (!nd)
			return -ENOMEM;

		nd->iface = iface;

		spin_lock(&list_lock);
		list_add(&nd->list, &net_devices);
		spin_unlock(&list_lock);
	}

	ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
	if (ch->linked) {
		pr_err("only one channel per instance & direction allowed\n");
		return -EINVAL;
	}

	if (nd->tx.linked || nd->rx.linked) {
		struct net_device *dev =
			alloc_netdev(0, "meth%d", NET_NAME_UNKNOWN,
				     most_nd_setup);

		if (!dev) {
			pr_err("no memory for net_device\n");
			return -ENOMEM;
		}

		nd->dev = dev;
		ch->ch_id = channel_idx;
		ch->linked = true;

		dev->ml_priv = nd;
		if (register_netdev(dev)) {
			pr_err("registering net device failed\n");
			ch->linked = false;
			free_netdev(dev);
			return -EINVAL;
		}
	}

	ch->ch_id = channel_idx;
	ch->linked = true;

	return 0;
}

static int aim_disconnect_channel(struct most_interface *iface,
				  int channel_idx)
{
	struct net_dev_context *nd;
	struct net_dev_channel *ch;

	nd = get_net_dev_context(iface);
	if (!nd)
		return -EINVAL;

	if (nd->rx.linked && channel_idx == nd->rx.ch_id)
		ch = &nd->rx;
	else if (nd->tx.linked && channel_idx == nd->tx.ch_id)
		ch = &nd->tx;
	else
		return -EINVAL;

	ch->linked = false;

	/*
	 * do not call most_stop_channel() here, because channels are
	 * going to be closed in ndo_stop() after unregister_netdev()
	 */
	most_net_rm_netdev_safe(nd);

	if (!nd->rx.linked && !nd->tx.linked) {
		spin_lock(&list_lock);
		list_del(&nd->list);
		spin_unlock(&list_lock);
		kfree(nd);
	}

	return 0;
}

static int aim_resume_tx_channel(struct most_interface *iface,
				 int channel_idx)
{
	struct net_dev_context *nd;

	nd = get_net_dev_context(iface);
	if (!nd || !nd->channels_opened || nd->tx.ch_id != channel_idx)
		return 0;

	if (!nd->dev)
		return 0;

	netif_wake_queue(nd->dev);
	return 0;
}

static int aim_rx_data(struct mbo *mbo)
{
	const u32 zero = 0;
	struct net_dev_context *nd;
	char *buf = mbo->virt_address;
	u32 len = mbo->processed_length;
	struct sk_buff *skb;
	struct net_device *dev;

	nd = get_net_dev_context(mbo->ifp);
	if (!nd || !nd->channels_opened || nd->rx.ch_id != mbo->hdm_channel_id)
		return -EIO;

	dev = nd->dev;
	if (!dev) {
		pr_err_once("drop packet: missing net_device\n");
		return -EIO;
	}

	if (nd->is_mamac) {
		if (!PMS_IS_MAMAC(buf, len))
			return -EIO;

		skb = dev_alloc_skb(len - MDP_HDR_LEN + 2 * ETH_ALEN + 2);
	} else {
		if (!PMS_IS_MEP(buf, len))
			return -EIO;

		skb = dev_alloc_skb(len - MEP_HDR_LEN);
	}

	if (!skb) {
		dev->stats.rx_dropped++;
		pr_err_once("drop packet: no memory for skb\n");
		goto out;
	}

	skb->dev = dev;

	if (nd->is_mamac) {
		/* dest */
		ether_addr_copy(skb_put(skb, ETH_ALEN), dev->dev_addr);

		/* src */
		memcpy(skb_put(skb, 4), &zero, 4);
		memcpy(skb_put(skb, 2), buf + 5, 2);

		/* eth type */
		memcpy(skb_put(skb, 2), buf + 10, 2);

		buf += MDP_HDR_LEN;
		len -= MDP_HDR_LEN;
	} else {
		buf += MEP_HDR_LEN;
		len -= MEP_HDR_LEN;
	}

	memcpy(skb_put(skb, len), buf, len);
	skb->protocol = eth_type_trans(skb, dev);
	dev->stats.rx_packets++;
	dev->stats.rx_bytes += skb->len;
	netif_rx(skb);

out:
	most_put_mbo(mbo);
	return 0;
}

static struct most_aim aim = {
	.name = "networking",
	.probe_channel = aim_probe_channel,
	.disconnect_channel = aim_disconnect_channel,
	.tx_completion = aim_resume_tx_channel,
	.rx_completion = aim_rx_data,
};

static int __init most_net_init(void)
{
	pr_info("most_net_init()\n");
	spin_lock_init(&list_lock);
	return most_register_aim(&aim);
}

static void __exit most_net_exit(void)
{
	struct net_dev_context *nd, *tmp;

	spin_lock(&list_lock);
	list_for_each_entry_safe(nd, tmp, &net_devices, list) {
		list_del(&nd->list);
		spin_unlock(&list_lock);
		/*
		 * do not call most_stop_channel() here, because channels are
		 * going to be closed in ndo_stop() after unregister_netdev()
		 */
		most_net_rm_netdev_safe(nd);
		kfree(nd);
		spin_lock(&list_lock);
	}
	spin_unlock(&list_lock);

	most_deregister_aim(&aim);
	pr_info("most_net_exit()\n");
}

/**
 * most_deliver_netinfo - callback for HDM to be informed about HW's MAC
 * @param iface - most interface instance
 * @param link_stat - link status
 * @param mac_addr - MAC address
 */
void most_deliver_netinfo(struct most_interface *iface,
			  unsigned char link_stat, unsigned char *mac_addr)
{
	struct net_dev_context *nd;
	struct net_device *dev;

	pr_info("Received netinfo from %s\n", iface->description);

	nd = get_net_dev_context(iface);
	if (!nd)
		return;

	dev = nd->dev;
	if (!dev)
		return;

	if (mac_addr)
		ether_addr_copy(dev->dev_addr, mac_addr);

	if (nd->link_stat != link_stat) {
		nd->link_stat = link_stat;
		if (nd->link_stat)
			netif_wake_queue(dev);
		else
			netif_stop_queue(dev);
	}
}
EXPORT_SYMBOL(most_deliver_netinfo);

module_init(most_net_init);
module_exit(most_net_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
MODULE_DESCRIPTION("Networking Application Interface Module for MostCore");
