drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_fdma.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_fdma.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_fdma.c
Extension
.c
Size
9359 bytes
Lines
405
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 (port && port->ndev) {
			sparx5->rx.ndev = port->ndev;
			break;
		}
	}
}

static void lan969x_fdma_tx_init(struct sparx5 *sparx5)
{
	struct fdma *fdma = &sparx5->tx.fdma;

	fdma->channel_id = FDMA_INJ_CHANNEL;
	fdma->n_dcbs = FDMA_DCB_MAX;
	fdma->n_dbs = 1;
	fdma->priv = sparx5;
	fdma->size = fdma_get_size(fdma);
	fdma->db_size = PAGE_SIZE;
	fdma->ops.dataptr_cb = &lan969x_fdma_tx_dataptr_cb;
	fdma->ops.nextptr_cb = &fdma_nextptr_cb;
}

int lan969x_fdma_napi_poll(struct napi_struct *napi, int weight)
{
	struct sparx5_rx *rx = container_of(napi, struct sparx5_rx, napi);
	struct sparx5 *sparx5 = container_of(rx, struct sparx5, rx);
	int old_dcb, dcb_reload, counter = 0;
	struct fdma *fdma = &rx->fdma;
	struct sk_buff *skb;

	dcb_reload = fdma->dcb_index;

	lan969x_fdma_tx_clear_buf(sparx5, weight);

	/* Process RX data */
	while (counter < weight) {
		if (!fdma_has_frames(fdma))
			break;

		skb = lan969x_fdma_rx_get_frame(sparx5, rx);
		if (!skb)
			break;

		napi_gro_receive(&rx->napi, skb);

		fdma_db_advance(fdma);
		counter++;
		/* Check if the DCB can be reused */
		if (fdma_dcb_is_reusable(fdma))
			continue;

		fdma_db_reset(fdma);
		fdma_dcb_advance(fdma);
	}

	/* Allocate new pages and map them */
	while (dcb_reload != fdma->dcb_index) {
		old_dcb = dcb_reload;
		dcb_reload++;
		 /* n_dcbs must be a power of 2 */
		dcb_reload &= fdma->n_dcbs - 1;

		fdma_dcb_add(fdma,
			     old_dcb,
			     FDMA_DCB_INFO_DATAL(fdma->db_size),
			     FDMA_DCB_STATUS_INTR);

		sparx5_fdma_reload(sparx5, fdma);
	}

	if (counter < weight && napi_complete_done(napi, counter))
		spx5_wr(0xff, sparx5, FDMA_INTR_DB_ENA);

	return counter;
}

int lan969x_fdma_xmit(struct sparx5 *sparx5, u32 *ifh, struct sk_buff *skb,
		      struct net_device *dev)
{
	int next_dcb, needed_headroom, needed_tailroom, err;
	struct sparx5_tx *tx = &sparx5->tx;
	struct fdma *fdma = &tx->fdma;
	struct sparx5_tx_buf *db_buf;
	u64 status;

	next_dcb = lan969x_fdma_get_next_dcb(tx);
	if (next_dcb < 0)
		return -EBUSY;

	needed_headroom = max_t(int, IFH_LEN * 4 - skb_headroom(skb), 0);
	needed_tailroom = max_t(int, ETH_FCS_LEN - skb_tailroom(skb), 0);

Annotation

Implementation Notes