brintos

brintos / linux-shallow public Read only

0
0
Text · 5.6 KiB · 3f0d9f7 Raw
229 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright Sunplus Technology Co., Ltd.3 *       All rights reserved.4 */5 6#include <linux/platform_device.h>7#include <linux/netdevice.h>8#include <linux/of_mdio.h>9 10#include "spl2sw_define.h"11#include "spl2sw_desc.h"12 13void spl2sw_rx_descs_flush(struct spl2sw_common *comm)14{15	struct spl2sw_skb_info *rx_skbinfo;16	struct spl2sw_mac_desc *rx_desc;17	u32 i, j;18 19	for (i = 0; i < RX_DESC_QUEUE_NUM; i++) {20		rx_desc = comm->rx_desc[i];21		rx_skbinfo = comm->rx_skb_info[i];22		for (j = 0; j < comm->rx_desc_num[i]; j++) {23			rx_desc[j].addr1 = rx_skbinfo[j].mapping;24			rx_desc[j].cmd2 = (j == comm->rx_desc_num[i] - 1) ?25					  RXD_EOR | comm->rx_desc_buff_size :26					  comm->rx_desc_buff_size;27			wmb();	/* Set RXD_OWN after other fields are ready. */28			rx_desc[j].cmd1 = RXD_OWN;29		}30	}31}32 33void spl2sw_tx_descs_clean(struct spl2sw_common *comm)34{35	u32 i;36 37	if (!comm->tx_desc)38		return;39 40	for (i = 0; i < TX_DESC_NUM; i++) {41		comm->tx_desc[i].cmd1 = 0;42		wmb();	/* Clear TXD_OWN and then set other fields. */43		comm->tx_desc[i].cmd2 = 0;44		comm->tx_desc[i].addr1 = 0;45		comm->tx_desc[i].addr2 = 0;46 47		if (comm->tx_temp_skb_info[i].mapping) {48			dma_unmap_single(&comm->pdev->dev, comm->tx_temp_skb_info[i].mapping,49					 comm->tx_temp_skb_info[i].skb->len, DMA_TO_DEVICE);50			comm->tx_temp_skb_info[i].mapping = 0;51		}52 53		if (comm->tx_temp_skb_info[i].skb) {54			dev_kfree_skb_any(comm->tx_temp_skb_info[i].skb);55			comm->tx_temp_skb_info[i].skb = NULL;56		}57	}58}59 60void spl2sw_rx_descs_clean(struct spl2sw_common *comm)61{62	struct spl2sw_skb_info *rx_skbinfo;63	struct spl2sw_mac_desc *rx_desc;64	u32 i, j;65 66	for (i = 0; i < RX_DESC_QUEUE_NUM; i++) {67		if (!comm->rx_skb_info[i])68			continue;69 70		rx_desc = comm->rx_desc[i];71		rx_skbinfo = comm->rx_skb_info[i];72		for (j = 0; j < comm->rx_desc_num[i]; j++) {73			rx_desc[j].cmd1 = 0;74			wmb();	/* Clear RXD_OWN and then set other fields. */75			rx_desc[j].cmd2 = 0;76			rx_desc[j].addr1 = 0;77 78			if (rx_skbinfo[j].skb) {79				dma_unmap_single(&comm->pdev->dev, rx_skbinfo[j].mapping,80						 comm->rx_desc_buff_size, DMA_FROM_DEVICE);81				dev_kfree_skb_any(rx_skbinfo[j].skb);82				rx_skbinfo[j].skb = NULL;83				rx_skbinfo[j].mapping = 0;84			}85		}86 87		kfree(rx_skbinfo);88		comm->rx_skb_info[i] = NULL;89	}90}91 92void spl2sw_descs_clean(struct spl2sw_common *comm)93{94	spl2sw_rx_descs_clean(comm);95	spl2sw_tx_descs_clean(comm);96}97 98void spl2sw_descs_free(struct spl2sw_common *comm)99{100	u32 i;101 102	spl2sw_descs_clean(comm);103	comm->tx_desc = NULL;104	for (i = 0; i < RX_DESC_QUEUE_NUM; i++)105		comm->rx_desc[i] = NULL;106 107	/*  Free descriptor area  */108	if (comm->desc_base) {109		dma_free_coherent(&comm->pdev->dev, comm->desc_size, comm->desc_base,110				  comm->desc_dma);111		comm->desc_base = NULL;112		comm->desc_dma = 0;113		comm->desc_size = 0;114	}115}116 117void spl2sw_tx_descs_init(struct spl2sw_common *comm)118{119	memset(comm->tx_desc, '\0', sizeof(struct spl2sw_mac_desc) *120	       (TX_DESC_NUM + MAC_GUARD_DESC_NUM));121}122 123int spl2sw_rx_descs_init(struct spl2sw_common *comm)124{125	struct spl2sw_skb_info *rx_skbinfo;126	struct spl2sw_mac_desc *rx_desc;127	struct sk_buff *skb;128	u32 mapping;129	u32 i, j;130 131	for (i = 0; i < RX_DESC_QUEUE_NUM; i++) {132		comm->rx_skb_info[i] = kcalloc(comm->rx_desc_num[i], sizeof(*rx_skbinfo),133					       GFP_KERNEL | GFP_DMA);134		if (!comm->rx_skb_info[i])135			goto mem_alloc_fail;136 137		rx_skbinfo = comm->rx_skb_info[i];138		rx_desc = comm->rx_desc[i];139		for (j = 0; j < comm->rx_desc_num[i]; j++) {140			skb = netdev_alloc_skb(NULL, comm->rx_desc_buff_size);141			if (!skb)142				goto mem_alloc_fail;143 144			rx_skbinfo[j].skb = skb;145			mapping = dma_map_single(&comm->pdev->dev, skb->data,146						 comm->rx_desc_buff_size,147						 DMA_FROM_DEVICE);148			if (dma_mapping_error(&comm->pdev->dev, mapping))149				goto mem_alloc_fail;150 151			rx_skbinfo[j].mapping = mapping;152			rx_desc[j].addr1 = mapping;153			rx_desc[j].addr2 = 0;154			rx_desc[j].cmd2 = (j == comm->rx_desc_num[i] - 1) ?155					  RXD_EOR | comm->rx_desc_buff_size :156					  comm->rx_desc_buff_size;157			wmb();	/* Set RXD_OWN after other fields are effective. */158			rx_desc[j].cmd1 = RXD_OWN;159		}160	}161 162	return 0;163 164mem_alloc_fail:165	spl2sw_rx_descs_clean(comm);166	return -ENOMEM;167}168 169int spl2sw_descs_alloc(struct spl2sw_common *comm)170{171	s32 desc_size;172	u32 i;173 174	/* Alloc descriptor area  */175	desc_size = (TX_DESC_NUM + MAC_GUARD_DESC_NUM) * sizeof(struct spl2sw_mac_desc);176	for (i = 0; i < RX_DESC_QUEUE_NUM; i++)177		desc_size += comm->rx_desc_num[i] * sizeof(struct spl2sw_mac_desc);178 179	comm->desc_base = dma_alloc_coherent(&comm->pdev->dev, desc_size, &comm->desc_dma,180					     GFP_KERNEL);181	if (!comm->desc_base)182		return -ENOMEM;183 184	comm->desc_size = desc_size;185 186	/* Setup Tx descriptor */187	comm->tx_desc = comm->desc_base;188 189	/* Setup Rx descriptor */190	comm->rx_desc[0] = &comm->tx_desc[TX_DESC_NUM + MAC_GUARD_DESC_NUM];191	for (i = 1; i < RX_DESC_QUEUE_NUM; i++)192		comm->rx_desc[i] = comm->rx_desc[i - 1] + comm->rx_desc_num[i - 1];193 194	return 0;195}196 197int spl2sw_descs_init(struct spl2sw_common *comm)198{199	u32 i, ret;200 201	/* Initialize rx descriptor's data */202	comm->rx_desc_num[0] = RX_QUEUE0_DESC_NUM;203	comm->rx_desc_num[1] = RX_QUEUE1_DESC_NUM;204 205	for (i = 0; i < RX_DESC_QUEUE_NUM; i++) {206		comm->rx_desc[i] = NULL;207		comm->rx_skb_info[i] = NULL;208		comm->rx_pos[i] = 0;209	}210	comm->rx_desc_buff_size = MAC_RX_LEN_MAX;211 212	/* Initialize tx descriptor's data */213	comm->tx_done_pos = 0;214	comm->tx_desc = NULL;215	comm->tx_pos = 0;216	comm->tx_desc_full = 0;217	for (i = 0; i < TX_DESC_NUM; i++)218		comm->tx_temp_skb_info[i].skb = NULL;219 220	/* Allocate tx & rx descriptors. */221	ret = spl2sw_descs_alloc(comm);222	if (ret)223		return ret;224 225	spl2sw_tx_descs_init(comm);226 227	return spl2sw_rx_descs_init(comm);228}229