14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang * Copyright(c) 2019 Intel Corporation
34418919fSjohnjiang */
44418919fSjohnjiang
54418919fSjohnjiang #include <stdint.h>
64418919fSjohnjiang
74418919fSjohnjiang #include <rte_bus_pci.h>
84418919fSjohnjiang #include <rte_ethdev.h>
94418919fSjohnjiang #include <rte_pci.h>
104418919fSjohnjiang #include <rte_malloc.h>
114418919fSjohnjiang
124418919fSjohnjiang #include <rte_mbuf.h>
134418919fSjohnjiang #include <rte_sched.h>
144418919fSjohnjiang #include <rte_ethdev_driver.h>
154418919fSjohnjiang
164418919fSjohnjiang #include <rte_io.h>
174418919fSjohnjiang #include <rte_rawdev.h>
184418919fSjohnjiang #include <rte_rawdev_pmd.h>
194418919fSjohnjiang #include <rte_bus_ifpga.h>
204418919fSjohnjiang #include <ifpga_common.h>
214418919fSjohnjiang #include <ifpga_logs.h>
224418919fSjohnjiang #include <ifpga_rawdev.h>
234418919fSjohnjiang
244418919fSjohnjiang #include "ipn3ke_rawdev_api.h"
254418919fSjohnjiang #include "ipn3ke_flow.h"
264418919fSjohnjiang #include "ipn3ke_logs.h"
274418919fSjohnjiang #include "ipn3ke_ethdev.h"
284418919fSjohnjiang
294418919fSjohnjiang static const struct rte_afu_uuid afu_uuid_ipn3ke_map[] = {
304418919fSjohnjiang { MAP_UUID_10G_LOW, MAP_UUID_10G_HIGH },
314418919fSjohnjiang { IPN3KE_UUID_10G_LOW, IPN3KE_UUID_10G_HIGH },
324418919fSjohnjiang { IPN3KE_UUID_VBNG_LOW, IPN3KE_UUID_VBNG_HIGH},
334418919fSjohnjiang { IPN3KE_UUID_25G_LOW, IPN3KE_UUID_25G_HIGH },
344418919fSjohnjiang { 0, 0 /* sentinel */ },
354418919fSjohnjiang };
364418919fSjohnjiang
374418919fSjohnjiang struct ipn3ke_pub_func ipn3ke_bridge_func;
384418919fSjohnjiang
394418919fSjohnjiang static int
ipn3ke_indirect_read(struct ipn3ke_hw * hw,uint32_t * rd_data,uint32_t addr,uint32_t dev_sel,uint32_t eth_group_sel)404418919fSjohnjiang ipn3ke_indirect_read(struct ipn3ke_hw *hw, uint32_t *rd_data,
414418919fSjohnjiang uint32_t addr, uint32_t dev_sel, uint32_t eth_group_sel)
424418919fSjohnjiang {
434418919fSjohnjiang uint32_t i, try_cnt;
444418919fSjohnjiang uint64_t indirect_value;
454418919fSjohnjiang volatile void *indirect_addrs;
464418919fSjohnjiang uint64_t target_addr;
474418919fSjohnjiang uint64_t read_data = 0;
484418919fSjohnjiang
494418919fSjohnjiang if (eth_group_sel != 0 && eth_group_sel != 1)
504418919fSjohnjiang return -1;
514418919fSjohnjiang
524418919fSjohnjiang target_addr = addr | dev_sel << 17;
534418919fSjohnjiang
544418919fSjohnjiang indirect_value = RCMD | target_addr << 32;
554418919fSjohnjiang indirect_addrs = hw->eth_group_bar[eth_group_sel] + 0x10;
564418919fSjohnjiang
574418919fSjohnjiang rte_delay_us(10);
584418919fSjohnjiang
594418919fSjohnjiang rte_write64((rte_cpu_to_le_64(indirect_value)), indirect_addrs);
604418919fSjohnjiang
614418919fSjohnjiang i = 0;
624418919fSjohnjiang try_cnt = 10;
634418919fSjohnjiang indirect_addrs = hw->eth_group_bar[eth_group_sel] +
644418919fSjohnjiang 0x18;
654418919fSjohnjiang do {
664418919fSjohnjiang read_data = rte_read64(indirect_addrs);
674418919fSjohnjiang if ((read_data >> 32) == 1)
684418919fSjohnjiang break;
694418919fSjohnjiang i++;
704418919fSjohnjiang } while (i <= try_cnt);
714418919fSjohnjiang if (i > try_cnt)
724418919fSjohnjiang return -1;
734418919fSjohnjiang
744418919fSjohnjiang *rd_data = rte_le_to_cpu_32(read_data);
754418919fSjohnjiang return 0;
764418919fSjohnjiang }
774418919fSjohnjiang
784418919fSjohnjiang static int
ipn3ke_indirect_write(struct ipn3ke_hw * hw,uint32_t wr_data,uint32_t addr,uint32_t dev_sel,uint32_t eth_group_sel)794418919fSjohnjiang ipn3ke_indirect_write(struct ipn3ke_hw *hw, uint32_t wr_data,
804418919fSjohnjiang uint32_t addr, uint32_t dev_sel, uint32_t eth_group_sel)
814418919fSjohnjiang {
824418919fSjohnjiang volatile void *indirect_addrs;
834418919fSjohnjiang uint64_t indirect_value;
844418919fSjohnjiang uint64_t target_addr;
854418919fSjohnjiang
864418919fSjohnjiang if (eth_group_sel != 0 && eth_group_sel != 1)
874418919fSjohnjiang return -1;
884418919fSjohnjiang
894418919fSjohnjiang target_addr = addr | dev_sel << 17;
904418919fSjohnjiang
914418919fSjohnjiang indirect_value = WCMD | target_addr << 32 | wr_data;
924418919fSjohnjiang indirect_addrs = hw->eth_group_bar[eth_group_sel] + 0x10;
934418919fSjohnjiang
944418919fSjohnjiang rte_write64((rte_cpu_to_le_64(indirect_value)), indirect_addrs);
954418919fSjohnjiang return 0;
964418919fSjohnjiang }
974418919fSjohnjiang
984418919fSjohnjiang static int
ipn3ke_indirect_mac_read(struct ipn3ke_hw * hw,uint32_t * rd_data,uint32_t addr,uint32_t mac_num,uint32_t eth_group_sel)994418919fSjohnjiang ipn3ke_indirect_mac_read(struct ipn3ke_hw *hw, uint32_t *rd_data,
1004418919fSjohnjiang uint32_t addr, uint32_t mac_num, uint32_t eth_group_sel)
1014418919fSjohnjiang {
1024418919fSjohnjiang uint32_t dev_sel;
1034418919fSjohnjiang
1044418919fSjohnjiang if (mac_num >= hw->port_num)
1054418919fSjohnjiang return -1;
1064418919fSjohnjiang
1074418919fSjohnjiang mac_num &= 0x7;
1084418919fSjohnjiang dev_sel = mac_num * 2 + 3;
1094418919fSjohnjiang
1104418919fSjohnjiang return ipn3ke_indirect_read(hw, rd_data, addr, dev_sel, eth_group_sel);
1114418919fSjohnjiang }
1124418919fSjohnjiang
1134418919fSjohnjiang static int
ipn3ke_indirect_mac_write(struct ipn3ke_hw * hw,uint32_t wr_data,uint32_t addr,uint32_t mac_num,uint32_t eth_group_sel)1144418919fSjohnjiang ipn3ke_indirect_mac_write(struct ipn3ke_hw *hw, uint32_t wr_data,
1154418919fSjohnjiang uint32_t addr, uint32_t mac_num, uint32_t eth_group_sel)
1164418919fSjohnjiang {
1174418919fSjohnjiang uint32_t dev_sel;
1184418919fSjohnjiang
1194418919fSjohnjiang if (mac_num >= hw->port_num)
1204418919fSjohnjiang return -1;
1214418919fSjohnjiang
1224418919fSjohnjiang mac_num &= 0x7;
1234418919fSjohnjiang dev_sel = mac_num * 2 + 3;
1244418919fSjohnjiang
1254418919fSjohnjiang return ipn3ke_indirect_write(hw, wr_data, addr, dev_sel, eth_group_sel);
1264418919fSjohnjiang }
1274418919fSjohnjiang
1284418919fSjohnjiang static void
ipn3ke_hw_cap_init(struct ipn3ke_hw * hw)1294418919fSjohnjiang ipn3ke_hw_cap_init(struct ipn3ke_hw *hw)
1304418919fSjohnjiang {
1314418919fSjohnjiang hw->hw_cap.version_number = IPN3KE_MASK_READ_REG(hw,
1324418919fSjohnjiang (IPN3KE_HW_BASE + 0), 0, 0xFFFF);
1334418919fSjohnjiang hw->hw_cap.capability_registers_block_offset = IPN3KE_MASK_READ_REG(hw,
1344418919fSjohnjiang (IPN3KE_HW_BASE + 0x8), 0, 0xFFFFFFFF);
1354418919fSjohnjiang hw->hw_cap.status_registers_block_offset = IPN3KE_MASK_READ_REG(hw,
1364418919fSjohnjiang (IPN3KE_HW_BASE + 0x10), 0, 0xFFFFFFFF);
1374418919fSjohnjiang hw->hw_cap.control_registers_block_offset = IPN3KE_MASK_READ_REG(hw,
1384418919fSjohnjiang (IPN3KE_HW_BASE + 0x18), 0, 0xFFFFFFFF);
1394418919fSjohnjiang hw->hw_cap.classify_offset = IPN3KE_MASK_READ_REG(hw,
1404418919fSjohnjiang (IPN3KE_HW_BASE + 0x20), 0, 0xFFFFFFFF);
1414418919fSjohnjiang hw->hw_cap.classy_size = IPN3KE_MASK_READ_REG(hw,
1424418919fSjohnjiang (IPN3KE_HW_BASE + 0x24), 0, 0xFFFF);
1434418919fSjohnjiang hw->hw_cap.policer_offset = IPN3KE_MASK_READ_REG(hw,
1444418919fSjohnjiang (IPN3KE_HW_BASE + 0x28), 0, 0xFFFFFFFF);
1454418919fSjohnjiang hw->hw_cap.policer_entry_size = IPN3KE_MASK_READ_REG(hw,
1464418919fSjohnjiang (IPN3KE_HW_BASE + 0x2C), 0, 0xFFFF);
1474418919fSjohnjiang hw->hw_cap.rss_key_array_offset = IPN3KE_MASK_READ_REG(hw,
1484418919fSjohnjiang (IPN3KE_HW_BASE + 0x30), 0, 0xFFFFFFFF);
1494418919fSjohnjiang hw->hw_cap.rss_key_entry_size = IPN3KE_MASK_READ_REG(hw,
1504418919fSjohnjiang (IPN3KE_HW_BASE + 0x34), 0, 0xFFFF);
1514418919fSjohnjiang hw->hw_cap.rss_indirection_table_array_offset = IPN3KE_MASK_READ_REG(hw,
1524418919fSjohnjiang (IPN3KE_HW_BASE + 0x38), 0, 0xFFFFFFFF);
1534418919fSjohnjiang hw->hw_cap.rss_indirection_table_entry_size = IPN3KE_MASK_READ_REG(hw,
1544418919fSjohnjiang (IPN3KE_HW_BASE + 0x3C), 0, 0xFFFF);
1554418919fSjohnjiang hw->hw_cap.dmac_map_offset = IPN3KE_MASK_READ_REG(hw,
1564418919fSjohnjiang (IPN3KE_HW_BASE + 0x40), 0, 0xFFFFFFFF);
1574418919fSjohnjiang hw->hw_cap.dmac_map_size = IPN3KE_MASK_READ_REG(hw,
1584418919fSjohnjiang (IPN3KE_HW_BASE + 0x44), 0, 0xFFFF);
1594418919fSjohnjiang hw->hw_cap.qm_offset = IPN3KE_MASK_READ_REG(hw,
1604418919fSjohnjiang (IPN3KE_HW_BASE + 0x48), 0, 0xFFFFFFFF);
1614418919fSjohnjiang hw->hw_cap.qm_size = IPN3KE_MASK_READ_REG(hw,
1624418919fSjohnjiang (IPN3KE_HW_BASE + 0x4C), 0, 0xFFFF);
1634418919fSjohnjiang hw->hw_cap.ccb_offset = IPN3KE_MASK_READ_REG(hw,
1644418919fSjohnjiang (IPN3KE_HW_BASE + 0x50), 0, 0xFFFFFFFF);
1654418919fSjohnjiang hw->hw_cap.ccb_entry_size = IPN3KE_MASK_READ_REG(hw,
1664418919fSjohnjiang (IPN3KE_HW_BASE + 0x54), 0, 0xFFFF);
1674418919fSjohnjiang hw->hw_cap.qos_offset = IPN3KE_MASK_READ_REG(hw,
1684418919fSjohnjiang (IPN3KE_HW_BASE + 0x58), 0, 0xFFFFFFFF);
1694418919fSjohnjiang hw->hw_cap.qos_size = IPN3KE_MASK_READ_REG(hw,
1704418919fSjohnjiang (IPN3KE_HW_BASE + 0x5C), 0, 0xFFFF);
1714418919fSjohnjiang
1724418919fSjohnjiang hw->hw_cap.num_rx_flow = IPN3KE_MASK_READ_REG(hw,
1734418919fSjohnjiang IPN3KE_CAPABILITY_REGISTERS_BLOCK_OFFSET,
1744418919fSjohnjiang 0, 0xFFFF);
1754418919fSjohnjiang hw->hw_cap.num_rss_blocks = IPN3KE_MASK_READ_REG(hw,
1764418919fSjohnjiang IPN3KE_CAPABILITY_REGISTERS_BLOCK_OFFSET,
1774418919fSjohnjiang 4, 0xFFFF);
1784418919fSjohnjiang hw->hw_cap.num_dmac_map = IPN3KE_MASK_READ_REG(hw,
1794418919fSjohnjiang IPN3KE_CAPABILITY_REGISTERS_BLOCK_OFFSET,
1804418919fSjohnjiang 8, 0xFFFF);
1814418919fSjohnjiang hw->hw_cap.num_tx_flow = IPN3KE_MASK_READ_REG(hw,
1824418919fSjohnjiang IPN3KE_CAPABILITY_REGISTERS_BLOCK_OFFSET,
1834418919fSjohnjiang 0xC, 0xFFFF);
1844418919fSjohnjiang hw->hw_cap.num_smac_map = IPN3KE_MASK_READ_REG(hw,
1854418919fSjohnjiang IPN3KE_CAPABILITY_REGISTERS_BLOCK_OFFSET,
1864418919fSjohnjiang 0x10, 0xFFFF);
1874418919fSjohnjiang
1884418919fSjohnjiang hw->hw_cap.link_speed_mbps = IPN3KE_MASK_READ_REG(hw,
1894418919fSjohnjiang IPN3KE_STATUS_REGISTERS_BLOCK_OFFSET,
1904418919fSjohnjiang 0, 0xFFFFF);
1914418919fSjohnjiang }
1924418919fSjohnjiang
1934418919fSjohnjiang static int
ipn3ke_vbng_init_done(struct ipn3ke_hw * hw)1944418919fSjohnjiang ipn3ke_vbng_init_done(struct ipn3ke_hw *hw)
1954418919fSjohnjiang {
1964418919fSjohnjiang uint32_t timeout = 10000;
1974418919fSjohnjiang while (timeout > 0) {
1984418919fSjohnjiang if (IPN3KE_READ_REG(hw, IPN3KE_VBNG_INIT_STS)
1994418919fSjohnjiang == IPN3KE_VBNG_INIT_DONE)
2004418919fSjohnjiang break;
2014418919fSjohnjiang rte_delay_us(1000);
2024418919fSjohnjiang timeout--;
2034418919fSjohnjiang }
2044418919fSjohnjiang
2054418919fSjohnjiang if (!timeout) {
2064418919fSjohnjiang IPN3KE_AFU_PMD_ERR("IPN3KE vBNG INIT timeout.\n");
2074418919fSjohnjiang return -1;
2084418919fSjohnjiang }
2094418919fSjohnjiang
2104418919fSjohnjiang return 0;
2114418919fSjohnjiang }
2124418919fSjohnjiang
2134418919fSjohnjiang static uint32_t
ipn3ke_mtu_cal(uint32_t tx,uint32_t rx)2144418919fSjohnjiang ipn3ke_mtu_cal(uint32_t tx, uint32_t rx)
2154418919fSjohnjiang {
2164418919fSjohnjiang uint32_t tmp;
2174418919fSjohnjiang tmp = RTE_MIN(tx, rx);
2184418919fSjohnjiang tmp = RTE_MAX(tmp, (uint32_t)RTE_ETHER_MIN_MTU);
2194418919fSjohnjiang tmp = RTE_MIN(tmp, (uint32_t)(IPN3KE_MAC_FRAME_SIZE_MAX -
2204418919fSjohnjiang IPN3KE_ETH_OVERHEAD));
2214418919fSjohnjiang return tmp;
2224418919fSjohnjiang }
2234418919fSjohnjiang
2244418919fSjohnjiang static void
ipn3ke_mtu_set(struct ipn3ke_hw * hw,uint32_t mac_num,uint32_t eth_group_sel,uint32_t txaddr,uint32_t rxaddr)2254418919fSjohnjiang ipn3ke_mtu_set(struct ipn3ke_hw *hw, uint32_t mac_num,
2264418919fSjohnjiang uint32_t eth_group_sel, uint32_t txaddr, uint32_t rxaddr)
2274418919fSjohnjiang {
2284418919fSjohnjiang uint32_t tx;
2294418919fSjohnjiang uint32_t rx;
2304418919fSjohnjiang uint32_t tmp;
2314418919fSjohnjiang
2324418919fSjohnjiang if (!(*hw->f_mac_read) || !(*hw->f_mac_write))
2334418919fSjohnjiang return;
2344418919fSjohnjiang
2354418919fSjohnjiang (*hw->f_mac_read)(hw,
2364418919fSjohnjiang &tx,
2374418919fSjohnjiang txaddr,
2384418919fSjohnjiang mac_num,
2394418919fSjohnjiang eth_group_sel);
2404418919fSjohnjiang
2414418919fSjohnjiang (*hw->f_mac_read)(hw,
2424418919fSjohnjiang &rx,
2434418919fSjohnjiang rxaddr,
2444418919fSjohnjiang mac_num,
2454418919fSjohnjiang eth_group_sel);
2464418919fSjohnjiang
2474418919fSjohnjiang tmp = ipn3ke_mtu_cal(tx, rx);
2484418919fSjohnjiang
2494418919fSjohnjiang (*hw->f_mac_write)(hw,
2504418919fSjohnjiang tmp,
2514418919fSjohnjiang txaddr,
2524418919fSjohnjiang mac_num,
2534418919fSjohnjiang eth_group_sel);
2544418919fSjohnjiang
2554418919fSjohnjiang (*hw->f_mac_write)(hw,
2564418919fSjohnjiang tmp,
2574418919fSjohnjiang rxaddr,
2584418919fSjohnjiang mac_num,
2594418919fSjohnjiang eth_group_sel);
2604418919fSjohnjiang }
2614418919fSjohnjiang
2624418919fSjohnjiang static void
ipn3ke_10G_mtu_setup(struct ipn3ke_hw * hw,uint32_t mac_num,uint32_t eth_group_sel)2634418919fSjohnjiang ipn3ke_10G_mtu_setup(struct ipn3ke_hw *hw, uint32_t mac_num,
2644418919fSjohnjiang uint32_t eth_group_sel)
2654418919fSjohnjiang {
2664418919fSjohnjiang ipn3ke_mtu_set(hw, mac_num, eth_group_sel,
2674418919fSjohnjiang IPN3KE_10G_TX_FRAME_MAXLENGTH, IPN3KE_10G_RX_FRAME_MAXLENGTH);
2684418919fSjohnjiang }
2694418919fSjohnjiang
2704418919fSjohnjiang static void
ipn3ke_25G_mtu_setup(struct ipn3ke_hw * hw,uint32_t mac_num,uint32_t eth_group_sel)2714418919fSjohnjiang ipn3ke_25G_mtu_setup(struct ipn3ke_hw *hw, uint32_t mac_num,
2724418919fSjohnjiang uint32_t eth_group_sel)
2734418919fSjohnjiang {
2744418919fSjohnjiang ipn3ke_mtu_set(hw, mac_num, eth_group_sel,
2754418919fSjohnjiang IPN3KE_25G_MAX_TX_SIZE_CONFIG, IPN3KE_25G_MAX_RX_SIZE_CONFIG);
2764418919fSjohnjiang }
2774418919fSjohnjiang
2784418919fSjohnjiang static void
ipn3ke_mtu_setup(struct ipn3ke_hw * hw)2794418919fSjohnjiang ipn3ke_mtu_setup(struct ipn3ke_hw *hw)
2804418919fSjohnjiang {
2814418919fSjohnjiang int i;
2824418919fSjohnjiang if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
2834418919fSjohnjiang for (i = 0; i < hw->port_num; i++) {
2844418919fSjohnjiang ipn3ke_10G_mtu_setup(hw, i, 0);
2854418919fSjohnjiang ipn3ke_10G_mtu_setup(hw, i, 1);
2864418919fSjohnjiang }
2874418919fSjohnjiang } else if (hw->retimer.mac_type ==
2884418919fSjohnjiang IFPGA_RAWDEV_RETIMER_MAC_TYPE_25GE_25GAUI) {
2894418919fSjohnjiang for (i = 0; i < hw->port_num; i++) {
2904418919fSjohnjiang ipn3ke_25G_mtu_setup(hw, i, 0);
2914418919fSjohnjiang ipn3ke_25G_mtu_setup(hw, i, 1);
2924418919fSjohnjiang }
2934418919fSjohnjiang }
2944418919fSjohnjiang }
2954418919fSjohnjiang
2964418919fSjohnjiang static int
ipn3ke_hw_init(struct rte_afu_device * afu_dev,struct ipn3ke_hw * hw)2974418919fSjohnjiang ipn3ke_hw_init(struct rte_afu_device *afu_dev,
2984418919fSjohnjiang struct ipn3ke_hw *hw)
2994418919fSjohnjiang {
3004418919fSjohnjiang struct rte_rawdev *rawdev;
3014418919fSjohnjiang int ret;
3024418919fSjohnjiang int i;
3034418919fSjohnjiang uint64_t port_num, mac_type, index;
3044418919fSjohnjiang
3054418919fSjohnjiang rawdev = afu_dev->rawdev;
3064418919fSjohnjiang
3074418919fSjohnjiang hw->afu_id.uuid.uuid_low = afu_dev->id.uuid.uuid_low;
3084418919fSjohnjiang hw->afu_id.uuid.uuid_high = afu_dev->id.uuid.uuid_high;
3094418919fSjohnjiang hw->afu_id.port = afu_dev->id.port;
3104418919fSjohnjiang hw->hw_addr = (uint8_t *)(afu_dev->mem_resource[0].addr);
3114418919fSjohnjiang hw->f_mac_read = ipn3ke_indirect_mac_read;
3124418919fSjohnjiang hw->f_mac_write = ipn3ke_indirect_mac_write;
3134418919fSjohnjiang hw->rawdev = rawdev;
3144418919fSjohnjiang rawdev->dev_ops->attr_get(rawdev,
3154418919fSjohnjiang "LineSideBARIndex", &index);
3164418919fSjohnjiang hw->eth_group_bar[0] = (uint8_t *)(afu_dev->mem_resource[index].addr);
3174418919fSjohnjiang rawdev->dev_ops->attr_get(rawdev,
3184418919fSjohnjiang "NICSideBARIndex", &index);
3194418919fSjohnjiang hw->eth_group_bar[1] = (uint8_t *)(afu_dev->mem_resource[index].addr);
3204418919fSjohnjiang rawdev->dev_ops->attr_get(rawdev,
3214418919fSjohnjiang "LineSideLinkPortNum", &port_num);
3224418919fSjohnjiang hw->retimer.port_num = (int)port_num;
3234418919fSjohnjiang hw->port_num = hw->retimer.port_num;
3244418919fSjohnjiang rawdev->dev_ops->attr_get(rawdev,
3254418919fSjohnjiang "LineSideMACType", &mac_type);
3264418919fSjohnjiang hw->retimer.mac_type = (int)mac_type;
3274418919fSjohnjiang
3284418919fSjohnjiang hw->acc_tm = 0;
3294418919fSjohnjiang hw->acc_flow = 0;
3304418919fSjohnjiang
3314418919fSjohnjiang if (afu_dev->id.uuid.uuid_low == IPN3KE_UUID_VBNG_LOW &&
3324418919fSjohnjiang afu_dev->id.uuid.uuid_high == IPN3KE_UUID_VBNG_HIGH) {
3334418919fSjohnjiang /* After power on, wait until init done */
3344418919fSjohnjiang if (ipn3ke_vbng_init_done(hw))
3354418919fSjohnjiang return -1;
3364418919fSjohnjiang
3374418919fSjohnjiang ipn3ke_hw_cap_init(hw);
3384418919fSjohnjiang
3394418919fSjohnjiang /* Reset vBNG IP */
3404418919fSjohnjiang IPN3KE_WRITE_REG(hw, IPN3KE_CTRL_RESET, 1);
3414418919fSjohnjiang rte_delay_us(10);
3424418919fSjohnjiang IPN3KE_WRITE_REG(hw, IPN3KE_CTRL_RESET, 0);
3434418919fSjohnjiang
3444418919fSjohnjiang /* After reset, wait until init done */
3454418919fSjohnjiang if (ipn3ke_vbng_init_done(hw))
3464418919fSjohnjiang return -1;
3474418919fSjohnjiang
3484418919fSjohnjiang hw->acc_tm = 1;
3494418919fSjohnjiang hw->acc_flow = 1;
3504418919fSjohnjiang
3514418919fSjohnjiang IPN3KE_AFU_PMD_DEBUG("UPL_version is 0x%x\n",
3524418919fSjohnjiang IPN3KE_READ_REG(hw, 0));
3534418919fSjohnjiang }
3544418919fSjohnjiang
3554418919fSjohnjiang if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
3564418919fSjohnjiang /* Enable inter connect channel */
3574418919fSjohnjiang for (i = 0; i < hw->port_num; i++) {
3584418919fSjohnjiang /* Enable the TX path */
3594418919fSjohnjiang ipn3ke_xmac_tx_enable(hw, i, 1);
3604418919fSjohnjiang
3614418919fSjohnjiang /* Disables source address override */
3624418919fSjohnjiang ipn3ke_xmac_smac_ovd_dis(hw, i, 1);
3634418919fSjohnjiang
3644418919fSjohnjiang /* Enable the RX path */
3654418919fSjohnjiang ipn3ke_xmac_rx_enable(hw, i, 1);
3664418919fSjohnjiang
3674418919fSjohnjiang /* Clear NIC side TX statistics counters */
3684418919fSjohnjiang ipn3ke_xmac_tx_clr_10G_stcs(hw, i, 1);
3694418919fSjohnjiang
3704418919fSjohnjiang /* Clear NIC side RX statistics counters */
3714418919fSjohnjiang ipn3ke_xmac_rx_clr_10G_stcs(hw, i, 1);
3724418919fSjohnjiang
3734418919fSjohnjiang /* Clear line side TX statistics counters */
3744418919fSjohnjiang ipn3ke_xmac_tx_clr_10G_stcs(hw, i, 0);
3754418919fSjohnjiang
3764418919fSjohnjiang /* Clear line RX statistics counters */
3774418919fSjohnjiang ipn3ke_xmac_rx_clr_10G_stcs(hw, i, 0);
3784418919fSjohnjiang }
3794418919fSjohnjiang } else if (hw->retimer.mac_type ==
3804418919fSjohnjiang IFPGA_RAWDEV_RETIMER_MAC_TYPE_25GE_25GAUI) {
3814418919fSjohnjiang /* Enable inter connect channel */
3824418919fSjohnjiang for (i = 0; i < hw->port_num; i++) {
3834418919fSjohnjiang /* Clear NIC side TX statistics counters */
3844418919fSjohnjiang ipn3ke_xmac_tx_clr_25G_stcs(hw, i, 1);
3854418919fSjohnjiang
3864418919fSjohnjiang /* Clear NIC side RX statistics counters */
3874418919fSjohnjiang ipn3ke_xmac_rx_clr_25G_stcs(hw, i, 1);
3884418919fSjohnjiang
3894418919fSjohnjiang /* Clear line side TX statistics counters */
3904418919fSjohnjiang ipn3ke_xmac_tx_clr_25G_stcs(hw, i, 0);
3914418919fSjohnjiang
3924418919fSjohnjiang /* Clear line side RX statistics counters */
3934418919fSjohnjiang ipn3ke_xmac_rx_clr_25G_stcs(hw, i, 0);
3944418919fSjohnjiang }
3954418919fSjohnjiang }
3964418919fSjohnjiang
3974418919fSjohnjiang /* init mtu */
3984418919fSjohnjiang ipn3ke_mtu_setup(hw);
3994418919fSjohnjiang
4004418919fSjohnjiang ret = rte_eth_switch_domain_alloc(&hw->switch_domain_id);
4014418919fSjohnjiang if (ret)
4024418919fSjohnjiang IPN3KE_AFU_PMD_WARN("failed to allocate switch domain for device %d",
4034418919fSjohnjiang ret);
4044418919fSjohnjiang
4054418919fSjohnjiang hw->tm_hw_enable = 0;
4064418919fSjohnjiang hw->flow_hw_enable = 0;
4074418919fSjohnjiang if (afu_dev->id.uuid.uuid_low == IPN3KE_UUID_VBNG_LOW &&
4084418919fSjohnjiang afu_dev->id.uuid.uuid_high == IPN3KE_UUID_VBNG_HIGH) {
4094418919fSjohnjiang ret = ipn3ke_hw_tm_init(hw);
4104418919fSjohnjiang if (ret)
4114418919fSjohnjiang return ret;
4124418919fSjohnjiang hw->tm_hw_enable = 1;
4134418919fSjohnjiang
4144418919fSjohnjiang ret = ipn3ke_flow_init(hw);
4154418919fSjohnjiang if (ret)
4164418919fSjohnjiang return ret;
4174418919fSjohnjiang hw->flow_hw_enable = 1;
4184418919fSjohnjiang }
4194418919fSjohnjiang
4204418919fSjohnjiang return 0;
4214418919fSjohnjiang }
4224418919fSjohnjiang
4234418919fSjohnjiang static void
ipn3ke_hw_uninit(struct ipn3ke_hw * hw)4244418919fSjohnjiang ipn3ke_hw_uninit(struct ipn3ke_hw *hw)
4254418919fSjohnjiang {
4264418919fSjohnjiang int i;
4274418919fSjohnjiang
4284418919fSjohnjiang if (hw->retimer.mac_type == IFPGA_RAWDEV_RETIMER_MAC_TYPE_10GE_XFI) {
4294418919fSjohnjiang for (i = 0; i < hw->port_num; i++) {
4304418919fSjohnjiang /* Disable the TX path */
4314418919fSjohnjiang ipn3ke_xmac_tx_disable(hw, i, 1);
4324418919fSjohnjiang
4334418919fSjohnjiang /* Disable the RX path */
4344418919fSjohnjiang ipn3ke_xmac_rx_disable(hw, i, 1);
4354418919fSjohnjiang
4364418919fSjohnjiang /* Clear NIC side TX statistics counters */
4374418919fSjohnjiang ipn3ke_xmac_tx_clr_10G_stcs(hw, i, 1);
4384418919fSjohnjiang
4394418919fSjohnjiang /* Clear NIC side RX statistics counters */
4404418919fSjohnjiang ipn3ke_xmac_rx_clr_10G_stcs(hw, i, 1);
4414418919fSjohnjiang
4424418919fSjohnjiang /* Clear line side TX statistics counters */
4434418919fSjohnjiang ipn3ke_xmac_tx_clr_10G_stcs(hw, i, 0);
4444418919fSjohnjiang
4454418919fSjohnjiang /* Clear line side RX statistics counters */
4464418919fSjohnjiang ipn3ke_xmac_rx_clr_10G_stcs(hw, i, 0);
4474418919fSjohnjiang }
4484418919fSjohnjiang } else if (hw->retimer.mac_type ==
4494418919fSjohnjiang IFPGA_RAWDEV_RETIMER_MAC_TYPE_25GE_25GAUI) {
4504418919fSjohnjiang for (i = 0; i < hw->port_num; i++) {
4514418919fSjohnjiang /* Clear NIC side TX statistics counters */
4524418919fSjohnjiang ipn3ke_xmac_tx_clr_25G_stcs(hw, i, 1);
4534418919fSjohnjiang
4544418919fSjohnjiang /* Clear NIC side RX statistics counters */
4554418919fSjohnjiang ipn3ke_xmac_rx_clr_25G_stcs(hw, i, 1);
4564418919fSjohnjiang
4574418919fSjohnjiang /* Clear line side TX statistics counters */
4584418919fSjohnjiang ipn3ke_xmac_tx_clr_25G_stcs(hw, i, 0);
4594418919fSjohnjiang
4604418919fSjohnjiang /* Clear line side RX statistics counters */
4614418919fSjohnjiang ipn3ke_xmac_rx_clr_25G_stcs(hw, i, 0);
4624418919fSjohnjiang }
4634418919fSjohnjiang }
4644418919fSjohnjiang }
4654418919fSjohnjiang
ipn3ke_vswitch_probe(struct rte_afu_device * afu_dev)4664418919fSjohnjiang static int ipn3ke_vswitch_probe(struct rte_afu_device *afu_dev)
4674418919fSjohnjiang {
4684418919fSjohnjiang char name[RTE_ETH_NAME_MAX_LEN];
4694418919fSjohnjiang struct ipn3ke_hw *hw;
4704418919fSjohnjiang struct rte_eth_dev *i40e_eth;
4714418919fSjohnjiang struct ifpga_rawdev *ifpga_dev;
4724418919fSjohnjiang uint16_t port_id;
4734418919fSjohnjiang int i, j, retval;
4744418919fSjohnjiang char *fvl_bdf;
4754418919fSjohnjiang
4764418919fSjohnjiang /* check if the AFU device has been probed already */
4774418919fSjohnjiang /* allocate shared mcp_vswitch structure */
4784418919fSjohnjiang if (!afu_dev->shared.data) {
4794418919fSjohnjiang snprintf(name, sizeof(name), "net_%s_hw",
4804418919fSjohnjiang afu_dev->device.name);
4814418919fSjohnjiang hw = rte_zmalloc_socket(name,
4824418919fSjohnjiang sizeof(struct ipn3ke_hw),
4834418919fSjohnjiang RTE_CACHE_LINE_SIZE,
4844418919fSjohnjiang afu_dev->device.numa_node);
4854418919fSjohnjiang if (!hw) {
4864418919fSjohnjiang IPN3KE_AFU_PMD_ERR("failed to allocate hardwart data");
4874418919fSjohnjiang retval = -ENOMEM;
4884418919fSjohnjiang return -ENOMEM;
4894418919fSjohnjiang }
4904418919fSjohnjiang afu_dev->shared.data = hw;
4914418919fSjohnjiang
4924418919fSjohnjiang rte_spinlock_init(&afu_dev->shared.lock);
4934418919fSjohnjiang } else {
4944418919fSjohnjiang hw = afu_dev->shared.data;
4954418919fSjohnjiang }
4964418919fSjohnjiang
4974418919fSjohnjiang retval = ipn3ke_hw_init(afu_dev, hw);
4984418919fSjohnjiang if (retval)
4994418919fSjohnjiang return retval;
5004418919fSjohnjiang
5014418919fSjohnjiang if (ipn3ke_bridge_func.get_ifpga_rawdev == NULL)
5024418919fSjohnjiang return -ENOMEM;
5034418919fSjohnjiang ifpga_dev = ipn3ke_bridge_func.get_ifpga_rawdev(hw->rawdev);
5044418919fSjohnjiang if (!ifpga_dev)
5054418919fSjohnjiang IPN3KE_AFU_PMD_ERR("failed to find ifpga_device.");
5064418919fSjohnjiang
5074418919fSjohnjiang /* probe representor ports */
5084418919fSjohnjiang j = 0;
5094418919fSjohnjiang for (i = 0; i < hw->port_num; i++) {
5104418919fSjohnjiang struct ipn3ke_rpst rpst = {
5114418919fSjohnjiang .port_id = i,
5124418919fSjohnjiang .switch_domain_id = hw->switch_domain_id,
5134418919fSjohnjiang .hw = hw
5144418919fSjohnjiang };
5154418919fSjohnjiang
5164418919fSjohnjiang /* representor port net_bdf_port */
5174418919fSjohnjiang snprintf(name, sizeof(name), "net_%s_representor_%d",
5184418919fSjohnjiang afu_dev->device.name, i);
5194418919fSjohnjiang
5204418919fSjohnjiang for (; j < 8; j++) {
5214418919fSjohnjiang fvl_bdf = ifpga_dev->fvl_bdf[j];
5224418919fSjohnjiang retval = rte_eth_dev_get_port_by_name(fvl_bdf,
5234418919fSjohnjiang &port_id);
5244418919fSjohnjiang if (retval) {
5254418919fSjohnjiang continue;
5264418919fSjohnjiang } else {
5274418919fSjohnjiang i40e_eth = &rte_eth_devices[port_id];
5284418919fSjohnjiang rpst.i40e_pf_eth = i40e_eth;
5294418919fSjohnjiang rpst.i40e_pf_eth_port_id = port_id;
5304418919fSjohnjiang
5314418919fSjohnjiang j++;
5324418919fSjohnjiang break;
5334418919fSjohnjiang }
5344418919fSjohnjiang }
5354418919fSjohnjiang
5364418919fSjohnjiang retval = rte_eth_dev_create(&afu_dev->device, name,
5374418919fSjohnjiang sizeof(struct ipn3ke_rpst), NULL, NULL,
5384418919fSjohnjiang ipn3ke_rpst_init, &rpst);
5394418919fSjohnjiang
5404418919fSjohnjiang if (retval)
5414418919fSjohnjiang IPN3KE_AFU_PMD_ERR("failed to create ipn3ke representor %s.",
5424418919fSjohnjiang name);
5434418919fSjohnjiang
5444418919fSjohnjiang }
5454418919fSjohnjiang
5464418919fSjohnjiang return 0;
5474418919fSjohnjiang }
5484418919fSjohnjiang
ipn3ke_vswitch_remove(struct rte_afu_device * afu_dev)5494418919fSjohnjiang static int ipn3ke_vswitch_remove(struct rte_afu_device *afu_dev)
5504418919fSjohnjiang {
5514418919fSjohnjiang char name[RTE_ETH_NAME_MAX_LEN];
5524418919fSjohnjiang struct ipn3ke_hw *hw;
5534418919fSjohnjiang struct rte_eth_dev *ethdev;
5544418919fSjohnjiang int i, ret;
5554418919fSjohnjiang
5564418919fSjohnjiang hw = afu_dev->shared.data;
5574418919fSjohnjiang
5584418919fSjohnjiang /* remove representor ports */
5594418919fSjohnjiang for (i = 0; i < hw->port_num; i++) {
5604418919fSjohnjiang /* representor port net_bdf_port */
5614418919fSjohnjiang snprintf(name, sizeof(name), "net_%s_representor_%d",
5624418919fSjohnjiang afu_dev->device.name, i);
5634418919fSjohnjiang
5644418919fSjohnjiang ethdev = rte_eth_dev_allocated(afu_dev->device.name);
565*2d9fd380Sjfb8856606 if (ethdev != NULL)
5664418919fSjohnjiang rte_eth_dev_destroy(ethdev, ipn3ke_rpst_uninit);
5674418919fSjohnjiang }
5684418919fSjohnjiang
5694418919fSjohnjiang ret = rte_eth_switch_domain_free(hw->switch_domain_id);
5704418919fSjohnjiang if (ret)
5714418919fSjohnjiang IPN3KE_AFU_PMD_WARN("failed to free switch domain: %d", ret);
5724418919fSjohnjiang
5734418919fSjohnjiang /* hw uninit*/
5744418919fSjohnjiang ipn3ke_hw_uninit(hw);
5754418919fSjohnjiang
5764418919fSjohnjiang return 0;
5774418919fSjohnjiang }
5784418919fSjohnjiang
5794418919fSjohnjiang static struct rte_afu_driver afu_ipn3ke_driver = {
5804418919fSjohnjiang .id_table = afu_uuid_ipn3ke_map,
5814418919fSjohnjiang .probe = ipn3ke_vswitch_probe,
5824418919fSjohnjiang .remove = ipn3ke_vswitch_remove,
5834418919fSjohnjiang };
5844418919fSjohnjiang
5854418919fSjohnjiang RTE_PMD_REGISTER_AFU(net_ipn3ke_afu, afu_ipn3ke_driver);
586*2d9fd380Sjfb8856606 RTE_LOG_REGISTER(ipn3ke_afu_logtype, pmd.afu.ipn3ke, NOTICE);
587