2018-06-05 12:53:53 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
2018-01-16 22:34:48 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018 Mellanox Technologies. All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2019-02-13 14:55:40 +08:00
|
|
|
#include <linux/mlx5/vport.h>
|
2018-01-16 22:34:48 +08:00
|
|
|
#include "ib_rep.h"
|
2018-11-29 02:53:41 +08:00
|
|
|
#include "srq.h"
|
2018-01-16 22:34:48 +08:00
|
|
|
|
2019-03-28 21:27:41 +08:00
|
|
|
static int
|
|
|
|
mlx5_ib_set_vport_rep(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
|
|
|
|
{
|
|
|
|
struct mlx5_ib_dev *ibdev;
|
|
|
|
int vport_index;
|
|
|
|
|
|
|
|
ibdev = mlx5_ib_get_uplink_ibdev(dev->priv.eswitch);
|
2019-06-29 06:35:53 +08:00
|
|
|
vport_index = rep->vport_index;
|
2019-03-28 21:27:41 +08:00
|
|
|
|
|
|
|
ibdev->port[vport_index].rep = rep;
|
2019-06-29 06:35:55 +08:00
|
|
|
rep->rep_data[REP_IB].priv = ibdev;
|
2019-03-28 21:27:41 +08:00
|
|
|
write_lock(&ibdev->port[vport_index].roce.netdev_lock);
|
|
|
|
ibdev->port[vport_index].roce.netdev =
|
|
|
|
mlx5_ib_get_rep_netdev(dev->priv.eswitch, rep->vport);
|
|
|
|
write_unlock(&ibdev->port[vport_index].roce.netdev_lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-01-16 22:34:48 +08:00
|
|
|
static int
|
|
|
|
mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
|
|
|
|
{
|
2019-05-15 13:04:27 +08:00
|
|
|
int num_ports = mlx5_eswitch_get_total_vports(dev);
|
2019-02-13 14:55:34 +08:00
|
|
|
const struct mlx5_ib_profile *profile;
|
2018-01-23 19:16:30 +08:00
|
|
|
struct mlx5_ib_dev *ibdev;
|
2019-03-28 21:27:41 +08:00
|
|
|
int vport_index;
|
2018-01-23 19:16:30 +08:00
|
|
|
|
2019-02-13 14:55:40 +08:00
|
|
|
if (rep->vport == MLX5_VPORT_UPLINK)
|
2019-02-13 14:55:34 +08:00
|
|
|
profile = &uplink_rep_profile;
|
|
|
|
else
|
2019-03-28 21:27:41 +08:00
|
|
|
return mlx5_ib_set_vport_rep(dev, rep);
|
2019-02-13 14:55:34 +08:00
|
|
|
|
2019-01-30 18:49:11 +08:00
|
|
|
ibdev = ib_alloc_device(mlx5_ib_dev, ib_dev);
|
2018-01-23 19:16:30 +08:00
|
|
|
if (!ibdev)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2019-03-28 21:27:35 +08:00
|
|
|
ibdev->port = kcalloc(num_ports, sizeof(*ibdev->port),
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!ibdev->port) {
|
|
|
|
ib_dealloc_device(&ibdev->ib_dev);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2019-03-28 21:27:37 +08:00
|
|
|
ibdev->is_rep = true;
|
2019-06-29 06:35:53 +08:00
|
|
|
vport_index = rep->vport_index;
|
2019-03-28 21:27:41 +08:00
|
|
|
ibdev->port[vport_index].rep = rep;
|
|
|
|
ibdev->port[vport_index].roce.netdev =
|
2019-03-28 21:27:39 +08:00
|
|
|
mlx5_ib_get_rep_netdev(dev->priv.eswitch, rep->vport);
|
2018-01-23 19:16:30 +08:00
|
|
|
ibdev->mdev = dev;
|
2019-03-28 21:27:35 +08:00
|
|
|
ibdev->num_ports = num_ports;
|
|
|
|
|
2019-03-28 21:27:34 +08:00
|
|
|
if (!__mlx5_ib_add(ibdev, profile))
|
2018-01-23 19:16:30 +08:00
|
|
|
return -EINVAL;
|
|
|
|
|
2019-05-30 06:50:41 +08:00
|
|
|
rep->rep_data[REP_IB].priv = ibdev;
|
2018-01-23 19:16:30 +08:00
|
|
|
|
2018-01-16 22:34:48 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep)
|
|
|
|
{
|
2019-06-29 06:35:55 +08:00
|
|
|
struct mlx5_ib_dev *dev = mlx5_ib_rep_to_dev(rep);
|
|
|
|
struct mlx5_ib_port *port;
|
2018-01-23 19:16:30 +08:00
|
|
|
|
2019-06-29 06:35:55 +08:00
|
|
|
port = &dev->port[rep->vport_index];
|
|
|
|
write_lock(&port->roce.netdev_lock);
|
|
|
|
port->roce.netdev = NULL;
|
|
|
|
write_unlock(&port->roce.netdev_lock);
|
2019-05-30 06:50:41 +08:00
|
|
|
rep->rep_data[REP_IB].priv = NULL;
|
2019-06-29 06:35:55 +08:00
|
|
|
port->rep = NULL;
|
|
|
|
|
|
|
|
if (rep->vport == MLX5_VPORT_UPLINK)
|
|
|
|
__mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX);
|
2018-01-16 22:34:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void *mlx5_ib_vport_get_proto_dev(struct mlx5_eswitch_rep *rep)
|
|
|
|
{
|
|
|
|
return mlx5_ib_rep_to_dev(rep);
|
|
|
|
}
|
|
|
|
|
2019-05-30 06:50:41 +08:00
|
|
|
static const struct mlx5_eswitch_rep_ops rep_ops = {
|
|
|
|
.load = mlx5_ib_vport_rep_load,
|
|
|
|
.unload = mlx5_ib_vport_rep_unload,
|
|
|
|
.get_proto_dev = mlx5_ib_vport_get_proto_dev,
|
|
|
|
};
|
|
|
|
|
2019-02-13 14:55:34 +08:00
|
|
|
void mlx5_ib_register_vport_reps(struct mlx5_core_dev *mdev)
|
2018-01-16 22:34:48 +08:00
|
|
|
{
|
2019-02-13 14:55:34 +08:00
|
|
|
struct mlx5_eswitch *esw = mdev->priv.eswitch;
|
net/mlx5: E-Switch, Centralize repersentor reg/unreg to eswitch driver
Eswitch has two users: IB and ETH. They both register repersentors
when mlx5 interface is added, and unregister the repersentors when
mlx5 interface is removed. Ideally, each driver should only deal with
the entities which are unique to itself. However, current IB and ETH
drivers have to perform the following eswitch operations:
1. When registering, specify how many vports to register. This number
is the same for both drivers which is the total available vport
numbers.
2. When unregistering, specify the number of registered vports to do
unregister. Also, unload the repersentors which are already loaded.
It's unnecessary for eswitch driver to hands out the control of above
operations to individual driver users, as they're not unique to each
driver. Instead, such operations should be centralized to eswitch
driver. This consolidates eswitch control flow, and simplified IB and
ETH driver.
This patch doesn't change any functionality.
Signed-off-by: Bodong Wang <bodong@mellanox.com>
Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
2019-02-01 07:42:57 +08:00
|
|
|
|
2019-05-30 06:50:41 +08:00
|
|
|
mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB);
|
2018-01-16 22:34:48 +08:00
|
|
|
}
|
|
|
|
|
2019-02-13 14:55:34 +08:00
|
|
|
void mlx5_ib_unregister_vport_reps(struct mlx5_core_dev *mdev)
|
2018-01-16 22:34:48 +08:00
|
|
|
{
|
2019-02-13 14:55:34 +08:00
|
|
|
struct mlx5_eswitch *esw = mdev->priv.eswitch;
|
2018-01-16 22:34:48 +08:00
|
|
|
|
net/mlx5: E-Switch, Centralize repersentor reg/unreg to eswitch driver
Eswitch has two users: IB and ETH. They both register repersentors
when mlx5 interface is added, and unregister the repersentors when
mlx5 interface is removed. Ideally, each driver should only deal with
the entities which are unique to itself. However, current IB and ETH
drivers have to perform the following eswitch operations:
1. When registering, specify how many vports to register. This number
is the same for both drivers which is the total available vport
numbers.
2. When unregistering, specify the number of registered vports to do
unregister. Also, unload the repersentors which are already loaded.
It's unnecessary for eswitch driver to hands out the control of above
operations to individual driver users, as they're not unique to each
driver. Instead, such operations should be centralized to eswitch
driver. This consolidates eswitch control flow, and simplified IB and
ETH driver.
This patch doesn't change any functionality.
Signed-off-by: Bodong Wang <bodong@mellanox.com>
Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
2019-02-01 07:42:57 +08:00
|
|
|
mlx5_eswitch_unregister_vport_reps(esw, REP_IB);
|
2018-01-16 22:34:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw)
|
|
|
|
{
|
|
|
|
return mlx5_eswitch_mode(esw);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw,
|
2019-04-05 14:07:19 +08:00
|
|
|
u16 vport_num)
|
2018-01-16 22:34:48 +08:00
|
|
|
{
|
2019-04-05 14:07:19 +08:00
|
|
|
return mlx5_eswitch_get_proto_dev(esw, vport_num, REP_IB);
|
2018-01-16 22:34:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
|
2019-04-05 14:07:19 +08:00
|
|
|
u16 vport_num)
|
2018-01-16 22:34:48 +08:00
|
|
|
{
|
2019-04-05 14:07:19 +08:00
|
|
|
return mlx5_eswitch_get_proto_dev(esw, vport_num, REP_ETH);
|
2018-01-16 22:34:48 +08:00
|
|
|
}
|
|
|
|
|
2018-01-23 19:16:30 +08:00
|
|
|
struct mlx5_ib_dev *mlx5_ib_get_uplink_ibdev(struct mlx5_eswitch *esw)
|
|
|
|
{
|
|
|
|
return mlx5_eswitch_uplink_get_proto_dev(esw, REP_IB);
|
|
|
|
}
|
|
|
|
|
2019-04-05 14:07:19 +08:00
|
|
|
struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw,
|
|
|
|
u16 vport_num)
|
2018-01-16 22:34:48 +08:00
|
|
|
{
|
2019-04-05 14:07:19 +08:00
|
|
|
return mlx5_eswitch_vport_rep(esw, vport_num);
|
2018-01-16 22:34:48 +08:00
|
|
|
}
|
2018-01-29 18:40:37 +08:00
|
|
|
|
2019-03-28 21:27:38 +08:00
|
|
|
struct mlx5_flow_handle *create_flow_rule_vport_sq(struct mlx5_ib_dev *dev,
|
|
|
|
struct mlx5_ib_sq *sq,
|
|
|
|
u16 port)
|
2018-01-29 18:40:37 +08:00
|
|
|
{
|
|
|
|
struct mlx5_eswitch *esw = dev->mdev->priv.eswitch;
|
2019-03-28 21:27:38 +08:00
|
|
|
struct mlx5_eswitch_rep *rep;
|
2018-01-29 18:40:37 +08:00
|
|
|
|
2019-03-28 21:27:38 +08:00
|
|
|
if (!dev->is_rep || !port)
|
|
|
|
return NULL;
|
2018-01-29 18:40:37 +08:00
|
|
|
|
2019-03-28 21:27:38 +08:00
|
|
|
if (!dev->port[port - 1].rep)
|
|
|
|
return ERR_PTR(-EINVAL);
|
2018-01-29 18:40:37 +08:00
|
|
|
|
2019-03-28 21:27:38 +08:00
|
|
|
rep = dev->port[port - 1].rep;
|
|
|
|
|
|
|
|
return mlx5_eswitch_add_send_to_vport_rule(esw, rep->vport,
|
|
|
|
sq->base.mqp.qpn);
|
2018-01-29 18:40:37 +08:00
|
|
|
}
|