// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright 2007-2012 Siemens AG
 *
 * Written by:
 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
 * Sergey Lapin <slapin@ossfans.org>
 * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
 * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
 */

#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/crc-ccitt.h>
#include <asm/unaligned.h>

#include <net/rtnetlink.h>
#include <net/ieee802154_netdev.h>
#include <net/mac802154.h>
#include <net/cfg802154.h>

#include "ieee802154_i.h"
#include "driver-ops.h"

void ieee802154_xmit_sync_worker(struct work_struct *work)
{
	struct ieee802154_local *local =
		container_of(work, struct ieee802154_local, sync_tx_work);
	struct sk_buff *skb = local->tx_skb;
	struct net_device *dev = skb->dev;
	int res;

	res = drv_xmit_sync(local, skb);
	if (res)
		goto err_tx;

	dev->stats.tx_packets++;
	dev->stats.tx_bytes += skb->len;

	ieee802154_xmit_complete(&local->hw, skb, false);

	return;

err_tx:
	/* Restart the netif queue on each sub_if_data object. */
	ieee802154_release_queue(local);
	if (atomic_dec_and_test(&local->phy->ongoing_txs))
		wake_up(&local->phy->sync_txq);
	kfree_skb(skb);
	netdev_dbg(dev, "transmission failed\n");
}

static netdev_tx_t
ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
{
	struct net_device *dev = skb->dev;
	int ret;

	if (!(local->hw.flags & IEEE802154_HW_TX_OMIT_CKSUM)) {
		struct sk_buff *nskb;
		u16 crc;

		if (unlikely(skb_tailroom(skb) < IEEE802154_FCS_LEN)) {
			nskb = skb_copy_expand(skb, 0, IEEE802154_FCS_LEN,
					       GFP_ATOMIC);
			if (likely(nskb)) {
				consume_skb(skb);
				skb = nskb;
			} else {
				goto err_free_skb;
			}
		}

		crc = crc_ccitt(0, skb->data, skb->len);
		put_unaligned_le16(crc, skb_put(skb, 2));
	}

	/* Stop the netif queue on each sub_if_data object. */
	ieee802154_hold_queue(local);
	atomic_inc(&local->phy->ongoing_txs);

	/* Drivers should preferably implement the async callback. In some rare
	 * cases they only provide a sync callback which we will use as a
	 * fallback.
	 */
	if (local->ops->xmit_async) {
		unsigned int len = skb->len;

		ret = drv_xmit_async(local, skb);
		if (ret)
			goto err_wake_netif_queue;

		dev->stats.tx_packets++;
		dev->stats.tx_bytes += len;
	} else {
		local->tx_skb = skb;
		queue_work(local->workqueue, &local->sync_tx_work);
	}

	return NETDEV_TX_OK;

err_wake_netif_queue:
	ieee802154_release_queue(local);
	if (atomic_dec_and_test(&local->phy->ongoing_txs))
		wake_up(&local->phy->sync_txq);
err_free_skb:
	kfree_skb(skb);
	return NETDEV_TX_OK;
}

static int ieee802154_sync_queue(struct ieee802154_local *local)
{
	int ret;

	ieee802154_hold_queue(local);
	ieee802154_disable_queue(local);
	wait_event(local->phy->sync_txq, !atomic_read(&local->phy->ongoing_txs));
	ret = local->tx_result;
	ieee802154_release_queue(local);

	return ret;
}

int ieee802154_sync_and_hold_queue(struct ieee802154_local *local)
{
	int ret;

	ieee802154_hold_queue(local);
	ret = ieee802154_sync_queue(local);
	set_bit(WPAN_PHY_FLAG_STATE_QUEUE_STOPPED, &local->phy->flags);

	return ret;
}

int ieee802154_mlme_op_pre(struct ieee802154_local *local)
{
	return ieee802154_sync_and_hold_queue(local);
}

int ieee802154_mlme_tx(struct ieee802154_local *local,
		       struct ieee802154_sub_if_data *sdata,
		       struct sk_buff *skb)
{
	int ret;

	/* Avoid possible calls to ->ndo_stop() when we asynchronously perform
	 * MLME transmissions.
	 */
	rtnl_lock();

	/* Ensure the device was not stopped, otherwise error out */
	if (!local->open_count) {
		rtnl_unlock();
		return -ENETDOWN;
	}

	/* Warn if the ieee802154 core thinks MLME frames can be sent while the
	 * net interface expects this cannot happen.
	 */
	if (WARN_ON_ONCE(!netif_running(sdata->dev))) {
		rtnl_unlock();
		return -ENETDOWN;
	}

	ieee802154_tx(local, skb);
	ret = ieee802154_sync_queue(local);

	rtnl_unlock();

	return ret;
}

void ieee802154_mlme_op_post(struct ieee802154_local *local)
{
	ieee802154_release_queue(local);
}

int ieee802154_mlme_tx_one(struct ieee802154_local *local,
			   struct ieee802154_sub_if_data *sdata,
			   struct sk_buff *skb)
{
	int ret;

	ieee802154_mlme_op_pre(local);
	ret = ieee802154_mlme_tx(local, sdata, skb);
	ieee802154_mlme_op_post(local);

	return ret;
}

static bool ieee802154_queue_is_stopped(struct ieee802154_local *local)
{
	return test_bit(WPAN_PHY_FLAG_STATE_QUEUE_STOPPED, &local->phy->flags);
}

static netdev_tx_t
ieee802154_hot_tx(struct ieee802154_local *local, struct sk_buff *skb)
{
	/* Warn if the net interface tries to transmit frames while the
	 * ieee802154 core assumes the queue is stopped.
	 */
	WARN_ON_ONCE(ieee802154_queue_is_stopped(local));

	return ieee802154_tx(local, skb);
}

netdev_tx_t
ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);

	skb->skb_iif = dev->ifindex;

	return ieee802154_hot_tx(sdata->local, skb);
}

netdev_tx_t
ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
	int rc;

	/* TODO we should move it to wpan_dev_hard_header and dev_hard_header
	 * functions. The reason is wireshark will show a mac header which is
	 * with security fields but the payload is not encrypted.
	 */
	rc = mac802154_llsec_encrypt(&sdata->sec, skb);
	if (rc) {
		netdev_warn(dev, "encryption failed: %i\n", rc);
		kfree_skb(skb);
		return NETDEV_TX_OK;
	}

	skb->skb_iif = dev->ifindex;

	return ieee802154_hot_tx(sdata->local, skb);
}
