Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fb66cb07 authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'mlx5-updates-2018-02-23' of git://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux



Saeed Mahameed says:

mlx5-update-2018-02-23 (IB representors)

From: Mark Bloch <markb@mellanox.com>
=========
Add IB representor when in switchdev mode

The following series adds support for an IB (RAW Ethernet only) device
representor which is created when the user switches to switchdev mode.

Today when switching to switchdev mode the only representors which are
created are net devices. Each netdev is a representor of a virtual
function and any data sent via the representor is received on the virtual
function, and any data sent via the virtual function is received by the
representor.

For the mlx5 driver the main use of this functionality is to be able to
use Open vSwitch on the hypervisor in order to manage/control traffic
from/to the virtual functions. Open vSwitch can also work with  DPDK
devices and not just net devices, this series exposes an IB device, which
Mellanox PMD driver uses, which then can be used by Open vSwitch DPDK.

An IB device representor exposes only RAW Ethernet QP capabilities and
the ability to create flow rules to direct traffic to its RX queues. The
state of the IB device (ACTIVE/DOWN etc..) is based on the state of the
corresponding net device representor. No other RDMA/RoCE functionality is
currently supported and no GID table is exposed.
=========

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3f5a6830 ec9c2fb8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2,3 +2,4 @@ obj-$(CONFIG_MLX5_INFINIBAND) += mlx5_ib.o

mlx5_ib-y :=	main.o cq.o doorbell.o qp.o mem.o srq.o mr.o ah.o mad.o gsi.o ib_virt.o cmd.o cong.o
mlx5_ib-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += odp.o
mlx5_ib-$(CONFIG_MLX5_ESWITCH) += ib_rep.o
+189 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
/*
 * Copyright (c) 2018 Mellanox Technologies. All rights reserved.
 */

#include "ib_rep.h"

static const struct mlx5_ib_profile rep_profile = {
	STAGE_CREATE(MLX5_IB_STAGE_INIT,
		     mlx5_ib_stage_init_init,
		     mlx5_ib_stage_init_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_FLOW_DB,
		     mlx5_ib_stage_rep_flow_db_init,
		     NULL),
	STAGE_CREATE(MLX5_IB_STAGE_CAPS,
		     mlx5_ib_stage_caps_init,
		     NULL),
	STAGE_CREATE(MLX5_IB_STAGE_NON_DEFAULT_CB,
		     mlx5_ib_stage_rep_non_default_cb,
		     NULL),
	STAGE_CREATE(MLX5_IB_STAGE_ROCE,
		     mlx5_ib_stage_rep_roce_init,
		     mlx5_ib_stage_rep_roce_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,
		     mlx5_ib_stage_dev_res_init,
		     mlx5_ib_stage_dev_res_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_COUNTERS,
		     mlx5_ib_stage_counters_init,
		     mlx5_ib_stage_counters_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_BFREG,
		     mlx5_ib_stage_bfrag_init,
		     mlx5_ib_stage_bfrag_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_IB_REG,
		     mlx5_ib_stage_ib_reg_init,
		     mlx5_ib_stage_ib_reg_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_UMR_RESOURCES,
		     mlx5_ib_stage_umr_res_init,
		     mlx5_ib_stage_umr_res_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_CLASS_ATTR,
		     mlx5_ib_stage_class_attr_init,
		     NULL),
};

static int
mlx5_ib_nic_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
{
	return 0;
}

static void
mlx5_ib_nic_rep_unload(struct mlx5_eswitch_rep *rep)
{
	rep->rep_if[REP_IB].priv = NULL;
}

static int
mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
{
	struct mlx5_ib_dev *ibdev;

	ibdev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*ibdev));
	if (!ibdev)
		return -ENOMEM;

	ibdev->rep = rep;
	ibdev->mdev = dev;
	ibdev->num_ports = max(MLX5_CAP_GEN(dev, num_ports),
			       MLX5_CAP_GEN(dev, num_vhca_ports));
	if (!__mlx5_ib_add(ibdev, &rep_profile))
		return -EINVAL;

	rep->rep_if[REP_IB].priv = ibdev;

	return 0;
}

static void
mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep)
{
	struct mlx5_ib_dev *dev;

	if (!rep->rep_if[REP_IB].priv)
		return;

	dev = mlx5_ib_rep_to_dev(rep);
	__mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX);
	rep->rep_if[REP_IB].priv = NULL;
}

static void *mlx5_ib_vport_get_proto_dev(struct mlx5_eswitch_rep *rep)
{
	return mlx5_ib_rep_to_dev(rep);
}

static void mlx5_ib_rep_register_vf_vports(struct mlx5_ib_dev *dev)
{
	struct mlx5_eswitch *esw   = dev->mdev->priv.eswitch;
	int total_vfs = MLX5_TOTAL_VPORTS(dev->mdev);
	int vport;

	for (vport = 1; vport < total_vfs; vport++) {
		struct mlx5_eswitch_rep_if rep_if = {};

		rep_if.load = mlx5_ib_vport_rep_load;
		rep_if.unload = mlx5_ib_vport_rep_unload;
		rep_if.get_proto_dev = mlx5_ib_vport_get_proto_dev;
		mlx5_eswitch_register_vport_rep(esw, vport, &rep_if, REP_IB);
	}
}

static void mlx5_ib_rep_unregister_vf_vports(struct mlx5_ib_dev *dev)
{
	struct mlx5_eswitch *esw   = dev->mdev->priv.eswitch;
	int total_vfs = MLX5_TOTAL_VPORTS(dev->mdev);
	int vport;

	for (vport = 1; vport < total_vfs; vport++)
		mlx5_eswitch_unregister_vport_rep(esw, vport, REP_IB);
}

void mlx5_ib_register_vport_reps(struct mlx5_ib_dev *dev)
{
	struct mlx5_eswitch *esw = dev->mdev->priv.eswitch;
	struct mlx5_eswitch_rep_if rep_if = {};

	rep_if.load = mlx5_ib_nic_rep_load;
	rep_if.unload = mlx5_ib_nic_rep_unload;
	rep_if.get_proto_dev = mlx5_ib_vport_get_proto_dev;
	rep_if.priv = dev;

	mlx5_eswitch_register_vport_rep(esw, 0, &rep_if, REP_IB);

	mlx5_ib_rep_register_vf_vports(dev);
}

void mlx5_ib_unregister_vport_reps(struct mlx5_ib_dev *dev)
{
	struct mlx5_eswitch *esw   = dev->mdev->priv.eswitch;

	mlx5_ib_rep_unregister_vf_vports(dev); /* VFs vports */
	mlx5_eswitch_unregister_vport_rep(esw, 0, REP_IB); /* UPLINK PF*/
}

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,
					  int vport_index)
{
	return mlx5_eswitch_get_proto_dev(esw, vport_index, REP_IB);
}

struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
					  int vport_index)
{
	return mlx5_eswitch_get_proto_dev(esw, vport_index, REP_ETH);
}

struct mlx5_ib_dev *mlx5_ib_get_uplink_ibdev(struct mlx5_eswitch *esw)
{
	return mlx5_eswitch_uplink_get_proto_dev(esw, REP_IB);
}

struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw, int vport)
{
	return mlx5_eswitch_vport_rep(esw, vport);
}

int create_flow_rule_vport_sq(struct mlx5_ib_dev *dev,
			      struct mlx5_ib_sq *sq)
{
	struct mlx5_flow_handle *flow_rule;
	struct mlx5_eswitch *esw = dev->mdev->priv.eswitch;

	if (!dev->rep)
		return 0;

	flow_rule =
		mlx5_eswitch_add_send_to_vport_rule(esw,
						    dev->rep->vport,
						    sq->base.mqp.qpn);
	if (IS_ERR(flow_rule))
		return PTR_ERR(flow_rule);
	sq->flow_rule = flow_rule;

	return 0;
}
+72 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
/*
 * Copyright (c) 2018 Mellanox Technologies. All rights reserved.
 */

#ifndef __MLX5_IB_REP_H__
#define __MLX5_IB_REP_H__

#include <linux/mlx5/eswitch.h>
#include "mlx5_ib.h"

#ifdef CONFIG_MLX5_ESWITCH
u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw);
struct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw,
					  int vport_index);
struct mlx5_ib_dev *mlx5_ib_get_uplink_ibdev(struct mlx5_eswitch *esw);
struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw,
					   int vport_index);
void mlx5_ib_register_vport_reps(struct mlx5_ib_dev *dev);
void mlx5_ib_unregister_vport_reps(struct mlx5_ib_dev *dev);
int create_flow_rule_vport_sq(struct mlx5_ib_dev *dev,
			      struct mlx5_ib_sq *sq);
struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
					  int vport_index);
#else /* CONFIG_MLX5_ESWITCH */
static inline u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw)
{
	return SRIOV_NONE;
}

static inline
struct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw,
					  int vport_index)
{
	return NULL;
}

static inline
struct mlx5_ib_dev *mlx5_ib_get_uplink_ibdev(struct mlx5_eswitch *esw)
{
	return NULL;
}

static inline
struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw,
					   int vport_index)
{
	return NULL;
}

static inline void mlx5_ib_register_vport_reps(struct mlx5_ib_dev *dev) {}
static inline void mlx5_ib_unregister_vport_reps(struct mlx5_ib_dev *dev) {}
static inline int create_flow_rule_vport_sq(struct mlx5_ib_dev *dev,
					    struct mlx5_ib_sq *sq)
{
	return 0;
}

static inline
struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
					  int vport_index)
{
	return NULL;
}
#endif

static inline
struct mlx5_ib_dev *mlx5_ib_rep_to_dev(struct mlx5_eswitch_rep *rep)
{
	return (struct mlx5_ib_dev *)rep->rep_if[REP_IB].priv;
}
#endif /* __MLX5_IB_REP_H__ */
+286 −75
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@
#include <linux/in.h>
#include <linux/etherdevice.h>
#include "mlx5_ib.h"
#include "ib_rep.h"
#include "cmd.h"

#define DRIVER_NAME "mlx5_ib"
@@ -130,7 +131,7 @@ static int get_port_state(struct ib_device *ibdev,
	int ret;

	memset(&attr, 0, sizeof(attr));
	ret = mlx5_ib_query_port(ibdev, port_num, &attr);
	ret = ibdev->query_port(ibdev, port_num, &attr);
	if (!ret)
		*state = attr.state;
	return ret;
@@ -154,10 +155,19 @@ static int mlx5_netdev_event(struct notifier_block *this,
	case NETDEV_REGISTER:
	case NETDEV_UNREGISTER:
		write_lock(&roce->netdev_lock);
		if (ibdev->rep) {
			struct mlx5_eswitch *esw = ibdev->mdev->priv.eswitch;
			struct net_device *rep_ndev;

		if (ndev->dev.parent == &mdev->pdev->dev)
			rep_ndev = mlx5_ib_get_rep_netdev(esw,
							  ibdev->rep->vport);
			if (rep_ndev == ndev)
				roce->netdev = (event == NETDEV_UNREGISTER) ?
					NULL : ndev;
		} else if (ndev->dev.parent == &ibdev->mdev->pdev->dev) {
			roce->netdev = (event == NETDEV_UNREGISTER) ?
				NULL : ndev;
		}
		write_unlock(&roce->netdev_lock);
		break;

@@ -1268,6 +1278,22 @@ int mlx5_ib_query_port(struct ib_device *ibdev, u8 port,
	return ret;
}

static int mlx5_ib_rep_query_port(struct ib_device *ibdev, u8 port,
				  struct ib_port_attr *props)
{
	int ret;

	/* Only link layer == ethernet is valid for representors */
	ret = mlx5_query_port_roce(ibdev, port, props);
	if (ret || !props)
		return ret;

	/* We don't support GIDS */
	props->gid_tbl_len = 0;

	return ret;
}

static int mlx5_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
			     union ib_gid *gid)
{
@@ -2631,7 +2657,7 @@ static int mlx5_ib_destroy_flow(struct ib_flow *flow_id)
							  ibflow);
	struct mlx5_ib_flow_handler *iter, *tmp;

	mutex_lock(&dev->flow_db.lock);
	mutex_lock(&dev->flow_db->lock);

	list_for_each_entry_safe(iter, tmp, &handler->list, list) {
		mlx5_del_flow_rules(iter->rule);
@@ -2642,7 +2668,7 @@ static int mlx5_ib_destroy_flow(struct ib_flow *flow_id)

	mlx5_del_flow_rules(handler->rule);
	put_flow_table(dev, handler->prio, true);
	mutex_unlock(&dev->flow_db.lock);
	mutex_unlock(&dev->flow_db->lock);

	kfree(handler);

@@ -2691,7 +2717,7 @@ static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
					     MLX5_FLOW_NAMESPACE_BYPASS);
		num_entries = MLX5_FS_MAX_ENTRIES;
		num_groups = MLX5_FS_MAX_TYPES;
		prio = &dev->flow_db.prios[priority];
		prio = &dev->flow_db->prios[priority];
	} else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
		   flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) {
		ns = mlx5_get_flow_namespace(dev->mdev,
@@ -2699,7 +2725,7 @@ static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
		build_leftovers_ft_param(&priority,
					 &num_entries,
					 &num_groups);
		prio = &dev->flow_db.prios[MLX5_IB_FLOW_LEFTOVERS_PRIO];
		prio = &dev->flow_db->prios[MLX5_IB_FLOW_LEFTOVERS_PRIO];
	} else if (flow_attr->type == IB_FLOW_ATTR_SNIFFER) {
		if (!MLX5_CAP_FLOWTABLE(dev->mdev,
					allow_sniffer_and_nic_rx_shared_tir))
@@ -2709,7 +2735,7 @@ static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
					     MLX5_FLOW_NAMESPACE_SNIFFER_RX :
					     MLX5_FLOW_NAMESPACE_SNIFFER_TX);

		prio = &dev->flow_db.sniffer[ft_type];
		prio = &dev->flow_db->sniffer[ft_type];
		priority = 0;
		num_entries = 1;
		num_groups = 1;
@@ -2802,6 +2828,18 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
	if (!flow_is_multicast_only(flow_attr))
		set_underlay_qp(dev, spec, underlay_qpn);

	if (dev->rep) {
		void *misc;

		misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
				    misc_parameters);
		MLX5_SET(fte_match_set_misc, misc, source_port,
			 dev->rep->vport);
		misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
				    misc_parameters);
		MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
	}

	spec->match_criteria_enable = get_match_criteria_enable(spec->match_criteria);
	if (is_drop) {
		flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
@@ -2999,7 +3037,7 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
	if (!dst)
		return ERR_PTR(-ENOMEM);

	mutex_lock(&dev->flow_db.lock);
	mutex_lock(&dev->flow_db->lock);

	ft_prio = get_flow_table(dev, flow_attr, MLX5_IB_FT_RX);
	if (IS_ERR(ft_prio)) {
@@ -3048,7 +3086,7 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
		goto destroy_ft;
	}

	mutex_unlock(&dev->flow_db.lock);
	mutex_unlock(&dev->flow_db->lock);
	kfree(dst);

	return &handler->ibflow;
@@ -3058,7 +3096,7 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
	if (ft_prio_tx)
		put_flow_table(dev, ft_prio_tx, false);
unlock:
	mutex_unlock(&dev->flow_db.lock);
	mutex_unlock(&dev->flow_db->lock);
	kfree(dst);
	kfree(handler);
	return ERR_PTR(err);
@@ -3772,6 +3810,25 @@ static int mlx5_port_immutable(struct ib_device *ibdev, u8 port_num,
	return 0;
}

static int mlx5_port_rep_immutable(struct ib_device *ibdev, u8 port_num,
				   struct ib_port_immutable *immutable)
{
	struct ib_port_attr attr;
	int err;

	immutable->core_cap_flags = RDMA_CORE_PORT_RAW_PACKET;

	err = ib_query_port(ibdev, port_num, &attr);
	if (err)
		return err;

	immutable->pkey_tbl_len = attr.pkey_tbl_len;
	immutable->gid_tbl_len = attr.gid_tbl_len;
	immutable->core_cap_flags = RDMA_CORE_PORT_RAW_PACKET;

	return 0;
}

static void get_dev_fw_str(struct ib_device *ibdev, char *str)
{
	struct mlx5_ib_dev *dev =
@@ -3802,7 +3859,7 @@ static int mlx5_eth_lag_init(struct mlx5_ib_dev *dev)
		goto err_destroy_vport_lag;
	}

	dev->flow_db.lag_demux_ft = ft;
	dev->flow_db->lag_demux_ft = ft;
	return 0;

err_destroy_vport_lag:
@@ -3814,9 +3871,9 @@ static void mlx5_eth_lag_cleanup(struct mlx5_ib_dev *dev)
{
	struct mlx5_core_dev *mdev = dev->mdev;

	if (dev->flow_db.lag_demux_ft) {
		mlx5_destroy_flow_table(dev->flow_db.lag_demux_ft);
		dev->flow_db.lag_demux_ft = NULL;
	if (dev->flow_db->lag_demux_ft) {
		mlx5_destroy_flow_table(dev->flow_db->lag_demux_ft);
		dev->flow_db->lag_demux_ft = NULL;

		mlx5_cmd_destroy_vport_lag(mdev);
	}
@@ -3848,14 +3905,10 @@ static int mlx5_enable_eth(struct mlx5_ib_dev *dev, u8 port_num)
{
	int err;

	err = mlx5_add_netdev_notifier(dev, port_num);
	if (err)
		return err;

	if (MLX5_CAP_GEN(dev->mdev, roce)) {
		err = mlx5_nic_vport_enable_roce(dev->mdev);
		if (err)
			goto err_unregister_netdevice_notifier;
			return err;
	}

	err = mlx5_eth_lag_init(dev);
@@ -3868,8 +3921,6 @@ static int mlx5_enable_eth(struct mlx5_ib_dev *dev, u8 port_num)
	if (MLX5_CAP_GEN(dev->mdev, roce))
		mlx5_nic_vport_disable_roce(dev->mdev);

err_unregister_netdevice_notifier:
	mlx5_remove_netdev_notifier(dev, port_num);
	return err;
}

@@ -4503,7 +4554,7 @@ static void mlx5_ib_cleanup_multiport_master(struct mlx5_ib_dev *dev)
	mlx5_nic_vport_disable_roce(dev->mdev);
}

static void mlx5_ib_stage_init_cleanup(struct mlx5_ib_dev *dev)
void mlx5_ib_stage_init_cleanup(struct mlx5_ib_dev *dev)
{
	mlx5_ib_cleanup_multiport_master(dev);
#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
@@ -4512,7 +4563,7 @@ static void mlx5_ib_stage_init_cleanup(struct mlx5_ib_dev *dev)
	kfree(dev->port);
}

static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
{
	struct mlx5_core_dev *mdev = dev->mdev;
	const char *name;
@@ -4564,7 +4615,6 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
		dev->mdev->priv.eq_table.num_comp_vectors;
	dev->ib_dev.dev.parent		= &mdev->pdev->dev;

	mutex_init(&dev->flow_db.lock);
	mutex_init(&dev->cap_mask_mutex);
	INIT_LIST_HEAD(&dev->qp_list);
	spin_lock_init(&dev->reset_flow_resource_lock);
@@ -4585,7 +4635,38 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
	return -ENOMEM;
}

static int mlx5_ib_stage_caps_init(struct mlx5_ib_dev *dev)
static int mlx5_ib_stage_flow_db_init(struct mlx5_ib_dev *dev)
{
	dev->flow_db = kzalloc(sizeof(*dev->flow_db), GFP_KERNEL);

	if (!dev->flow_db)
		return -ENOMEM;

	mutex_init(&dev->flow_db->lock);

	return 0;
}

int mlx5_ib_stage_rep_flow_db_init(struct mlx5_ib_dev *dev)
{
	struct mlx5_ib_dev *nic_dev;

	nic_dev = mlx5_ib_get_uplink_ibdev(dev->mdev->priv.eswitch);

	if (!nic_dev)
		return -EINVAL;

	dev->flow_db = nic_dev->flow_db;

	return 0;
}

static void mlx5_ib_stage_flow_db_cleanup(struct mlx5_ib_dev *dev)
{
	kfree(dev->flow_db);
}

int mlx5_ib_stage_caps_init(struct mlx5_ib_dev *dev)
{
	struct mlx5_core_dev *mdev = dev->mdev;
	int err;
@@ -4626,7 +4707,6 @@ static int mlx5_ib_stage_caps_init(struct mlx5_ib_dev *dev)
		(1ull << IB_USER_VERBS_EX_CMD_MODIFY_CQ);

	dev->ib_dev.query_device	= mlx5_ib_query_device;
	dev->ib_dev.query_port		= mlx5_ib_query_port;
	dev->ib_dev.get_link_layer	= mlx5_ib_port_link_layer;
	dev->ib_dev.query_gid		= mlx5_ib_query_gid;
	dev->ib_dev.add_gid		= mlx5_ib_add_gid;
@@ -4669,7 +4749,6 @@ static int mlx5_ib_stage_caps_init(struct mlx5_ib_dev *dev)
	dev->ib_dev.alloc_mr		= mlx5_ib_alloc_mr;
	dev->ib_dev.map_mr_sg		= mlx5_ib_map_mr_sg;
	dev->ib_dev.check_mr_status	= mlx5_ib_check_mr_status;
	dev->ib_dev.get_port_immutable  = mlx5_port_immutable;
	dev->ib_dev.get_dev_fw_str      = get_dev_fw_str;
	dev->ib_dev.get_vector_affinity	= mlx5_ib_get_vector_affinity;
	if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads))
@@ -4720,20 +4799,27 @@ static int mlx5_ib_stage_caps_init(struct mlx5_ib_dev *dev)
	return 0;
}

static int mlx5_ib_stage_roce_init(struct mlx5_ib_dev *dev)
static int mlx5_ib_stage_non_default_cb(struct mlx5_ib_dev *dev)
{
	struct mlx5_core_dev *mdev = dev->mdev;
	enum rdma_link_layer ll;
	int port_type_cap;
	u8 port_num;
	int err;
	int i;
	dev->ib_dev.get_port_immutable  = mlx5_port_immutable;
	dev->ib_dev.query_port		= mlx5_ib_query_port;

	port_num = mlx5_core_native_port_num(dev->mdev) - 1;
	port_type_cap = MLX5_CAP_GEN(mdev, port_type);
	ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);
	return 0;
}

int mlx5_ib_stage_rep_non_default_cb(struct mlx5_ib_dev *dev)
{
	dev->ib_dev.get_port_immutable  = mlx5_port_rep_immutable;
	dev->ib_dev.query_port		= mlx5_ib_rep_query_port;

	return 0;
}

static int mlx5_ib_stage_common_roce_init(struct mlx5_ib_dev *dev,
					  u8 port_num)
{
	int i;

	if (ll == IB_LINK_LAYER_ETHERNET) {
	for (i = 0; i < dev->num_ports; i++) {
		dev->roce[i].dev = dev;
		dev->roce[i].native_port_num = i + 1;
@@ -4746,18 +4832,74 @@ static int mlx5_ib_stage_roce_init(struct mlx5_ib_dev *dev)
	dev->ib_dev.destroy_wq	 = mlx5_ib_destroy_wq;
	dev->ib_dev.create_rwq_ind_table = mlx5_ib_create_rwq_ind_table;
	dev->ib_dev.destroy_rwq_ind_table = mlx5_ib_destroy_rwq_ind_table;

	dev->ib_dev.uverbs_ex_cmd_mask |=
			(1ull << IB_USER_VERBS_EX_CMD_CREATE_WQ) |
			(1ull << IB_USER_VERBS_EX_CMD_MODIFY_WQ) |
			(1ull << IB_USER_VERBS_EX_CMD_DESTROY_WQ) |
			(1ull << IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL) |
			(1ull << IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL);
		err = mlx5_enable_eth(dev, port_num);

	return mlx5_add_netdev_notifier(dev, port_num);
}

static void mlx5_ib_stage_common_roce_cleanup(struct mlx5_ib_dev *dev)
{
	u8 port_num = mlx5_core_native_port_num(dev->mdev) - 1;

	mlx5_remove_netdev_notifier(dev, port_num);
}

int mlx5_ib_stage_rep_roce_init(struct mlx5_ib_dev *dev)
{
	struct mlx5_core_dev *mdev = dev->mdev;
	enum rdma_link_layer ll;
	int port_type_cap;
	int err = 0;
	u8 port_num;

	port_num = mlx5_core_native_port_num(dev->mdev) - 1;
	port_type_cap = MLX5_CAP_GEN(mdev, port_type);
	ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);

	if (ll == IB_LINK_LAYER_ETHERNET)
		err = mlx5_ib_stage_common_roce_init(dev, port_num);

	return err;
}

void mlx5_ib_stage_rep_roce_cleanup(struct mlx5_ib_dev *dev)
{
	mlx5_ib_stage_common_roce_cleanup(dev);
}

static int mlx5_ib_stage_roce_init(struct mlx5_ib_dev *dev)
{
	struct mlx5_core_dev *mdev = dev->mdev;
	enum rdma_link_layer ll;
	int port_type_cap;
	u8 port_num;
	int err;

	port_num = mlx5_core_native_port_num(dev->mdev) - 1;
	port_type_cap = MLX5_CAP_GEN(mdev, port_type);
	ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);

	if (ll == IB_LINK_LAYER_ETHERNET) {
		err = mlx5_ib_stage_common_roce_init(dev, port_num);
		if (err)
			return err;

		err = mlx5_enable_eth(dev, port_num);
		if (err)
			goto cleanup;
	}

	return 0;
cleanup:
	mlx5_ib_stage_common_roce_cleanup(dev);

	return err;
}

static void mlx5_ib_stage_roce_cleanup(struct mlx5_ib_dev *dev)
@@ -4773,16 +4915,16 @@ static void mlx5_ib_stage_roce_cleanup(struct mlx5_ib_dev *dev)

	if (ll == IB_LINK_LAYER_ETHERNET) {
		mlx5_disable_eth(dev);
		mlx5_remove_netdev_notifier(dev, port_num);
		mlx5_ib_stage_common_roce_cleanup(dev);
	}
}

static int mlx5_ib_stage_dev_res_init(struct mlx5_ib_dev *dev)
int mlx5_ib_stage_dev_res_init(struct mlx5_ib_dev *dev)
{
	return create_dev_resources(&dev->devr);
}

static void mlx5_ib_stage_dev_res_cleanup(struct mlx5_ib_dev *dev)
void mlx5_ib_stage_dev_res_cleanup(struct mlx5_ib_dev *dev)
{
	destroy_dev_resources(&dev->devr);
}
@@ -4794,7 +4936,7 @@ static int mlx5_ib_stage_odp_init(struct mlx5_ib_dev *dev)
	return mlx5_ib_odp_init_one(dev);
}

static int mlx5_ib_stage_counters_init(struct mlx5_ib_dev *dev)
int mlx5_ib_stage_counters_init(struct mlx5_ib_dev *dev)
{
	if (MLX5_CAP_GEN(dev->mdev, max_qp_cnt)) {
		dev->ib_dev.get_hw_stats	= mlx5_ib_get_hw_stats;
@@ -4806,7 +4948,7 @@ static int mlx5_ib_stage_counters_init(struct mlx5_ib_dev *dev)
	return 0;
}

static void mlx5_ib_stage_counters_cleanup(struct mlx5_ib_dev *dev)
void mlx5_ib_stage_counters_cleanup(struct mlx5_ib_dev *dev)
{
	if (MLX5_CAP_GEN(dev->mdev, max_qp_cnt))
		mlx5_ib_dealloc_counters(dev);
@@ -4837,7 +4979,7 @@ static void mlx5_ib_stage_uar_cleanup(struct mlx5_ib_dev *dev)
	mlx5_put_uars_page(dev->mdev, dev->mdev->priv.uar);
}

static int mlx5_ib_stage_bfrag_init(struct mlx5_ib_dev *dev)
int mlx5_ib_stage_bfrag_init(struct mlx5_ib_dev *dev)
{
	int err;

@@ -4852,28 +4994,28 @@ static int mlx5_ib_stage_bfrag_init(struct mlx5_ib_dev *dev)
	return err;
}

static void mlx5_ib_stage_bfrag_cleanup(struct mlx5_ib_dev *dev)
void mlx5_ib_stage_bfrag_cleanup(struct mlx5_ib_dev *dev)
{
	mlx5_free_bfreg(dev->mdev, &dev->fp_bfreg);
	mlx5_free_bfreg(dev->mdev, &dev->bfreg);
}

static int mlx5_ib_stage_ib_reg_init(struct mlx5_ib_dev *dev)
int mlx5_ib_stage_ib_reg_init(struct mlx5_ib_dev *dev)
{
	return ib_register_device(&dev->ib_dev, NULL);
}

static void mlx5_ib_stage_ib_reg_cleanup(struct mlx5_ib_dev *dev)
void mlx5_ib_stage_ib_reg_cleanup(struct mlx5_ib_dev *dev)
{
	ib_unregister_device(&dev->ib_dev);
}

static int mlx5_ib_stage_umr_res_init(struct mlx5_ib_dev *dev)
int mlx5_ib_stage_umr_res_init(struct mlx5_ib_dev *dev)
{
	return create_umr_res(dev);
}

static void mlx5_ib_stage_umr_res_cleanup(struct mlx5_ib_dev *dev)
void mlx5_ib_stage_umr_res_cleanup(struct mlx5_ib_dev *dev)
{
	destroy_umrc_res(dev);
}
@@ -4890,7 +5032,7 @@ static void mlx5_ib_stage_delay_drop_cleanup(struct mlx5_ib_dev *dev)
	cancel_delay_drop(dev);
}

static int mlx5_ib_stage_class_attr_init(struct mlx5_ib_dev *dev)
int mlx5_ib_stage_class_attr_init(struct mlx5_ib_dev *dev)
{
	int err;
	int i;
@@ -4905,7 +5047,19 @@ static int mlx5_ib_stage_class_attr_init(struct mlx5_ib_dev *dev)
	return 0;
}

static void __mlx5_ib_remove(struct mlx5_ib_dev *dev,
static int mlx5_ib_stage_rep_reg_init(struct mlx5_ib_dev *dev)
{
	mlx5_ib_register_vport_reps(dev);

	return 0;
}

static void mlx5_ib_stage_rep_reg_cleanup(struct mlx5_ib_dev *dev)
{
	mlx5_ib_unregister_vport_reps(dev);
}

void __mlx5_ib_remove(struct mlx5_ib_dev *dev,
		      const struct mlx5_ib_profile *profile,
		      int stage)
{
@@ -4921,23 +5075,14 @@ static void __mlx5_ib_remove(struct mlx5_ib_dev *dev,

static void *mlx5_ib_add_slave_port(struct mlx5_core_dev *mdev, u8 port_num);

static void *__mlx5_ib_add(struct mlx5_core_dev *mdev,
void *__mlx5_ib_add(struct mlx5_ib_dev *dev,
		    const struct mlx5_ib_profile *profile)
{
	struct mlx5_ib_dev *dev;
	int err;
	int i;

	printk_once(KERN_INFO "%s", mlx5_version);

	dev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*dev));
	if (!dev)
		return NULL;

	dev->mdev = mdev;
	dev->num_ports = max(MLX5_CAP_GEN(mdev, num_ports),
			     MLX5_CAP_GEN(mdev, num_vhca_ports));

	for (i = 0; i < MLX5_IB_STAGE_MAX; i++) {
		if (profile->stage[i].init) {
			err = profile->stage[i].init(dev);
@@ -4961,9 +5106,15 @@ static const struct mlx5_ib_profile pf_profile = {
	STAGE_CREATE(MLX5_IB_STAGE_INIT,
		     mlx5_ib_stage_init_init,
		     mlx5_ib_stage_init_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_FLOW_DB,
		     mlx5_ib_stage_flow_db_init,
		     mlx5_ib_stage_flow_db_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_CAPS,
		     mlx5_ib_stage_caps_init,
		     NULL),
	STAGE_CREATE(MLX5_IB_STAGE_NON_DEFAULT_CB,
		     mlx5_ib_stage_non_default_cb,
		     NULL),
	STAGE_CREATE(MLX5_IB_STAGE_ROCE,
		     mlx5_ib_stage_roce_init,
		     mlx5_ib_stage_roce_cleanup),
@@ -4999,6 +5150,48 @@ static const struct mlx5_ib_profile pf_profile = {
		     NULL),
};

static const struct mlx5_ib_profile nic_rep_profile = {
	STAGE_CREATE(MLX5_IB_STAGE_INIT,
		     mlx5_ib_stage_init_init,
		     mlx5_ib_stage_init_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_FLOW_DB,
		     mlx5_ib_stage_flow_db_init,
		     mlx5_ib_stage_flow_db_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_CAPS,
		     mlx5_ib_stage_caps_init,
		     NULL),
	STAGE_CREATE(MLX5_IB_STAGE_NON_DEFAULT_CB,
		     mlx5_ib_stage_rep_non_default_cb,
		     NULL),
	STAGE_CREATE(MLX5_IB_STAGE_ROCE,
		     mlx5_ib_stage_rep_roce_init,
		     mlx5_ib_stage_rep_roce_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,
		     mlx5_ib_stage_dev_res_init,
		     mlx5_ib_stage_dev_res_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_COUNTERS,
		     mlx5_ib_stage_counters_init,
		     mlx5_ib_stage_counters_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_UAR,
		     mlx5_ib_stage_uar_init,
		     mlx5_ib_stage_uar_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_BFREG,
		     mlx5_ib_stage_bfrag_init,
		     mlx5_ib_stage_bfrag_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_IB_REG,
		     mlx5_ib_stage_ib_reg_init,
		     mlx5_ib_stage_ib_reg_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_UMR_RESOURCES,
		     mlx5_ib_stage_umr_res_init,
		     mlx5_ib_stage_umr_res_cleanup),
	STAGE_CREATE(MLX5_IB_STAGE_CLASS_ATTR,
		     mlx5_ib_stage_class_attr_init,
		     NULL),
	STAGE_CREATE(MLX5_IB_STAGE_REP_REG,
		     mlx5_ib_stage_rep_reg_init,
		     mlx5_ib_stage_rep_reg_cleanup),
};

static void *mlx5_ib_add_slave_port(struct mlx5_core_dev *mdev, u8 port_num)
{
	struct mlx5_ib_multiport_info *mpi;
@@ -5044,8 +5237,11 @@ static void *mlx5_ib_add_slave_port(struct mlx5_core_dev *mdev, u8 port_num)
static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
{
	enum rdma_link_layer ll;
	struct mlx5_ib_dev *dev;
	int port_type_cap;

	printk_once(KERN_INFO "%s", mlx5_version);

	port_type_cap = MLX5_CAP_GEN(mdev, port_type);
	ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);

@@ -5055,7 +5251,22 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
		return mlx5_ib_add_slave_port(mdev, port_num);
	}

	return __mlx5_ib_add(mdev, &pf_profile);
	dev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*dev));
	if (!dev)
		return NULL;

	dev->mdev = mdev;
	dev->num_ports = max(MLX5_CAP_GEN(mdev, num_ports),
			     MLX5_CAP_GEN(mdev, num_vhca_ports));

	if (MLX5_VPORT_MANAGER(mdev) &&
	    mlx5_ib_eswitch_mode(mdev->priv.eswitch) == SRIOV_OFFLOADS) {
		dev->rep = mlx5_ib_vport_rep(mdev->priv.eswitch, 0);

		return __mlx5_ib_add(dev, &nic_rep_profile);
	}

	return __mlx5_ib_add(dev, &pf_profile);
}

static void mlx5_ib_remove(struct mlx5_core_dev *mdev, void *context)
+31 −1

File changed.

Preview size limit exceeded, changes collapsed.

Loading