drivers/net/ethernet/synopsys/dwc-xlgmac-net.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/synopsys/dwc-xlgmac-net.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/synopsys/dwc-xlgmac-net.c
Extension
.c
Size
34815 bytes
Lines
1351
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct net_device_ops xlgmac_netdev_ops = {
	.ndo_open		= xlgmac_open,
	.ndo_stop		= xlgmac_close,
	.ndo_start_xmit		= xlgmac_xmit,
	.ndo_tx_timeout		= xlgmac_tx_timeout,
	.ndo_get_stats64	= xlgmac_get_stats64,
	.ndo_change_mtu		= xlgmac_change_mtu,
	.ndo_set_mac_address	= xlgmac_set_mac_address,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_eth_ioctl		= xlgmac_ioctl,
	.ndo_vlan_rx_add_vid	= xlgmac_vlan_rx_add_vid,
	.ndo_vlan_rx_kill_vid	= xlgmac_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= xlgmac_poll_controller,
#endif
	.ndo_set_features	= xlgmac_set_features,
	.ndo_set_rx_mode	= xlgmac_set_rx_mode,
};

const struct net_device_ops *xlgmac_get_netdev_ops(void)
{
	return &xlgmac_netdev_ops;
}

static void xlgmac_rx_refresh(struct xlgmac_channel *channel)
{
	struct xlgmac_pdata *pdata = channel->pdata;
	struct xlgmac_ring *ring = channel->rx_ring;
	struct xlgmac_desc_data *desc_data;
	struct xlgmac_desc_ops *desc_ops;
	struct xlgmac_hw_ops *hw_ops;

	desc_ops = &pdata->desc_ops;
	hw_ops = &pdata->hw_ops;

	while (ring->dirty != ring->cur) {
		desc_data = XLGMAC_GET_DESC_DATA(ring, ring->dirty);

		/* Reset desc_data values */
		desc_ops->unmap_desc_data(pdata, desc_data);

		if (desc_ops->map_rx_buffer(pdata, ring, desc_data))
			break;

		hw_ops->rx_desc_reset(pdata, desc_data, ring->dirty);

		ring->dirty++;
	}

	/* Make sure everything is written before the register write */
	wmb();

	/* Update the Rx Tail Pointer Register with address of
	 * the last cleaned entry
	 */
	desc_data = XLGMAC_GET_DESC_DATA(ring, ring->dirty - 1);
	writel(lower_32_bits(desc_data->dma_desc_addr),
	       XLGMAC_DMA_REG(channel, DMA_CH_RDTR_LO));
}

static struct sk_buff *xlgmac_create_skb(struct xlgmac_pdata *pdata,
					 struct napi_struct *napi,
					 struct xlgmac_desc_data *desc_data,
					 unsigned int len)
{
	unsigned int copy_len;
	struct sk_buff *skb;
	u8 *packet;

	skb = napi_alloc_skb(napi, desc_data->rx.hdr.dma_len);
	if (!skb)
		return NULL;

	/* Start with the header buffer which may contain just the header
	 * or the header plus data
	 */
	dma_sync_single_range_for_cpu(pdata->dev, desc_data->rx.hdr.dma_base,
				      desc_data->rx.hdr.dma_off,
				      desc_data->rx.hdr.dma_len,
				      DMA_FROM_DEVICE);

	packet = page_address(desc_data->rx.hdr.pa.pages) +
		 desc_data->rx.hdr.pa.pages_offset;
	copy_len = (desc_data->rx.hdr_len) ? desc_data->rx.hdr_len : len;
	copy_len = min(desc_data->rx.hdr.dma_len, copy_len);
	skb_copy_to_linear_data(skb, packet, copy_len);
	skb_put(skb, copy_len);

	len -= copy_len;
	if (len) {

Annotation

Implementation Notes