Commit 971ae1ed authored by Saeed Mahameed's avatar Saeed Mahameed
Browse files


  net/mlx5: Add ability to read and write ECE options
  net/mlx5: Add support for RDMA TX FT headers modifying
  net/mlx5: Move iseg access helper routines close to mlx5_core driver
  net/mlx5: Cleanup mlx5_ifc_fte_match_set_misc2_bits
  net/mlx5: Add support in forward to namespace
  {IB/net}/mlx5: Simplify don't trap code
  net/mlx5: Replace zero-length array with flexible-array

Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parents c223c7f2 6b646a7e
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -404,7 +404,10 @@ static bool mlx5_ib_modify_header_supported(struct mlx5_ib_dev *dev)
{
	return MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
					 max_modify_header_actions) ||
	       MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, max_modify_header_actions);
	       MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev,
					 max_modify_header_actions) ||
	       MLX5_CAP_FLOWTABLE_RDMA_TX(dev->mdev,
					 max_modify_header_actions);
}

static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER)(
+10 −37
Original line number Diff line number Diff line
@@ -3698,12 +3698,13 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
		if (!dest_num)
			rule_dst = NULL;
	} else {
		if (is_egress)
			flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW;
		else
		if (flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP)
			flow_act.action |=
				dest_num ?  MLX5_FLOW_CONTEXT_ACTION_FWD_DEST :
				MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
		if (is_egress)
			flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW;
		else if (dest_num)
			flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
	}

	if ((spec->flow_context.flags & FLOW_CONTEXT_HAS_TAG)  &&
@@ -3747,30 +3748,6 @@ static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev,
	return _create_flow_rule(dev, ft_prio, flow_attr, dst, 0, NULL);
}

static struct mlx5_ib_flow_handler *create_dont_trap_rule(struct mlx5_ib_dev *dev,
							  struct mlx5_ib_flow_prio *ft_prio,
							  struct ib_flow_attr *flow_attr,
							  struct mlx5_flow_destination *dst)
{
	struct mlx5_ib_flow_handler *handler_dst = NULL;
	struct mlx5_ib_flow_handler *handler = NULL;

	handler = create_flow_rule(dev, ft_prio, flow_attr, NULL);
	if (!IS_ERR(handler)) {
		handler_dst = create_flow_rule(dev, ft_prio,
					       flow_attr, dst);
		if (IS_ERR(handler_dst)) {
			mlx5_del_flow_rules(handler->rule);
			ft_prio->refcount--;
			kfree(handler);
			handler = handler_dst;
		} else {
			list_add(&handler_dst->list, &handler->list);
		}
	}

	return handler;
}
enum {
	LEFTOVERS_MC,
	LEFTOVERS_UC,
@@ -3974,15 +3951,11 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
	}

	if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
		if (flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP)  {
			handler = create_dont_trap_rule(dev, ft_prio,
							flow_attr, dst);
		} else {
			underlay_qpn = (mqp->flags & MLX5_IB_QP_UNDERLAY) ?
					mqp->underlay_qpn : 0;
			handler = _create_flow_rule(dev, ft_prio, flow_attr,
						    dst, underlay_qpn, ucmd);
		}
		underlay_qpn = (mqp->flags & IB_QP_CREATE_SOURCE_QPN) ?
				       mqp->underlay_qpn :
				       0;
		handler = _create_flow_rule(dev, ft_prio, flow_attr, dst,
					    underlay_qpn, ucmd);
	} else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
		   flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) {
		handler = create_leftovers_rule(dev, ft_prio, flow_attr,
+5 −0
Original line number Diff line number Diff line
@@ -1936,6 +1936,11 @@ static void free_cmd_page(struct mlx5_core_dev *dev, struct mlx5_cmd *cmd)
			  cmd->alloc_dma);
}

static u16 cmdif_rev(struct mlx5_core_dev *dev)
{
	return ioread32be(&dev->iseg->cmdif_rev_fw_sub) >> 16;
}

int mlx5_cmd_init(struct mlx5_core_dev *dev)
{
	int size = sizeof(struct mlx5_cmd_prot_block);
+4 −0
Original line number Diff line number Diff line
@@ -781,6 +781,10 @@ static int mlx5_cmd_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
		max_actions = MLX5_CAP_ESW_INGRESS_ACL(dev, max_modify_header_actions);
		table_type = FS_FT_ESW_INGRESS_ACL;
		break;
	case MLX5_FLOW_NAMESPACE_RDMA_TX:
		max_actions = MLX5_CAP_FLOWTABLE_RDMA_TX(dev, max_modify_header_actions);
		table_type = FS_FT_RDMA_TX;
		break;
	default:
		return -EOPNOTSUPP;
	}
+87 −35
Original line number Diff line number Diff line
@@ -379,6 +379,12 @@ static struct fs_prio *find_prio(struct mlx5_flow_namespace *ns,
	return NULL;
}

static bool is_fwd_next_action(u32 action)
{
	return action & (MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO |
			 MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS);
}

static bool check_valid_spec(const struct mlx5_flow_spec *spec)
{
	int i;
@@ -499,7 +505,7 @@ static void del_sw_hw_rule(struct fs_node *node)
	fs_get_obj(rule, node);
	fs_get_obj(fte, rule->node.parent);
	trace_mlx5_fs_del_rule(rule);
	if (rule->sw_action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
	if (is_fwd_next_action(rule->sw_action)) {
		mutex_lock(&rule->dest_attr.ft->lock);
		list_del(&rule->next_ft);
		mutex_unlock(&rule->dest_attr.ft->lock);
@@ -823,6 +829,36 @@ static struct mlx5_flow_table *find_prev_chained_ft(struct fs_prio *prio)
	return find_closest_ft(prio, true);
}

static struct fs_prio *find_fwd_ns_prio(struct mlx5_flow_root_namespace *root,
					struct mlx5_flow_namespace *ns)
{
	struct mlx5_flow_namespace *root_ns = &root->ns;
	struct fs_prio *iter_prio;
	struct fs_prio *prio;

	fs_get_obj(prio, ns->node.parent);
	list_for_each_entry(iter_prio, &root_ns->node.children, node.list) {
		if (iter_prio == prio &&
		    !list_is_last(&prio->node.children, &iter_prio->node.list))
			return list_next_entry(iter_prio, node.list);
	}
	return NULL;
}

static struct mlx5_flow_table *find_next_fwd_ft(struct mlx5_flow_table *ft,
						struct mlx5_flow_act *flow_act)
{
	struct mlx5_flow_root_namespace *root = find_root(&ft->node);
	struct fs_prio *prio;

	if (flow_act->action & MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS)
		prio = find_fwd_ns_prio(root, ft->ns);
	else
		fs_get_obj(prio, ft->node.parent);

	return (prio) ? find_next_chained_ft(prio) : NULL;
}

static int connect_fts_in_prio(struct mlx5_core_dev *dev,
			       struct fs_prio *prio,
			       struct mlx5_flow_table *ft)
@@ -973,6 +1009,10 @@ static int connect_fwd_rules(struct mlx5_core_dev *dev,
	list_splice_init(&old_next_ft->fwd_rules, &new_next_ft->fwd_rules);
	mutex_unlock(&old_next_ft->lock);
	list_for_each_entry(iter, &new_next_ft->fwd_rules, next_ft) {
		if ((iter->sw_action & MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS) &&
		    iter->ft->ns == new_next_ft->ns)
			continue;

		err = _mlx5_modify_rule_destination(iter, &dest);
		if (err)
			pr_err("mlx5_core: failed to modify rule to point on flow table %d\n",
@@ -1074,6 +1114,7 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
	next_ft = unmanaged ? ft_attr->next_ft :
			      find_next_chained_ft(fs_prio);
	ft->def_miss_action = ns->def_miss_action;
	ft->ns = ns;
	err = root->cmds->create_flow_table(root, ft, log_table_sz, next_ft);
	if (err)
		goto free_ft;
@@ -1898,48 +1939,59 @@ mlx5_add_flow_rules(struct mlx5_flow_table *ft,
{
	struct mlx5_flow_root_namespace *root = find_root(&ft->node);
	static const struct mlx5_flow_spec zero_spec = {};
	struct mlx5_flow_destination gen_dest = {};
	struct mlx5_flow_destination *gen_dest = NULL;
	struct mlx5_flow_table *next_ft = NULL;
	struct mlx5_flow_handle *handle = NULL;
	u32 sw_action = flow_act->action;
	struct fs_prio *prio;
	int i;

	if (!spec)
		spec = &zero_spec;

	fs_get_obj(prio, ft->node.parent);
	if (flow_act->action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
	if (!is_fwd_next_action(sw_action))
		return _mlx5_add_flow_rules(ft, spec, flow_act, dest, num_dest);

	if (!fwd_next_prio_supported(ft))
		return ERR_PTR(-EOPNOTSUPP);
		if (num_dest)
			return ERR_PTR(-EINVAL);

	mutex_lock(&root->chain_lock);
		next_ft = find_next_chained_ft(prio);
		if (next_ft) {
			gen_dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
			gen_dest.ft = next_ft;
			dest = &gen_dest;
			num_dest = 1;
			flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
		} else {
			mutex_unlock(&root->chain_lock);
			return ERR_PTR(-EOPNOTSUPP);
		}
	next_ft = find_next_fwd_ft(ft, flow_act);
	if (!next_ft) {
		handle = ERR_PTR(-EOPNOTSUPP);
		goto unlock;
	}

	gen_dest = kcalloc(num_dest + 1, sizeof(*dest),
			   GFP_KERNEL);
	if (!gen_dest) {
		handle = ERR_PTR(-ENOMEM);
		goto unlock;
	}
	for (i = 0; i < num_dest; i++)
		gen_dest[i] = dest[i];
	gen_dest[i].type =
		MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
	gen_dest[i].ft = next_ft;
	dest = gen_dest;
	num_dest++;
	flow_act->action &= ~(MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO |
			      MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS);
	flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
	handle = _mlx5_add_flow_rules(ft, spec, flow_act, dest, num_dest);
	if (IS_ERR(handle))
		goto unlock;

	if (sw_action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
		if (!IS_ERR_OR_NULL(handle) &&
		    (list_empty(&handle->rule[0]->next_ft))) {
	if (list_empty(&handle->rule[num_dest - 1]->next_ft)) {
		mutex_lock(&next_ft->lock);
			list_add(&handle->rule[0]->next_ft,
		list_add(&handle->rule[num_dest - 1]->next_ft,
			 &next_ft->fwd_rules);
		mutex_unlock(&next_ft->lock);
			handle->rule[0]->sw_action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
		handle->rule[num_dest - 1]->sw_action = sw_action;
		handle->rule[num_dest - 1]->ft = ft;
	}
unlock:
	mutex_unlock(&root->chain_lock);
	}
	kfree(gen_dest);
	return handle;
}
EXPORT_SYMBOL(mlx5_add_flow_rules);
Loading