14ec9e7b0SAlex Vesker // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 24ec9e7b0SAlex Vesker /* Copyright (c) 2019 Mellanox Technologies. */ 34ec9e7b0SAlex Vesker 44ec9e7b0SAlex Vesker #include <linux/mlx5/eswitch.h> 54ec9e7b0SAlex Vesker #include "dr_types.h" 64ec9e7b0SAlex Vesker 764f45c0fSYevgeny Kliteynik #define DR_DOMAIN_SW_STEERING_SUPPORTED(dmn, dmn_type) \ 864f45c0fSYevgeny Kliteynik ((dmn)->info.caps.dmn_type##_sw_owner || \ 964f45c0fSYevgeny Kliteynik ((dmn)->info.caps.dmn_type##_sw_owner_v2 && \ 1064f45c0fSYevgeny Kliteynik (dmn)->info.caps.sw_format_ver <= MLX5_STEERING_FORMAT_CONNECTX_6DX)) 1164f45c0fSYevgeny Kliteynik 12*c0e90fc2SYevgeny Kliteynik static void dr_domain_init_csum_recalc_fts(struct mlx5dr_domain *dmn) 134ec9e7b0SAlex Vesker { 144ec9e7b0SAlex Vesker /* Per vport cached FW FT for checksum recalculation, this 15*c0e90fc2SYevgeny Kliteynik * recalculation is needed due to a HW bug in STEv0. 164ec9e7b0SAlex Vesker */ 17*c0e90fc2SYevgeny Kliteynik xa_init(&dmn->csum_fts_xa); 184ec9e7b0SAlex Vesker } 194ec9e7b0SAlex Vesker 20*c0e90fc2SYevgeny Kliteynik static void dr_domain_uninit_csum_recalc_fts(struct mlx5dr_domain *dmn) 214ec9e7b0SAlex Vesker { 22*c0e90fc2SYevgeny Kliteynik struct mlx5dr_fw_recalc_cs_ft *recalc_cs_ft; 23*c0e90fc2SYevgeny Kliteynik unsigned long i; 244ec9e7b0SAlex Vesker 25*c0e90fc2SYevgeny Kliteynik xa_for_each(&dmn->csum_fts_xa, i, recalc_cs_ft) { 26*c0e90fc2SYevgeny Kliteynik if (recalc_cs_ft) 27*c0e90fc2SYevgeny Kliteynik mlx5dr_fw_destroy_recalc_cs_ft(dmn, recalc_cs_ft); 284ec9e7b0SAlex Vesker } 294ec9e7b0SAlex Vesker 30*c0e90fc2SYevgeny Kliteynik xa_destroy(&dmn->csum_fts_xa); 314ec9e7b0SAlex Vesker } 324ec9e7b0SAlex Vesker 33*c0e90fc2SYevgeny Kliteynik int mlx5dr_domain_get_recalc_cs_ft_addr(struct mlx5dr_domain *dmn, 34f9f93bd5SYevgeny Kliteynik u16 vport_num, 354ec9e7b0SAlex Vesker u64 *rx_icm_addr) 364ec9e7b0SAlex Vesker { 374ec9e7b0SAlex Vesker struct mlx5dr_fw_recalc_cs_ft *recalc_cs_ft; 38*c0e90fc2SYevgeny Kliteynik int ret; 394ec9e7b0SAlex Vesker 40*c0e90fc2SYevgeny Kliteynik recalc_cs_ft = xa_load(&dmn->csum_fts_xa, vport_num); 414ec9e7b0SAlex Vesker if (!recalc_cs_ft) { 42*c0e90fc2SYevgeny Kliteynik /* Table hasn't been created yet */ 434ec9e7b0SAlex Vesker recalc_cs_ft = mlx5dr_fw_create_recalc_cs_ft(dmn, vport_num); 444ec9e7b0SAlex Vesker if (!recalc_cs_ft) 454ec9e7b0SAlex Vesker return -EINVAL; 464ec9e7b0SAlex Vesker 47*c0e90fc2SYevgeny Kliteynik ret = xa_err(xa_store(&dmn->csum_fts_xa, vport_num, 48*c0e90fc2SYevgeny Kliteynik recalc_cs_ft, GFP_KERNEL)); 49*c0e90fc2SYevgeny Kliteynik if (ret) 50*c0e90fc2SYevgeny Kliteynik return ret; 514ec9e7b0SAlex Vesker } 524ec9e7b0SAlex Vesker 534ec9e7b0SAlex Vesker *rx_icm_addr = recalc_cs_ft->rx_icm_addr; 544ec9e7b0SAlex Vesker 554ec9e7b0SAlex Vesker return 0; 564ec9e7b0SAlex Vesker } 574ec9e7b0SAlex Vesker 584ec9e7b0SAlex Vesker static int dr_domain_init_resources(struct mlx5dr_domain *dmn) 594ec9e7b0SAlex Vesker { 604ec9e7b0SAlex Vesker int ret; 614ec9e7b0SAlex Vesker 625212f9c6SYevgeny Kliteynik dmn->ste_ctx = mlx5dr_ste_get_ctx(dmn->info.caps.sw_format_ver); 635212f9c6SYevgeny Kliteynik if (!dmn->ste_ctx) { 645212f9c6SYevgeny Kliteynik mlx5dr_err(dmn, "SW Steering on this device is unsupported\n"); 655212f9c6SYevgeny Kliteynik return -EOPNOTSUPP; 665212f9c6SYevgeny Kliteynik } 675212f9c6SYevgeny Kliteynik 684ec9e7b0SAlex Vesker ret = mlx5_core_alloc_pd(dmn->mdev, &dmn->pdn); 694ec9e7b0SAlex Vesker if (ret) { 70b7d0db55SErez Shitrit mlx5dr_err(dmn, "Couldn't allocate PD, ret: %d", ret); 714ec9e7b0SAlex Vesker return ret; 724ec9e7b0SAlex Vesker } 734ec9e7b0SAlex Vesker 744ec9e7b0SAlex Vesker dmn->uar = mlx5_get_uars_page(dmn->mdev); 754ec9e7b0SAlex Vesker if (!dmn->uar) { 764ec9e7b0SAlex Vesker mlx5dr_err(dmn, "Couldn't allocate UAR\n"); 7783de91f8SWei Yongjun ret = -ENOMEM; 784ec9e7b0SAlex Vesker goto clean_pd; 794ec9e7b0SAlex Vesker } 804ec9e7b0SAlex Vesker 814ec9e7b0SAlex Vesker dmn->ste_icm_pool = mlx5dr_icm_pool_create(dmn, DR_ICM_TYPE_STE); 824ec9e7b0SAlex Vesker if (!dmn->ste_icm_pool) { 8363d67f30SSaeed Mahameed mlx5dr_err(dmn, "Couldn't get icm memory\n"); 8483de91f8SWei Yongjun ret = -ENOMEM; 854ec9e7b0SAlex Vesker goto clean_uar; 864ec9e7b0SAlex Vesker } 874ec9e7b0SAlex Vesker 884ec9e7b0SAlex Vesker dmn->action_icm_pool = mlx5dr_icm_pool_create(dmn, DR_ICM_TYPE_MODIFY_ACTION); 894ec9e7b0SAlex Vesker if (!dmn->action_icm_pool) { 9063d67f30SSaeed Mahameed mlx5dr_err(dmn, "Couldn't get action icm memory\n"); 9183de91f8SWei Yongjun ret = -ENOMEM; 924ec9e7b0SAlex Vesker goto free_ste_icm_pool; 934ec9e7b0SAlex Vesker } 944ec9e7b0SAlex Vesker 954ec9e7b0SAlex Vesker ret = mlx5dr_send_ring_alloc(dmn); 964ec9e7b0SAlex Vesker if (ret) { 9763d67f30SSaeed Mahameed mlx5dr_err(dmn, "Couldn't create send-ring\n"); 984ec9e7b0SAlex Vesker goto free_action_icm_pool; 994ec9e7b0SAlex Vesker } 1004ec9e7b0SAlex Vesker 1014ec9e7b0SAlex Vesker return 0; 1024ec9e7b0SAlex Vesker 1034ec9e7b0SAlex Vesker free_action_icm_pool: 1044ec9e7b0SAlex Vesker mlx5dr_icm_pool_destroy(dmn->action_icm_pool); 1054ec9e7b0SAlex Vesker free_ste_icm_pool: 1064ec9e7b0SAlex Vesker mlx5dr_icm_pool_destroy(dmn->ste_icm_pool); 1074ec9e7b0SAlex Vesker clean_uar: 1084ec9e7b0SAlex Vesker mlx5_put_uars_page(dmn->mdev, dmn->uar); 1094ec9e7b0SAlex Vesker clean_pd: 1104ec9e7b0SAlex Vesker mlx5_core_dealloc_pd(dmn->mdev, dmn->pdn); 1114ec9e7b0SAlex Vesker 1124ec9e7b0SAlex Vesker return ret; 1134ec9e7b0SAlex Vesker } 1144ec9e7b0SAlex Vesker 1154ec9e7b0SAlex Vesker static void dr_domain_uninit_resources(struct mlx5dr_domain *dmn) 1164ec9e7b0SAlex Vesker { 1174ec9e7b0SAlex Vesker mlx5dr_send_ring_free(dmn, dmn->send_ring); 1184ec9e7b0SAlex Vesker mlx5dr_icm_pool_destroy(dmn->action_icm_pool); 1194ec9e7b0SAlex Vesker mlx5dr_icm_pool_destroy(dmn->ste_icm_pool); 1204ec9e7b0SAlex Vesker mlx5_put_uars_page(dmn->mdev, dmn->uar); 1214ec9e7b0SAlex Vesker mlx5_core_dealloc_pd(dmn->mdev, dmn->pdn); 1224ec9e7b0SAlex Vesker } 1234ec9e7b0SAlex Vesker 1244ec9e7b0SAlex Vesker static int dr_domain_query_vport(struct mlx5dr_domain *dmn, 125dd4acb2aSYevgeny Kliteynik u16 vport_number, 126dd4acb2aSYevgeny Kliteynik struct mlx5dr_cmd_vport_cap *vport_caps) 1274ec9e7b0SAlex Vesker { 128dd4acb2aSYevgeny Kliteynik u16 cmd_vport = vport_number; 129dd4acb2aSYevgeny Kliteynik bool other_vport = true; 1304ec9e7b0SAlex Vesker int ret; 1314ec9e7b0SAlex Vesker 132dd4acb2aSYevgeny Kliteynik if (dmn->info.caps.is_ecpf && vport_number == MLX5_VPORT_ECPF) { 133dd4acb2aSYevgeny Kliteynik other_vport = false; 134dd4acb2aSYevgeny Kliteynik cmd_vport = 0; 135dd4acb2aSYevgeny Kliteynik } 1364ec9e7b0SAlex Vesker 1374ec9e7b0SAlex Vesker ret = mlx5dr_cmd_query_esw_vport_context(dmn->mdev, 1384ec9e7b0SAlex Vesker other_vport, 139dd4acb2aSYevgeny Kliteynik cmd_vport, 1404ec9e7b0SAlex Vesker &vport_caps->icm_address_rx, 1414ec9e7b0SAlex Vesker &vport_caps->icm_address_tx); 1424ec9e7b0SAlex Vesker if (ret) 1434ec9e7b0SAlex Vesker return ret; 1444ec9e7b0SAlex Vesker 1454ec9e7b0SAlex Vesker ret = mlx5dr_cmd_query_gvmi(dmn->mdev, 1464ec9e7b0SAlex Vesker other_vport, 147dd4acb2aSYevgeny Kliteynik cmd_vport, 1484ec9e7b0SAlex Vesker &vport_caps->vport_gvmi); 1494ec9e7b0SAlex Vesker if (ret) 1504ec9e7b0SAlex Vesker return ret; 1514ec9e7b0SAlex Vesker 1524ec9e7b0SAlex Vesker vport_caps->num = vport_number; 1534ec9e7b0SAlex Vesker vport_caps->vhca_gvmi = dmn->info.caps.gvmi; 1544ec9e7b0SAlex Vesker 1554ec9e7b0SAlex Vesker return 0; 1564ec9e7b0SAlex Vesker } 1574ec9e7b0SAlex Vesker 158dd4acb2aSYevgeny Kliteynik static int dr_domain_query_esw_mngr(struct mlx5dr_domain *dmn) 159dd4acb2aSYevgeny Kliteynik { 160dd4acb2aSYevgeny Kliteynik return dr_domain_query_vport(dmn, 161dd4acb2aSYevgeny Kliteynik dmn->info.caps.is_ecpf ? MLX5_VPORT_ECPF : 0, 162dd4acb2aSYevgeny Kliteynik &dmn->info.caps.esw_manager_vport_caps); 163dd4acb2aSYevgeny Kliteynik } 164dd4acb2aSYevgeny Kliteynik 1654ec9e7b0SAlex Vesker static int dr_domain_query_vports(struct mlx5dr_domain *dmn) 1664ec9e7b0SAlex Vesker { 1674ec9e7b0SAlex Vesker struct mlx5dr_esw_caps *esw_caps = &dmn->info.caps.esw_caps; 1684ec9e7b0SAlex Vesker struct mlx5dr_cmd_vport_cap *wire_vport; 1694ec9e7b0SAlex Vesker int vport; 1704ec9e7b0SAlex Vesker int ret; 1714ec9e7b0SAlex Vesker 172dd4acb2aSYevgeny Kliteynik ret = dr_domain_query_esw_mngr(dmn); 173dd4acb2aSYevgeny Kliteynik if (ret) 174dd4acb2aSYevgeny Kliteynik return ret; 175dd4acb2aSYevgeny Kliteynik 1764ec9e7b0SAlex Vesker /* Query vports (except wire vport) */ 1774ec9e7b0SAlex Vesker for (vport = 0; vport < dmn->info.caps.num_esw_ports - 1; vport++) { 178dd4acb2aSYevgeny Kliteynik ret = dr_domain_query_vport(dmn, 179dd4acb2aSYevgeny Kliteynik vport, 180dd4acb2aSYevgeny Kliteynik &dmn->info.caps.vports_caps[vport]); 1814ec9e7b0SAlex Vesker if (ret) 1824ec9e7b0SAlex Vesker return ret; 1834ec9e7b0SAlex Vesker } 1844ec9e7b0SAlex Vesker 1854ec9e7b0SAlex Vesker /* Last vport is the wire port */ 1864ec9e7b0SAlex Vesker wire_vport = &dmn->info.caps.vports_caps[vport]; 1877ae8ac9aSYevgeny Kliteynik wire_vport->num = MLX5_VPORT_UPLINK; 1884ec9e7b0SAlex Vesker wire_vport->icm_address_rx = esw_caps->uplink_icm_address_rx; 1894ec9e7b0SAlex Vesker wire_vport->icm_address_tx = esw_caps->uplink_icm_address_tx; 1904ec9e7b0SAlex Vesker wire_vport->vport_gvmi = 0; 1914ec9e7b0SAlex Vesker wire_vport->vhca_gvmi = dmn->info.caps.gvmi; 1924ec9e7b0SAlex Vesker 1934ec9e7b0SAlex Vesker return 0; 1944ec9e7b0SAlex Vesker } 1954ec9e7b0SAlex Vesker 1964ec9e7b0SAlex Vesker static int dr_domain_query_fdb_caps(struct mlx5_core_dev *mdev, 1974ec9e7b0SAlex Vesker struct mlx5dr_domain *dmn) 1984ec9e7b0SAlex Vesker { 1994ec9e7b0SAlex Vesker int ret; 2004ec9e7b0SAlex Vesker 2014ec9e7b0SAlex Vesker if (!dmn->info.caps.eswitch_manager) 2024ec9e7b0SAlex Vesker return -EOPNOTSUPP; 2034ec9e7b0SAlex Vesker 2044ec9e7b0SAlex Vesker ret = mlx5dr_cmd_query_esw_caps(mdev, &dmn->info.caps.esw_caps); 2054ec9e7b0SAlex Vesker if (ret) 2064ec9e7b0SAlex Vesker return ret; 2074ec9e7b0SAlex Vesker 2084ec9e7b0SAlex Vesker dmn->info.caps.fdb_sw_owner = dmn->info.caps.esw_caps.sw_owner; 20964f45c0fSYevgeny Kliteynik dmn->info.caps.fdb_sw_owner_v2 = dmn->info.caps.esw_caps.sw_owner_v2; 2104ec9e7b0SAlex Vesker dmn->info.caps.esw_rx_drop_address = dmn->info.caps.esw_caps.drop_icm_address_rx; 2114ec9e7b0SAlex Vesker dmn->info.caps.esw_tx_drop_address = dmn->info.caps.esw_caps.drop_icm_address_tx; 2124ec9e7b0SAlex Vesker 2134ec9e7b0SAlex Vesker dmn->info.caps.vports_caps = kcalloc(dmn->info.caps.num_esw_ports, 2144ec9e7b0SAlex Vesker sizeof(dmn->info.caps.vports_caps[0]), 2154ec9e7b0SAlex Vesker GFP_KERNEL); 2164ec9e7b0SAlex Vesker if (!dmn->info.caps.vports_caps) 2174ec9e7b0SAlex Vesker return -ENOMEM; 2184ec9e7b0SAlex Vesker 2194ec9e7b0SAlex Vesker ret = dr_domain_query_vports(dmn); 2204ec9e7b0SAlex Vesker if (ret) { 221b7d0db55SErez Shitrit mlx5dr_err(dmn, "Failed to query vports caps (err: %d)", ret); 2224ec9e7b0SAlex Vesker goto free_vports_caps; 2234ec9e7b0SAlex Vesker } 2244ec9e7b0SAlex Vesker 2254ec9e7b0SAlex Vesker dmn->info.caps.num_vports = dmn->info.caps.num_esw_ports - 1; 2264ec9e7b0SAlex Vesker 2274ec9e7b0SAlex Vesker return 0; 2284ec9e7b0SAlex Vesker 2294ec9e7b0SAlex Vesker free_vports_caps: 2304ec9e7b0SAlex Vesker kfree(dmn->info.caps.vports_caps); 2314ec9e7b0SAlex Vesker dmn->info.caps.vports_caps = NULL; 2324ec9e7b0SAlex Vesker return ret; 2334ec9e7b0SAlex Vesker } 2344ec9e7b0SAlex Vesker 2354ec9e7b0SAlex Vesker static int dr_domain_caps_init(struct mlx5_core_dev *mdev, 2364ec9e7b0SAlex Vesker struct mlx5dr_domain *dmn) 2374ec9e7b0SAlex Vesker { 2384ec9e7b0SAlex Vesker struct mlx5dr_cmd_vport_cap *vport_cap; 2394ec9e7b0SAlex Vesker int ret; 2404ec9e7b0SAlex Vesker 2414ec9e7b0SAlex Vesker if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) { 242b7d0db55SErez Shitrit mlx5dr_err(dmn, "Failed to allocate domain, bad link type\n"); 2434ec9e7b0SAlex Vesker return -EOPNOTSUPP; 2444ec9e7b0SAlex Vesker } 2454ec9e7b0SAlex Vesker 2464ec9e7b0SAlex Vesker dmn->info.caps.num_esw_ports = mlx5_eswitch_get_total_vports(mdev); 2474ec9e7b0SAlex Vesker 2484ec9e7b0SAlex Vesker ret = mlx5dr_cmd_query_device(mdev, &dmn->info.caps); 2494ec9e7b0SAlex Vesker if (ret) 2504ec9e7b0SAlex Vesker return ret; 2514ec9e7b0SAlex Vesker 2524ec9e7b0SAlex Vesker ret = dr_domain_query_fdb_caps(mdev, dmn); 2534ec9e7b0SAlex Vesker if (ret) 2544ec9e7b0SAlex Vesker return ret; 2554ec9e7b0SAlex Vesker 2564ec9e7b0SAlex Vesker switch (dmn->type) { 2574ec9e7b0SAlex Vesker case MLX5DR_DOMAIN_TYPE_NIC_RX: 25864f45c0fSYevgeny Kliteynik if (!DR_DOMAIN_SW_STEERING_SUPPORTED(dmn, rx)) 2594ec9e7b0SAlex Vesker return -ENOTSUPP; 2604ec9e7b0SAlex Vesker 2614ec9e7b0SAlex Vesker dmn->info.supp_sw_steering = true; 26246f2a8aeSYevgeny Kliteynik dmn->info.rx.type = DR_DOMAIN_NIC_TYPE_RX; 2634ec9e7b0SAlex Vesker dmn->info.rx.default_icm_addr = dmn->info.caps.nic_rx_drop_address; 2644ec9e7b0SAlex Vesker dmn->info.rx.drop_icm_addr = dmn->info.caps.nic_rx_drop_address; 2654ec9e7b0SAlex Vesker break; 2664ec9e7b0SAlex Vesker case MLX5DR_DOMAIN_TYPE_NIC_TX: 26764f45c0fSYevgeny Kliteynik if (!DR_DOMAIN_SW_STEERING_SUPPORTED(dmn, tx)) 2684ec9e7b0SAlex Vesker return -ENOTSUPP; 2694ec9e7b0SAlex Vesker 2704ec9e7b0SAlex Vesker dmn->info.supp_sw_steering = true; 27146f2a8aeSYevgeny Kliteynik dmn->info.tx.type = DR_DOMAIN_NIC_TYPE_TX; 2724ec9e7b0SAlex Vesker dmn->info.tx.default_icm_addr = dmn->info.caps.nic_tx_allow_address; 2734ec9e7b0SAlex Vesker dmn->info.tx.drop_icm_addr = dmn->info.caps.nic_tx_drop_address; 2744ec9e7b0SAlex Vesker break; 2754ec9e7b0SAlex Vesker case MLX5DR_DOMAIN_TYPE_FDB: 2764ec9e7b0SAlex Vesker if (!dmn->info.caps.eswitch_manager) 2774ec9e7b0SAlex Vesker return -ENOTSUPP; 2784ec9e7b0SAlex Vesker 27964f45c0fSYevgeny Kliteynik if (!DR_DOMAIN_SW_STEERING_SUPPORTED(dmn, fdb)) 2804ec9e7b0SAlex Vesker return -ENOTSUPP; 2814ec9e7b0SAlex Vesker 28246f2a8aeSYevgeny Kliteynik dmn->info.rx.type = DR_DOMAIN_NIC_TYPE_RX; 28346f2a8aeSYevgeny Kliteynik dmn->info.tx.type = DR_DOMAIN_NIC_TYPE_TX; 284dd4acb2aSYevgeny Kliteynik vport_cap = &dmn->info.caps.esw_manager_vport_caps; 2854ec9e7b0SAlex Vesker 2864ec9e7b0SAlex Vesker dmn->info.supp_sw_steering = true; 2874ec9e7b0SAlex Vesker dmn->info.tx.default_icm_addr = vport_cap->icm_address_tx; 2884ec9e7b0SAlex Vesker dmn->info.rx.default_icm_addr = vport_cap->icm_address_rx; 2894ec9e7b0SAlex Vesker dmn->info.rx.drop_icm_addr = dmn->info.caps.esw_rx_drop_address; 2904ec9e7b0SAlex Vesker dmn->info.tx.drop_icm_addr = dmn->info.caps.esw_tx_drop_address; 2914ec9e7b0SAlex Vesker break; 2924ec9e7b0SAlex Vesker default: 293b7d0db55SErez Shitrit mlx5dr_err(dmn, "Invalid domain\n"); 2944ec9e7b0SAlex Vesker ret = -EINVAL; 2954ec9e7b0SAlex Vesker break; 2964ec9e7b0SAlex Vesker } 2974ec9e7b0SAlex Vesker 2984ec9e7b0SAlex Vesker return ret; 2994ec9e7b0SAlex Vesker } 3004ec9e7b0SAlex Vesker 3014ec9e7b0SAlex Vesker static void dr_domain_caps_uninit(struct mlx5dr_domain *dmn) 3024ec9e7b0SAlex Vesker { 3034ec9e7b0SAlex Vesker kfree(dmn->info.caps.vports_caps); 3044ec9e7b0SAlex Vesker } 3054ec9e7b0SAlex Vesker 3064ec9e7b0SAlex Vesker struct mlx5dr_domain * 3074ec9e7b0SAlex Vesker mlx5dr_domain_create(struct mlx5_core_dev *mdev, enum mlx5dr_domain_type type) 3084ec9e7b0SAlex Vesker { 3094ec9e7b0SAlex Vesker struct mlx5dr_domain *dmn; 3104ec9e7b0SAlex Vesker int ret; 3114ec9e7b0SAlex Vesker 3124ec9e7b0SAlex Vesker if (type > MLX5DR_DOMAIN_TYPE_FDB) 3134ec9e7b0SAlex Vesker return NULL; 3144ec9e7b0SAlex Vesker 3154ec9e7b0SAlex Vesker dmn = kzalloc(sizeof(*dmn), GFP_KERNEL); 3164ec9e7b0SAlex Vesker if (!dmn) 3174ec9e7b0SAlex Vesker return NULL; 3184ec9e7b0SAlex Vesker 3194ec9e7b0SAlex Vesker dmn->mdev = mdev; 3204ec9e7b0SAlex Vesker dmn->type = type; 3214ec9e7b0SAlex Vesker refcount_set(&dmn->refcount, 1); 322ed03a418SAlex Vesker mutex_init(&dmn->info.rx.mutex); 323ed03a418SAlex Vesker mutex_init(&dmn->info.tx.mutex); 3244ec9e7b0SAlex Vesker 3254ec9e7b0SAlex Vesker if (dr_domain_caps_init(mdev, dmn)) { 326b7d0db55SErez Shitrit mlx5dr_err(dmn, "Failed init domain, no caps\n"); 3274ec9e7b0SAlex Vesker goto free_domain; 3284ec9e7b0SAlex Vesker } 3294ec9e7b0SAlex Vesker 3304ec9e7b0SAlex Vesker dmn->info.max_log_action_icm_sz = DR_CHUNK_SIZE_4K; 3314ec9e7b0SAlex Vesker dmn->info.max_log_sw_icm_sz = min_t(u32, DR_CHUNK_SIZE_1024K, 3324ec9e7b0SAlex Vesker dmn->info.caps.log_icm_size); 3334ec9e7b0SAlex Vesker 3344ec9e7b0SAlex Vesker if (!dmn->info.supp_sw_steering) { 33563d67f30SSaeed Mahameed mlx5dr_err(dmn, "SW steering is not supported\n"); 3364ec9e7b0SAlex Vesker goto uninit_caps; 3374ec9e7b0SAlex Vesker } 3384ec9e7b0SAlex Vesker 3394ec9e7b0SAlex Vesker /* Allocate resources */ 3404ec9e7b0SAlex Vesker ret = dr_domain_init_resources(dmn); 3414ec9e7b0SAlex Vesker if (ret) { 34263d67f30SSaeed Mahameed mlx5dr_err(dmn, "Failed init domain resources\n"); 3434ec9e7b0SAlex Vesker goto uninit_caps; 3444ec9e7b0SAlex Vesker } 3454ec9e7b0SAlex Vesker 346*c0e90fc2SYevgeny Kliteynik dr_domain_init_csum_recalc_fts(dmn); 3474ec9e7b0SAlex Vesker 3484ec9e7b0SAlex Vesker return dmn; 3494ec9e7b0SAlex Vesker 3504ec9e7b0SAlex Vesker uninit_caps: 3514ec9e7b0SAlex Vesker dr_domain_caps_uninit(dmn); 3524ec9e7b0SAlex Vesker free_domain: 3534ec9e7b0SAlex Vesker kfree(dmn); 3544ec9e7b0SAlex Vesker return NULL; 3554ec9e7b0SAlex Vesker } 3564ec9e7b0SAlex Vesker 3574ec9e7b0SAlex Vesker /* Assure synchronization of the device steering tables with updates made by SW 3584ec9e7b0SAlex Vesker * insertion. 3594ec9e7b0SAlex Vesker */ 3604ec9e7b0SAlex Vesker int mlx5dr_domain_sync(struct mlx5dr_domain *dmn, u32 flags) 3614ec9e7b0SAlex Vesker { 3624ec9e7b0SAlex Vesker int ret = 0; 3634ec9e7b0SAlex Vesker 3644ec9e7b0SAlex Vesker if (flags & MLX5DR_DOMAIN_SYNC_FLAGS_SW) { 365ed03a418SAlex Vesker mlx5dr_domain_lock(dmn); 3664ec9e7b0SAlex Vesker ret = mlx5dr_send_ring_force_drain(dmn); 367ed03a418SAlex Vesker mlx5dr_domain_unlock(dmn); 368b7d0db55SErez Shitrit if (ret) { 369b7d0db55SErez Shitrit mlx5dr_err(dmn, "Force drain failed flags: %d, ret: %d\n", 370b7d0db55SErez Shitrit flags, ret); 3714ec9e7b0SAlex Vesker return ret; 3724ec9e7b0SAlex Vesker } 373b7d0db55SErez Shitrit } 3744ec9e7b0SAlex Vesker 3754ec9e7b0SAlex Vesker if (flags & MLX5DR_DOMAIN_SYNC_FLAGS_HW) 3764ec9e7b0SAlex Vesker ret = mlx5dr_cmd_sync_steering(dmn->mdev); 3774ec9e7b0SAlex Vesker 3784ec9e7b0SAlex Vesker return ret; 3794ec9e7b0SAlex Vesker } 3804ec9e7b0SAlex Vesker 3814ec9e7b0SAlex Vesker int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn) 3824ec9e7b0SAlex Vesker { 3834ec9e7b0SAlex Vesker if (refcount_read(&dmn->refcount) > 1) 3844ec9e7b0SAlex Vesker return -EBUSY; 3854ec9e7b0SAlex Vesker 3864ec9e7b0SAlex Vesker /* make sure resources are not used by the hardware */ 3874ec9e7b0SAlex Vesker mlx5dr_cmd_sync_steering(dmn->mdev); 388*c0e90fc2SYevgeny Kliteynik dr_domain_uninit_csum_recalc_fts(dmn); 3894ec9e7b0SAlex Vesker dr_domain_uninit_resources(dmn); 3904ec9e7b0SAlex Vesker dr_domain_caps_uninit(dmn); 391ed03a418SAlex Vesker mutex_destroy(&dmn->info.tx.mutex); 392ed03a418SAlex Vesker mutex_destroy(&dmn->info.rx.mutex); 3934ec9e7b0SAlex Vesker kfree(dmn); 3944ec9e7b0SAlex Vesker return 0; 3954ec9e7b0SAlex Vesker } 3964ec9e7b0SAlex Vesker 3974ec9e7b0SAlex Vesker void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn, 3984ec9e7b0SAlex Vesker struct mlx5dr_domain *peer_dmn) 3994ec9e7b0SAlex Vesker { 400ed03a418SAlex Vesker mlx5dr_domain_lock(dmn); 4014ec9e7b0SAlex Vesker 4024ec9e7b0SAlex Vesker if (dmn->peer_dmn) 4034ec9e7b0SAlex Vesker refcount_dec(&dmn->peer_dmn->refcount); 4044ec9e7b0SAlex Vesker 4054ec9e7b0SAlex Vesker dmn->peer_dmn = peer_dmn; 4064ec9e7b0SAlex Vesker 4074ec9e7b0SAlex Vesker if (dmn->peer_dmn) 4084ec9e7b0SAlex Vesker refcount_inc(&dmn->peer_dmn->refcount); 4094ec9e7b0SAlex Vesker 410ed03a418SAlex Vesker mlx5dr_domain_unlock(dmn); 4114ec9e7b0SAlex Vesker } 412