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