// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2025 Intel Corporation */
#include <linux/bitfield.h>
#include <net/libeth/rx.h>
#include <linux/net/intel/libie/controlq.h>
#define LIBIE_CTLQ_DESC_QWORD0(sz) \
(LIBIE_CTLQ_DESC_FLAG_BUF | \
LIBIE_CTLQ_DESC_FLAG_RD | \
FIELD_PREP(LIBIE_CTLQ_DESC_DATA_LEN, sz))
/**
* libie_ctlq_free_fq - free fill queue resources, including buffers
* @ctlq: Rx control queue whose resources need to be freed
*/
static void libie_ctlq_free_fq(struct libie_ctlq_info *ctlq)
{
struct libeth_fq fq = {
.fqes = ctlq->rx_fqes,
.pp = ctlq->pp,
};
for (u32 ntc = ctlq->next_to_clean; ntc != ctlq->next_to_post; ) {
page_pool_put_full_netmem(fq.pp, fq.fqes[ntc].netmem, false);
if (++ntc >= ctlq->ring_len)
ntc = 0;
}
libeth_rx_fq_destroy(&fq);
}
/**
* libie_ctlq_init_fq - initialize fill queue for an Rx controlq
* @ctlq: control queue that needs Rx buffer allocation
*
* Return: %0 on success, -%errno on failure
*/
static int libie_ctlq_init_fq(struct libie_ctlq_info *ctlq)
{
struct libeth_fq fq = {
.count = ctlq->ring_len,
.truesize = LIBIE_CTLQ_MAX_BUF_LEN,
.nid = NUMA_NO_NODE,
.type = LIBETH_FQE_SHORT,
.hsplit = true,
.no_napi = true,
};
int err;
err = libeth_rx_fq_create(&fq, ctlq->dev);
if (err)
return err;
ctlq->pp = fq.pp;
ctlq->rx_fqes = fq.fqes;
ctlq->truesize = fq.truesize;
return 0;
}
/**
* libie_ctlq_prep_rx_desc - prepare the descriptor with a new address
* @desc: descriptor to (re)initialize
* @addr: physical address to put into descriptor
* @mem_truesize: size of the accessible memory
*/
static void libie_ctlq_prep_rx_desc(struct libie_ctlq_desc *desc,
dma_addr_t addr, u32 mem_truesize)
{
u64 qword;
qword = LIBIE_CTLQ_DESC_QWORD0(mem_truesize);
desc->qword0 = cpu_to_le64(qword);
qword = FIELD_PREP(LIBIE_CTLQ_DESC_DATA_ADDR_HIGH,
upper_32_bits(addr)) |
FIELD_PREP(LIBIE_CTLQ_DESC_DATA_ADDR_LOW,
lower_32_bits(addr));
desc->qword3 = cpu_to_le64(qword);
}
/**
* libie_ctlq_post_rx_buffs - post buffers to descriptor ring
* @ctlq: control queue that requires Rx descriptor ring to be initiali