Commit 749b9eef authored by Doug Ledford's avatar Doug Ledford
Browse files

Merge remote-tracking branch 'mlx5-next/mlx5-next' into wip/dl-for-next



Merging tip of mlx5-next in order to get changes related to adding
XRQ support to the DEVX interface needed prior to the following two
patches.

Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parents db50077b b1635ee6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -930,6 +930,7 @@ static bool devx_is_general_cmd(void *in, struct mlx5_ib_dev *dev)
	case MLX5_CMD_OP_QUERY_CONG_STATUS:
	case MLX5_CMD_OP_QUERY_CONG_PARAMS:
	case MLX5_CMD_OP_QUERY_CONG_STATISTICS:
	case MLX5_CMD_OP_QUERY_LAG:
		return true;
	default:
		return false;
+3 −3
Original line number Diff line number Diff line
@@ -86,7 +86,7 @@ struct mlx5_core_srq *mlx5_cmd_get_srq(struct mlx5_ib_dev *dev, u32 srqn)
	xa_lock(&table->array);
	srq = xa_load(&table->array, srqn);
	if (srq)
		atomic_inc(&srq->common.refcount);
		refcount_inc(&srq->common.refcount);
	xa_unlock(&table->array);

	return srq;
@@ -592,7 +592,7 @@ int mlx5_cmd_create_srq(struct mlx5_ib_dev *dev, struct mlx5_core_srq *srq,
	if (err)
		return err;

	atomic_set(&srq->common.refcount, 1);
	refcount_set(&srq->common.refcount, 1);
	init_completion(&srq->common.free);

	err = xa_err(xa_store_irq(&table->array, srq->srqn, srq, GFP_KERNEL));
@@ -675,7 +675,7 @@ static int srq_event_notifier(struct notifier_block *nb,
	xa_lock(&table->array);
	srq = xa_load(&table->array, srqn);
	if (srq)
		atomic_inc(&srq->common.refcount);
		refcount_inc(&srq->common.refcount);
	xa_unlock(&table->array);

	if (!srq)
+4 −0
Original line number Diff line number Diff line
@@ -446,6 +446,8 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
	case MLX5_CMD_OP_CREATE_UMEM:
	case MLX5_CMD_OP_DESTROY_UMEM:
	case MLX5_CMD_OP_ALLOC_MEMIC:
	case MLX5_CMD_OP_MODIFY_XRQ:
	case MLX5_CMD_OP_RELEASE_XRQ_ERROR:
		*status = MLX5_DRIVER_STATUS_ABORTED;
		*synd = MLX5_DRIVER_SYND;
		return -EIO;
@@ -637,6 +639,8 @@ const char *mlx5_command_str(int command)
	MLX5_COMMAND_STR_CASE(DESTROY_UCTX);
	MLX5_COMMAND_STR_CASE(CREATE_UMEM);
	MLX5_COMMAND_STR_CASE(DESTROY_UMEM);
	MLX5_COMMAND_STR_CASE(RELEASE_XRQ_ERROR);
	MLX5_COMMAND_STR_CASE(MODIFY_XRQ);
	default: return "unknown command opcode";
	}
}
+1 −11
Original line number Diff line number Diff line
@@ -215,11 +215,7 @@ static int mlx5_eq_async_int(struct notifier_block *nb,
		 */
		dma_rmb();

		if (likely(eqe->type < MLX5_EVENT_TYPE_MAX))
		atomic_notifier_call_chain(&eqt->nh[eqe->type], eqe->type, eqe);
		else
			mlx5_core_warn_once(dev, "notifier_call_chain is not setup for eqe: %d\n", eqe->type);

		atomic_notifier_call_chain(&eqt->nh[MLX5_EVENT_TYPE_NOTIFY_ANY], eqe->type, eqe);

		++eq->cons_index;
@@ -945,9 +941,6 @@ int mlx5_eq_notifier_register(struct mlx5_core_dev *dev, struct mlx5_nb *nb)
{
	struct mlx5_eq_table *eqt = dev->priv.eq_table;

	if (nb->event_type >= MLX5_EVENT_TYPE_MAX)
		return -EINVAL;

	return atomic_notifier_chain_register(&eqt->nh[nb->event_type], &nb->nb);
}
EXPORT_SYMBOL(mlx5_eq_notifier_register);
@@ -956,9 +949,6 @@ int mlx5_eq_notifier_unregister(struct mlx5_core_dev *dev, struct mlx5_nb *nb)
{
	struct mlx5_eq_table *eqt = dev->priv.eq_table;

	if (nb->event_type >= MLX5_EVENT_TYPE_MAX)
		return -EINVAL;

	return atomic_notifier_chain_unregister(&eqt->nh[nb->event_type], &nb->nb);
}
EXPORT_SYMBOL(mlx5_eq_notifier_unregister);
+118 −66
Original line number Diff line number Diff line
@@ -58,20 +58,9 @@ struct vport_addr {
	bool mc_promisc;
};

enum {
	UC_ADDR_CHANGE = BIT(0),
	MC_ADDR_CHANGE = BIT(1),
	PROMISC_CHANGE = BIT(3),
};

static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw);
static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw);

/* Vport context events */
#define SRIOV_VPORT_EVENTS (UC_ADDR_CHANGE | \
			    MC_ADDR_CHANGE | \
			    PROMISC_CHANGE)

struct mlx5_vport *__must_check
mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num)
{
@@ -108,13 +97,13 @@ static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport,

	MLX5_SET(nic_vport_context, nic_vport_ctx, arm_change_event, 1);

	if (events_mask & UC_ADDR_CHANGE)
	if (events_mask & MLX5_VPORT_UC_ADDR_CHANGE)
		MLX5_SET(nic_vport_context, nic_vport_ctx,
			 event_on_uc_address_change, 1);
	if (events_mask & MC_ADDR_CHANGE)
	if (events_mask & MLX5_VPORT_MC_ADDR_CHANGE)
		MLX5_SET(nic_vport_context, nic_vport_ctx,
			 event_on_mc_address_change, 1);
	if (events_mask & PROMISC_CHANGE)
	if (events_mask & MLX5_VPORT_PROMISC_CHANGE)
		MLX5_SET(nic_vport_context, nic_vport_ctx,
			 event_on_promisc_change, 1);

@@ -463,6 +452,22 @@ static int esw_create_legacy_table(struct mlx5_eswitch *esw)
	return err;
}

#define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \
					MLX5_VPORT_MC_ADDR_CHANGE | \
					MLX5_VPORT_PROMISC_CHANGE)

static int esw_legacy_enable(struct mlx5_eswitch *esw)
{
	int ret;

	ret = esw_create_legacy_table(esw);
	if (ret)
		return ret;

	mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_LEGACY_SRIOV_VPORT_EVENTS);
	return 0;
}

static void esw_destroy_legacy_table(struct mlx5_eswitch *esw)
{
	esw_cleanup_vepa_rules(esw);
@@ -470,6 +475,19 @@ static void esw_destroy_legacy_table(struct mlx5_eswitch *esw)
	esw_destroy_legacy_vepa_table(esw);
}

static void esw_legacy_disable(struct mlx5_eswitch *esw)
{
	struct esw_mc_addr *mc_promisc;

	mlx5_eswitch_disable_pf_vf_vports(esw);

	mc_promisc = &esw->mc_promisc;
	if (mc_promisc->uplink_rule)
		mlx5_del_flow_rules(mc_promisc->uplink_rule);

	esw_destroy_legacy_table(esw);
}

/* E-Switch vport UC/MC lists management */
typedef int (*vport_addr_action)(struct mlx5_eswitch *esw,
				 struct vport_addr *vaddr);
@@ -901,21 +919,21 @@ static void esw_vport_change_handle_locked(struct mlx5_vport *vport)
	esw_debug(dev, "vport[%d] Context Changed: perm mac: %pM\n",
		  vport->vport, mac);

	if (vport->enabled_events & UC_ADDR_CHANGE) {
	if (vport->enabled_events & MLX5_VPORT_UC_ADDR_CHANGE) {
		esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC);
		esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC);
	}

	if (vport->enabled_events & MC_ADDR_CHANGE)
	if (vport->enabled_events & MLX5_VPORT_MC_ADDR_CHANGE)
		esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC);

	if (vport->enabled_events & PROMISC_CHANGE) {
	if (vport->enabled_events & MLX5_VPORT_PROMISC_CHANGE) {
		esw_update_vport_rx_mode(esw, vport);
		if (!IS_ERR_OR_NULL(vport->allmulti_rule))
			esw_update_vport_mc_promisc(esw, vport);
	}

	if (vport->enabled_events & (PROMISC_CHANGE | MC_ADDR_CHANGE))
	if (vport->enabled_events & (MLX5_VPORT_PROMISC_CHANGE | MLX5_VPORT_MC_ADDR_CHANGE))
		esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC);

	esw_debug(esw->dev, "vport[%d] Context Changed: Done\n", vport->vport);
@@ -1393,18 +1411,49 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw,
	return err;
}

static bool element_type_supported(struct mlx5_eswitch *esw, int type)
{
	const struct mlx5_core_dev *dev = esw->dev;

	switch (type) {
	case SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR:
		return MLX5_CAP_QOS(dev, esw_element_type) &
		       ELEMENT_TYPE_CAP_MASK_TASR;
	case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT:
		return MLX5_CAP_QOS(dev, esw_element_type) &
		       ELEMENT_TYPE_CAP_MASK_VPORT;
	case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT_TC:
		return MLX5_CAP_QOS(dev, esw_element_type) &
		       ELEMENT_TYPE_CAP_MASK_VPORT_TC;
	case SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC:
		return MLX5_CAP_QOS(dev, esw_element_type) &
		       ELEMENT_TYPE_CAP_MASK_PARA_VPORT_TC;
	}
	return false;
}

/* Vport QoS management */
static int esw_create_tsar(struct mlx5_eswitch *esw)
static void esw_create_tsar(struct mlx5_eswitch *esw)
{
	u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
	struct mlx5_core_dev *dev = esw->dev;
	__be32 *attr;
	int err;

	if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
		return 0;
		return;

	if (!element_type_supported(esw, SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR))
		return;

	if (esw->qos.enabled)
		return -EEXIST;
		return;

	MLX5_SET(scheduling_context, tsar_ctx, element_type,
		 SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR);

	attr = MLX5_ADDR_OF(scheduling_context, tsar_ctx, element_attributes);
	*attr = cpu_to_be32(TSAR_ELEMENT_TSAR_TYPE_DWRR << 16);

	err = mlx5_create_scheduling_element_cmd(dev,
						 SCHEDULING_HIERARCHY_E_SWITCH,
@@ -1412,11 +1461,10 @@ static int esw_create_tsar(struct mlx5_eswitch *esw)
						 &esw->qos.root_tsar_id);
	if (err) {
		esw_warn(esw->dev, "E-Switch create TSAR failed (%d)\n", err);
		return err;
		return;
	}

	esw->qos.enabled = true;
	return 0;
}

static void esw_destroy_tsar(struct mlx5_eswitch *esw)
@@ -1619,7 +1667,7 @@ static void esw_vport_destroy_drop_counters(struct mlx5_vport *vport)
}

static void esw_enable_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
			     int enable_events)
			     enum mlx5_eswitch_vport_event enabled_events)
{
	u16 vport_num = vport->vport;

@@ -1641,7 +1689,7 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
		esw_warn(esw->dev, "Failed to attach vport %d to eswitch rate limiter", vport_num);

	/* Sync with current vport context */
	vport->enabled_events = enable_events;
	vport->enabled_events = enabled_events;
	vport->enabled = true;

	/* Esw manager is trusted by default. Host PF (vport 0) is trusted as well
@@ -1770,11 +1818,46 @@ static void mlx5_eswitch_event_handlers_unregister(struct mlx5_eswitch *esw)
/* Public E-Switch API */
#define ESW_ALLOWED(esw) ((esw) && MLX5_ESWITCH_MANAGER((esw)->dev))

int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode)
/* mlx5_eswitch_enable_pf_vf_vports() enables vports of PF, ECPF and VFs
 * whichever are present on the eswitch.
 */
void
mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
				 enum mlx5_eswitch_vport_event enabled_events)
{
	struct mlx5_vport *vport;
	int i;

	/* Enable PF vport */
	vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
	esw_enable_vport(esw, vport, enabled_events);

	/* Enable ECPF vports */
	if (mlx5_ecpf_vport_exists(esw->dev)) {
		vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF);
		esw_enable_vport(esw, vport, enabled_events);
	}

	/* Enable VF vports */
	mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
		esw_enable_vport(esw, vport, enabled_events);
}

/* mlx5_eswitch_disable_pf_vf_vports() disables vports of PF, ECPF and VFs
 * whichever are previously enabled on the eswitch.
 */
void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw)
{
	struct mlx5_vport *vport;
	int i;

	mlx5_esw_for_all_vports_reverse(esw, i, vport)
		esw_disable_vport(esw, vport);
}

int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode)
{
	int err;
	int i, enabled_events;

	if (!ESW_ALLOWED(esw) ||
	    !MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) {
@@ -1788,44 +1871,23 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode)
	if (!MLX5_CAP_ESW_EGRESS_ACL(esw->dev, ft_support))
		esw_warn(esw->dev, "engress ACL is not supported by FW\n");

	esw_create_tsar(esw);

	esw->mode = mode;

	mlx5_lag_update(esw->dev);

	if (mode == MLX5_ESWITCH_LEGACY) {
		err = esw_create_legacy_table(esw);
		if (err)
			goto abort;
		err = esw_legacy_enable(esw);
	} else {
		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
		err = esw_offloads_init(esw);
		err = esw_offloads_enable(esw);
	}

	if (err)
		goto abort;

	err = esw_create_tsar(esw);
	if (err)
		esw_warn(esw->dev, "Failed to create eswitch TSAR");

	enabled_events = (mode == MLX5_ESWITCH_LEGACY) ? SRIOV_VPORT_EVENTS :
		UC_ADDR_CHANGE;

	/* Enable PF vport */
	vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
	esw_enable_vport(esw, vport, enabled_events);

	/* Enable ECPF vports */
	if (mlx5_ecpf_vport_exists(esw->dev)) {
		vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF);
		esw_enable_vport(esw, vport, enabled_events);
	}

	/* Enable VF vports */
	mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
		esw_enable_vport(esw, vport, enabled_events);

	mlx5_eswitch_event_handlers_register(esw);

	esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), active vports(%d)\n",
@@ -1847,10 +1909,7 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode)

void mlx5_eswitch_disable(struct mlx5_eswitch *esw)
{
	struct esw_mc_addr *mc_promisc;
	struct mlx5_vport *vport;
	int old_mode;
	int i;

	if (!ESW_ALLOWED(esw) || esw->mode == MLX5_ESWITCH_NONE)
		return;
@@ -1859,21 +1918,14 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw)
		 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
		 esw->esw_funcs.num_vfs, esw->enabled_vports);

	mc_promisc = &esw->mc_promisc;
	mlx5_eswitch_event_handlers_unregister(esw);

	mlx5_esw_for_all_vports(esw, i, vport)
		esw_disable_vport(esw, vport);

	if (mc_promisc && mc_promisc->uplink_rule)
		mlx5_del_flow_rules(mc_promisc->uplink_rule);

	esw_destroy_tsar(esw);

	if (esw->mode == MLX5_ESWITCH_LEGACY)
		esw_destroy_legacy_table(esw);
		esw_legacy_disable(esw);
	else if (esw->mode == MLX5_ESWITCH_OFFLOADS)
		esw_offloads_cleanup(esw);
		esw_offloads_disable(esw);

	esw_destroy_tsar(esw);

	old_mode = esw->mode;
	esw->mode = MLX5_ESWITCH_NONE;
Loading