[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <1762494656.4215019-2-xuanzhuo@linux.alibaba.com>
Date: Fri, 7 Nov 2025 13:50:56 +0800
From: Xuan Zhuo <xuanzhuo@...ux.alibaba.com>
To: Xuan Zhuo <xuanzhuo@...ux.alibaba.com>
Cc: Andrew Lunn <andrew+netdev@...n.ch>,
"David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>,
Wen Gu <guwen@...ux.alibaba.com>,
Philo Lu <lulie@...ux.alibaba.com>,
Lorenzo Bianconi <lorenzo@...nel.org>,
Vadim Fedorenko <vadim.fedorenko@...ux.dev>,
Lukas Bulwahn <lukas.bulwahn@...hat.com>,
Geert Uytterhoeven <geert+renesas@...der.be>,
Vivian Wang <wangruikang@...as.ac.cn>,
Troy Mitchell <troy.mitchell@...ux.spacemit.com>,
Dust Li <dust.li@...ux.alibaba.com>,
netdev@...r.kernel.org
Subject: Re: [PATCH net-next v11 2/5] eea: introduce ring and descriptor structures
Please ignore this.
On Fri, 7 Nov 2025 13:48:17 +0800, Xuan Zhuo <xuanzhuo@...ux.alibaba.com> wrote:
> Add basic driver framework for the Alibaba Elastic Ethernet Adapter(EEA).
>
> This commit introduces the ring and descriptor implementations.
>
> These structures and ring APIs are used by the RX, TX, and admin queues.
>
> Reviewed-by: Dust Li <dust.li@...ux.alibaba.com>
> Reviewed-by: Philo Lu <lulie@...ux.alibaba.com>
> Signed-off-by: Wen Gu <guwen@...ux.alibaba.com>
> Signed-off-by: Xuan Zhuo <xuanzhuo@...ux.alibaba.com>
> ---
> drivers/net/ethernet/alibaba/eea/Makefile | 3 +-
> drivers/net/ethernet/alibaba/eea/eea_desc.h | 156 ++++++++++++
> drivers/net/ethernet/alibaba/eea/eea_ring.c | 260 ++++++++++++++++++++
> drivers/net/ethernet/alibaba/eea/eea_ring.h | 91 +++++++
> 4 files changed, 509 insertions(+), 1 deletion(-)
> create mode 100644 drivers/net/ethernet/alibaba/eea/eea_desc.h
> create mode 100644 drivers/net/ethernet/alibaba/eea/eea_ring.c
> create mode 100644 drivers/net/ethernet/alibaba/eea/eea_ring.h
>
> diff --git a/drivers/net/ethernet/alibaba/eea/Makefile b/drivers/net/ethernet/alibaba/eea/Makefile
> index cf2acf1733fd..e5e4007810a6 100644
> --- a/drivers/net/ethernet/alibaba/eea/Makefile
> +++ b/drivers/net/ethernet/alibaba/eea/Makefile
> @@ -1,3 +1,4 @@
>
> obj-$(CONFIG_EEA) += eea.o
> -eea-y := eea_pci.o
> +eea-y := eea_ring.o \
> + eea_pci.o
> diff --git a/drivers/net/ethernet/alibaba/eea/eea_desc.h b/drivers/net/ethernet/alibaba/eea/eea_desc.h
> new file mode 100644
> index 000000000000..541346a03375
> --- /dev/null
> +++ b/drivers/net/ethernet/alibaba/eea/eea_desc.h
> @@ -0,0 +1,156 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Driver for Alibaba Elastic Ethernet Adapter.
> + *
> + * Copyright (C) 2025 Alibaba Inc.
> + */
> +
> +#ifndef __EEA_DESC_H__
> +#define __EEA_DESC_H__
> +
> +#define EEA_DESC_TS_MASK GENMASK(47, 0)
> +#define EEA_DESC_TS(desc) (le64_to_cpu((desc)->ts) & EEA_DESC_TS_MASK)
> +
> +struct eea_aq_desc {
> + __le16 flags;
> + __le16 id;
> + __le16 reserved;
> + u8 classid;
> + u8 command;
> + __le64 data_addr;
> + __le64 reply_addr;
> + __le32 data_len;
> + __le32 reply_len;
> +};
> +
> +struct eea_aq_cdesc {
> + __le16 flags;
> + __le16 id;
> +#define EEA_OK 0
> +#define EEA_ERR 0xffffffff
> + __le32 status;
> + __le32 reply_len;
> + __le32 reserved1;
> +
> + __le64 reserved2;
> + __le64 reserved3;
> +};
> +
> +struct eea_rx_desc {
> + __le16 flags;
> + __le16 id;
> + __le16 len;
> + __le16 reserved1;
> +
> + __le64 addr;
> +
> + __le64 hdr_addr;
> + __le32 reserved2;
> + __le32 reserved3;
> +};
> +
> +#define EEA_RX_CDESC_HDR_LEN_MASK GENMASK(9, 0)
> +
> +struct eea_rx_cdesc {
> +#define EEA_DESC_F_DATA_VALID BIT(6)
> +#define EEA_DESC_F_SPLIT_HDR BIT(5)
> + __le16 flags;
> + __le16 id;
> + __le16 len;
> +#define EEA_NET_PT_NONE 0
> +#define EEA_NET_PT_IPv4 1
> +#define EEA_NET_PT_TCPv4 2
> +#define EEA_NET_PT_UDPv4 3
> +#define EEA_NET_PT_IPv6 4
> +#define EEA_NET_PT_TCPv6 5
> +#define EEA_NET_PT_UDPv6 6
> +#define EEA_NET_PT_IPv6_EX 7
> +#define EEA_NET_PT_TCPv6_EX 8
> +#define EEA_NET_PT_UDPv6_EX 9
> + /* [9:0] is packet type. */
> + __le16 type;
> +
> + /* hw timestamp [0:47]: ts */
> + __le64 ts;
> +
> + __le32 hash;
> +
> + /* 0-9: hdr_len split header
> + * 10-15: reserved1
> + */
> + __le16 len_ex;
> + __le16 reserved2;
> +
> + __le32 reserved3;
> + __le32 reserved4;
> +};
> +
> +#define EEA_TX_GSO_NONE 0
> +#define EEA_TX_GSO_TCPV4 1
> +#define EEA_TX_GSO_TCPV6 4
> +#define EEA_TX_GSO_UDP_L4 5
> +#define EEA_TX_GSO_ECN 0x80
> +
> +struct eea_tx_desc {
> +#define EEA_DESC_F_DO_CSUM BIT(6)
> + __le16 flags;
> + __le16 id;
> + __le16 len;
> + __le16 reserved1;
> +
> + __le64 addr;
> +
> + __le16 csum_start;
> + __le16 csum_offset;
> + u8 gso_type;
> + u8 reserved2;
> + __le16 gso_size;
> + __le64 reserved3;
> +};
> +
> +struct eea_tx_cdesc {
> + __le16 flags;
> + __le16 id;
> + __le16 len;
> + __le16 reserved1;
> +
> + /* hw timestamp [0:47]: ts */
> + __le64 ts;
> + __le64 reserved2;
> + __le64 reserved3;
> +};
> +
> +struct eea_db {
> +#define EEA_IDX_PRESENT BIT(0)
> +#define EEA_IRQ_MASK BIT(1)
> +#define EEA_IRQ_UNMASK BIT(2)
> +#define EEA_DIRECT_INLINE BIT(3)
> +#define EEA_DIRECT_DESC BIT(4)
> + u8 kick_flags;
> + u8 reserved;
> + __le16 idx;
> +
> + __le16 tx_cq_head;
> + __le16 rx_cq_head;
> +};
> +
> +struct eea_db_direct {
> + u8 kick_flags;
> + u8 reserved;
> + __le16 idx;
> +
> + __le16 tx_cq_head;
> + __le16 rx_cq_head;
> +
> + u8 desc[24];
> +};
> +
> +static_assert(sizeof(struct eea_rx_desc) == 32, "rx desc size does not match");
> +static_assert(sizeof(struct eea_rx_cdesc) == 32,
> + "rx cdesc size does not match");
> +static_assert(sizeof(struct eea_tx_desc) == 32, "tx desc size does not match");
> +static_assert(sizeof(struct eea_tx_cdesc) == 32,
> + "tx cdesc size does not match");
> +static_assert(sizeof(struct eea_db_direct) == 32,
> + "db direct size does not match");
> +#endif
> diff --git a/drivers/net/ethernet/alibaba/eea/eea_ring.c b/drivers/net/ethernet/alibaba/eea/eea_ring.c
> new file mode 100644
> index 000000000000..f05745474ecf
> --- /dev/null
> +++ b/drivers/net/ethernet/alibaba/eea/eea_ring.c
> @@ -0,0 +1,260 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Driver for Alibaba Elastic Ethernet Adapter.
> + *
> + * Copyright (C) 2025 Alibaba Inc.
> + */
> +
> +#include "eea_pci.h"
> +#include "eea_ring.h"
> +
> +void ering_irq_unactive(struct eea_ring *ering)
> +{
> + union {
> + u64 data;
> + struct eea_db db;
> + } val;
> +
> + if (ering->mask == EEA_IRQ_MASK)
> + return;
> +
> + ering->mask = EEA_IRQ_MASK;
> +
> + val.db.kick_flags = EEA_IRQ_MASK;
> +
> + writeq(val.data, (void __iomem *)ering->db);
> +}
> +
> +void ering_irq_active(struct eea_ring *ering, struct eea_ring *tx_ering)
> +{
> + union {
> + u64 data;
> + struct eea_db db;
> + } val;
> +
> + if (ering->mask == EEA_IRQ_UNMASK)
> + return;
> +
> + ering->mask = EEA_IRQ_UNMASK;
> +
> + val.db.kick_flags = EEA_IRQ_UNMASK;
> +
> + val.db.tx_cq_head = cpu_to_le16(tx_ering->cq.hw_idx);
> + val.db.rx_cq_head = cpu_to_le16(ering->cq.hw_idx);
> +
> + writeq(val.data, ering->db);
> +}
> +
> +void *ering_cq_get_desc(const struct eea_ring *ering)
> +{
> + u8 phase;
> + u8 *desc;
> +
> + desc = ering->cq.desc + (ering->cq.head << ering->cq.desc_size_shift);
> +
> + phase = *(u8 *)(desc + ering->cq.desc_size - 1);
> +
> + if ((phase & EEA_RING_DESC_F_CQ_PHASE) == ering->cq.phase) {
> + dma_rmb();
> + return desc;
> + }
> +
> + return NULL;
> +}
> +
> +/* sq api */
> +void *ering_sq_alloc_desc(struct eea_ring *ering, u16 id, bool is_last,
> + u16 flags)
> +{
> + struct eea_ring_sq *sq = &ering->sq;
> + struct eea_common_desc *desc;
> +
> + if (!sq->shadow_num) {
> + sq->shadow_idx = sq->head;
> + sq->shadow_id = cpu_to_le16(id);
> + }
> +
> + if (!is_last)
> + flags |= EEA_RING_DESC_F_MORE;
> +
> + desc = sq->desc + (sq->shadow_idx << sq->desc_size_shift);
> +
> + desc->flags = cpu_to_le16(flags);
> + desc->id = sq->shadow_id;
> +
> + if (unlikely(++sq->shadow_idx >= ering->num))
> + sq->shadow_idx = 0;
> +
> + ++sq->shadow_num;
> +
> + return desc;
> +}
> +
> +/* alloc desc for adminq */
> +void *ering_aq_alloc_desc(struct eea_ring *ering)
> +{
> + struct eea_ring_sq *sq = &ering->sq;
> + struct eea_common_desc *desc;
> +
> + sq->shadow_idx = sq->head;
> +
> + desc = sq->desc + (sq->shadow_idx << sq->desc_size_shift);
> +
> + if (unlikely(++sq->shadow_idx >= ering->num))
> + sq->shadow_idx = 0;
> +
> + ++sq->shadow_num;
> +
> + return desc;
> +}
> +
> +void ering_sq_commit_desc(struct eea_ring *ering)
> +{
> + struct eea_ring_sq *sq = &ering->sq;
> + int num;
> +
> + num = sq->shadow_num;
> +
> + ering->num_free -= num;
> +
> + sq->head = sq->shadow_idx;
> + sq->hw_idx += num;
> + sq->shadow_num = 0;
> +}
> +
> +void ering_sq_cancel(struct eea_ring *ering)
> +{
> + ering->sq.shadow_num = 0;
> +}
> +
> +/* cq api */
> +void ering_cq_ack_desc(struct eea_ring *ering, u32 num)
> +{
> + struct eea_ring_cq *cq = &ering->cq;
> +
> + cq->head += num;
> + cq->hw_idx += num;
> +
> + if (unlikely(cq->head >= ering->num)) {
> + cq->head -= ering->num;
> + cq->phase ^= EEA_RING_DESC_F_CQ_PHASE;
> + }
> +
> + ering->num_free += num;
> +}
> +
> +/* notify */
> +bool ering_kick(struct eea_ring *ering)
> +{
> + union {
> + struct eea_db db;
> + u64 data;
> + } val;
> +
> + val.db.kick_flags = EEA_IDX_PRESENT;
> + val.db.idx = cpu_to_le16(ering->sq.hw_idx);
> +
> + writeq(val.data, ering->db);
> +
> + return true;
> +}
> +
> +/* ering alloc/free */
> +static void ering_free_queue(struct eea_device *edev, size_t size,
> + void *queue, dma_addr_t dma_handle)
> +{
> + dma_free_coherent(edev->dma_dev, size, queue, dma_handle);
> +}
> +
> +static void *ering_alloc_queue(struct eea_device *edev, size_t size,
> + dma_addr_t *dma_handle)
> +{
> + gfp_t flags = GFP_KERNEL | __GFP_NOWARN;
> +
> + return dma_alloc_coherent(edev->dma_dev, size, dma_handle, flags);
> +}
> +
> +static int ering_alloc_queues(struct eea_ring *ering, struct eea_device *edev,
> + u32 num, u8 sq_desc_size, u8 cq_desc_size)
> +{
> + dma_addr_t addr;
> + size_t size;
> + void *ring;
> +
> + size = num * sq_desc_size;
> +
> + ring = ering_alloc_queue(edev, size, &addr);
> + if (!ring)
> + return -ENOMEM;
> +
> + ering->sq.desc = ring;
> + ering->sq.dma_addr = addr;
> + ering->sq.dma_size = size;
> + ering->sq.desc_size = sq_desc_size;
> + ering->sq.desc_size_shift = fls(sq_desc_size) - 1;
> +
> + size = num * cq_desc_size;
> +
> + ring = ering_alloc_queue(edev, size, &addr);
> + if (!ring)
> + goto err_free_sq;
> +
> + ering->cq.desc = ring;
> + ering->cq.dma_addr = addr;
> + ering->cq.dma_size = size;
> + ering->cq.desc_size = cq_desc_size;
> + ering->cq.desc_size_shift = fls(cq_desc_size) - 1;
> +
> + ering->num = num;
> +
> + return 0;
> +
> +err_free_sq:
> + ering_free_queue(ering->edev, ering->sq.dma_size,
> + ering->sq.desc, ering->sq.dma_addr);
> + return -ENOMEM;
> +}
> +
> +static void ering_init(struct eea_ring *ering)
> +{
> + ering->cq.phase = EEA_RING_DESC_F_CQ_PHASE;
> + ering->num_free = ering->num;
> +}
> +
> +struct eea_ring *ering_alloc(u32 index, u32 num, struct eea_device *edev,
> + u8 sq_desc_size, u8 cq_desc_size,
> + const char *name)
> +{
> + struct eea_ring *ering;
> +
> + ering = kzalloc(sizeof(*ering), GFP_KERNEL);
> + if (!ering)
> + return NULL;
> +
> + ering->edev = edev;
> + ering->name = name;
> + ering->index = index;
> + ering->msix_vec = index / 2 + 1; /* vec 0 is for error notify. */
> +
> + if (ering_alloc_queues(ering, edev, num, sq_desc_size, cq_desc_size))
> + goto err_free;
> +
> + ering_init(ering);
> +
> + return ering;
> +
> +err_free:
> + kfree(ering);
> + return NULL;
> +}
> +
> +void ering_free(struct eea_ring *ering)
> +{
> + ering_free_queue(ering->edev, ering->cq.dma_size,
> + ering->cq.desc, ering->cq.dma_addr);
> +
> + ering_free_queue(ering->edev, ering->sq.dma_size,
> + ering->sq.desc, ering->sq.dma_addr);
> +
> + kfree(ering);
> +}
> diff --git a/drivers/net/ethernet/alibaba/eea/eea_ring.h b/drivers/net/ethernet/alibaba/eea/eea_ring.h
> new file mode 100644
> index 000000000000..ea7adc32bb23
> --- /dev/null
> +++ b/drivers/net/ethernet/alibaba/eea/eea_ring.h
> @@ -0,0 +1,91 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Driver for Alibaba Elastic Ethernet Adapter.
> + *
> + * Copyright (C) 2025 Alibaba Inc.
> + */
> +
> +#ifndef __EEA_RING_H__
> +#define __EEA_RING_H__
> +
> +#include <linux/dma-mapping.h>
> +#include "eea_desc.h"
> +
> +#define EEA_RING_DESC_F_MORE BIT(0)
> +#define EEA_RING_DESC_F_CQ_PHASE BIT(7)
> +
> +struct eea_common_desc {
> + __le16 flags;
> + __le16 id;
> +};
> +
> +struct eea_device;
> +
> +struct eea_ring_sq {
> + void *desc;
> +
> + u16 head;
> + u16 hw_idx;
> +
> + u16 shadow_idx;
> + __le16 shadow_id;
> + u16 shadow_num;
> +
> + u8 desc_size;
> + u8 desc_size_shift;
> +
> + dma_addr_t dma_addr;
> + u32 dma_size;
> +};
> +
> +struct eea_ring_cq {
> + void *desc;
> +
> + u16 head;
> + u16 hw_idx;
> +
> + u8 phase;
> + u8 desc_size_shift;
> + u8 desc_size;
> +
> + dma_addr_t dma_addr;
> + u32 dma_size;
> +};
> +
> +struct eea_ring {
> + const char *name;
> + struct eea_device *edev;
> + u32 index;
> + void __iomem *db;
> + u16 msix_vec;
> +
> + u8 mask;
> +
> + u32 num;
> +
> + u32 num_free;
> +
> + struct eea_ring_sq sq;
> + struct eea_ring_cq cq;
> +
> + char irq_name[32];
> +};
> +
> +struct eea_ring *ering_alloc(u32 index, u32 num, struct eea_device *edev,
> + u8 sq_desc_size, u8 cq_desc_size,
> + const char *name);
> +void ering_free(struct eea_ring *ering);
> +bool ering_kick(struct eea_ring *ering);
> +
> +void *ering_sq_alloc_desc(struct eea_ring *ering, u16 id,
> + bool is_last, u16 flags);
> +void *ering_aq_alloc_desc(struct eea_ring *ering);
> +void ering_sq_commit_desc(struct eea_ring *ering);
> +void ering_sq_cancel(struct eea_ring *ering);
> +
> +void ering_cq_ack_desc(struct eea_ring *ering, u32 num);
> +
> +void ering_irq_unactive(struct eea_ring *ering);
> +void ering_irq_active(struct eea_ring *ering, struct eea_ring *tx_ering);
> +void *ering_cq_get_desc(const struct eea_ring *ering);
> +#endif
> --
> 2.32.0.3.g01195cf9f
>
Powered by blists - more mailing lists