// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2023, 2024 Pengutronix,
//               Marc Kleine-Budde <kernel@pengutronix.de>
//

#include <net/netdev_queues.h>

#include "rockchip_canfd.h"

static bool rkcanfd_tx_tail_is_eff(const struct rkcanfd_priv *priv)
{
	const struct canfd_frame *cfd;
	const struct sk_buff *skb;
	unsigned int tx_tail;

	if (!rkcanfd_get_tx_pending(priv))
		return false;

	tx_tail = rkcanfd_get_tx_tail(priv);
	skb = priv->can.echo_skb[tx_tail];
	if (!skb) {
		netdev_err(priv->ndev,
			   "%s: echo_skb[%u]=NULL tx_head=0x%08x tx_tail=0x%08x\n",
			   __func__, tx_tail,
			   priv->tx_head, priv->tx_tail);

		return false;
	}

	cfd = (struct canfd_frame *)skb->data;

	return cfd->can_id & CAN_EFF_FLAG;
}

unsigned int rkcanfd_get_effective_tx_free(const struct rkcanfd_priv *priv)
{
	if (priv->devtype_data.quirks & RKCANFD_QUIRK_RK3568_ERRATUM_6 &&
	    rkcanfd_tx_tail_is_eff(priv))
		return 0;

	return rkcanfd_get_tx_free(priv);
}

static void rkcanfd_start_xmit_write_cmd(const struct rkcanfd_priv *priv,
					 const u32 reg_cmd)
{
	if (priv->devtype_data.quirks & RKCANFD_QUIRK_RK3568_ERRATUM_12)
		rkcanfd_write(priv, RKCANFD_REG_MODE, priv->reg_mode_default |
			      RKCANFD_REG_MODE_SPACE_RX_MODE);

	rkcanfd_write(priv, RKCANFD_REG_CMD, reg_cmd);

	if (priv->devtype_data.quirks & RKCANFD_QUIRK_RK3568_ERRATUM_12)
		rkcanfd_write(priv, RKCANFD_REG_MODE, priv->reg_mode_default);
}

void rkcanfd_xmit_retry(struct rkcanfd_priv *priv)
{
	const unsigned int tx_head = rkcanfd_get_tx_head(priv);
	const u32 reg_cmd = RKCANFD_REG_CMD_TX_REQ(tx_head);

	rkcanfd_start_xmit_write_cmd(priv, reg_cmd);
}

netdev_tx_t rkcanfd_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
	struct rkcanfd_priv *priv = netdev_priv(ndev);
	u32 reg_frameinfo, reg_id, reg_cmd;
	unsigned int tx_head, frame_len;
	const struct canfd_frame *cfd;
	int err;
	u8 i;

	if (can_dropped_invalid_skb(ndev, skb))
		return NETDEV_TX_OK;

	if (!netif_subqueue_maybe_stop(priv->ndev, 0,
				       rkcanfd_get_effective_tx_free(priv),
				       RKCANFD_TX_STOP_THRESHOLD,
				       RKCANFD_TX_START_THRESHOLD)) {
		if (net_ratelimit())
			netdev_info(priv->ndev,
				    "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, tx_pending=%d)\n",
				    priv->tx_head, priv->tx_tail,
				    rkcanfd_get_tx_pending(priv));

		return NETDEV_TX_BUSY;
	}

	cfd = (struct canfd_frame *)skb->data;

	if (cfd->can_id & CAN_EFF_FLAG) {
		reg_frameinfo = RKCANFD_REG_FD_FRAMEINFO_FRAME_FORMAT;
		reg_id = FIELD_PREP(RKCANFD_REG_FD_ID_EFF, cfd->can_id);
	} else {
		reg_frameinfo = 0;
		reg_id = FIELD_PREP(RKCANFD_REG_FD_ID_SFF, cfd->can_id);
	}

	if (cfd->can_id & CAN_RTR_FLAG)
		reg_frameinfo |= RKCANFD_REG_FD_FRAMEINFO_RTR;

	if (can_is_canfd_skb(skb)) {
		reg_frameinfo |= RKCANFD_REG_FD_FRAMEINFO_FDF;

		if (cfd->flags & CANFD_BRS)
			reg_frameinfo |= RKCANFD_REG_FD_FRAMEINFO_BRS;

		reg_frameinfo |= FIELD_PREP(RKCANFD_REG_FD_FRAMEINFO_DATA_LENGTH,
					    can_fd_len2dlc(cfd->len));
	} else {
		reg_frameinfo |= FIELD_PREP(RKCANFD_REG_FD_FRAMEINFO_DATA_LENGTH,
					    cfd->len);
	}

	tx_head = rkcanfd_get_tx_head(priv);
	reg_cmd = RKCANFD_REG_CMD_TX_REQ(tx_head);

	rkcanfd_write(priv, RKCANFD_REG_FD_TXFRAMEINFO, reg_frameinfo);
	rkcanfd_write(priv, RKCANFD_REG_FD_TXID, reg_id);
	for (i = 0; i < cfd->len; i += 4)
		rkcanfd_write(priv, RKCANFD_REG_FD_TXDATA0 + i,
			      *(u32 *)(cfd->data + i));

	frame_len = can_skb_get_frame_len(skb);
	err = can_put_echo_skb(skb, ndev, tx_head, frame_len);
	if (!err)
		netdev_sent_queue(priv->ndev, frame_len);

	WRITE_ONCE(priv->tx_head, priv->tx_head + 1);

	rkcanfd_start_xmit_write_cmd(priv, reg_cmd);

	netif_subqueue_maybe_stop(priv->ndev, 0,
				  rkcanfd_get_effective_tx_free(priv),
				  RKCANFD_TX_STOP_THRESHOLD,
				  RKCANFD_TX_START_THRESHOLD);

	return NETDEV_TX_OK;
}

void rkcanfd_handle_tx_done_one(struct rkcanfd_priv *priv, const u32 ts,
				unsigned int *frame_len_p)
{
	struct net_device_stats *stats = &priv->ndev->stats;
	unsigned int tx_tail;
	struct sk_buff *skb;

	tx_tail = rkcanfd_get_tx_tail(priv);
	skb = priv->can.echo_skb[tx_tail];

	/* Manual handling of CAN Bus Error counters. See
	 * rkcanfd_get_corrected_berr_counter() for detailed
	 * explanation.
	 */
	if (priv->bec.txerr)
		priv->bec.txerr--;

	if (skb)
		rkcanfd_skb_set_timestamp(priv, skb, ts);
	stats->tx_bytes +=
		can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload,
							    tx_tail, ts,
							    frame_len_p);
	stats->tx_packets++;
}
