18c2ecf20Sopenharmony_ci/* Synopsys DesignWare Core Enterprise Ethernet (XLGMAC) Driver
28c2ecf20Sopenharmony_ci *
38c2ecf20Sopenharmony_ci * Copyright (c) 2017 Synopsys, Inc. (www.synopsys.com)
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This program is dual-licensed; you may select either version 2 of
68c2ecf20Sopenharmony_ci * the GNU General Public License ("GPL") or BSD license ("BSD").
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * This Synopsys DWC XLGMAC software driver and associated documentation
98c2ecf20Sopenharmony_ci * (hereinafter the "Software") is an unsupported proprietary work of
108c2ecf20Sopenharmony_ci * Synopsys, Inc. unless otherwise expressly agreed to in writing between
118c2ecf20Sopenharmony_ci * Synopsys and you. The Software IS NOT an item of Licensed Software or a
128c2ecf20Sopenharmony_ci * Licensed Product under any End User Software License Agreement or
138c2ecf20Sopenharmony_ci * Agreement for Licensed Products with Synopsys or any supplement thereto.
148c2ecf20Sopenharmony_ci * Synopsys is a registered trademark of Synopsys, Inc. Other names included
158c2ecf20Sopenharmony_ci * in the SOFTWARE may be the trademarks of their respective owners.
168c2ecf20Sopenharmony_ci */
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include "dwc-xlgmac.h"
198c2ecf20Sopenharmony_ci#include "dwc-xlgmac-reg.h"
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistatic void xlgmac_unmap_desc_data(struct xlgmac_pdata *pdata,
228c2ecf20Sopenharmony_ci				   struct xlgmac_desc_data *desc_data)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	if (desc_data->skb_dma) {
258c2ecf20Sopenharmony_ci		if (desc_data->mapped_as_page) {
268c2ecf20Sopenharmony_ci			dma_unmap_page(pdata->dev, desc_data->skb_dma,
278c2ecf20Sopenharmony_ci				       desc_data->skb_dma_len, DMA_TO_DEVICE);
288c2ecf20Sopenharmony_ci		} else {
298c2ecf20Sopenharmony_ci			dma_unmap_single(pdata->dev, desc_data->skb_dma,
308c2ecf20Sopenharmony_ci					 desc_data->skb_dma_len, DMA_TO_DEVICE);
318c2ecf20Sopenharmony_ci		}
328c2ecf20Sopenharmony_ci		desc_data->skb_dma = 0;
338c2ecf20Sopenharmony_ci		desc_data->skb_dma_len = 0;
348c2ecf20Sopenharmony_ci	}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	if (desc_data->skb) {
378c2ecf20Sopenharmony_ci		dev_kfree_skb_any(desc_data->skb);
388c2ecf20Sopenharmony_ci		desc_data->skb = NULL;
398c2ecf20Sopenharmony_ci	}
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	if (desc_data->rx.hdr.pa.pages)
428c2ecf20Sopenharmony_ci		put_page(desc_data->rx.hdr.pa.pages);
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	if (desc_data->rx.hdr.pa_unmap.pages) {
458c2ecf20Sopenharmony_ci		dma_unmap_page(pdata->dev, desc_data->rx.hdr.pa_unmap.pages_dma,
468c2ecf20Sopenharmony_ci			       desc_data->rx.hdr.pa_unmap.pages_len,
478c2ecf20Sopenharmony_ci			       DMA_FROM_DEVICE);
488c2ecf20Sopenharmony_ci		put_page(desc_data->rx.hdr.pa_unmap.pages);
498c2ecf20Sopenharmony_ci	}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	if (desc_data->rx.buf.pa.pages)
528c2ecf20Sopenharmony_ci		put_page(desc_data->rx.buf.pa.pages);
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	if (desc_data->rx.buf.pa_unmap.pages) {
558c2ecf20Sopenharmony_ci		dma_unmap_page(pdata->dev, desc_data->rx.buf.pa_unmap.pages_dma,
568c2ecf20Sopenharmony_ci			       desc_data->rx.buf.pa_unmap.pages_len,
578c2ecf20Sopenharmony_ci			       DMA_FROM_DEVICE);
588c2ecf20Sopenharmony_ci		put_page(desc_data->rx.buf.pa_unmap.pages);
598c2ecf20Sopenharmony_ci	}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	memset(&desc_data->tx, 0, sizeof(desc_data->tx));
628c2ecf20Sopenharmony_ci	memset(&desc_data->rx, 0, sizeof(desc_data->rx));
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	desc_data->mapped_as_page = 0;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	if (desc_data->state_saved) {
678c2ecf20Sopenharmony_ci		desc_data->state_saved = 0;
688c2ecf20Sopenharmony_ci		desc_data->state.skb = NULL;
698c2ecf20Sopenharmony_ci		desc_data->state.len = 0;
708c2ecf20Sopenharmony_ci		desc_data->state.error = 0;
718c2ecf20Sopenharmony_ci	}
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistatic void xlgmac_free_ring(struct xlgmac_pdata *pdata,
758c2ecf20Sopenharmony_ci			     struct xlgmac_ring *ring)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	struct xlgmac_desc_data *desc_data;
788c2ecf20Sopenharmony_ci	unsigned int i;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	if (!ring)
818c2ecf20Sopenharmony_ci		return;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	if (ring->desc_data_head) {
848c2ecf20Sopenharmony_ci		for (i = 0; i < ring->dma_desc_count; i++) {
858c2ecf20Sopenharmony_ci			desc_data = XLGMAC_GET_DESC_DATA(ring, i);
868c2ecf20Sopenharmony_ci			xlgmac_unmap_desc_data(pdata, desc_data);
878c2ecf20Sopenharmony_ci		}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci		kfree(ring->desc_data_head);
908c2ecf20Sopenharmony_ci		ring->desc_data_head = NULL;
918c2ecf20Sopenharmony_ci	}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	if (ring->rx_hdr_pa.pages) {
948c2ecf20Sopenharmony_ci		dma_unmap_page(pdata->dev, ring->rx_hdr_pa.pages_dma,
958c2ecf20Sopenharmony_ci			       ring->rx_hdr_pa.pages_len, DMA_FROM_DEVICE);
968c2ecf20Sopenharmony_ci		put_page(ring->rx_hdr_pa.pages);
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci		ring->rx_hdr_pa.pages = NULL;
998c2ecf20Sopenharmony_ci		ring->rx_hdr_pa.pages_len = 0;
1008c2ecf20Sopenharmony_ci		ring->rx_hdr_pa.pages_offset = 0;
1018c2ecf20Sopenharmony_ci		ring->rx_hdr_pa.pages_dma = 0;
1028c2ecf20Sopenharmony_ci	}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	if (ring->rx_buf_pa.pages) {
1058c2ecf20Sopenharmony_ci		dma_unmap_page(pdata->dev, ring->rx_buf_pa.pages_dma,
1068c2ecf20Sopenharmony_ci			       ring->rx_buf_pa.pages_len, DMA_FROM_DEVICE);
1078c2ecf20Sopenharmony_ci		put_page(ring->rx_buf_pa.pages);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci		ring->rx_buf_pa.pages = NULL;
1108c2ecf20Sopenharmony_ci		ring->rx_buf_pa.pages_len = 0;
1118c2ecf20Sopenharmony_ci		ring->rx_buf_pa.pages_offset = 0;
1128c2ecf20Sopenharmony_ci		ring->rx_buf_pa.pages_dma = 0;
1138c2ecf20Sopenharmony_ci	}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	if (ring->dma_desc_head) {
1168c2ecf20Sopenharmony_ci		dma_free_coherent(pdata->dev,
1178c2ecf20Sopenharmony_ci				  (sizeof(struct xlgmac_dma_desc) *
1188c2ecf20Sopenharmony_ci				  ring->dma_desc_count),
1198c2ecf20Sopenharmony_ci				  ring->dma_desc_head,
1208c2ecf20Sopenharmony_ci				  ring->dma_desc_head_addr);
1218c2ecf20Sopenharmony_ci		ring->dma_desc_head = NULL;
1228c2ecf20Sopenharmony_ci	}
1238c2ecf20Sopenharmony_ci}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_cistatic int xlgmac_init_ring(struct xlgmac_pdata *pdata,
1268c2ecf20Sopenharmony_ci			    struct xlgmac_ring *ring,
1278c2ecf20Sopenharmony_ci			    unsigned int dma_desc_count)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	if (!ring)
1308c2ecf20Sopenharmony_ci		return 0;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	/* Descriptors */
1338c2ecf20Sopenharmony_ci	ring->dma_desc_count = dma_desc_count;
1348c2ecf20Sopenharmony_ci	ring->dma_desc_head = dma_alloc_coherent(pdata->dev,
1358c2ecf20Sopenharmony_ci					(sizeof(struct xlgmac_dma_desc) *
1368c2ecf20Sopenharmony_ci					 dma_desc_count),
1378c2ecf20Sopenharmony_ci					&ring->dma_desc_head_addr,
1388c2ecf20Sopenharmony_ci					GFP_KERNEL);
1398c2ecf20Sopenharmony_ci	if (!ring->dma_desc_head)
1408c2ecf20Sopenharmony_ci		return -ENOMEM;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	/* Array of descriptor data */
1438c2ecf20Sopenharmony_ci	ring->desc_data_head = kcalloc(dma_desc_count,
1448c2ecf20Sopenharmony_ci					sizeof(struct xlgmac_desc_data),
1458c2ecf20Sopenharmony_ci					GFP_KERNEL);
1468c2ecf20Sopenharmony_ci	if (!ring->desc_data_head)
1478c2ecf20Sopenharmony_ci		return -ENOMEM;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	netif_dbg(pdata, drv, pdata->netdev,
1508c2ecf20Sopenharmony_ci		  "dma_desc_head=%p, dma_desc_head_addr=%pad, desc_data_head=%p\n",
1518c2ecf20Sopenharmony_ci		ring->dma_desc_head,
1528c2ecf20Sopenharmony_ci		&ring->dma_desc_head_addr,
1538c2ecf20Sopenharmony_ci		ring->desc_data_head);
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	return 0;
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistatic void xlgmac_free_rings(struct xlgmac_pdata *pdata)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	struct xlgmac_channel *channel;
1618c2ecf20Sopenharmony_ci	unsigned int i;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	if (!pdata->channel_head)
1648c2ecf20Sopenharmony_ci		return;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	channel = pdata->channel_head;
1678c2ecf20Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
1688c2ecf20Sopenharmony_ci		xlgmac_free_ring(pdata, channel->tx_ring);
1698c2ecf20Sopenharmony_ci		xlgmac_free_ring(pdata, channel->rx_ring);
1708c2ecf20Sopenharmony_ci	}
1718c2ecf20Sopenharmony_ci}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_cistatic int xlgmac_alloc_rings(struct xlgmac_pdata *pdata)
1748c2ecf20Sopenharmony_ci{
1758c2ecf20Sopenharmony_ci	struct xlgmac_channel *channel;
1768c2ecf20Sopenharmony_ci	unsigned int i;
1778c2ecf20Sopenharmony_ci	int ret;
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	channel = pdata->channel_head;
1808c2ecf20Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
1818c2ecf20Sopenharmony_ci		netif_dbg(pdata, drv, pdata->netdev, "%s - Tx ring:\n",
1828c2ecf20Sopenharmony_ci			  channel->name);
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci		ret = xlgmac_init_ring(pdata, channel->tx_ring,
1858c2ecf20Sopenharmony_ci				       pdata->tx_desc_count);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci		if (ret) {
1888c2ecf20Sopenharmony_ci			netdev_alert(pdata->netdev,
1898c2ecf20Sopenharmony_ci				     "error initializing Tx ring");
1908c2ecf20Sopenharmony_ci			goto err_init_ring;
1918c2ecf20Sopenharmony_ci		}
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci		netif_dbg(pdata, drv, pdata->netdev, "%s - Rx ring:\n",
1948c2ecf20Sopenharmony_ci			  channel->name);
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci		ret = xlgmac_init_ring(pdata, channel->rx_ring,
1978c2ecf20Sopenharmony_ci				       pdata->rx_desc_count);
1988c2ecf20Sopenharmony_ci		if (ret) {
1998c2ecf20Sopenharmony_ci			netdev_alert(pdata->netdev,
2008c2ecf20Sopenharmony_ci				     "error initializing Rx ring\n");
2018c2ecf20Sopenharmony_ci			goto err_init_ring;
2028c2ecf20Sopenharmony_ci		}
2038c2ecf20Sopenharmony_ci	}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	return 0;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_cierr_init_ring:
2088c2ecf20Sopenharmony_ci	xlgmac_free_rings(pdata);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	return ret;
2118c2ecf20Sopenharmony_ci}
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_cistatic void xlgmac_free_channels(struct xlgmac_pdata *pdata)
2148c2ecf20Sopenharmony_ci{
2158c2ecf20Sopenharmony_ci	if (!pdata->channel_head)
2168c2ecf20Sopenharmony_ci		return;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	kfree(pdata->channel_head->tx_ring);
2198c2ecf20Sopenharmony_ci	pdata->channel_head->tx_ring = NULL;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	kfree(pdata->channel_head->rx_ring);
2228c2ecf20Sopenharmony_ci	pdata->channel_head->rx_ring = NULL;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	kfree(pdata->channel_head);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	pdata->channel_head = NULL;
2278c2ecf20Sopenharmony_ci	pdata->channel_count = 0;
2288c2ecf20Sopenharmony_ci}
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_cistatic int xlgmac_alloc_channels(struct xlgmac_pdata *pdata)
2318c2ecf20Sopenharmony_ci{
2328c2ecf20Sopenharmony_ci	struct xlgmac_channel *channel_head, *channel;
2338c2ecf20Sopenharmony_ci	struct xlgmac_ring *tx_ring, *rx_ring;
2348c2ecf20Sopenharmony_ci	int ret = -ENOMEM;
2358c2ecf20Sopenharmony_ci	unsigned int i;
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	channel_head = kcalloc(pdata->channel_count,
2388c2ecf20Sopenharmony_ci			       sizeof(struct xlgmac_channel), GFP_KERNEL);
2398c2ecf20Sopenharmony_ci	if (!channel_head)
2408c2ecf20Sopenharmony_ci		return ret;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	netif_dbg(pdata, drv, pdata->netdev,
2438c2ecf20Sopenharmony_ci		  "channel_head=%p\n", channel_head);
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	tx_ring = kcalloc(pdata->tx_ring_count, sizeof(struct xlgmac_ring),
2468c2ecf20Sopenharmony_ci			  GFP_KERNEL);
2478c2ecf20Sopenharmony_ci	if (!tx_ring)
2488c2ecf20Sopenharmony_ci		goto err_tx_ring;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	rx_ring = kcalloc(pdata->rx_ring_count, sizeof(struct xlgmac_ring),
2518c2ecf20Sopenharmony_ci			  GFP_KERNEL);
2528c2ecf20Sopenharmony_ci	if (!rx_ring)
2538c2ecf20Sopenharmony_ci		goto err_rx_ring;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	for (i = 0, channel = channel_head; i < pdata->channel_count;
2568c2ecf20Sopenharmony_ci		i++, channel++) {
2578c2ecf20Sopenharmony_ci		snprintf(channel->name, sizeof(channel->name), "channel-%u", i);
2588c2ecf20Sopenharmony_ci		channel->pdata = pdata;
2598c2ecf20Sopenharmony_ci		channel->queue_index = i;
2608c2ecf20Sopenharmony_ci		channel->dma_regs = pdata->mac_regs + DMA_CH_BASE +
2618c2ecf20Sopenharmony_ci				    (DMA_CH_INC * i);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci		if (pdata->per_channel_irq) {
2648c2ecf20Sopenharmony_ci			/* Get the per DMA interrupt */
2658c2ecf20Sopenharmony_ci			ret = pdata->channel_irq[i];
2668c2ecf20Sopenharmony_ci			if (ret < 0) {
2678c2ecf20Sopenharmony_ci				netdev_err(pdata->netdev,
2688c2ecf20Sopenharmony_ci					   "get_irq %u failed\n",
2698c2ecf20Sopenharmony_ci					   i + 1);
2708c2ecf20Sopenharmony_ci				goto err_irq;
2718c2ecf20Sopenharmony_ci			}
2728c2ecf20Sopenharmony_ci			channel->dma_irq = ret;
2738c2ecf20Sopenharmony_ci		}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci		if (i < pdata->tx_ring_count)
2768c2ecf20Sopenharmony_ci			channel->tx_ring = tx_ring++;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci		if (i < pdata->rx_ring_count)
2798c2ecf20Sopenharmony_ci			channel->rx_ring = rx_ring++;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci		netif_dbg(pdata, drv, pdata->netdev,
2828c2ecf20Sopenharmony_ci			  "%s: dma_regs=%p, tx_ring=%p, rx_ring=%p\n",
2838c2ecf20Sopenharmony_ci			  channel->name, channel->dma_regs,
2848c2ecf20Sopenharmony_ci			  channel->tx_ring, channel->rx_ring);
2858c2ecf20Sopenharmony_ci	}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	pdata->channel_head = channel_head;
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	return 0;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_cierr_irq:
2928c2ecf20Sopenharmony_ci	kfree(rx_ring);
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_cierr_rx_ring:
2958c2ecf20Sopenharmony_ci	kfree(tx_ring);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_cierr_tx_ring:
2988c2ecf20Sopenharmony_ci	kfree(channel_head);
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	return ret;
3018c2ecf20Sopenharmony_ci}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_cistatic void xlgmac_free_channels_and_rings(struct xlgmac_pdata *pdata)
3048c2ecf20Sopenharmony_ci{
3058c2ecf20Sopenharmony_ci	xlgmac_free_rings(pdata);
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	xlgmac_free_channels(pdata);
3088c2ecf20Sopenharmony_ci}
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_cistatic int xlgmac_alloc_channels_and_rings(struct xlgmac_pdata *pdata)
3118c2ecf20Sopenharmony_ci{
3128c2ecf20Sopenharmony_ci	int ret;
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	ret = xlgmac_alloc_channels(pdata);
3158c2ecf20Sopenharmony_ci	if (ret)
3168c2ecf20Sopenharmony_ci		goto err_alloc;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	ret = xlgmac_alloc_rings(pdata);
3198c2ecf20Sopenharmony_ci	if (ret)
3208c2ecf20Sopenharmony_ci		goto err_alloc;
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	return 0;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_cierr_alloc:
3258c2ecf20Sopenharmony_ci	xlgmac_free_channels_and_rings(pdata);
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	return ret;
3288c2ecf20Sopenharmony_ci}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_cistatic int xlgmac_alloc_pages(struct xlgmac_pdata *pdata,
3318c2ecf20Sopenharmony_ci			      struct xlgmac_page_alloc *pa,
3328c2ecf20Sopenharmony_ci			      gfp_t gfp, int order)
3338c2ecf20Sopenharmony_ci{
3348c2ecf20Sopenharmony_ci	struct page *pages = NULL;
3358c2ecf20Sopenharmony_ci	dma_addr_t pages_dma;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	/* Try to obtain pages, decreasing order if necessary */
3388c2ecf20Sopenharmony_ci	gfp |= __GFP_COMP | __GFP_NOWARN;
3398c2ecf20Sopenharmony_ci	while (order >= 0) {
3408c2ecf20Sopenharmony_ci		pages = alloc_pages(gfp, order);
3418c2ecf20Sopenharmony_ci		if (pages)
3428c2ecf20Sopenharmony_ci			break;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci		order--;
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_ci	if (!pages)
3478c2ecf20Sopenharmony_ci		return -ENOMEM;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	/* Map the pages */
3508c2ecf20Sopenharmony_ci	pages_dma = dma_map_page(pdata->dev, pages, 0,
3518c2ecf20Sopenharmony_ci				 PAGE_SIZE << order, DMA_FROM_DEVICE);
3528c2ecf20Sopenharmony_ci	if (dma_mapping_error(pdata->dev, pages_dma)) {
3538c2ecf20Sopenharmony_ci		put_page(pages);
3548c2ecf20Sopenharmony_ci		return -ENOMEM;
3558c2ecf20Sopenharmony_ci	}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	pa->pages = pages;
3588c2ecf20Sopenharmony_ci	pa->pages_len = PAGE_SIZE << order;
3598c2ecf20Sopenharmony_ci	pa->pages_offset = 0;
3608c2ecf20Sopenharmony_ci	pa->pages_dma = pages_dma;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	return 0;
3638c2ecf20Sopenharmony_ci}
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_cistatic void xlgmac_set_buffer_data(struct xlgmac_buffer_data *bd,
3668c2ecf20Sopenharmony_ci				   struct xlgmac_page_alloc *pa,
3678c2ecf20Sopenharmony_ci				   unsigned int len)
3688c2ecf20Sopenharmony_ci{
3698c2ecf20Sopenharmony_ci	get_page(pa->pages);
3708c2ecf20Sopenharmony_ci	bd->pa = *pa;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	bd->dma_base = pa->pages_dma;
3738c2ecf20Sopenharmony_ci	bd->dma_off = pa->pages_offset;
3748c2ecf20Sopenharmony_ci	bd->dma_len = len;
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	pa->pages_offset += len;
3778c2ecf20Sopenharmony_ci	if ((pa->pages_offset + len) > pa->pages_len) {
3788c2ecf20Sopenharmony_ci		/* This data descriptor is responsible for unmapping page(s) */
3798c2ecf20Sopenharmony_ci		bd->pa_unmap = *pa;
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci		/* Get a new allocation next time */
3828c2ecf20Sopenharmony_ci		pa->pages = NULL;
3838c2ecf20Sopenharmony_ci		pa->pages_len = 0;
3848c2ecf20Sopenharmony_ci		pa->pages_offset = 0;
3858c2ecf20Sopenharmony_ci		pa->pages_dma = 0;
3868c2ecf20Sopenharmony_ci	}
3878c2ecf20Sopenharmony_ci}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_cistatic int xlgmac_map_rx_buffer(struct xlgmac_pdata *pdata,
3908c2ecf20Sopenharmony_ci				struct xlgmac_ring *ring,
3918c2ecf20Sopenharmony_ci				struct xlgmac_desc_data *desc_data)
3928c2ecf20Sopenharmony_ci{
3938c2ecf20Sopenharmony_ci	int order, ret;
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	if (!ring->rx_hdr_pa.pages) {
3968c2ecf20Sopenharmony_ci		ret = xlgmac_alloc_pages(pdata, &ring->rx_hdr_pa,
3978c2ecf20Sopenharmony_ci					 GFP_ATOMIC, 0);
3988c2ecf20Sopenharmony_ci		if (ret)
3998c2ecf20Sopenharmony_ci			return ret;
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	if (!ring->rx_buf_pa.pages) {
4038c2ecf20Sopenharmony_ci		order = max_t(int, PAGE_ALLOC_COSTLY_ORDER - 1, 0);
4048c2ecf20Sopenharmony_ci		ret = xlgmac_alloc_pages(pdata, &ring->rx_buf_pa,
4058c2ecf20Sopenharmony_ci					 GFP_ATOMIC, order);
4068c2ecf20Sopenharmony_ci		if (ret)
4078c2ecf20Sopenharmony_ci			return ret;
4088c2ecf20Sopenharmony_ci	}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	/* Set up the header page info */
4118c2ecf20Sopenharmony_ci	xlgmac_set_buffer_data(&desc_data->rx.hdr, &ring->rx_hdr_pa,
4128c2ecf20Sopenharmony_ci			       XLGMAC_SKB_ALLOC_SIZE);
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	/* Set up the buffer page info */
4158c2ecf20Sopenharmony_ci	xlgmac_set_buffer_data(&desc_data->rx.buf, &ring->rx_buf_pa,
4168c2ecf20Sopenharmony_ci			       pdata->rx_buf_size);
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	return 0;
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_cistatic void xlgmac_tx_desc_init(struct xlgmac_pdata *pdata)
4228c2ecf20Sopenharmony_ci{
4238c2ecf20Sopenharmony_ci	struct xlgmac_hw_ops *hw_ops = &pdata->hw_ops;
4248c2ecf20Sopenharmony_ci	struct xlgmac_desc_data *desc_data;
4258c2ecf20Sopenharmony_ci	struct xlgmac_dma_desc *dma_desc;
4268c2ecf20Sopenharmony_ci	struct xlgmac_channel *channel;
4278c2ecf20Sopenharmony_ci	struct xlgmac_ring *ring;
4288c2ecf20Sopenharmony_ci	dma_addr_t dma_desc_addr;
4298c2ecf20Sopenharmony_ci	unsigned int i, j;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	channel = pdata->channel_head;
4328c2ecf20Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
4338c2ecf20Sopenharmony_ci		ring = channel->tx_ring;
4348c2ecf20Sopenharmony_ci		if (!ring)
4358c2ecf20Sopenharmony_ci			break;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci		dma_desc = ring->dma_desc_head;
4388c2ecf20Sopenharmony_ci		dma_desc_addr = ring->dma_desc_head_addr;
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci		for (j = 0; j < ring->dma_desc_count; j++) {
4418c2ecf20Sopenharmony_ci			desc_data = XLGMAC_GET_DESC_DATA(ring, j);
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci			desc_data->dma_desc = dma_desc;
4448c2ecf20Sopenharmony_ci			desc_data->dma_desc_addr = dma_desc_addr;
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci			dma_desc++;
4478c2ecf20Sopenharmony_ci			dma_desc_addr += sizeof(struct xlgmac_dma_desc);
4488c2ecf20Sopenharmony_ci		}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci		ring->cur = 0;
4518c2ecf20Sopenharmony_ci		ring->dirty = 0;
4528c2ecf20Sopenharmony_ci		memset(&ring->tx, 0, sizeof(ring->tx));
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci		hw_ops->tx_desc_init(channel);
4558c2ecf20Sopenharmony_ci	}
4568c2ecf20Sopenharmony_ci}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_cistatic void xlgmac_rx_desc_init(struct xlgmac_pdata *pdata)
4598c2ecf20Sopenharmony_ci{
4608c2ecf20Sopenharmony_ci	struct xlgmac_hw_ops *hw_ops = &pdata->hw_ops;
4618c2ecf20Sopenharmony_ci	struct xlgmac_desc_data *desc_data;
4628c2ecf20Sopenharmony_ci	struct xlgmac_dma_desc *dma_desc;
4638c2ecf20Sopenharmony_ci	struct xlgmac_channel *channel;
4648c2ecf20Sopenharmony_ci	struct xlgmac_ring *ring;
4658c2ecf20Sopenharmony_ci	dma_addr_t dma_desc_addr;
4668c2ecf20Sopenharmony_ci	unsigned int i, j;
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	channel = pdata->channel_head;
4698c2ecf20Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
4708c2ecf20Sopenharmony_ci		ring = channel->rx_ring;
4718c2ecf20Sopenharmony_ci		if (!ring)
4728c2ecf20Sopenharmony_ci			break;
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci		dma_desc = ring->dma_desc_head;
4758c2ecf20Sopenharmony_ci		dma_desc_addr = ring->dma_desc_head_addr;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci		for (j = 0; j < ring->dma_desc_count; j++) {
4788c2ecf20Sopenharmony_ci			desc_data = XLGMAC_GET_DESC_DATA(ring, j);
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci			desc_data->dma_desc = dma_desc;
4818c2ecf20Sopenharmony_ci			desc_data->dma_desc_addr = dma_desc_addr;
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci			if (xlgmac_map_rx_buffer(pdata, ring, desc_data))
4848c2ecf20Sopenharmony_ci				break;
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci			dma_desc++;
4878c2ecf20Sopenharmony_ci			dma_desc_addr += sizeof(struct xlgmac_dma_desc);
4888c2ecf20Sopenharmony_ci		}
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci		ring->cur = 0;
4918c2ecf20Sopenharmony_ci		ring->dirty = 0;
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci		hw_ops->rx_desc_init(channel);
4948c2ecf20Sopenharmony_ci	}
4958c2ecf20Sopenharmony_ci}
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_cistatic int xlgmac_map_tx_skb(struct xlgmac_channel *channel,
4988c2ecf20Sopenharmony_ci			     struct sk_buff *skb)
4998c2ecf20Sopenharmony_ci{
5008c2ecf20Sopenharmony_ci	struct xlgmac_pdata *pdata = channel->pdata;
5018c2ecf20Sopenharmony_ci	struct xlgmac_ring *ring = channel->tx_ring;
5028c2ecf20Sopenharmony_ci	unsigned int start_index, cur_index;
5038c2ecf20Sopenharmony_ci	struct xlgmac_desc_data *desc_data;
5048c2ecf20Sopenharmony_ci	unsigned int offset, datalen, len;
5058c2ecf20Sopenharmony_ci	struct xlgmac_pkt_info *pkt_info;
5068c2ecf20Sopenharmony_ci	skb_frag_t *frag;
5078c2ecf20Sopenharmony_ci	unsigned int tso, vlan;
5088c2ecf20Sopenharmony_ci	dma_addr_t skb_dma;
5098c2ecf20Sopenharmony_ci	unsigned int i;
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	offset = 0;
5128c2ecf20Sopenharmony_ci	start_index = ring->cur;
5138c2ecf20Sopenharmony_ci	cur_index = ring->cur;
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	pkt_info = &ring->pkt_info;
5168c2ecf20Sopenharmony_ci	pkt_info->desc_count = 0;
5178c2ecf20Sopenharmony_ci	pkt_info->length = 0;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	tso = XLGMAC_GET_REG_BITS(pkt_info->attributes,
5208c2ecf20Sopenharmony_ci				  TX_PACKET_ATTRIBUTES_TSO_ENABLE_POS,
5218c2ecf20Sopenharmony_ci				  TX_PACKET_ATTRIBUTES_TSO_ENABLE_LEN);
5228c2ecf20Sopenharmony_ci	vlan = XLGMAC_GET_REG_BITS(pkt_info->attributes,
5238c2ecf20Sopenharmony_ci				   TX_PACKET_ATTRIBUTES_VLAN_CTAG_POS,
5248c2ecf20Sopenharmony_ci				   TX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN);
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	/* Save space for a context descriptor if needed */
5278c2ecf20Sopenharmony_ci	if ((tso && (pkt_info->mss != ring->tx.cur_mss)) ||
5288c2ecf20Sopenharmony_ci	    (vlan && (pkt_info->vlan_ctag != ring->tx.cur_vlan_ctag)))
5298c2ecf20Sopenharmony_ci		cur_index++;
5308c2ecf20Sopenharmony_ci	desc_data = XLGMAC_GET_DESC_DATA(ring, cur_index);
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	if (tso) {
5338c2ecf20Sopenharmony_ci		/* Map the TSO header */
5348c2ecf20Sopenharmony_ci		skb_dma = dma_map_single(pdata->dev, skb->data,
5358c2ecf20Sopenharmony_ci					 pkt_info->header_len, DMA_TO_DEVICE);
5368c2ecf20Sopenharmony_ci		if (dma_mapping_error(pdata->dev, skb_dma)) {
5378c2ecf20Sopenharmony_ci			netdev_alert(pdata->netdev, "dma_map_single failed\n");
5388c2ecf20Sopenharmony_ci			goto err_out;
5398c2ecf20Sopenharmony_ci		}
5408c2ecf20Sopenharmony_ci		desc_data->skb_dma = skb_dma;
5418c2ecf20Sopenharmony_ci		desc_data->skb_dma_len = pkt_info->header_len;
5428c2ecf20Sopenharmony_ci		netif_dbg(pdata, tx_queued, pdata->netdev,
5438c2ecf20Sopenharmony_ci			  "skb header: index=%u, dma=%pad, len=%u\n",
5448c2ecf20Sopenharmony_ci			  cur_index, &skb_dma, pkt_info->header_len);
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci		offset = pkt_info->header_len;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci		pkt_info->length += pkt_info->header_len;
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci		cur_index++;
5518c2ecf20Sopenharmony_ci		desc_data = XLGMAC_GET_DESC_DATA(ring, cur_index);
5528c2ecf20Sopenharmony_ci	}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	/* Map the (remainder of the) packet */
5558c2ecf20Sopenharmony_ci	for (datalen = skb_headlen(skb) - offset; datalen; ) {
5568c2ecf20Sopenharmony_ci		len = min_t(unsigned int, datalen, XLGMAC_TX_MAX_BUF_SIZE);
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci		skb_dma = dma_map_single(pdata->dev, skb->data + offset, len,
5598c2ecf20Sopenharmony_ci					 DMA_TO_DEVICE);
5608c2ecf20Sopenharmony_ci		if (dma_mapping_error(pdata->dev, skb_dma)) {
5618c2ecf20Sopenharmony_ci			netdev_alert(pdata->netdev, "dma_map_single failed\n");
5628c2ecf20Sopenharmony_ci			goto err_out;
5638c2ecf20Sopenharmony_ci		}
5648c2ecf20Sopenharmony_ci		desc_data->skb_dma = skb_dma;
5658c2ecf20Sopenharmony_ci		desc_data->skb_dma_len = len;
5668c2ecf20Sopenharmony_ci		netif_dbg(pdata, tx_queued, pdata->netdev,
5678c2ecf20Sopenharmony_ci			  "skb data: index=%u, dma=%pad, len=%u\n",
5688c2ecf20Sopenharmony_ci			  cur_index, &skb_dma, len);
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci		datalen -= len;
5718c2ecf20Sopenharmony_ci		offset += len;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci		pkt_info->length += len;
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci		cur_index++;
5768c2ecf20Sopenharmony_ci		desc_data = XLGMAC_GET_DESC_DATA(ring, cur_index);
5778c2ecf20Sopenharmony_ci	}
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
5808c2ecf20Sopenharmony_ci		netif_dbg(pdata, tx_queued, pdata->netdev,
5818c2ecf20Sopenharmony_ci			  "mapping frag %u\n", i);
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci		frag = &skb_shinfo(skb)->frags[i];
5848c2ecf20Sopenharmony_ci		offset = 0;
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci		for (datalen = skb_frag_size(frag); datalen; ) {
5878c2ecf20Sopenharmony_ci			len = min_t(unsigned int, datalen,
5888c2ecf20Sopenharmony_ci				    XLGMAC_TX_MAX_BUF_SIZE);
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci			skb_dma = skb_frag_dma_map(pdata->dev, frag, offset,
5918c2ecf20Sopenharmony_ci						   len, DMA_TO_DEVICE);
5928c2ecf20Sopenharmony_ci			if (dma_mapping_error(pdata->dev, skb_dma)) {
5938c2ecf20Sopenharmony_ci				netdev_alert(pdata->netdev,
5948c2ecf20Sopenharmony_ci					     "skb_frag_dma_map failed\n");
5958c2ecf20Sopenharmony_ci				goto err_out;
5968c2ecf20Sopenharmony_ci			}
5978c2ecf20Sopenharmony_ci			desc_data->skb_dma = skb_dma;
5988c2ecf20Sopenharmony_ci			desc_data->skb_dma_len = len;
5998c2ecf20Sopenharmony_ci			desc_data->mapped_as_page = 1;
6008c2ecf20Sopenharmony_ci			netif_dbg(pdata, tx_queued, pdata->netdev,
6018c2ecf20Sopenharmony_ci				  "skb frag: index=%u, dma=%pad, len=%u\n",
6028c2ecf20Sopenharmony_ci				  cur_index, &skb_dma, len);
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci			datalen -= len;
6058c2ecf20Sopenharmony_ci			offset += len;
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci			pkt_info->length += len;
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci			cur_index++;
6108c2ecf20Sopenharmony_ci			desc_data = XLGMAC_GET_DESC_DATA(ring, cur_index);
6118c2ecf20Sopenharmony_ci		}
6128c2ecf20Sopenharmony_ci	}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	/* Save the skb address in the last entry. We always have some data
6158c2ecf20Sopenharmony_ci	 * that has been mapped so desc_data is always advanced past the last
6168c2ecf20Sopenharmony_ci	 * piece of mapped data - use the entry pointed to by cur_index - 1.
6178c2ecf20Sopenharmony_ci	 */
6188c2ecf20Sopenharmony_ci	desc_data = XLGMAC_GET_DESC_DATA(ring, cur_index - 1);
6198c2ecf20Sopenharmony_ci	desc_data->skb = skb;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	/* Save the number of descriptor entries used */
6228c2ecf20Sopenharmony_ci	pkt_info->desc_count = cur_index - start_index;
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	return pkt_info->desc_count;
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_cierr_out:
6278c2ecf20Sopenharmony_ci	while (start_index < cur_index) {
6288c2ecf20Sopenharmony_ci		desc_data = XLGMAC_GET_DESC_DATA(ring, start_index++);
6298c2ecf20Sopenharmony_ci		xlgmac_unmap_desc_data(pdata, desc_data);
6308c2ecf20Sopenharmony_ci	}
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	return 0;
6338c2ecf20Sopenharmony_ci}
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_civoid xlgmac_init_desc_ops(struct xlgmac_desc_ops *desc_ops)
6368c2ecf20Sopenharmony_ci{
6378c2ecf20Sopenharmony_ci	desc_ops->alloc_channles_and_rings = xlgmac_alloc_channels_and_rings;
6388c2ecf20Sopenharmony_ci	desc_ops->free_channels_and_rings = xlgmac_free_channels_and_rings;
6398c2ecf20Sopenharmony_ci	desc_ops->map_tx_skb = xlgmac_map_tx_skb;
6408c2ecf20Sopenharmony_ci	desc_ops->map_rx_buffer = xlgmac_map_rx_buffer;
6418c2ecf20Sopenharmony_ci	desc_ops->unmap_desc_data = xlgmac_unmap_desc_data;
6428c2ecf20Sopenharmony_ci	desc_ops->tx_desc_init = xlgmac_tx_desc_init;
6438c2ecf20Sopenharmony_ci	desc_ops->rx_desc_init = xlgmac_rx_desc_init;
6448c2ecf20Sopenharmony_ci}
645