// SPDX-License-Identifier: GPL-2.0-only
/****************************************************************************
 * Driver for Solarflare network controllers and boards
 * Copyright 2005-2019 Solarflare Communications Inc.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation, incorporated herein by reference.
 */

#include "net_driver.h"
#include "ef100_rx.h"
#include "rx_common.h"
#include "efx.h"
#include "nic_common.h"
#include "mcdi_functions.h"
#include "ef100_regs.h"
#include "ef100_nic.h"
#include "io.h"

/* Get the value of a field in the RX prefix */
#define PREFIX_OFFSET_W(_f)	(ESF_GZ_RX_PREFIX_ ## _f ## _LBN / 32)
#define PREFIX_OFFSET_B(_f)	(ESF_GZ_RX_PREFIX_ ## _f ## _LBN % 32)
#define PREFIX_WIDTH_MASK(_f)	((1ULL << ESF_GZ_RX_PREFIX_ ## _f ## _WIDTH) - 1)
#define PREFIX_WORD(_p, _f)	le32_to_cpu((__force __le32)(_p)[PREFIX_OFFSET_W(_f)])
#define PREFIX_FIELD(_p, _f)	((PREFIX_WORD(_p, _f) >> PREFIX_OFFSET_B(_f)) & \
				 PREFIX_WIDTH_MASK(_f))

#define ESF_GZ_RX_PREFIX_NT_OR_INNER_L3_CLASS_LBN	\
		(ESF_GZ_RX_PREFIX_CLASS_LBN + ESF_GZ_RX_PREFIX_HCLASS_NT_OR_INNER_L3_CLASS_LBN)
#define ESF_GZ_RX_PREFIX_NT_OR_INNER_L3_CLASS_WIDTH	\
		ESF_GZ_RX_PREFIX_HCLASS_NT_OR_INNER_L3_CLASS_WIDTH

bool ef100_rx_buf_hash_valid(const u8 *prefix)
{
	return PREFIX_FIELD(prefix, RSS_HASH_VALID);
}

static bool ef100_has_fcs_error(struct efx_channel *channel, u32 *prefix)
{
	u16 rxclass;
	u8 l2status;

	rxclass = le16_to_cpu((__force __le16)PREFIX_FIELD(prefix, CLASS));
	l2status = PREFIX_FIELD(&rxclass, HCLASS_L2_STATUS);

	if (likely(l2status == ESE_GZ_RH_HCLASS_L2_STATUS_OK))
		/* Everything is ok */
		return false;

	if (l2status == ESE_GZ_RH_HCLASS_L2_STATUS_FCS_ERR)
		channel->n_rx_eth_crc_err++;
	return true;
}

void __ef100_rx_packet(struct efx_channel *channel)
{
	struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
	struct efx_rx_buffer *rx_buf = efx_rx_buffer(rx_queue,
						     channel->rx_pkt_index);
	struct efx_nic *efx = channel->efx;
	struct ef100_nic_data *nic_data;
	u8 *eh = efx_rx_buf_va(rx_buf);
	__wsum csum = 0;
	u16 ing_port;
	u32 *prefix;

	prefix = (u32 *)(eh - ESE_GZ_RX_PKT_PREFIX_LEN);

	if (channel->type->receive_raw) {
		u32 mark = PREFIX_FIELD(prefix, USER_MARK);

		if (channel->type->receive_raw(rx_queue, mark))
			return; /* packet was consumed */
	}

	if (ef100_has_fcs_error(channel, prefix) &&
	    unlikely(!(efx->net_dev->features & NETIF_F_RXALL)))
		goto out;

	rx_buf->len = le16_to_cpu((__force __le16)PREFIX_FIELD(prefix, LENGTH));
	if (rx_buf->len <= sizeof(struct ethhdr)) {
		if (net_ratelimit())
			netif_err(channel->efx, rx_err, channel->efx->net_dev,
				  "RX packet too small (%d)\n", rx_buf->len);
		++channel->n_rx_frm_trunc;
		goto out;
	}

	ing_port = le16_to_cpu((__force __le16) PREFIX_FIELD(prefix, INGRESS_MPORT));

	nic_data = efx->nic_data;

	if (nic_data->have_mport && ing_port != nic_data->base_mport) {
#ifdef CONFIG_SFC_SRIOV
		struct efx_rep *efv;

		rcu_read_lock();
		efv = efx_ef100_find_rep_by_mport(efx, ing_port);
		if (efv) {
			if (efv->net_dev->flags & IFF_UP)
				efx_ef100_rep_rx_packet(efv, rx_buf);
			rcu_read_unlock();
			/* Representor Rx doesn't care about PF Rx buffer
			 * ownership, it just makes a copy. So, we are done
			 * with the Rx buffer from PF point of view and should
			 * free it.
			 */
			goto free_rx_buffer;
		}
		rcu_read_unlock();
#endif
		if (net_ratelimit())
			netif_warn(efx, drv, efx->net_dev,
				   "Unrecognised ing_port %04x (base %04x), dropping\n",
				   ing_port, nic_data->base_mport);
		channel->n_rx_mport_bad++;
		goto free_rx_buffer;
	}

	if (likely(efx->net_dev->features & NETIF_F_RXCSUM)) {
		if (PREFIX_FIELD(prefix, NT_OR_INNER_L3_CLASS) == 1) {
			++channel->n_rx_ip_hdr_chksum_err;
		} else {
			u16 sum = be16_to_cpu((__force __be16)PREFIX_FIELD(prefix, CSUM_FRAME));

			csum = (__force __wsum) sum;
		}
	}

	if (channel->type->receive_skb) {
		/* no support for special channels yet, so just discard */
		WARN_ON_ONCE(1);
		goto free_rx_buffer;
	}

	efx_rx_packet_gro(channel, rx_buf, channel->rx_pkt_n_frags, eh, csum);
	goto out;

free_rx_buffer:
	efx_free_rx_buffers(rx_queue, rx_buf, 1);
out:
	channel->rx_pkt_n_frags = 0;
}

static void ef100_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index)
{
	struct efx_rx_buffer *rx_buf = efx_rx_buffer(rx_queue, index);
	struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
	struct efx_nic *efx = rx_queue->efx;

	++rx_queue->rx_packets;

	netif_vdbg(efx, rx_status, efx->net_dev,
		   "RX queue %d received id %x\n",
		   efx_rx_queue_index(rx_queue), index);

	efx_sync_rx_buffer(efx, rx_buf, efx->rx_dma_len);

	prefetch(efx_rx_buf_va(rx_buf));

	rx_buf->page_offset += efx->rx_prefix_size;

	efx_recycle_rx_pages(channel, rx_buf, 1);

	efx_rx_flush_packet(channel);
	channel->rx_pkt_n_frags = 1;
	channel->rx_pkt_index = index;
}

void efx_ef100_ev_rx(struct efx_channel *channel, const efx_qword_t *p_event)
{
	struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
	unsigned int n_packets =
		EFX_QWORD_FIELD(*p_event, ESF_GZ_EV_RXPKTS_NUM_PKT);
	int i;

	WARN_ON_ONCE(!n_packets);
	if (n_packets > 1)
		++channel->n_rx_merge_events;

	channel->irq_mod_score += 2 * n_packets;

	for (i = 0; i < n_packets; ++i) {
		ef100_rx_packet(rx_queue,
				rx_queue->removed_count & rx_queue->ptr_mask);
		++rx_queue->removed_count;
	}
}

void ef100_rx_write(struct efx_rx_queue *rx_queue)
{
	unsigned int notified_count = rx_queue->notified_count;
	struct efx_rx_buffer *rx_buf;
	unsigned int idx;
	efx_qword_t *rxd;
	efx_dword_t rxdb;

	while (notified_count != rx_queue->added_count) {
		idx = notified_count & rx_queue->ptr_mask;
		rx_buf = efx_rx_buffer(rx_queue, idx);
		rxd = efx_rx_desc(rx_queue, idx);

		EFX_POPULATE_QWORD_1(*rxd, ESF_GZ_RX_BUF_ADDR, rx_buf->dma_addr);

		++notified_count;
	}
	if (notified_count == rx_queue->notified_count)
		return;

	wmb();
	EFX_POPULATE_DWORD_1(rxdb, ERF_GZ_RX_RING_PIDX,
			     rx_queue->added_count & rx_queue->ptr_mask);
	efx_writed_page(rx_queue->efx, &rxdb,
			ER_GZ_RX_RING_DOORBELL, efx_rx_queue_index(rx_queue));
	if (rx_queue->grant_credits)
		wmb();
	rx_queue->notified_count = notified_count;
	if (rx_queue->grant_credits)
		schedule_work(&rx_queue->grant_work);
}
