drivers/net/ethernet/aquantia/atlantic/aq_vec.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/aquantia/atlantic/aq_vec.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/aquantia/atlantic/aq_vec.c
Extension
.c
Size
8170 bytes
Lines
380
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

struct aq_vec_s {
	const struct aq_hw_ops *aq_hw_ops;
	struct aq_hw_s *aq_hw;
	struct aq_nic_s *aq_nic;
	unsigned int tx_rings;
	unsigned int rx_rings;
	struct aq_ring_param_s aq_ring_param;
	struct napi_struct napi;
	struct aq_ring_s ring[AQ_CFG_TCS_MAX][2];
};

#define AQ_VEC_TX_ID 0
#define AQ_VEC_RX_ID 1

static int aq_vec_poll(struct napi_struct *napi, int budget)
{
	struct aq_vec_s *self = container_of(napi, struct aq_vec_s, napi);
	unsigned int sw_tail_old = 0U;
	struct aq_ring_s *ring = NULL;
	bool was_tx_cleaned = true;
	unsigned int i = 0U;
	int work_done = 0;
	int err = 0;

	if (!self) {
		err = -EINVAL;
	} else {
		for (i = 0U; self->tx_rings > i; ++i) {
			ring = self->ring[i];
			u64_stats_update_begin(&ring[AQ_VEC_RX_ID].stats.rx.syncp);
			ring[AQ_VEC_RX_ID].stats.rx.polls++;
			u64_stats_update_end(&ring[AQ_VEC_RX_ID].stats.rx.syncp);
			if (self->aq_hw_ops->hw_ring_tx_head_update) {
				err = self->aq_hw_ops->hw_ring_tx_head_update(
							self->aq_hw,
							&ring[AQ_VEC_TX_ID]);
				if (err < 0)
					goto err_exit;
			}

			if (ring[AQ_VEC_TX_ID].sw_head !=
			    ring[AQ_VEC_TX_ID].hw_head) {
				was_tx_cleaned = aq_ring_tx_clean(&ring[AQ_VEC_TX_ID]);
				aq_ring_update_queue_state(&ring[AQ_VEC_TX_ID]);
			}

			err = self->aq_hw_ops->hw_ring_rx_receive(self->aq_hw,
					    &ring[AQ_VEC_RX_ID]);
			if (err < 0)
				goto err_exit;

			if (ring[AQ_VEC_RX_ID].sw_head !=
				ring[AQ_VEC_RX_ID].hw_head) {
				err = aq_ring_rx_clean(&ring[AQ_VEC_RX_ID],
						       napi,
						       &work_done,
						       budget - work_done);
				if (err < 0)
					goto err_exit;

				sw_tail_old = ring[AQ_VEC_RX_ID].sw_tail;

				err = aq_ring_rx_fill(&ring[AQ_VEC_RX_ID]);
				if (err < 0)
					goto err_exit;

				err = self->aq_hw_ops->hw_ring_rx_fill(
					self->aq_hw,
					&ring[AQ_VEC_RX_ID], sw_tail_old);
				if (err < 0)
					goto err_exit;
			}
		}

err_exit:
		if (!was_tx_cleaned)
			work_done = budget;

		if (work_done < budget) {
			napi_complete_done(napi, work_done);
			self->aq_hw_ops->hw_irq_enable(self->aq_hw,
					1U << self->aq_ring_param.vec_idx);
		}
	}

	return work_done;
}

struct aq_vec_s *aq_vec_alloc(struct aq_nic_s *aq_nic, unsigned int idx,
			      struct aq_nic_cfg_s *aq_nic_cfg)

Annotation

Implementation Notes