1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
20c6bd470Sfengbojiang * Copyright 2018-2020 NXP
3d30ea906Sjfb8856606 */
4d30ea906Sjfb8856606
5d30ea906Sjfb8856606 #include <stdbool.h>
6d30ea906Sjfb8856606 #include <rte_ethdev_pci.h>
74418919fSjohnjiang #include <rte_random.h>
84418919fSjohnjiang #include <dpaax_iova_table.h>
9d30ea906Sjfb8856606
10d30ea906Sjfb8856606 #include "enetc_logs.h"
11d30ea906Sjfb8856606 #include "enetc.h"
12d30ea906Sjfb8856606
13d30ea906Sjfb8856606 static int
enetc_dev_start(struct rte_eth_dev * dev)14d30ea906Sjfb8856606 enetc_dev_start(struct rte_eth_dev *dev)
15d30ea906Sjfb8856606 {
16d30ea906Sjfb8856606 struct enetc_eth_hw *hw =
17d30ea906Sjfb8856606 ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
184418919fSjohnjiang struct enetc_hw *enetc_hw = &hw->hw;
19d30ea906Sjfb8856606 uint32_t val;
20d30ea906Sjfb8856606
21d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE();
224418919fSjohnjiang val = enetc_port_rd(enetc_hw, ENETC_PM0_CMD_CFG);
234418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PM0_CMD_CFG,
24d30ea906Sjfb8856606 val | ENETC_PM0_TX_EN | ENETC_PM0_RX_EN);
25d30ea906Sjfb8856606
26d30ea906Sjfb8856606 /* Enable port */
274418919fSjohnjiang val = enetc_port_rd(enetc_hw, ENETC_PMR);
284418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PMR, val | ENETC_PMR_EN);
294418919fSjohnjiang
304418919fSjohnjiang /* set auto-speed for RGMII */
314418919fSjohnjiang if (enetc_port_rd(enetc_hw, ENETC_PM0_IF_MODE) & ENETC_PMO_IFM_RG) {
324418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PM0_IF_MODE,
334418919fSjohnjiang ENETC_PM0_IFM_RGAUTO);
344418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PM1_IF_MODE,
354418919fSjohnjiang ENETC_PM0_IFM_RGAUTO);
364418919fSjohnjiang }
374418919fSjohnjiang if (enetc_global_rd(enetc_hw,
384418919fSjohnjiang ENETC_G_EPFBLPR(1)) == ENETC_G_EPFBLPR1_XGMII) {
394418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PM0_IF_MODE,
404418919fSjohnjiang ENETC_PM0_IFM_XGMII);
414418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PM1_IF_MODE,
424418919fSjohnjiang ENETC_PM0_IFM_XGMII);
434418919fSjohnjiang }
44d30ea906Sjfb8856606
45d30ea906Sjfb8856606 return 0;
46d30ea906Sjfb8856606 }
47d30ea906Sjfb8856606
48*2d9fd380Sjfb8856606 static int
enetc_dev_stop(struct rte_eth_dev * dev)49d30ea906Sjfb8856606 enetc_dev_stop(struct rte_eth_dev *dev)
50d30ea906Sjfb8856606 {
51d30ea906Sjfb8856606 struct enetc_eth_hw *hw =
52d30ea906Sjfb8856606 ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
534418919fSjohnjiang struct enetc_hw *enetc_hw = &hw->hw;
54d30ea906Sjfb8856606 uint32_t val;
55d30ea906Sjfb8856606
56d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE();
57*2d9fd380Sjfb8856606 dev->data->dev_started = 0;
58d30ea906Sjfb8856606 /* Disable port */
594418919fSjohnjiang val = enetc_port_rd(enetc_hw, ENETC_PMR);
604418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PMR, val & (~ENETC_PMR_EN));
61d30ea906Sjfb8856606
624418919fSjohnjiang val = enetc_port_rd(enetc_hw, ENETC_PM0_CMD_CFG);
634418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PM0_CMD_CFG,
64d30ea906Sjfb8856606 val & (~(ENETC_PM0_TX_EN | ENETC_PM0_RX_EN)));
65*2d9fd380Sjfb8856606
66*2d9fd380Sjfb8856606 return 0;
67d30ea906Sjfb8856606 }
68d30ea906Sjfb8856606
69d30ea906Sjfb8856606 static const uint32_t *
enetc_supported_ptypes_get(struct rte_eth_dev * dev __rte_unused)70d30ea906Sjfb8856606 enetc_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
71d30ea906Sjfb8856606 {
72d30ea906Sjfb8856606 static const uint32_t ptypes[] = {
73d30ea906Sjfb8856606 RTE_PTYPE_L2_ETHER,
74d30ea906Sjfb8856606 RTE_PTYPE_L3_IPV4,
75d30ea906Sjfb8856606 RTE_PTYPE_L3_IPV6,
76d30ea906Sjfb8856606 RTE_PTYPE_L4_TCP,
77d30ea906Sjfb8856606 RTE_PTYPE_L4_UDP,
78d30ea906Sjfb8856606 RTE_PTYPE_L4_SCTP,
79d30ea906Sjfb8856606 RTE_PTYPE_L4_ICMP,
80d30ea906Sjfb8856606 RTE_PTYPE_UNKNOWN
81d30ea906Sjfb8856606 };
82d30ea906Sjfb8856606
83d30ea906Sjfb8856606 return ptypes;
84d30ea906Sjfb8856606 }
85d30ea906Sjfb8856606
86d30ea906Sjfb8856606 /* return 0 means link status changed, -1 means not changed */
87d30ea906Sjfb8856606 static int
enetc_link_update(struct rte_eth_dev * dev,int wait_to_complete __rte_unused)88d30ea906Sjfb8856606 enetc_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
89d30ea906Sjfb8856606 {
90d30ea906Sjfb8856606 struct enetc_eth_hw *hw =
91d30ea906Sjfb8856606 ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
924418919fSjohnjiang struct enetc_hw *enetc_hw = &hw->hw;
93d30ea906Sjfb8856606 struct rte_eth_link link;
94d30ea906Sjfb8856606 uint32_t status;
95d30ea906Sjfb8856606
96d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE();
97d30ea906Sjfb8856606
98d30ea906Sjfb8856606 memset(&link, 0, sizeof(link));
99d30ea906Sjfb8856606
1004418919fSjohnjiang status = enetc_port_rd(enetc_hw, ENETC_PM0_STATUS);
101d30ea906Sjfb8856606
102d30ea906Sjfb8856606 if (status & ENETC_LINK_MODE)
103d30ea906Sjfb8856606 link.link_duplex = ETH_LINK_FULL_DUPLEX;
104d30ea906Sjfb8856606 else
105d30ea906Sjfb8856606 link.link_duplex = ETH_LINK_HALF_DUPLEX;
106d30ea906Sjfb8856606
107d30ea906Sjfb8856606 if (status & ENETC_LINK_STATUS)
108d30ea906Sjfb8856606 link.link_status = ETH_LINK_UP;
109d30ea906Sjfb8856606 else
110d30ea906Sjfb8856606 link.link_status = ETH_LINK_DOWN;
111d30ea906Sjfb8856606
112d30ea906Sjfb8856606 switch (status & ENETC_LINK_SPEED_MASK) {
113d30ea906Sjfb8856606 case ENETC_LINK_SPEED_1G:
114d30ea906Sjfb8856606 link.link_speed = ETH_SPEED_NUM_1G;
115d30ea906Sjfb8856606 break;
116d30ea906Sjfb8856606
117d30ea906Sjfb8856606 case ENETC_LINK_SPEED_100M:
118d30ea906Sjfb8856606 link.link_speed = ETH_SPEED_NUM_100M;
119d30ea906Sjfb8856606 break;
120d30ea906Sjfb8856606
121d30ea906Sjfb8856606 default:
122d30ea906Sjfb8856606 case ENETC_LINK_SPEED_10M:
123d30ea906Sjfb8856606 link.link_speed = ETH_SPEED_NUM_10M;
124d30ea906Sjfb8856606 }
125d30ea906Sjfb8856606
126d30ea906Sjfb8856606 return rte_eth_linkstatus_set(dev, &link);
127d30ea906Sjfb8856606 }
128d30ea906Sjfb8856606
1294418919fSjohnjiang static void
print_ethaddr(const char * name,const struct rte_ether_addr * eth_addr)1304418919fSjohnjiang print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr)
1314418919fSjohnjiang {
1324418919fSjohnjiang char buf[RTE_ETHER_ADDR_FMT_SIZE];
1334418919fSjohnjiang
1344418919fSjohnjiang rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
1354418919fSjohnjiang ENETC_PMD_NOTICE("%s%s\n", name, buf);
1364418919fSjohnjiang }
1374418919fSjohnjiang
138d30ea906Sjfb8856606 static int
enetc_hardware_init(struct enetc_eth_hw * hw)139d30ea906Sjfb8856606 enetc_hardware_init(struct enetc_eth_hw *hw)
140d30ea906Sjfb8856606 {
1414418919fSjohnjiang struct enetc_hw *enetc_hw = &hw->hw;
1424418919fSjohnjiang uint32_t *mac = (uint32_t *)hw->mac.addr;
1434418919fSjohnjiang uint32_t high_mac = 0;
1444418919fSjohnjiang uint16_t low_mac = 0;
145d30ea906Sjfb8856606
146d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE();
147d30ea906Sjfb8856606 /* Calculating and storing the base HW addresses */
148d30ea906Sjfb8856606 hw->hw.port = (void *)((size_t)hw->hw.reg + ENETC_PORT_BASE);
149d30ea906Sjfb8856606 hw->hw.global = (void *)((size_t)hw->hw.reg + ENETC_GLOBAL_BASE);
150d30ea906Sjfb8856606
1510c6bd470Sfengbojiang /* WA for Rx lock-up HW erratum */
1520c6bd470Sfengbojiang enetc_port_wr(enetc_hw, ENETC_PM0_RX_FIFO, 1);
1530c6bd470Sfengbojiang
154*2d9fd380Sjfb8856606 /* set ENETC transaction flags to coherent, don't allocate.
155*2d9fd380Sjfb8856606 * BD writes merge with surrounding cache line data, frame data writes
156*2d9fd380Sjfb8856606 * overwrite cache line.
157*2d9fd380Sjfb8856606 */
158*2d9fd380Sjfb8856606 enetc_wr(enetc_hw, ENETC_SICAR0, ENETC_SICAR0_COHERENT);
159*2d9fd380Sjfb8856606
160d30ea906Sjfb8856606 /* Enabling Station Interface */
1614418919fSjohnjiang enetc_wr(enetc_hw, ENETC_SIMR, ENETC_SIMR_EN);
162d30ea906Sjfb8856606
1634418919fSjohnjiang *mac = (uint32_t)enetc_port_rd(enetc_hw, ENETC_PSIPMAR0(0));
1644418919fSjohnjiang high_mac = (uint32_t)*mac;
1654418919fSjohnjiang mac++;
1664418919fSjohnjiang *mac = (uint16_t)enetc_port_rd(enetc_hw, ENETC_PSIPMAR1(0));
1674418919fSjohnjiang low_mac = (uint16_t)*mac;
168d30ea906Sjfb8856606
1694418919fSjohnjiang if ((high_mac | low_mac) == 0) {
1704418919fSjohnjiang char *first_byte;
171d30ea906Sjfb8856606
1724418919fSjohnjiang ENETC_PMD_NOTICE("MAC is not available for this SI, "
1734418919fSjohnjiang "set random MAC\n");
1744418919fSjohnjiang mac = (uint32_t *)hw->mac.addr;
1754418919fSjohnjiang *mac = (uint32_t)rte_rand();
1764418919fSjohnjiang first_byte = (char *)mac;
1774418919fSjohnjiang *first_byte &= 0xfe; /* clear multicast bit */
1784418919fSjohnjiang *first_byte |= 0x02; /* set local assignment bit (IEEE802) */
1794418919fSjohnjiang
1804418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PSIPMAR0(0), *mac);
1814418919fSjohnjiang mac++;
1824418919fSjohnjiang *mac = (uint16_t)rte_rand();
1834418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PSIPMAR1(0), *mac);
1844418919fSjohnjiang print_ethaddr("New address: ",
1854418919fSjohnjiang (const struct rte_ether_addr *)hw->mac.addr);
1864418919fSjohnjiang }
187d30ea906Sjfb8856606
188d30ea906Sjfb8856606 return 0;
189d30ea906Sjfb8856606 }
190d30ea906Sjfb8856606
1914418919fSjohnjiang static int
enetc_dev_infos_get(struct rte_eth_dev * dev __rte_unused,struct rte_eth_dev_info * dev_info)192d30ea906Sjfb8856606 enetc_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
193d30ea906Sjfb8856606 struct rte_eth_dev_info *dev_info)
194d30ea906Sjfb8856606 {
195d30ea906Sjfb8856606 PMD_INIT_FUNC_TRACE();
196d30ea906Sjfb8856606 dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
197d30ea906Sjfb8856606 .nb_max = MAX_BD_COUNT,
198d30ea906Sjfb8856606 .nb_min = MIN_BD_COUNT,
199d30ea906Sjfb8856606 .nb_align = BD_ALIGN,
200d30ea906Sjfb8856606 };
201d30ea906Sjfb8856606 dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
202d30ea906Sjfb8856606 .nb_max = MAX_BD_COUNT,
203d30ea906Sjfb8856606 .nb_min = MIN_BD_COUNT,
204d30ea906Sjfb8856606 .nb_align = BD_ALIGN,
205d30ea906Sjfb8856606 };
206d30ea906Sjfb8856606 dev_info->max_rx_queues = MAX_RX_RINGS;
207d30ea906Sjfb8856606 dev_info->max_tx_queues = MAX_TX_RINGS;
2084418919fSjohnjiang dev_info->max_rx_pktlen = ENETC_MAC_MAXFRM_SIZE;
2094418919fSjohnjiang dev_info->rx_offload_capa =
2104418919fSjohnjiang (DEV_RX_OFFLOAD_IPV4_CKSUM |
2114418919fSjohnjiang DEV_RX_OFFLOAD_UDP_CKSUM |
2124418919fSjohnjiang DEV_RX_OFFLOAD_TCP_CKSUM |
2134418919fSjohnjiang DEV_RX_OFFLOAD_KEEP_CRC |
2144418919fSjohnjiang DEV_RX_OFFLOAD_JUMBO_FRAME);
2154418919fSjohnjiang
2164418919fSjohnjiang return 0;
217d30ea906Sjfb8856606 }
218d30ea906Sjfb8856606
219d30ea906Sjfb8856606 static int
enetc_alloc_txbdr(struct enetc_bdr * txr,uint16_t nb_desc)220d30ea906Sjfb8856606 enetc_alloc_txbdr(struct enetc_bdr *txr, uint16_t nb_desc)
221d30ea906Sjfb8856606 {
222d30ea906Sjfb8856606 int size;
223d30ea906Sjfb8856606
224d30ea906Sjfb8856606 size = nb_desc * sizeof(struct enetc_swbd);
2254418919fSjohnjiang txr->q_swbd = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
226d30ea906Sjfb8856606 if (txr->q_swbd == NULL)
227d30ea906Sjfb8856606 return -ENOMEM;
228d30ea906Sjfb8856606
229d30ea906Sjfb8856606 size = nb_desc * sizeof(struct enetc_tx_bd);
2304418919fSjohnjiang txr->bd_base = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
231d30ea906Sjfb8856606 if (txr->bd_base == NULL) {
232d30ea906Sjfb8856606 rte_free(txr->q_swbd);
233d30ea906Sjfb8856606 txr->q_swbd = NULL;
234d30ea906Sjfb8856606 return -ENOMEM;
235d30ea906Sjfb8856606 }
236d30ea906Sjfb8856606
237d30ea906Sjfb8856606 txr->bd_count = nb_desc;
238d30ea906Sjfb8856606 txr->next_to_clean = 0;
239d30ea906Sjfb8856606 txr->next_to_use = 0;
240d30ea906Sjfb8856606
241d30ea906Sjfb8856606 return 0;
242d30ea906Sjfb8856606 }
243d30ea906Sjfb8856606
244d30ea906Sjfb8856606 static void
enetc_free_bdr(struct enetc_bdr * rxr)245d30ea906Sjfb8856606 enetc_free_bdr(struct enetc_bdr *rxr)
246d30ea906Sjfb8856606 {
247d30ea906Sjfb8856606 rte_free(rxr->q_swbd);
248d30ea906Sjfb8856606 rte_free(rxr->bd_base);
249d30ea906Sjfb8856606 rxr->q_swbd = NULL;
250d30ea906Sjfb8856606 rxr->bd_base = NULL;
251d30ea906Sjfb8856606 }
252d30ea906Sjfb8856606
253d30ea906Sjfb8856606 static void
enetc_setup_txbdr(struct enetc_hw * hw,struct enetc_bdr * tx_ring)254d30ea906Sjfb8856606 enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
255d30ea906Sjfb8856606 {
256d30ea906Sjfb8856606 int idx = tx_ring->index;
2574418919fSjohnjiang phys_addr_t bd_address;
258d30ea906Sjfb8856606
2594418919fSjohnjiang bd_address = (phys_addr_t)
2604418919fSjohnjiang rte_mem_virt2iova((const void *)tx_ring->bd_base);
261d30ea906Sjfb8856606 enetc_txbdr_wr(hw, idx, ENETC_TBBAR0,
2624418919fSjohnjiang lower_32_bits((uint64_t)bd_address));
263d30ea906Sjfb8856606 enetc_txbdr_wr(hw, idx, ENETC_TBBAR1,
2644418919fSjohnjiang upper_32_bits((uint64_t)bd_address));
265d30ea906Sjfb8856606 enetc_txbdr_wr(hw, idx, ENETC_TBLENR,
266d30ea906Sjfb8856606 ENETC_RTBLENR_LEN(tx_ring->bd_count));
267d30ea906Sjfb8856606
268d30ea906Sjfb8856606 enetc_txbdr_wr(hw, idx, ENETC_TBCIR, 0);
269d30ea906Sjfb8856606 enetc_txbdr_wr(hw, idx, ENETC_TBCISR, 0);
270d30ea906Sjfb8856606 tx_ring->tcir = (void *)((size_t)hw->reg +
271d30ea906Sjfb8856606 ENETC_BDR(TX, idx, ENETC_TBCIR));
272d30ea906Sjfb8856606 tx_ring->tcisr = (void *)((size_t)hw->reg +
273d30ea906Sjfb8856606 ENETC_BDR(TX, idx, ENETC_TBCISR));
274d30ea906Sjfb8856606 }
275d30ea906Sjfb8856606
276d30ea906Sjfb8856606 static int
enetc_tx_queue_setup(struct rte_eth_dev * dev,uint16_t queue_idx,uint16_t nb_desc,unsigned int socket_id __rte_unused,const struct rte_eth_txconf * tx_conf)2774418919fSjohnjiang enetc_tx_queue_setup(struct rte_eth_dev *dev,
278d30ea906Sjfb8856606 uint16_t queue_idx,
2794418919fSjohnjiang uint16_t nb_desc,
2804418919fSjohnjiang unsigned int socket_id __rte_unused,
2814418919fSjohnjiang const struct rte_eth_txconf *tx_conf)
282d30ea906Sjfb8856606 {
2834418919fSjohnjiang int err = 0;
284d30ea906Sjfb8856606 struct enetc_bdr *tx_ring;
285d30ea906Sjfb8856606 struct rte_eth_dev_data *data = dev->data;
286d30ea906Sjfb8856606 struct enetc_eth_adapter *priv =
287d30ea906Sjfb8856606 ENETC_DEV_PRIVATE(data->dev_private);
288d30ea906Sjfb8856606
2894418919fSjohnjiang PMD_INIT_FUNC_TRACE();
2904418919fSjohnjiang if (nb_desc > MAX_BD_COUNT)
2914418919fSjohnjiang return -1;
2924418919fSjohnjiang
293d30ea906Sjfb8856606 tx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0);
294d30ea906Sjfb8856606 if (tx_ring == NULL) {
295d30ea906Sjfb8856606 ENETC_PMD_ERR("Failed to allocate TX ring memory");
296d30ea906Sjfb8856606 err = -ENOMEM;
297d30ea906Sjfb8856606 return -1;
298d30ea906Sjfb8856606 }
299d30ea906Sjfb8856606
300d30ea906Sjfb8856606 err = enetc_alloc_txbdr(tx_ring, nb_desc);
301d30ea906Sjfb8856606 if (err)
302d30ea906Sjfb8856606 goto fail;
303d30ea906Sjfb8856606
304d30ea906Sjfb8856606 tx_ring->index = queue_idx;
305d30ea906Sjfb8856606 tx_ring->ndev = dev;
306d30ea906Sjfb8856606 enetc_setup_txbdr(&priv->hw.hw, tx_ring);
307d30ea906Sjfb8856606 data->tx_queues[queue_idx] = tx_ring;
308d30ea906Sjfb8856606
3094418919fSjohnjiang if (!tx_conf->tx_deferred_start) {
3104418919fSjohnjiang /* enable ring */
3114418919fSjohnjiang enetc_txbdr_wr(&priv->hw.hw, tx_ring->index,
3124418919fSjohnjiang ENETC_TBMR, ENETC_TBMR_EN);
3134418919fSjohnjiang dev->data->tx_queue_state[tx_ring->index] =
3144418919fSjohnjiang RTE_ETH_QUEUE_STATE_STARTED;
3154418919fSjohnjiang } else {
3164418919fSjohnjiang dev->data->tx_queue_state[tx_ring->index] =
3174418919fSjohnjiang RTE_ETH_QUEUE_STATE_STOPPED;
3184418919fSjohnjiang }
3194418919fSjohnjiang
320d30ea906Sjfb8856606 return 0;
321d30ea906Sjfb8856606 fail:
322d30ea906Sjfb8856606 rte_free(tx_ring);
323d30ea906Sjfb8856606
324d30ea906Sjfb8856606 return err;
325d30ea906Sjfb8856606 }
326d30ea906Sjfb8856606
327d30ea906Sjfb8856606 static void
enetc_tx_queue_release(void * txq)328d30ea906Sjfb8856606 enetc_tx_queue_release(void *txq)
329d30ea906Sjfb8856606 {
330d30ea906Sjfb8856606 if (txq == NULL)
331d30ea906Sjfb8856606 return;
332d30ea906Sjfb8856606
333d30ea906Sjfb8856606 struct enetc_bdr *tx_ring = (struct enetc_bdr *)txq;
334d30ea906Sjfb8856606 struct enetc_eth_hw *eth_hw =
335d30ea906Sjfb8856606 ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private);
336d30ea906Sjfb8856606 struct enetc_hw *hw;
337d30ea906Sjfb8856606 struct enetc_swbd *tx_swbd;
338d30ea906Sjfb8856606 int i;
339d30ea906Sjfb8856606 uint32_t val;
340d30ea906Sjfb8856606
341d30ea906Sjfb8856606 /* Disable the ring */
342d30ea906Sjfb8856606 hw = ð_hw->hw;
343d30ea906Sjfb8856606 val = enetc_txbdr_rd(hw, tx_ring->index, ENETC_TBMR);
344d30ea906Sjfb8856606 val &= (~ENETC_TBMR_EN);
345d30ea906Sjfb8856606 enetc_txbdr_wr(hw, tx_ring->index, ENETC_TBMR, val);
346d30ea906Sjfb8856606
347d30ea906Sjfb8856606 /* clean the ring*/
348d30ea906Sjfb8856606 i = tx_ring->next_to_clean;
349d30ea906Sjfb8856606 tx_swbd = &tx_ring->q_swbd[i];
350d30ea906Sjfb8856606 while (tx_swbd->buffer_addr != NULL) {
351d30ea906Sjfb8856606 rte_pktmbuf_free(tx_swbd->buffer_addr);
352d30ea906Sjfb8856606 tx_swbd->buffer_addr = NULL;
353d30ea906Sjfb8856606 tx_swbd++;
354d30ea906Sjfb8856606 i++;
355d30ea906Sjfb8856606 if (unlikely(i == tx_ring->bd_count)) {
356d30ea906Sjfb8856606 i = 0;
357d30ea906Sjfb8856606 tx_swbd = &tx_ring->q_swbd[i];
358d30ea906Sjfb8856606 }
359d30ea906Sjfb8856606 }
360d30ea906Sjfb8856606
361d30ea906Sjfb8856606 enetc_free_bdr(tx_ring);
362d30ea906Sjfb8856606 rte_free(tx_ring);
363d30ea906Sjfb8856606 }
364d30ea906Sjfb8856606
365d30ea906Sjfb8856606 static int
enetc_alloc_rxbdr(struct enetc_bdr * rxr,uint16_t nb_rx_desc)366d30ea906Sjfb8856606 enetc_alloc_rxbdr(struct enetc_bdr *rxr,
367d30ea906Sjfb8856606 uint16_t nb_rx_desc)
368d30ea906Sjfb8856606 {
369d30ea906Sjfb8856606 int size;
370d30ea906Sjfb8856606
371d30ea906Sjfb8856606 size = nb_rx_desc * sizeof(struct enetc_swbd);
3724418919fSjohnjiang rxr->q_swbd = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
373d30ea906Sjfb8856606 if (rxr->q_swbd == NULL)
374d30ea906Sjfb8856606 return -ENOMEM;
375d30ea906Sjfb8856606
376d30ea906Sjfb8856606 size = nb_rx_desc * sizeof(union enetc_rx_bd);
3774418919fSjohnjiang rxr->bd_base = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
378d30ea906Sjfb8856606 if (rxr->bd_base == NULL) {
379d30ea906Sjfb8856606 rte_free(rxr->q_swbd);
380d30ea906Sjfb8856606 rxr->q_swbd = NULL;
381d30ea906Sjfb8856606 return -ENOMEM;
382d30ea906Sjfb8856606 }
383d30ea906Sjfb8856606
384d30ea906Sjfb8856606 rxr->bd_count = nb_rx_desc;
385d30ea906Sjfb8856606 rxr->next_to_clean = 0;
386d30ea906Sjfb8856606 rxr->next_to_use = 0;
387d30ea906Sjfb8856606 rxr->next_to_alloc = 0;
388d30ea906Sjfb8856606
389d30ea906Sjfb8856606 return 0;
390d30ea906Sjfb8856606 }
391d30ea906Sjfb8856606
392d30ea906Sjfb8856606 static void
enetc_setup_rxbdr(struct enetc_hw * hw,struct enetc_bdr * rx_ring,struct rte_mempool * mb_pool)393d30ea906Sjfb8856606 enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
394d30ea906Sjfb8856606 struct rte_mempool *mb_pool)
395d30ea906Sjfb8856606 {
396d30ea906Sjfb8856606 int idx = rx_ring->index;
397d30ea906Sjfb8856606 uint16_t buf_size;
3984418919fSjohnjiang phys_addr_t bd_address;
399d30ea906Sjfb8856606
4004418919fSjohnjiang bd_address = (phys_addr_t)
4014418919fSjohnjiang rte_mem_virt2iova((const void *)rx_ring->bd_base);
402d30ea906Sjfb8856606 enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0,
4034418919fSjohnjiang lower_32_bits((uint64_t)bd_address));
404d30ea906Sjfb8856606 enetc_rxbdr_wr(hw, idx, ENETC_RBBAR1,
4054418919fSjohnjiang upper_32_bits((uint64_t)bd_address));
406d30ea906Sjfb8856606 enetc_rxbdr_wr(hw, idx, ENETC_RBLENR,
407d30ea906Sjfb8856606 ENETC_RTBLENR_LEN(rx_ring->bd_count));
408d30ea906Sjfb8856606
409d30ea906Sjfb8856606 rx_ring->mb_pool = mb_pool;
410d30ea906Sjfb8856606 rx_ring->rcir = (void *)((size_t)hw->reg +
411d30ea906Sjfb8856606 ENETC_BDR(RX, idx, ENETC_RBCIR));
412d30ea906Sjfb8856606 enetc_refill_rx_ring(rx_ring, (enetc_bd_unused(rx_ring)));
413d30ea906Sjfb8856606 buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rx_ring->mb_pool) -
414d30ea906Sjfb8856606 RTE_PKTMBUF_HEADROOM);
415d30ea906Sjfb8856606 enetc_rxbdr_wr(hw, idx, ENETC_RBBSR, buf_size);
4161646932aSjfb8856606 enetc_rxbdr_wr(hw, idx, ENETC_RBPIR, 0);
417d30ea906Sjfb8856606 }
418d30ea906Sjfb8856606
419d30ea906Sjfb8856606 static int
enetc_rx_queue_setup(struct rte_eth_dev * dev,uint16_t rx_queue_id,uint16_t nb_rx_desc,unsigned int socket_id __rte_unused,const struct rte_eth_rxconf * rx_conf,struct rte_mempool * mb_pool)4204418919fSjohnjiang enetc_rx_queue_setup(struct rte_eth_dev *dev,
421d30ea906Sjfb8856606 uint16_t rx_queue_id,
422d30ea906Sjfb8856606 uint16_t nb_rx_desc,
4234418919fSjohnjiang unsigned int socket_id __rte_unused,
4244418919fSjohnjiang const struct rte_eth_rxconf *rx_conf,
425d30ea906Sjfb8856606 struct rte_mempool *mb_pool)
426d30ea906Sjfb8856606 {
4274418919fSjohnjiang int err = 0;
428d30ea906Sjfb8856606 struct enetc_bdr *rx_ring;
429d30ea906Sjfb8856606 struct rte_eth_dev_data *data = dev->data;
430d30ea906Sjfb8856606 struct enetc_eth_adapter *adapter =
431d30ea906Sjfb8856606 ENETC_DEV_PRIVATE(data->dev_private);
4324418919fSjohnjiang uint64_t rx_offloads = data->dev_conf.rxmode.offloads;
4334418919fSjohnjiang
4344418919fSjohnjiang PMD_INIT_FUNC_TRACE();
4354418919fSjohnjiang if (nb_rx_desc > MAX_BD_COUNT)
4364418919fSjohnjiang return -1;
437d30ea906Sjfb8856606
438d30ea906Sjfb8856606 rx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0);
439d30ea906Sjfb8856606 if (rx_ring == NULL) {
440d30ea906Sjfb8856606 ENETC_PMD_ERR("Failed to allocate RX ring memory");
441d30ea906Sjfb8856606 err = -ENOMEM;
442d30ea906Sjfb8856606 return err;
443d30ea906Sjfb8856606 }
444d30ea906Sjfb8856606
445d30ea906Sjfb8856606 err = enetc_alloc_rxbdr(rx_ring, nb_rx_desc);
446d30ea906Sjfb8856606 if (err)
447d30ea906Sjfb8856606 goto fail;
448d30ea906Sjfb8856606
449d30ea906Sjfb8856606 rx_ring->index = rx_queue_id;
450d30ea906Sjfb8856606 rx_ring->ndev = dev;
451d30ea906Sjfb8856606 enetc_setup_rxbdr(&adapter->hw.hw, rx_ring, mb_pool);
452d30ea906Sjfb8856606 data->rx_queues[rx_queue_id] = rx_ring;
453d30ea906Sjfb8856606
4544418919fSjohnjiang if (!rx_conf->rx_deferred_start) {
4554418919fSjohnjiang /* enable ring */
4564418919fSjohnjiang enetc_rxbdr_wr(&adapter->hw.hw, rx_ring->index, ENETC_RBMR,
4574418919fSjohnjiang ENETC_RBMR_EN);
4584418919fSjohnjiang dev->data->rx_queue_state[rx_ring->index] =
4594418919fSjohnjiang RTE_ETH_QUEUE_STATE_STARTED;
4604418919fSjohnjiang } else {
4614418919fSjohnjiang dev->data->rx_queue_state[rx_ring->index] =
4624418919fSjohnjiang RTE_ETH_QUEUE_STATE_STOPPED;
4634418919fSjohnjiang }
4644418919fSjohnjiang
4654418919fSjohnjiang rx_ring->crc_len = (uint8_t)((rx_offloads & DEV_RX_OFFLOAD_KEEP_CRC) ?
4664418919fSjohnjiang RTE_ETHER_CRC_LEN : 0);
4674418919fSjohnjiang
468d30ea906Sjfb8856606 return 0;
469d30ea906Sjfb8856606 fail:
470d30ea906Sjfb8856606 rte_free(rx_ring);
471d30ea906Sjfb8856606
472d30ea906Sjfb8856606 return err;
473d30ea906Sjfb8856606 }
474d30ea906Sjfb8856606
475d30ea906Sjfb8856606 static void
enetc_rx_queue_release(void * rxq)476d30ea906Sjfb8856606 enetc_rx_queue_release(void *rxq)
477d30ea906Sjfb8856606 {
478d30ea906Sjfb8856606 if (rxq == NULL)
479d30ea906Sjfb8856606 return;
480d30ea906Sjfb8856606
481d30ea906Sjfb8856606 struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq;
482d30ea906Sjfb8856606 struct enetc_eth_hw *eth_hw =
483d30ea906Sjfb8856606 ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private);
484d30ea906Sjfb8856606 struct enetc_swbd *q_swbd;
485d30ea906Sjfb8856606 struct enetc_hw *hw;
486d30ea906Sjfb8856606 uint32_t val;
487d30ea906Sjfb8856606 int i;
488d30ea906Sjfb8856606
489d30ea906Sjfb8856606 /* Disable the ring */
490d30ea906Sjfb8856606 hw = ð_hw->hw;
491d30ea906Sjfb8856606 val = enetc_rxbdr_rd(hw, rx_ring->index, ENETC_RBMR);
492d30ea906Sjfb8856606 val &= (~ENETC_RBMR_EN);
493d30ea906Sjfb8856606 enetc_rxbdr_wr(hw, rx_ring->index, ENETC_RBMR, val);
494d30ea906Sjfb8856606
495d30ea906Sjfb8856606 /* Clean the ring */
496d30ea906Sjfb8856606 i = rx_ring->next_to_clean;
497d30ea906Sjfb8856606 q_swbd = &rx_ring->q_swbd[i];
498d30ea906Sjfb8856606 while (i != rx_ring->next_to_use) {
499d30ea906Sjfb8856606 rte_pktmbuf_free(q_swbd->buffer_addr);
500d30ea906Sjfb8856606 q_swbd->buffer_addr = NULL;
501d30ea906Sjfb8856606 q_swbd++;
502d30ea906Sjfb8856606 i++;
503d30ea906Sjfb8856606 if (unlikely(i == rx_ring->bd_count)) {
504d30ea906Sjfb8856606 i = 0;
505d30ea906Sjfb8856606 q_swbd = &rx_ring->q_swbd[i];
506d30ea906Sjfb8856606 }
507d30ea906Sjfb8856606 }
508d30ea906Sjfb8856606
509d30ea906Sjfb8856606 enetc_free_bdr(rx_ring);
510d30ea906Sjfb8856606 rte_free(rx_ring);
511d30ea906Sjfb8856606 }
512d30ea906Sjfb8856606
5134418919fSjohnjiang static
enetc_stats_get(struct rte_eth_dev * dev,struct rte_eth_stats * stats)5144418919fSjohnjiang int enetc_stats_get(struct rte_eth_dev *dev,
5154418919fSjohnjiang struct rte_eth_stats *stats)
5164418919fSjohnjiang {
5174418919fSjohnjiang struct enetc_eth_hw *hw =
5184418919fSjohnjiang ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
5194418919fSjohnjiang struct enetc_hw *enetc_hw = &hw->hw;
5204418919fSjohnjiang
5214418919fSjohnjiang /* Total received packets, bad + good, if we want to get counters of
5224418919fSjohnjiang * only good received packets then use ENETC_PM0_RFRM,
5234418919fSjohnjiang * ENETC_PM0_TFRM registers.
5244418919fSjohnjiang */
5254418919fSjohnjiang stats->ipackets = enetc_port_rd(enetc_hw, ENETC_PM0_RPKT);
5264418919fSjohnjiang stats->opackets = enetc_port_rd(enetc_hw, ENETC_PM0_TPKT);
5274418919fSjohnjiang stats->ibytes = enetc_port_rd(enetc_hw, ENETC_PM0_REOCT);
5284418919fSjohnjiang stats->obytes = enetc_port_rd(enetc_hw, ENETC_PM0_TEOCT);
5294418919fSjohnjiang /* Dropped + Truncated packets, use ENETC_PM0_RDRNTP for without
5304418919fSjohnjiang * truncated packets
5314418919fSjohnjiang */
5324418919fSjohnjiang stats->imissed = enetc_port_rd(enetc_hw, ENETC_PM0_RDRP);
5334418919fSjohnjiang stats->ierrors = enetc_port_rd(enetc_hw, ENETC_PM0_RERR);
5344418919fSjohnjiang stats->oerrors = enetc_port_rd(enetc_hw, ENETC_PM0_TERR);
5354418919fSjohnjiang
5364418919fSjohnjiang return 0;
5374418919fSjohnjiang }
5384418919fSjohnjiang
5394418919fSjohnjiang static int
enetc_stats_reset(struct rte_eth_dev * dev)5404418919fSjohnjiang enetc_stats_reset(struct rte_eth_dev *dev)
5414418919fSjohnjiang {
5424418919fSjohnjiang struct enetc_eth_hw *hw =
5434418919fSjohnjiang ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
5444418919fSjohnjiang struct enetc_hw *enetc_hw = &hw->hw;
5454418919fSjohnjiang
5464418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PM0_STAT_CONFIG, ENETC_CLEAR_STATS);
5474418919fSjohnjiang
5484418919fSjohnjiang return 0;
5494418919fSjohnjiang }
5504418919fSjohnjiang
551*2d9fd380Sjfb8856606 static int
enetc_dev_close(struct rte_eth_dev * dev)5524418919fSjohnjiang enetc_dev_close(struct rte_eth_dev *dev)
5534418919fSjohnjiang {
5544418919fSjohnjiang uint16_t i;
555*2d9fd380Sjfb8856606 int ret;
5564418919fSjohnjiang
5574418919fSjohnjiang PMD_INIT_FUNC_TRACE();
558*2d9fd380Sjfb8856606 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
559*2d9fd380Sjfb8856606 return 0;
560*2d9fd380Sjfb8856606
561*2d9fd380Sjfb8856606 ret = enetc_dev_stop(dev);
5624418919fSjohnjiang
5634418919fSjohnjiang for (i = 0; i < dev->data->nb_rx_queues; i++) {
5644418919fSjohnjiang enetc_rx_queue_release(dev->data->rx_queues[i]);
5654418919fSjohnjiang dev->data->rx_queues[i] = NULL;
5664418919fSjohnjiang }
5674418919fSjohnjiang dev->data->nb_rx_queues = 0;
5684418919fSjohnjiang
5694418919fSjohnjiang for (i = 0; i < dev->data->nb_tx_queues; i++) {
5704418919fSjohnjiang enetc_tx_queue_release(dev->data->tx_queues[i]);
5714418919fSjohnjiang dev->data->tx_queues[i] = NULL;
5724418919fSjohnjiang }
5734418919fSjohnjiang dev->data->nb_tx_queues = 0;
574*2d9fd380Sjfb8856606
575*2d9fd380Sjfb8856606 if (rte_eal_iova_mode() == RTE_IOVA_PA)
576*2d9fd380Sjfb8856606 dpaax_iova_table_depopulate();
577*2d9fd380Sjfb8856606
578*2d9fd380Sjfb8856606 return ret;
5794418919fSjohnjiang }
5804418919fSjohnjiang
5814418919fSjohnjiang static int
enetc_promiscuous_enable(struct rte_eth_dev * dev)5824418919fSjohnjiang enetc_promiscuous_enable(struct rte_eth_dev *dev)
5834418919fSjohnjiang {
5844418919fSjohnjiang struct enetc_eth_hw *hw =
5854418919fSjohnjiang ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
5864418919fSjohnjiang struct enetc_hw *enetc_hw = &hw->hw;
5874418919fSjohnjiang uint32_t psipmr = 0;
5884418919fSjohnjiang
5894418919fSjohnjiang psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR);
5904418919fSjohnjiang
5914418919fSjohnjiang /* Setting to enable promiscuous mode*/
5924418919fSjohnjiang psipmr |= ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0);
5934418919fSjohnjiang
5944418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr);
5954418919fSjohnjiang
5964418919fSjohnjiang return 0;
5974418919fSjohnjiang }
5984418919fSjohnjiang
5994418919fSjohnjiang static int
enetc_promiscuous_disable(struct rte_eth_dev * dev)6004418919fSjohnjiang enetc_promiscuous_disable(struct rte_eth_dev *dev)
6014418919fSjohnjiang {
6024418919fSjohnjiang struct enetc_eth_hw *hw =
6034418919fSjohnjiang ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
6044418919fSjohnjiang struct enetc_hw *enetc_hw = &hw->hw;
6054418919fSjohnjiang uint32_t psipmr = 0;
6064418919fSjohnjiang
6074418919fSjohnjiang /* Setting to disable promiscuous mode for SI0*/
6084418919fSjohnjiang psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR);
6094418919fSjohnjiang psipmr &= (~ENETC_PSIPMR_SET_UP(0));
6104418919fSjohnjiang
6114418919fSjohnjiang if (dev->data->all_multicast == 0)
6124418919fSjohnjiang psipmr &= (~ENETC_PSIPMR_SET_MP(0));
6134418919fSjohnjiang
6144418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr);
6154418919fSjohnjiang
6164418919fSjohnjiang return 0;
6174418919fSjohnjiang }
6184418919fSjohnjiang
6194418919fSjohnjiang static int
enetc_allmulticast_enable(struct rte_eth_dev * dev)6204418919fSjohnjiang enetc_allmulticast_enable(struct rte_eth_dev *dev)
6214418919fSjohnjiang {
6224418919fSjohnjiang struct enetc_eth_hw *hw =
6234418919fSjohnjiang ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
6244418919fSjohnjiang struct enetc_hw *enetc_hw = &hw->hw;
6254418919fSjohnjiang uint32_t psipmr = 0;
6264418919fSjohnjiang
6274418919fSjohnjiang psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR);
6284418919fSjohnjiang
6294418919fSjohnjiang /* Setting to enable allmulticast mode for SI0*/
6304418919fSjohnjiang psipmr |= ENETC_PSIPMR_SET_MP(0);
6314418919fSjohnjiang
6324418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr);
6334418919fSjohnjiang
6344418919fSjohnjiang return 0;
6354418919fSjohnjiang }
6364418919fSjohnjiang
6374418919fSjohnjiang static int
enetc_allmulticast_disable(struct rte_eth_dev * dev)6384418919fSjohnjiang enetc_allmulticast_disable(struct rte_eth_dev *dev)
6394418919fSjohnjiang {
6404418919fSjohnjiang struct enetc_eth_hw *hw =
6414418919fSjohnjiang ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
6424418919fSjohnjiang struct enetc_hw *enetc_hw = &hw->hw;
6434418919fSjohnjiang uint32_t psipmr = 0;
6444418919fSjohnjiang
6454418919fSjohnjiang if (dev->data->promiscuous == 1)
6464418919fSjohnjiang return 0; /* must remain in all_multicast mode */
6474418919fSjohnjiang
6484418919fSjohnjiang /* Setting to disable all multicast mode for SI0*/
6494418919fSjohnjiang psipmr = enetc_port_rd(enetc_hw, ENETC_PSIPMR) &
6504418919fSjohnjiang ~(ENETC_PSIPMR_SET_MP(0));
6514418919fSjohnjiang
6524418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PSIPMR, psipmr);
6534418919fSjohnjiang
6544418919fSjohnjiang return 0;
6554418919fSjohnjiang }
6564418919fSjohnjiang
6574418919fSjohnjiang static int
enetc_mtu_set(struct rte_eth_dev * dev,uint16_t mtu)6584418919fSjohnjiang enetc_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
6594418919fSjohnjiang {
6604418919fSjohnjiang struct enetc_eth_hw *hw =
6614418919fSjohnjiang ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
6624418919fSjohnjiang struct enetc_hw *enetc_hw = &hw->hw;
6634418919fSjohnjiang uint32_t frame_size = mtu + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN;
6644418919fSjohnjiang
6654418919fSjohnjiang /* check that mtu is within the allowed range */
6664418919fSjohnjiang if (mtu < ENETC_MAC_MINFRM_SIZE || frame_size > ENETC_MAC_MAXFRM_SIZE)
6674418919fSjohnjiang return -EINVAL;
6684418919fSjohnjiang
6694418919fSjohnjiang /*
6704418919fSjohnjiang * Refuse mtu that requires the support of scattered packets
6714418919fSjohnjiang * when this feature has not been enabled before.
6724418919fSjohnjiang */
6734418919fSjohnjiang if (dev->data->min_rx_buf_size &&
6744418919fSjohnjiang !dev->data->scattered_rx && frame_size >
6754418919fSjohnjiang dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM) {
6764418919fSjohnjiang ENETC_PMD_ERR("SG not enabled, will not fit in one buffer");
6774418919fSjohnjiang return -EINVAL;
6784418919fSjohnjiang }
6794418919fSjohnjiang
6804418919fSjohnjiang if (frame_size > RTE_ETHER_MAX_LEN)
6814418919fSjohnjiang dev->data->dev_conf.rxmode.offloads &=
6824418919fSjohnjiang DEV_RX_OFFLOAD_JUMBO_FRAME;
6834418919fSjohnjiang else
6844418919fSjohnjiang dev->data->dev_conf.rxmode.offloads &=
6854418919fSjohnjiang ~DEV_RX_OFFLOAD_JUMBO_FRAME;
6864418919fSjohnjiang
6874418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PTCMSDUR(0), ENETC_MAC_MAXFRM_SIZE);
6884418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PTXMBAR, 2 * ENETC_MAC_MAXFRM_SIZE);
6894418919fSjohnjiang
6904418919fSjohnjiang dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
6914418919fSjohnjiang
6924418919fSjohnjiang /*setting the MTU*/
6934418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PM0_MAXFRM, ENETC_SET_MAXFRM(frame_size) |
6944418919fSjohnjiang ENETC_SET_TX_MTU(ENETC_MAC_MAXFRM_SIZE));
6954418919fSjohnjiang
6964418919fSjohnjiang return 0;
6974418919fSjohnjiang }
6984418919fSjohnjiang
6994418919fSjohnjiang static int
enetc_dev_configure(struct rte_eth_dev * dev)7004418919fSjohnjiang enetc_dev_configure(struct rte_eth_dev *dev)
7014418919fSjohnjiang {
7024418919fSjohnjiang struct enetc_eth_hw *hw =
7034418919fSjohnjiang ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
7044418919fSjohnjiang struct enetc_hw *enetc_hw = &hw->hw;
7054418919fSjohnjiang struct rte_eth_conf *eth_conf = &dev->data->dev_conf;
7064418919fSjohnjiang uint64_t rx_offloads = eth_conf->rxmode.offloads;
7074418919fSjohnjiang uint32_t checksum = L3_CKSUM | L4_CKSUM;
7084418919fSjohnjiang
7094418919fSjohnjiang PMD_INIT_FUNC_TRACE();
7104418919fSjohnjiang
7114418919fSjohnjiang if (rx_offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) {
7124418919fSjohnjiang uint32_t max_len;
7134418919fSjohnjiang
7144418919fSjohnjiang max_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
7154418919fSjohnjiang
7164418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PM0_MAXFRM,
7174418919fSjohnjiang ENETC_SET_MAXFRM(max_len));
7184418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PTCMSDUR(0),
7194418919fSjohnjiang ENETC_MAC_MAXFRM_SIZE);
7204418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PTXMBAR,
7214418919fSjohnjiang 2 * ENETC_MAC_MAXFRM_SIZE);
7224418919fSjohnjiang dev->data->mtu = RTE_ETHER_MAX_LEN - RTE_ETHER_HDR_LEN -
7234418919fSjohnjiang RTE_ETHER_CRC_LEN;
7244418919fSjohnjiang }
7254418919fSjohnjiang
7264418919fSjohnjiang if (rx_offloads & DEV_RX_OFFLOAD_KEEP_CRC) {
7274418919fSjohnjiang int config;
7284418919fSjohnjiang
7294418919fSjohnjiang config = enetc_port_rd(enetc_hw, ENETC_PM0_CMD_CFG);
7304418919fSjohnjiang config |= ENETC_PM0_CRC;
7314418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PM0_CMD_CFG, config);
7324418919fSjohnjiang }
7334418919fSjohnjiang
7344418919fSjohnjiang if (rx_offloads & DEV_RX_OFFLOAD_IPV4_CKSUM)
7354418919fSjohnjiang checksum &= ~L3_CKSUM;
7364418919fSjohnjiang
7374418919fSjohnjiang if (rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM))
7384418919fSjohnjiang checksum &= ~L4_CKSUM;
7394418919fSjohnjiang
7404418919fSjohnjiang enetc_port_wr(enetc_hw, ENETC_PAR_PORT_CFG, checksum);
7414418919fSjohnjiang
7424418919fSjohnjiang
7434418919fSjohnjiang return 0;
7444418919fSjohnjiang }
7454418919fSjohnjiang
7464418919fSjohnjiang static int
enetc_rx_queue_start(struct rte_eth_dev * dev,uint16_t qidx)7474418919fSjohnjiang enetc_rx_queue_start(struct rte_eth_dev *dev, uint16_t qidx)
7484418919fSjohnjiang {
7494418919fSjohnjiang struct enetc_eth_adapter *priv =
7504418919fSjohnjiang ENETC_DEV_PRIVATE(dev->data->dev_private);
7514418919fSjohnjiang struct enetc_bdr *rx_ring;
7524418919fSjohnjiang uint32_t rx_data;
7534418919fSjohnjiang
7544418919fSjohnjiang rx_ring = dev->data->rx_queues[qidx];
7554418919fSjohnjiang if (dev->data->rx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) {
7564418919fSjohnjiang rx_data = enetc_rxbdr_rd(&priv->hw.hw, rx_ring->index,
7574418919fSjohnjiang ENETC_RBMR);
7584418919fSjohnjiang rx_data = rx_data | ENETC_RBMR_EN;
7594418919fSjohnjiang enetc_rxbdr_wr(&priv->hw.hw, rx_ring->index, ENETC_RBMR,
7604418919fSjohnjiang rx_data);
7614418919fSjohnjiang dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED;
7624418919fSjohnjiang }
7634418919fSjohnjiang
7644418919fSjohnjiang return 0;
7654418919fSjohnjiang }
7664418919fSjohnjiang
7674418919fSjohnjiang static int
enetc_rx_queue_stop(struct rte_eth_dev * dev,uint16_t qidx)7684418919fSjohnjiang enetc_rx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx)
7694418919fSjohnjiang {
7704418919fSjohnjiang struct enetc_eth_adapter *priv =
7714418919fSjohnjiang ENETC_DEV_PRIVATE(dev->data->dev_private);
7724418919fSjohnjiang struct enetc_bdr *rx_ring;
7734418919fSjohnjiang uint32_t rx_data;
7744418919fSjohnjiang
7754418919fSjohnjiang rx_ring = dev->data->rx_queues[qidx];
7764418919fSjohnjiang if (dev->data->rx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED) {
7774418919fSjohnjiang rx_data = enetc_rxbdr_rd(&priv->hw.hw, rx_ring->index,
7784418919fSjohnjiang ENETC_RBMR);
7794418919fSjohnjiang rx_data = rx_data & (~ENETC_RBMR_EN);
7804418919fSjohnjiang enetc_rxbdr_wr(&priv->hw.hw, rx_ring->index, ENETC_RBMR,
7814418919fSjohnjiang rx_data);
7824418919fSjohnjiang dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
7834418919fSjohnjiang }
7844418919fSjohnjiang
7854418919fSjohnjiang return 0;
7864418919fSjohnjiang }
7874418919fSjohnjiang
7884418919fSjohnjiang static int
enetc_tx_queue_start(struct rte_eth_dev * dev,uint16_t qidx)7894418919fSjohnjiang enetc_tx_queue_start(struct rte_eth_dev *dev, uint16_t qidx)
7904418919fSjohnjiang {
7914418919fSjohnjiang struct enetc_eth_adapter *priv =
7924418919fSjohnjiang ENETC_DEV_PRIVATE(dev->data->dev_private);
7934418919fSjohnjiang struct enetc_bdr *tx_ring;
7944418919fSjohnjiang uint32_t tx_data;
7954418919fSjohnjiang
7964418919fSjohnjiang tx_ring = dev->data->tx_queues[qidx];
7974418919fSjohnjiang if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) {
7984418919fSjohnjiang tx_data = enetc_txbdr_rd(&priv->hw.hw, tx_ring->index,
7994418919fSjohnjiang ENETC_TBMR);
8004418919fSjohnjiang tx_data = tx_data | ENETC_TBMR_EN;
8014418919fSjohnjiang enetc_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR,
8024418919fSjohnjiang tx_data);
8034418919fSjohnjiang dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED;
8044418919fSjohnjiang }
8054418919fSjohnjiang
8064418919fSjohnjiang return 0;
8074418919fSjohnjiang }
8084418919fSjohnjiang
8094418919fSjohnjiang static int
enetc_tx_queue_stop(struct rte_eth_dev * dev,uint16_t qidx)8104418919fSjohnjiang enetc_tx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx)
8114418919fSjohnjiang {
8124418919fSjohnjiang struct enetc_eth_adapter *priv =
8134418919fSjohnjiang ENETC_DEV_PRIVATE(dev->data->dev_private);
8144418919fSjohnjiang struct enetc_bdr *tx_ring;
8154418919fSjohnjiang uint32_t tx_data;
8164418919fSjohnjiang
8174418919fSjohnjiang tx_ring = dev->data->tx_queues[qidx];
8184418919fSjohnjiang if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED) {
8194418919fSjohnjiang tx_data = enetc_txbdr_rd(&priv->hw.hw, tx_ring->index,
8204418919fSjohnjiang ENETC_TBMR);
8214418919fSjohnjiang tx_data = tx_data & (~ENETC_TBMR_EN);
8224418919fSjohnjiang enetc_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR,
8234418919fSjohnjiang tx_data);
8244418919fSjohnjiang dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
8254418919fSjohnjiang }
8264418919fSjohnjiang
8274418919fSjohnjiang return 0;
8284418919fSjohnjiang }
8294418919fSjohnjiang
8304418919fSjohnjiang /*
8314418919fSjohnjiang * The set of PCI devices this driver supports
8324418919fSjohnjiang */
8334418919fSjohnjiang static const struct rte_pci_id pci_id_enetc_map[] = {
8344418919fSjohnjiang { RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID) },
8354418919fSjohnjiang { RTE_PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_VF) },
8364418919fSjohnjiang { .vendor_id = 0, /* sentinel */ },
8374418919fSjohnjiang };
8384418919fSjohnjiang
8394418919fSjohnjiang /* Features supported by this driver */
8404418919fSjohnjiang static const struct eth_dev_ops enetc_ops = {
8414418919fSjohnjiang .dev_configure = enetc_dev_configure,
8424418919fSjohnjiang .dev_start = enetc_dev_start,
8434418919fSjohnjiang .dev_stop = enetc_dev_stop,
8444418919fSjohnjiang .dev_close = enetc_dev_close,
8454418919fSjohnjiang .link_update = enetc_link_update,
8464418919fSjohnjiang .stats_get = enetc_stats_get,
8474418919fSjohnjiang .stats_reset = enetc_stats_reset,
8484418919fSjohnjiang .promiscuous_enable = enetc_promiscuous_enable,
8494418919fSjohnjiang .promiscuous_disable = enetc_promiscuous_disable,
8504418919fSjohnjiang .allmulticast_enable = enetc_allmulticast_enable,
8514418919fSjohnjiang .allmulticast_disable = enetc_allmulticast_disable,
8524418919fSjohnjiang .dev_infos_get = enetc_dev_infos_get,
8534418919fSjohnjiang .mtu_set = enetc_mtu_set,
8544418919fSjohnjiang .rx_queue_setup = enetc_rx_queue_setup,
8554418919fSjohnjiang .rx_queue_start = enetc_rx_queue_start,
8564418919fSjohnjiang .rx_queue_stop = enetc_rx_queue_stop,
8574418919fSjohnjiang .rx_queue_release = enetc_rx_queue_release,
8584418919fSjohnjiang .tx_queue_setup = enetc_tx_queue_setup,
8594418919fSjohnjiang .tx_queue_start = enetc_tx_queue_start,
8604418919fSjohnjiang .tx_queue_stop = enetc_tx_queue_stop,
8614418919fSjohnjiang .tx_queue_release = enetc_tx_queue_release,
8624418919fSjohnjiang .dev_supported_ptypes_get = enetc_supported_ptypes_get,
8634418919fSjohnjiang };
8644418919fSjohnjiang
8654418919fSjohnjiang /**
8664418919fSjohnjiang * Initialisation of the enetc device
8674418919fSjohnjiang *
8684418919fSjohnjiang * @param eth_dev
8694418919fSjohnjiang * - Pointer to the structure rte_eth_dev
8704418919fSjohnjiang *
8714418919fSjohnjiang * @return
8724418919fSjohnjiang * - On success, zero.
8734418919fSjohnjiang * - On failure, negative value.
8744418919fSjohnjiang */
8754418919fSjohnjiang static int
enetc_dev_init(struct rte_eth_dev * eth_dev)8764418919fSjohnjiang enetc_dev_init(struct rte_eth_dev *eth_dev)
8774418919fSjohnjiang {
8784418919fSjohnjiang int error = 0;
8794418919fSjohnjiang struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
8804418919fSjohnjiang struct enetc_eth_hw *hw =
8814418919fSjohnjiang ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
8824418919fSjohnjiang
8834418919fSjohnjiang PMD_INIT_FUNC_TRACE();
8844418919fSjohnjiang eth_dev->dev_ops = &enetc_ops;
8854418919fSjohnjiang eth_dev->rx_pkt_burst = &enetc_recv_pkts;
8864418919fSjohnjiang eth_dev->tx_pkt_burst = &enetc_xmit_pkts;
8874418919fSjohnjiang
888*2d9fd380Sjfb8856606 eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
889*2d9fd380Sjfb8856606
8904418919fSjohnjiang /* Retrieving and storing the HW base address of device */
8914418919fSjohnjiang hw->hw.reg = (void *)pci_dev->mem_resource[0].addr;
8924418919fSjohnjiang hw->device_id = pci_dev->id.device_id;
8934418919fSjohnjiang
8944418919fSjohnjiang error = enetc_hardware_init(hw);
8954418919fSjohnjiang if (error != 0) {
8964418919fSjohnjiang ENETC_PMD_ERR("Hardware initialization failed");
8974418919fSjohnjiang return -1;
8984418919fSjohnjiang }
8994418919fSjohnjiang
9004418919fSjohnjiang /* Allocate memory for storing MAC addresses */
9014418919fSjohnjiang eth_dev->data->mac_addrs = rte_zmalloc("enetc_eth",
9024418919fSjohnjiang RTE_ETHER_ADDR_LEN, 0);
9034418919fSjohnjiang if (!eth_dev->data->mac_addrs) {
9044418919fSjohnjiang ENETC_PMD_ERR("Failed to allocate %d bytes needed to "
9054418919fSjohnjiang "store MAC addresses",
9064418919fSjohnjiang RTE_ETHER_ADDR_LEN * 1);
9074418919fSjohnjiang error = -ENOMEM;
9084418919fSjohnjiang return -1;
9094418919fSjohnjiang }
9104418919fSjohnjiang
9114418919fSjohnjiang /* Copy the permanent MAC address */
9124418919fSjohnjiang rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.addr,
9134418919fSjohnjiang ð_dev->data->mac_addrs[0]);
9144418919fSjohnjiang
9154418919fSjohnjiang /* Set MTU */
9164418919fSjohnjiang enetc_port_wr(&hw->hw, ENETC_PM0_MAXFRM,
9174418919fSjohnjiang ENETC_SET_MAXFRM(RTE_ETHER_MAX_LEN));
9184418919fSjohnjiang eth_dev->data->mtu = RTE_ETHER_MAX_LEN - RTE_ETHER_HDR_LEN -
9194418919fSjohnjiang RTE_ETHER_CRC_LEN;
9204418919fSjohnjiang
9214418919fSjohnjiang if (rte_eal_iova_mode() == RTE_IOVA_PA)
9224418919fSjohnjiang dpaax_iova_table_populate();
9234418919fSjohnjiang
9244418919fSjohnjiang ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x",
9254418919fSjohnjiang eth_dev->data->port_id, pci_dev->id.vendor_id,
9264418919fSjohnjiang pci_dev->id.device_id);
9274418919fSjohnjiang return 0;
9284418919fSjohnjiang }
9294418919fSjohnjiang
9304418919fSjohnjiang static int
enetc_dev_uninit(struct rte_eth_dev * eth_dev)931*2d9fd380Sjfb8856606 enetc_dev_uninit(struct rte_eth_dev *eth_dev)
9324418919fSjohnjiang {
9334418919fSjohnjiang PMD_INIT_FUNC_TRACE();
9344418919fSjohnjiang
935*2d9fd380Sjfb8856606 return enetc_dev_close(eth_dev);
9364418919fSjohnjiang }
9374418919fSjohnjiang
938d30ea906Sjfb8856606 static int
enetc_pci_probe(struct rte_pci_driver * pci_drv __rte_unused,struct rte_pci_device * pci_dev)939d30ea906Sjfb8856606 enetc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
940d30ea906Sjfb8856606 struct rte_pci_device *pci_dev)
941d30ea906Sjfb8856606 {
942d30ea906Sjfb8856606 return rte_eth_dev_pci_generic_probe(pci_dev,
943d30ea906Sjfb8856606 sizeof(struct enetc_eth_adapter),
944d30ea906Sjfb8856606 enetc_dev_init);
945d30ea906Sjfb8856606 }
946d30ea906Sjfb8856606
947d30ea906Sjfb8856606 static int
enetc_pci_remove(struct rte_pci_device * pci_dev)948d30ea906Sjfb8856606 enetc_pci_remove(struct rte_pci_device *pci_dev)
949d30ea906Sjfb8856606 {
950d30ea906Sjfb8856606 return rte_eth_dev_pci_generic_remove(pci_dev, enetc_dev_uninit);
951d30ea906Sjfb8856606 }
952d30ea906Sjfb8856606
953d30ea906Sjfb8856606 static struct rte_pci_driver rte_enetc_pmd = {
954d30ea906Sjfb8856606 .id_table = pci_id_enetc_map,
9554418919fSjohnjiang .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
956d30ea906Sjfb8856606 .probe = enetc_pci_probe,
957d30ea906Sjfb8856606 .remove = enetc_pci_remove,
958d30ea906Sjfb8856606 };
959d30ea906Sjfb8856606
960d30ea906Sjfb8856606 RTE_PMD_REGISTER_PCI(net_enetc, rte_enetc_pmd);
961d30ea906Sjfb8856606 RTE_PMD_REGISTER_PCI_TABLE(net_enetc, pci_id_enetc_map);
962d30ea906Sjfb8856606 RTE_PMD_REGISTER_KMOD_DEP(net_enetc, "* vfio-pci");
963*2d9fd380Sjfb8856606 RTE_LOG_REGISTER(enetc_logtype_pmd, pmd.net.enetc, NOTICE);
964