drivers/net/ethernet/altera/altera_sgdma.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/altera/altera_sgdma.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/altera/altera_sgdma.c
Extension
.c
Size
14861 bytes
Lines
528
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 (rxstatus) {
			csrwr8(0, desc, sgdma_descroffs(status));

			rxbuffer = dequeue_rx(priv);
			if (rxbuffer == NULL)
				netdev_info(priv->dev,
					    "sgdma rx and rx queue empty!\n");

			/* Clear control */
			csrwr32(0, priv->rx_dma_csr, sgdma_csroffs(control));
			/* clear status */
			csrwr32(0xf, priv->rx_dma_csr, sgdma_csroffs(status));

			/* kick the rx sgdma after reaping this descriptor */
			sgdma_async_read(priv);

		} else {
			/* If the SGDMA indicated an end of packet on recv,
			 * then it's expected that the rxstatus from the
			 * descriptor is non-zero - meaning a valid packet
			 * with a nonzero length, or an error has been
			 * indicated. if not, then all we can do is signal
			 * an error and return no packet received. Most likely
			 * there is a system design error, or an error in the
			 * underlying kernel (cache or cache management problem)
			 */
			netdev_err(priv->dev,
				   "SGDMA RX Error Info: %x, %x, %x\n",
				   sts, csrrd8(desc, sgdma_descroffs(status)),
				   rxstatus);
		}
	} else if (sts == 0) {
		sgdma_async_read(priv);
	}

	return rxstatus;
}


/* Private functions */
static void sgdma_setup_descrip(struct sgdma_descrip __iomem *desc,
				struct sgdma_descrip __iomem *ndesc,
				dma_addr_t ndesc_phys,
				dma_addr_t raddr,
				dma_addr_t waddr,
				u16 length,
				int generate_eop,
				int rfixed,
				int wfixed)
{
	/* Clear the next descriptor as not owned by hardware */

	u32 ctrl = csrrd8(ndesc, sgdma_descroffs(control));
	ctrl &= ~SGDMA_CONTROL_HW_OWNED;
	csrwr8(ctrl, ndesc, sgdma_descroffs(control));

	ctrl = SGDMA_CONTROL_HW_OWNED;
	ctrl |= generate_eop;
	ctrl |= rfixed;
	ctrl |= wfixed;

	/* Channel is implicitly zero, initialized to 0 by default */
	csrwr32(lower_32_bits(raddr), desc, sgdma_descroffs(raddr));
	csrwr32(lower_32_bits(waddr), desc, sgdma_descroffs(waddr));

	csrwr32(0, desc, sgdma_descroffs(pad1));
	csrwr32(0, desc, sgdma_descroffs(pad2));
	csrwr32(lower_32_bits(ndesc_phys), desc, sgdma_descroffs(next));

	csrwr8(ctrl, desc, sgdma_descroffs(control));
	csrwr8(0, desc, sgdma_descroffs(status));
	csrwr8(0, desc, sgdma_descroffs(wburst));
	csrwr8(0, desc, sgdma_descroffs(rburst));
	csrwr16(length, desc, sgdma_descroffs(bytes));
	csrwr16(0, desc, sgdma_descroffs(bytes_xferred));
}

/* If hardware is busy, don't restart async read.
 * if status register is 0 - meaning initial state, restart async read,
 * probably for the first time when populating a receive buffer.
 * If read status indicate not busy and a status, restart the async
 * DMA read.
 */
static int sgdma_async_read(struct altera_tse_private *priv)
{
	struct sgdma_descrip __iomem *descbase =
		(struct sgdma_descrip __iomem *)priv->rx_dma_desc;

	struct sgdma_descrip __iomem *cdesc = &descbase[0];
	struct sgdma_descrip __iomem *ndesc = &descbase[1];

Annotation

Implementation Notes