drivers/net/ethernet/sunplus/spl2sw_desc.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/sunplus/spl2sw_desc.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/sunplus/spl2sw_desc.c
Extension
.c
Size
5694 bytes
Lines
230
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 (comm->tx_temp_skb_info[i].mapping) {
			dma_unmap_single(&comm->pdev->dev, comm->tx_temp_skb_info[i].mapping,
					 comm->tx_temp_skb_info[i].skb->len, DMA_TO_DEVICE);
			comm->tx_temp_skb_info[i].mapping = 0;
		}

		if (comm->tx_temp_skb_info[i].skb) {
			dev_kfree_skb_any(comm->tx_temp_skb_info[i].skb);
			comm->tx_temp_skb_info[i].skb = NULL;
		}
	}
}

void spl2sw_rx_descs_clean(struct spl2sw_common *comm)
{
	struct spl2sw_skb_info *rx_skbinfo;
	struct spl2sw_mac_desc *rx_desc;
	u32 i, j;

	for (i = 0; i < RX_DESC_QUEUE_NUM; i++) {
		if (!comm->rx_skb_info[i])
			continue;

		rx_desc = comm->rx_desc[i];
		rx_skbinfo = comm->rx_skb_info[i];
		for (j = 0; j < comm->rx_desc_num[i]; j++) {
			rx_desc[j].cmd1 = 0;
			wmb();	/* Clear RXD_OWN and then set other fields. */
			rx_desc[j].cmd2 = 0;
			rx_desc[j].addr1 = 0;

			if (rx_skbinfo[j].skb) {
				dma_unmap_single(&comm->pdev->dev, rx_skbinfo[j].mapping,
						 comm->rx_desc_buff_size, DMA_FROM_DEVICE);
				dev_kfree_skb_any(rx_skbinfo[j].skb);
				rx_skbinfo[j].skb = NULL;
				rx_skbinfo[j].mapping = 0;
			}
		}

		kfree(rx_skbinfo);
		comm->rx_skb_info[i] = NULL;
	}
}

void spl2sw_descs_clean(struct spl2sw_common *comm)
{
	spl2sw_rx_descs_clean(comm);
	spl2sw_tx_descs_clean(comm);
}

void spl2sw_descs_free(struct spl2sw_common *comm)
{
	u32 i;

	spl2sw_descs_clean(comm);
	comm->tx_desc = NULL;
	for (i = 0; i < RX_DESC_QUEUE_NUM; i++)
		comm->rx_desc[i] = NULL;

	/*  Free descriptor area  */
	if (comm->desc_base) {
		dma_free_coherent(&comm->pdev->dev, comm->desc_size, comm->desc_base,
				  comm->desc_dma);
		comm->desc_base = NULL;
		comm->desc_dma = 0;
		comm->desc_size = 0;
	}
}

void spl2sw_tx_descs_init(struct spl2sw_common *comm)
{
	memset(comm->tx_desc, '\0', sizeof(struct spl2sw_mac_desc) *
	       (TX_DESC_NUM + MAC_GUARD_DESC_NUM));
}

int spl2sw_rx_descs_init(struct spl2sw_common *comm)
{
	struct spl2sw_skb_info *rx_skbinfo;
	struct spl2sw_mac_desc *rx_desc;
	struct sk_buff *skb;
	u32 mapping;
	u32 i, j;

	for (i = 0; i < RX_DESC_QUEUE_NUM; i++) {
		comm->rx_skb_info[i] = kzalloc_objs(*rx_skbinfo,
						    comm->rx_desc_num[i],
						    GFP_KERNEL | GFP_DMA);
		if (!comm->rx_skb_info[i])
			goto mem_alloc_fail;

Annotation

Implementation Notes