drivers/net/ethernet/alibaba/eea/eea_ring.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/alibaba/eea/eea_ring.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/alibaba/eea/eea_ring.c
Extension
.c
Size
5146 bytes
Lines
250
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// 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 eea_ering_irq_active(struct eea_ring *ering, struct eea_ring *tx_ering)
{
	u64 value = 0, rx_idx, tx_idx;

	tx_idx = (u64)tx_ering->cq.hw_idx;
	rx_idx = (u64)ering->cq.hw_idx;

	value |= EEA_IRQ_UNMASK << EEA_DB_FLAGS_OFF;
	value |= tx_idx << EEA_DB_TX_CQ_HEAD_OFF;
	value |= rx_idx << EEA_DB_RX_CQ_HEAD_OFF;

	writeq(value, ering->db);
}

void *eea_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 = READ_ONCE(*(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 *eea_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;
}

/* This is an allocation API for admin Q. For each call to admin Q, only one
 * desc will be allocated.
 */
void *eea_ering_aq_alloc_desc(struct eea_ring *ering)
{
	struct eea_ring_sq *sq = &ering->sq;
	struct eea_common_desc *desc;

	if (!sq->shadow_num)
		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;
}

Annotation

Implementation Notes