18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2018 Mellanox Technologies. All rights reserved.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/mlx5/vport.h>
78c2ecf20Sopenharmony_ci#include "ib_rep.h"
88c2ecf20Sopenharmony_ci#include "srq.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_cistatic int
118c2ecf20Sopenharmony_cimlx5_ib_set_vport_rep(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
128c2ecf20Sopenharmony_ci{
138c2ecf20Sopenharmony_ci	struct mlx5_ib_dev *ibdev;
148c2ecf20Sopenharmony_ci	int vport_index;
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci	ibdev = mlx5_ib_get_uplink_ibdev(dev->priv.eswitch);
178c2ecf20Sopenharmony_ci	vport_index = rep->vport_index;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	ibdev->port[vport_index].rep = rep;
208c2ecf20Sopenharmony_ci	rep->rep_data[REP_IB].priv = ibdev;
218c2ecf20Sopenharmony_ci	write_lock(&ibdev->port[vport_index].roce.netdev_lock);
228c2ecf20Sopenharmony_ci	ibdev->port[vport_index].roce.netdev =
238c2ecf20Sopenharmony_ci		mlx5_ib_get_rep_netdev(dev->priv.eswitch, rep->vport);
248c2ecf20Sopenharmony_ci	write_unlock(&ibdev->port[vport_index].roce.netdev_lock);
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	return 0;
278c2ecf20Sopenharmony_ci}
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic int
308c2ecf20Sopenharmony_cimlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	int num_ports = mlx5_eswitch_get_total_vports(dev);
338c2ecf20Sopenharmony_ci	const struct mlx5_ib_profile *profile;
348c2ecf20Sopenharmony_ci	struct mlx5_ib_dev *ibdev;
358c2ecf20Sopenharmony_ci	int vport_index;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	if (rep->vport == MLX5_VPORT_UPLINK)
388c2ecf20Sopenharmony_ci		profile = &raw_eth_profile;
398c2ecf20Sopenharmony_ci	else
408c2ecf20Sopenharmony_ci		return mlx5_ib_set_vport_rep(dev, rep);
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	ibdev = ib_alloc_device(mlx5_ib_dev, ib_dev);
438c2ecf20Sopenharmony_ci	if (!ibdev)
448c2ecf20Sopenharmony_ci		return -ENOMEM;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	ibdev->port = kcalloc(num_ports, sizeof(*ibdev->port),
478c2ecf20Sopenharmony_ci			      GFP_KERNEL);
488c2ecf20Sopenharmony_ci	if (!ibdev->port) {
498c2ecf20Sopenharmony_ci		ib_dealloc_device(&ibdev->ib_dev);
508c2ecf20Sopenharmony_ci		return -ENOMEM;
518c2ecf20Sopenharmony_ci	}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	ibdev->is_rep = true;
548c2ecf20Sopenharmony_ci	vport_index = rep->vport_index;
558c2ecf20Sopenharmony_ci	ibdev->port[vport_index].rep = rep;
568c2ecf20Sopenharmony_ci	ibdev->port[vport_index].roce.netdev =
578c2ecf20Sopenharmony_ci		mlx5_ib_get_rep_netdev(dev->priv.eswitch, rep->vport);
588c2ecf20Sopenharmony_ci	ibdev->mdev = dev;
598c2ecf20Sopenharmony_ci	ibdev->num_ports = num_ports;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	if (!__mlx5_ib_add(ibdev, profile))
628c2ecf20Sopenharmony_ci		return -EINVAL;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	rep->rep_data[REP_IB].priv = ibdev;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	return 0;
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistatic void
708c2ecf20Sopenharmony_cimlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	struct mlx5_ib_dev *dev = mlx5_ib_rep_to_dev(rep);
738c2ecf20Sopenharmony_ci	struct mlx5_ib_port *port;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	port = &dev->port[rep->vport_index];
768c2ecf20Sopenharmony_ci	write_lock(&port->roce.netdev_lock);
778c2ecf20Sopenharmony_ci	port->roce.netdev = NULL;
788c2ecf20Sopenharmony_ci	write_unlock(&port->roce.netdev_lock);
798c2ecf20Sopenharmony_ci	rep->rep_data[REP_IB].priv = NULL;
808c2ecf20Sopenharmony_ci	port->rep = NULL;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	if (rep->vport == MLX5_VPORT_UPLINK)
838c2ecf20Sopenharmony_ci		__mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX);
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic void *mlx5_ib_vport_get_proto_dev(struct mlx5_eswitch_rep *rep)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	return mlx5_ib_rep_to_dev(rep);
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic const struct mlx5_eswitch_rep_ops rep_ops = {
928c2ecf20Sopenharmony_ci	.load = mlx5_ib_vport_rep_load,
938c2ecf20Sopenharmony_ci	.unload = mlx5_ib_vport_rep_unload,
948c2ecf20Sopenharmony_ci	.get_proto_dev = mlx5_ib_vport_get_proto_dev,
958c2ecf20Sopenharmony_ci};
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_civoid mlx5_ib_register_vport_reps(struct mlx5_core_dev *mdev)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	struct mlx5_eswitch *esw = mdev->priv.eswitch;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB);
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_civoid mlx5_ib_unregister_vport_reps(struct mlx5_core_dev *mdev)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	struct mlx5_eswitch *esw = mdev->priv.eswitch;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	mlx5_eswitch_unregister_vport_reps(esw, REP_IB);
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ciu8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	return mlx5_eswitch_mode(esw);
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistruct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw,
1178c2ecf20Sopenharmony_ci					  u16 vport_num)
1188c2ecf20Sopenharmony_ci{
1198c2ecf20Sopenharmony_ci	return mlx5_eswitch_get_proto_dev(esw, vport_num, REP_IB);
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cistruct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
1238c2ecf20Sopenharmony_ci					  u16 vport_num)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	return mlx5_eswitch_get_proto_dev(esw, vport_num, REP_ETH);
1268c2ecf20Sopenharmony_ci}
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cistruct mlx5_ib_dev *mlx5_ib_get_uplink_ibdev(struct mlx5_eswitch *esw)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	return mlx5_eswitch_uplink_get_proto_dev(esw, REP_IB);
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistruct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw,
1348c2ecf20Sopenharmony_ci					   u16 vport_num)
1358c2ecf20Sopenharmony_ci{
1368c2ecf20Sopenharmony_ci	return mlx5_eswitch_vport_rep(esw, vport_num);
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistruct mlx5_flow_handle *create_flow_rule_vport_sq(struct mlx5_ib_dev *dev,
1408c2ecf20Sopenharmony_ci						   struct mlx5_ib_sq *sq,
1418c2ecf20Sopenharmony_ci						   u16 port)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	struct mlx5_eswitch *esw = dev->mdev->priv.eswitch;
1448c2ecf20Sopenharmony_ci	struct mlx5_eswitch_rep *rep;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	if (!dev->is_rep || !port)
1478c2ecf20Sopenharmony_ci		return NULL;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	if (!dev->port[port - 1].rep)
1508c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	rep = dev->port[port - 1].rep;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	return mlx5_eswitch_add_send_to_vport_rule(esw, rep->vport,
1558c2ecf20Sopenharmony_ci						   sq->base.mqp.qpn);
1568c2ecf20Sopenharmony_ci}
157