17838e172SAlex Vesker // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 27838e172SAlex Vesker /* Copyright (c) 2019 Mellanox Technologies. */ 37838e172SAlex Vesker 47838e172SAlex Vesker #include "dr_types.h" 57838e172SAlex Vesker 6cc2295cdSYevgeny Kliteynik static int dr_table_set_miss_action_nic(struct mlx5dr_domain *dmn, 7cc2295cdSYevgeny Kliteynik struct mlx5dr_table_rx_tx *nic_tbl, 8cc2295cdSYevgeny Kliteynik struct mlx5dr_action *action) 9cc2295cdSYevgeny Kliteynik { 10cc2295cdSYevgeny Kliteynik struct mlx5dr_matcher_rx_tx *last_nic_matcher = NULL; 11cc2295cdSYevgeny Kliteynik struct mlx5dr_htbl_connect_info info; 12cc2295cdSYevgeny Kliteynik struct mlx5dr_ste_htbl *last_htbl; 13cc2295cdSYevgeny Kliteynik int ret; 14cc2295cdSYevgeny Kliteynik 15cc2295cdSYevgeny Kliteynik if (!list_empty(&nic_tbl->nic_matcher_list)) 16cc2295cdSYevgeny Kliteynik last_nic_matcher = list_last_entry(&nic_tbl->nic_matcher_list, 17cc2295cdSYevgeny Kliteynik struct mlx5dr_matcher_rx_tx, 18cc2295cdSYevgeny Kliteynik list_node); 19cc2295cdSYevgeny Kliteynik 20cc2295cdSYevgeny Kliteynik if (last_nic_matcher) 21cc2295cdSYevgeny Kliteynik last_htbl = last_nic_matcher->e_anchor; 22cc2295cdSYevgeny Kliteynik else 23cc2295cdSYevgeny Kliteynik last_htbl = nic_tbl->s_anchor; 24cc2295cdSYevgeny Kliteynik 25cc2295cdSYevgeny Kliteynik if (action) 26cc2295cdSYevgeny Kliteynik nic_tbl->default_icm_addr = 27cc2295cdSYevgeny Kliteynik nic_tbl->nic_dmn->type == DR_DOMAIN_NIC_TYPE_RX ? 28cc2295cdSYevgeny Kliteynik action->dest_tbl->tbl->rx.s_anchor->chunk->icm_addr : 29cc2295cdSYevgeny Kliteynik action->dest_tbl->tbl->tx.s_anchor->chunk->icm_addr; 30cc2295cdSYevgeny Kliteynik else 31cc2295cdSYevgeny Kliteynik nic_tbl->default_icm_addr = nic_tbl->nic_dmn->default_icm_addr; 32cc2295cdSYevgeny Kliteynik 33cc2295cdSYevgeny Kliteynik info.type = CONNECT_MISS; 34cc2295cdSYevgeny Kliteynik info.miss_icm_addr = nic_tbl->default_icm_addr; 35cc2295cdSYevgeny Kliteynik 36cc2295cdSYevgeny Kliteynik ret = mlx5dr_ste_htbl_init_and_postsend(dmn, nic_tbl->nic_dmn, 37cc2295cdSYevgeny Kliteynik last_htbl, &info, true); 38cc2295cdSYevgeny Kliteynik if (ret) 39cc2295cdSYevgeny Kliteynik mlx5dr_dbg(dmn, "Failed to set NIC RX/TX miss action, ret %d\n", ret); 40cc2295cdSYevgeny Kliteynik 41cc2295cdSYevgeny Kliteynik return ret; 42cc2295cdSYevgeny Kliteynik } 43cc2295cdSYevgeny Kliteynik 447838e172SAlex Vesker int mlx5dr_table_set_miss_action(struct mlx5dr_table *tbl, 457838e172SAlex Vesker struct mlx5dr_action *action) 467838e172SAlex Vesker { 477838e172SAlex Vesker int ret; 487838e172SAlex Vesker 497838e172SAlex Vesker if (action && action->action_type != DR_ACTION_TYP_FT) 507838e172SAlex Vesker return -EOPNOTSUPP; 517838e172SAlex Vesker 52ed03a418SAlex Vesker mlx5dr_domain_lock(tbl->dmn); 537838e172SAlex Vesker 547838e172SAlex Vesker if (tbl->dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX || 557838e172SAlex Vesker tbl->dmn->type == MLX5DR_DOMAIN_TYPE_FDB) { 56cc2295cdSYevgeny Kliteynik ret = dr_table_set_miss_action_nic(tbl->dmn, &tbl->rx, action); 57cc2295cdSYevgeny Kliteynik if (ret) 587838e172SAlex Vesker goto out; 597838e172SAlex Vesker } 607838e172SAlex Vesker 617838e172SAlex Vesker if (tbl->dmn->type == MLX5DR_DOMAIN_TYPE_NIC_TX || 627838e172SAlex Vesker tbl->dmn->type == MLX5DR_DOMAIN_TYPE_FDB) { 63cc2295cdSYevgeny Kliteynik ret = dr_table_set_miss_action_nic(tbl->dmn, &tbl->tx, action); 64cc2295cdSYevgeny Kliteynik if (ret) 657838e172SAlex Vesker goto out; 667838e172SAlex Vesker } 677838e172SAlex Vesker 687838e172SAlex Vesker /* Release old action */ 697838e172SAlex Vesker if (tbl->miss_action) 707838e172SAlex Vesker refcount_dec(&tbl->miss_action->refcount); 717838e172SAlex Vesker 727838e172SAlex Vesker /* Set new miss action */ 737838e172SAlex Vesker tbl->miss_action = action; 747838e172SAlex Vesker if (tbl->miss_action) 757838e172SAlex Vesker refcount_inc(&action->refcount); 767838e172SAlex Vesker 777838e172SAlex Vesker out: 78ed03a418SAlex Vesker mlx5dr_domain_unlock(tbl->dmn); 797838e172SAlex Vesker return ret; 807838e172SAlex Vesker } 817838e172SAlex Vesker 827838e172SAlex Vesker static void dr_table_uninit_nic(struct mlx5dr_table_rx_tx *nic_tbl) 837838e172SAlex Vesker { 847838e172SAlex Vesker mlx5dr_htbl_put(nic_tbl->s_anchor); 857838e172SAlex Vesker } 867838e172SAlex Vesker 877838e172SAlex Vesker static void dr_table_uninit_fdb(struct mlx5dr_table *tbl) 887838e172SAlex Vesker { 897838e172SAlex Vesker dr_table_uninit_nic(&tbl->rx); 907838e172SAlex Vesker dr_table_uninit_nic(&tbl->tx); 917838e172SAlex Vesker } 927838e172SAlex Vesker 937838e172SAlex Vesker static void dr_table_uninit(struct mlx5dr_table *tbl) 947838e172SAlex Vesker { 95ed03a418SAlex Vesker mlx5dr_domain_lock(tbl->dmn); 967838e172SAlex Vesker 977838e172SAlex Vesker switch (tbl->dmn->type) { 987838e172SAlex Vesker case MLX5DR_DOMAIN_TYPE_NIC_RX: 997838e172SAlex Vesker dr_table_uninit_nic(&tbl->rx); 1007838e172SAlex Vesker break; 1017838e172SAlex Vesker case MLX5DR_DOMAIN_TYPE_NIC_TX: 1027838e172SAlex Vesker dr_table_uninit_nic(&tbl->tx); 1037838e172SAlex Vesker break; 1047838e172SAlex Vesker case MLX5DR_DOMAIN_TYPE_FDB: 1057838e172SAlex Vesker dr_table_uninit_fdb(tbl); 1067838e172SAlex Vesker break; 1077838e172SAlex Vesker default: 1087838e172SAlex Vesker WARN_ON(true); 1097838e172SAlex Vesker break; 1107838e172SAlex Vesker } 1117838e172SAlex Vesker 112ed03a418SAlex Vesker mlx5dr_domain_unlock(tbl->dmn); 1137838e172SAlex Vesker } 1147838e172SAlex Vesker 1157838e172SAlex Vesker static int dr_table_init_nic(struct mlx5dr_domain *dmn, 1167838e172SAlex Vesker struct mlx5dr_table_rx_tx *nic_tbl) 1177838e172SAlex Vesker { 1187838e172SAlex Vesker struct mlx5dr_domain_rx_tx *nic_dmn = nic_tbl->nic_dmn; 1197838e172SAlex Vesker struct mlx5dr_htbl_connect_info info; 1207838e172SAlex Vesker int ret; 1217838e172SAlex Vesker 122cc2295cdSYevgeny Kliteynik INIT_LIST_HEAD(&nic_tbl->nic_matcher_list); 123cc2295cdSYevgeny Kliteynik 1247838e172SAlex Vesker nic_tbl->default_icm_addr = nic_dmn->default_icm_addr; 1257838e172SAlex Vesker 1267838e172SAlex Vesker nic_tbl->s_anchor = mlx5dr_ste_htbl_alloc(dmn->ste_icm_pool, 1277838e172SAlex Vesker DR_CHUNK_SIZE_1, 1287838e172SAlex Vesker MLX5DR_STE_LU_TYPE_DONT_CARE, 1297838e172SAlex Vesker 0); 130b7d0db55SErez Shitrit if (!nic_tbl->s_anchor) { 131b7d0db55SErez Shitrit mlx5dr_err(dmn, "Failed allocating htbl\n"); 1327838e172SAlex Vesker return -ENOMEM; 133b7d0db55SErez Shitrit } 1347838e172SAlex Vesker 1357838e172SAlex Vesker info.type = CONNECT_MISS; 1367838e172SAlex Vesker info.miss_icm_addr = nic_dmn->default_icm_addr; 1377838e172SAlex Vesker ret = mlx5dr_ste_htbl_init_and_postsend(dmn, nic_dmn, 1387838e172SAlex Vesker nic_tbl->s_anchor, 1397838e172SAlex Vesker &info, true); 140b7d0db55SErez Shitrit if (ret) { 141b7d0db55SErez Shitrit mlx5dr_err(dmn, "Failed int and send htbl\n"); 1427838e172SAlex Vesker goto free_s_anchor; 143b7d0db55SErez Shitrit } 1447838e172SAlex Vesker 1457838e172SAlex Vesker mlx5dr_htbl_get(nic_tbl->s_anchor); 1467838e172SAlex Vesker 1477838e172SAlex Vesker return 0; 1487838e172SAlex Vesker 1497838e172SAlex Vesker free_s_anchor: 1507838e172SAlex Vesker mlx5dr_ste_htbl_free(nic_tbl->s_anchor); 1517838e172SAlex Vesker return ret; 1527838e172SAlex Vesker } 1537838e172SAlex Vesker 1547838e172SAlex Vesker static int dr_table_init_fdb(struct mlx5dr_table *tbl) 1557838e172SAlex Vesker { 1567838e172SAlex Vesker int ret; 1577838e172SAlex Vesker 1587838e172SAlex Vesker ret = dr_table_init_nic(tbl->dmn, &tbl->rx); 1597838e172SAlex Vesker if (ret) 1607838e172SAlex Vesker return ret; 1617838e172SAlex Vesker 1627838e172SAlex Vesker ret = dr_table_init_nic(tbl->dmn, &tbl->tx); 1637838e172SAlex Vesker if (ret) 1647838e172SAlex Vesker goto destroy_rx; 1657838e172SAlex Vesker 1667838e172SAlex Vesker return 0; 1677838e172SAlex Vesker 1687838e172SAlex Vesker destroy_rx: 1697838e172SAlex Vesker dr_table_uninit_nic(&tbl->rx); 1707838e172SAlex Vesker return ret; 1717838e172SAlex Vesker } 1727838e172SAlex Vesker 1737838e172SAlex Vesker static int dr_table_init(struct mlx5dr_table *tbl) 1747838e172SAlex Vesker { 1757838e172SAlex Vesker int ret = 0; 1767838e172SAlex Vesker 1777838e172SAlex Vesker INIT_LIST_HEAD(&tbl->matcher_list); 1787838e172SAlex Vesker 179ed03a418SAlex Vesker mlx5dr_domain_lock(tbl->dmn); 1807838e172SAlex Vesker 1817838e172SAlex Vesker switch (tbl->dmn->type) { 1827838e172SAlex Vesker case MLX5DR_DOMAIN_TYPE_NIC_RX: 1837838e172SAlex Vesker tbl->table_type = MLX5_FLOW_TABLE_TYPE_NIC_RX; 1847838e172SAlex Vesker tbl->rx.nic_dmn = &tbl->dmn->info.rx; 1857838e172SAlex Vesker ret = dr_table_init_nic(tbl->dmn, &tbl->rx); 1867838e172SAlex Vesker break; 1877838e172SAlex Vesker case MLX5DR_DOMAIN_TYPE_NIC_TX: 1887838e172SAlex Vesker tbl->table_type = MLX5_FLOW_TABLE_TYPE_NIC_TX; 1897838e172SAlex Vesker tbl->tx.nic_dmn = &tbl->dmn->info.tx; 1907838e172SAlex Vesker ret = dr_table_init_nic(tbl->dmn, &tbl->tx); 1917838e172SAlex Vesker break; 1927838e172SAlex Vesker case MLX5DR_DOMAIN_TYPE_FDB: 1937838e172SAlex Vesker tbl->table_type = MLX5_FLOW_TABLE_TYPE_FDB; 1947838e172SAlex Vesker tbl->rx.nic_dmn = &tbl->dmn->info.rx; 1957838e172SAlex Vesker tbl->tx.nic_dmn = &tbl->dmn->info.tx; 1967838e172SAlex Vesker ret = dr_table_init_fdb(tbl); 1977838e172SAlex Vesker break; 1987838e172SAlex Vesker default: 1997838e172SAlex Vesker WARN_ON(true); 2007838e172SAlex Vesker break; 2017838e172SAlex Vesker } 2027838e172SAlex Vesker 203ed03a418SAlex Vesker mlx5dr_domain_unlock(tbl->dmn); 2047838e172SAlex Vesker 2057838e172SAlex Vesker return ret; 2067838e172SAlex Vesker } 2077838e172SAlex Vesker 2087838e172SAlex Vesker static int dr_table_destroy_sw_owned_tbl(struct mlx5dr_table *tbl) 2097838e172SAlex Vesker { 2107838e172SAlex Vesker return mlx5dr_cmd_destroy_flow_table(tbl->dmn->mdev, 2117838e172SAlex Vesker tbl->table_id, 2127838e172SAlex Vesker tbl->table_type); 2137838e172SAlex Vesker } 2147838e172SAlex Vesker 2157838e172SAlex Vesker static int dr_table_create_sw_owned_tbl(struct mlx5dr_table *tbl) 2167838e172SAlex Vesker { 217988fd6b3SErez Shitrit bool en_encap = !!(tbl->flags & MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT); 218988fd6b3SErez Shitrit bool en_decap = !!(tbl->flags & MLX5_FLOW_TABLE_TUNNEL_EN_DECAP); 219cc78dbd7SAlex Vesker struct mlx5dr_cmd_create_flow_table_attr ft_attr = {}; 2207838e172SAlex Vesker u64 icm_addr_rx = 0; 2217838e172SAlex Vesker u64 icm_addr_tx = 0; 2227838e172SAlex Vesker int ret; 2237838e172SAlex Vesker 2247838e172SAlex Vesker if (tbl->rx.s_anchor) 2257838e172SAlex Vesker icm_addr_rx = tbl->rx.s_anchor->chunk->icm_addr; 2267838e172SAlex Vesker 2277838e172SAlex Vesker if (tbl->tx.s_anchor) 2287838e172SAlex Vesker icm_addr_tx = tbl->tx.s_anchor->chunk->icm_addr; 2297838e172SAlex Vesker 230cc78dbd7SAlex Vesker ft_attr.table_type = tbl->table_type; 231cc78dbd7SAlex Vesker ft_attr.icm_addr_rx = icm_addr_rx; 232cc78dbd7SAlex Vesker ft_attr.icm_addr_tx = icm_addr_tx; 233cc78dbd7SAlex Vesker ft_attr.level = tbl->dmn->info.caps.max_ft_level - 1; 234cc78dbd7SAlex Vesker ft_attr.sw_owner = true; 235988fd6b3SErez Shitrit ft_attr.decap_en = en_decap; 236988fd6b3SErez Shitrit ft_attr.reformat_en = en_encap; 237cc78dbd7SAlex Vesker 238cc78dbd7SAlex Vesker ret = mlx5dr_cmd_create_flow_table(tbl->dmn->mdev, &ft_attr, 239cc78dbd7SAlex Vesker NULL, &tbl->table_id); 2407838e172SAlex Vesker 2417838e172SAlex Vesker return ret; 2427838e172SAlex Vesker } 2437838e172SAlex Vesker 244988fd6b3SErez Shitrit struct mlx5dr_table *mlx5dr_table_create(struct mlx5dr_domain *dmn, u32 level, u32 flags) 2457838e172SAlex Vesker { 2467838e172SAlex Vesker struct mlx5dr_table *tbl; 2477838e172SAlex Vesker int ret; 2487838e172SAlex Vesker 2497838e172SAlex Vesker refcount_inc(&dmn->refcount); 2507838e172SAlex Vesker 2517838e172SAlex Vesker tbl = kzalloc(sizeof(*tbl), GFP_KERNEL); 2527838e172SAlex Vesker if (!tbl) 2537838e172SAlex Vesker goto dec_ref; 2547838e172SAlex Vesker 2557838e172SAlex Vesker tbl->dmn = dmn; 2567838e172SAlex Vesker tbl->level = level; 257988fd6b3SErez Shitrit tbl->flags = flags; 2587838e172SAlex Vesker refcount_set(&tbl->refcount, 1); 2597838e172SAlex Vesker 2607838e172SAlex Vesker ret = dr_table_init(tbl); 2617838e172SAlex Vesker if (ret) 2627838e172SAlex Vesker goto free_tbl; 2637838e172SAlex Vesker 2647838e172SAlex Vesker ret = dr_table_create_sw_owned_tbl(tbl); 2657838e172SAlex Vesker if (ret) 2667838e172SAlex Vesker goto uninit_tbl; 2677838e172SAlex Vesker 2689222f0b2SMuhammad Sammar INIT_LIST_HEAD(&tbl->dbg_node); 2699222f0b2SMuhammad Sammar mlx5dr_dbg_tbl_add(tbl); 2707838e172SAlex Vesker return tbl; 2717838e172SAlex Vesker 2727838e172SAlex Vesker uninit_tbl: 2737838e172SAlex Vesker dr_table_uninit(tbl); 2747838e172SAlex Vesker free_tbl: 2757838e172SAlex Vesker kfree(tbl); 2767838e172SAlex Vesker dec_ref: 2777838e172SAlex Vesker refcount_dec(&dmn->refcount); 2787838e172SAlex Vesker return NULL; 2797838e172SAlex Vesker } 2807838e172SAlex Vesker 2817838e172SAlex Vesker int mlx5dr_table_destroy(struct mlx5dr_table *tbl) 2827838e172SAlex Vesker { 2837838e172SAlex Vesker int ret; 2847838e172SAlex Vesker 285b5412827SYevgeny Kliteynik if (WARN_ON_ONCE(refcount_read(&tbl->refcount) > 1)) 2867838e172SAlex Vesker return -EBUSY; 2877838e172SAlex Vesker 2889222f0b2SMuhammad Sammar mlx5dr_dbg_tbl_del(tbl); 2897838e172SAlex Vesker ret = dr_table_destroy_sw_owned_tbl(tbl); 2907838e172SAlex Vesker if (ret) 2917838e172SAlex Vesker return ret; 2927838e172SAlex Vesker 2937838e172SAlex Vesker dr_table_uninit(tbl); 2947838e172SAlex Vesker 2957838e172SAlex Vesker if (tbl->miss_action) 2967838e172SAlex Vesker refcount_dec(&tbl->miss_action->refcount); 2977838e172SAlex Vesker 2987838e172SAlex Vesker refcount_dec(&tbl->dmn->refcount); 2997838e172SAlex Vesker kfree(tbl); 3007838e172SAlex Vesker 3017838e172SAlex Vesker return ret; 3027838e172SAlex Vesker } 3037838e172SAlex Vesker 3047838e172SAlex Vesker u32 mlx5dr_table_get_id(struct mlx5dr_table *tbl) 3057838e172SAlex Vesker { 3067838e172SAlex Vesker return tbl->table_id; 3077838e172SAlex Vesker } 308*34ea969dSPaul Blakey 309*34ea969dSPaul Blakey struct mlx5dr_table *mlx5dr_table_get_from_fs_ft(struct mlx5_flow_table *ft) 310*34ea969dSPaul Blakey { 311*34ea969dSPaul Blakey return ft->fs_dr_table.dr_table; 312*34ea969dSPaul Blakey } 313