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

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

File Facts

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

if (page_ref_count(rxbuf->rxdata.page) > 1) {
			/* Try reuse buffer */
			rxbuf->rxdata.pg_off += frame_max + page_offset +
						tail_size;
			if (rxbuf->rxdata.pg_off + frame_max + tail_size <=
			    (PAGE_SIZE << order)) {
				u64_stats_update_begin(&self->stats.rx.syncp);
				self->stats.rx.pg_flips++;
				u64_stats_update_end(&self->stats.rx.syncp);

			} else {
				/* Buffer exhausted. We have other users and
				 * should release this page and realloc
				 */
				aq_free_rxpage(&rxbuf->rxdata,
					       aq_nic_get_dev(self->aq_nic));
				u64_stats_update_begin(&self->stats.rx.syncp);
				self->stats.rx.pg_losts++;
				u64_stats_update_end(&self->stats.rx.syncp);
			}
		} else {
			rxbuf->rxdata.pg_off = page_offset;
			u64_stats_update_begin(&self->stats.rx.syncp);
			self->stats.rx.pg_reuses++;
			u64_stats_update_end(&self->stats.rx.syncp);
		}
	}

	if (!rxbuf->rxdata.page) {
		ret = aq_alloc_rxpages(&rxbuf->rxdata, self);
		if (ret) {
			u64_stats_update_begin(&self->stats.rx.syncp);
			self->stats.rx.alloc_fails++;
			u64_stats_update_end(&self->stats.rx.syncp);
		}
		return ret;
	}

	return 0;
}

static int aq_ring_alloc(struct aq_ring_s *self,
			 struct aq_nic_s *aq_nic)
{
	int err = 0;

	self->buff_ring =
		kzalloc_objs(struct aq_ring_buff_s, self->size);

	if (!self->buff_ring) {
		err = -ENOMEM;
		goto err_exit;
	}

	self->dx_ring = dma_alloc_coherent(aq_nic_get_dev(aq_nic),
					   self->size * self->dx_size,
					   &self->dx_ring_pa, GFP_KERNEL);
	if (!self->dx_ring) {
		err = -ENOMEM;
		goto err_exit;
	}

err_exit:
	if (err < 0) {
		aq_ring_free(self);
	}

	return err;
}

int aq_ring_tx_alloc(struct aq_ring_s *self,
		     struct aq_nic_s *aq_nic,
		     unsigned int idx,
		     struct aq_nic_cfg_s *aq_nic_cfg)
{
	self->aq_nic = aq_nic;
	self->idx = idx;
	self->size = aq_nic_cfg->txds;
	self->dx_size = aq_nic_cfg->aq_hw_caps->txd_size;

	return aq_ring_alloc(self, aq_nic);
}

int aq_ring_rx_alloc(struct aq_ring_s *self,
		     struct aq_nic_s *aq_nic,
		     unsigned int idx,
		     struct aq_nic_cfg_s *aq_nic_cfg)
{
	self->aq_nic = aq_nic;
	self->idx = idx;

Annotation

Implementation Notes