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

Merge tag 'mlx5-updates-2019-11-01' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux



Saeed Mahameed says:

====================
mlx5-updates-2019-11-01

Misc updates for mlx5 netdev and core driver

1) Steering Core: Replace CRC32 internal implementation with standard
   kernel lib.
2) Steering Core: Support IPv4 and IPv6 mixed matcher.
3) Steering Core: Lockless FTE read lookups
4) TC: Bit sized fields rewrite support.
5) FPGA: Standalone FPGA support.
6) SRIOV: Reset VF parameters configurations on SRIOV disable.
7) netdev: Dump WQs wqe descriptors on CQE with error events.
8) MISC Cleanups.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a37ac8ae 667f2646
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ mlx5_core-$(CONFIG_MLX5_EN_TLS) += en_accel/tls.o en_accel/tls_rxtx.o en_accel/t

mlx5_core-$(CONFIG_MLX5_SW_STEERING) += steering/dr_domain.o steering/dr_table.o \
					steering/dr_matcher.o steering/dr_rule.o \
					steering/dr_icm_pool.o steering/dr_crc32.o \
					steering/dr_icm_pool.o \
					steering/dr_ste.o steering/dr_send.o \
					steering/dr_cmd.o steering/dr_fw.o \
					steering/dr_action.o steering/fs_dr.o
+1 −1
Original line number Diff line number Diff line
@@ -866,7 +866,7 @@ static void cmd_work_handler(struct work_struct *work)
	if (!ent->page_queue) {
		alloc_ret = alloc_ent(cmd);
		if (alloc_ret < 0) {
			mlx5_core_err(dev, "failed to allocate command entry\n");
			mlx5_core_err_rl(dev, "failed to allocate command entry\n");
			if (ent->callback) {
				ent->callback(-EAGAIN, ent->context);
				mlx5_free_cmd_msg(dev, ent->out);
+69 −60
Original line number Diff line number Diff line
@@ -2241,13 +2241,14 @@ out_err:

struct mlx5_fields {
	u8  field;
	u8  size;
	u8  field_bsize;
	u32 field_mask;
	u32 offset;
	u32 match_offset;
};

#define OFFLOAD(fw_field, size, field, off, match_field) \
		{MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, size, \
#define OFFLOAD(fw_field, field_bsize, field_mask, field, off, match_field) \
		{MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, field_bsize, field_mask, \
		 offsetof(struct pedit_headers, field) + (off), \
		 MLX5_BYTE_OFF(fte_match_set_lyr_2_4, match_field)}

@@ -2265,18 +2266,18 @@ struct mlx5_fields {
})

static bool cmp_val_mask(void *valp, void *maskp, void *matchvalp,
			 void *matchmaskp, int size)
			 void *matchmaskp, u8 bsize)
{
	bool same = false;

	switch (size) {
	case sizeof(u8):
	switch (bsize) {
	case 8:
		same = SAME_VAL_MASK(u8, valp, maskp, matchvalp, matchmaskp);
		break;
	case sizeof(u16):
	case 16:
		same = SAME_VAL_MASK(u16, valp, maskp, matchvalp, matchmaskp);
		break;
	case sizeof(u32):
	case 32:
		same = SAME_VAL_MASK(u32, valp, maskp, matchvalp, matchmaskp);
		break;
	}
@@ -2285,41 +2286,43 @@ static bool cmp_val_mask(void *valp, void *maskp, void *matchvalp,
}

static struct mlx5_fields fields[] = {
	OFFLOAD(DMAC_47_16, 4, eth.h_dest[0], 0, dmac_47_16),
	OFFLOAD(DMAC_15_0,  2, eth.h_dest[4], 0, dmac_15_0),
	OFFLOAD(SMAC_47_16, 4, eth.h_source[0], 0, smac_47_16),
	OFFLOAD(SMAC_15_0,  2, eth.h_source[4], 0, smac_15_0),
	OFFLOAD(ETHERTYPE,  2, eth.h_proto, 0, ethertype),
	OFFLOAD(FIRST_VID,  2, vlan.h_vlan_TCI, 0, first_vid),

	OFFLOAD(IP_TTL, 1, ip4.ttl,   0, ttl_hoplimit),
	OFFLOAD(SIPV4,  4, ip4.saddr, 0, src_ipv4_src_ipv6.ipv4_layout.ipv4),
	OFFLOAD(DIPV4,  4, ip4.daddr, 0, dst_ipv4_dst_ipv6.ipv4_layout.ipv4),

	OFFLOAD(SIPV6_127_96, 4, ip6.saddr.s6_addr32[0], 0,
	OFFLOAD(DMAC_47_16, 32, U32_MAX, eth.h_dest[0], 0, dmac_47_16),
	OFFLOAD(DMAC_15_0,  16, U16_MAX, eth.h_dest[4], 0, dmac_15_0),
	OFFLOAD(SMAC_47_16, 32, U32_MAX, eth.h_source[0], 0, smac_47_16),
	OFFLOAD(SMAC_15_0,  16, U16_MAX, eth.h_source[4], 0, smac_15_0),
	OFFLOAD(ETHERTYPE,  16, U16_MAX, eth.h_proto, 0, ethertype),
	OFFLOAD(FIRST_VID,  16, U16_MAX, vlan.h_vlan_TCI, 0, first_vid),

	OFFLOAD(IP_DSCP, 8,    0xfc, ip4.tos,   0, ip_dscp),
	OFFLOAD(IP_TTL,  8,  U8_MAX, ip4.ttl,   0, ttl_hoplimit),
	OFFLOAD(SIPV4,  32, U32_MAX, ip4.saddr, 0, src_ipv4_src_ipv6.ipv4_layout.ipv4),
	OFFLOAD(DIPV4,  32, U32_MAX, ip4.daddr, 0, dst_ipv4_dst_ipv6.ipv4_layout.ipv4),

	OFFLOAD(SIPV6_127_96, 32, U32_MAX, ip6.saddr.s6_addr32[0], 0,
		src_ipv4_src_ipv6.ipv6_layout.ipv6[0]),
	OFFLOAD(SIPV6_95_64,  4, ip6.saddr.s6_addr32[1], 0,
	OFFLOAD(SIPV6_95_64,  32, U32_MAX, ip6.saddr.s6_addr32[1], 0,
		src_ipv4_src_ipv6.ipv6_layout.ipv6[4]),
	OFFLOAD(SIPV6_63_32,  4, ip6.saddr.s6_addr32[2], 0,
	OFFLOAD(SIPV6_63_32,  32, U32_MAX, ip6.saddr.s6_addr32[2], 0,
		src_ipv4_src_ipv6.ipv6_layout.ipv6[8]),
	OFFLOAD(SIPV6_31_0,   4, ip6.saddr.s6_addr32[3], 0,
	OFFLOAD(SIPV6_31_0,   32, U32_MAX, ip6.saddr.s6_addr32[3], 0,
		src_ipv4_src_ipv6.ipv6_layout.ipv6[12]),
	OFFLOAD(DIPV6_127_96, 4, ip6.daddr.s6_addr32[0], 0,
	OFFLOAD(DIPV6_127_96, 32, U32_MAX, ip6.daddr.s6_addr32[0], 0,
		dst_ipv4_dst_ipv6.ipv6_layout.ipv6[0]),
	OFFLOAD(DIPV6_95_64,  4, ip6.daddr.s6_addr32[1], 0,
	OFFLOAD(DIPV6_95_64,  32, U32_MAX, ip6.daddr.s6_addr32[1], 0,
		dst_ipv4_dst_ipv6.ipv6_layout.ipv6[4]),
	OFFLOAD(DIPV6_63_32,  4, ip6.daddr.s6_addr32[2], 0,
	OFFLOAD(DIPV6_63_32,  32, U32_MAX, ip6.daddr.s6_addr32[2], 0,
		dst_ipv4_dst_ipv6.ipv6_layout.ipv6[8]),
	OFFLOAD(DIPV6_31_0,   4, ip6.daddr.s6_addr32[3], 0,
	OFFLOAD(DIPV6_31_0,   32, U32_MAX, ip6.daddr.s6_addr32[3], 0,
		dst_ipv4_dst_ipv6.ipv6_layout.ipv6[12]),
	OFFLOAD(IPV6_HOPLIMIT, 1, ip6.hop_limit, 0, ttl_hoplimit),
	OFFLOAD(IPV6_HOPLIMIT, 8,  U8_MAX, ip6.hop_limit, 0, ttl_hoplimit),

	OFFLOAD(TCP_SPORT, 2, tcp.source,  0, tcp_sport),
	OFFLOAD(TCP_DPORT, 2, tcp.dest,    0, tcp_dport),
	OFFLOAD(TCP_FLAGS, 1, tcp.ack_seq, 5, tcp_flags),
	OFFLOAD(TCP_SPORT, 16, U16_MAX, tcp.source,  0, tcp_sport),
	OFFLOAD(TCP_DPORT, 16, U16_MAX, tcp.dest,    0, tcp_dport),
	/* in linux iphdr tcp_flags is 8 bits long */
	OFFLOAD(TCP_FLAGS,  8,  U8_MAX, tcp.ack_seq, 5, tcp_flags),

	OFFLOAD(UDP_SPORT, 2, udp.source, 0, udp_sport),
	OFFLOAD(UDP_DPORT, 2, udp.dest,   0, udp_dport),
	OFFLOAD(UDP_SPORT, 16, U16_MAX, udp.source, 0, udp_sport),
	OFFLOAD(UDP_DPORT, 16, U16_MAX, udp.dest,   0, udp_dport),
};

/* On input attr->max_mod_hdr_actions tells how many HW actions can be parsed at
@@ -2332,19 +2335,17 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
				struct netlink_ext_ack *extack)
{
	struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals;
	void *headers_c = get_match_headers_criteria(*action_flags,
						     &parse_attr->spec);
	void *headers_v = get_match_headers_value(*action_flags,
						  &parse_attr->spec);
	int i, action_size, nactions, max_actions, first, last, next_z;
	void *s_masks_p, *a_masks_p, *vals_p;
	void *headers_c, *headers_v, *action, *vals_p;
	u32 *s_masks_p, *a_masks_p, s_mask, a_mask;
	struct mlx5_fields *f;
	u8 cmd, field_bsize;
	u32 s_mask, a_mask;
	unsigned long mask;
	__be32 mask_be32;
	__be16 mask_be16;
	void *action;
	u8 cmd;

	headers_c = get_match_headers_criteria(*action_flags, &parse_attr->spec);
	headers_v = get_match_headers_value(*action_flags, &parse_attr->spec);

	set_masks = &hdrs[0].masks;
	add_masks = &hdrs[1].masks;
@@ -2369,8 +2370,8 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
		s_masks_p = (void *)set_masks + f->offset;
		a_masks_p = (void *)add_masks + f->offset;

		memcpy(&s_mask, s_masks_p, f->size);
		memcpy(&a_mask, a_masks_p, f->size);
		s_mask = *s_masks_p & f->field_mask;
		a_mask = *a_masks_p & f->field_mask;

		if (!s_mask && !a_mask) /* nothing to offload here */
			continue;
@@ -2399,38 +2400,34 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
			vals_p = (void *)set_vals + f->offset;
			/* don't rewrite if we have a match on the same value */
			if (cmp_val_mask(vals_p, s_masks_p, match_val,
					 match_mask, f->size))
					 match_mask, f->field_bsize))
				skip = true;
			/* clear to denote we consumed this field */
			memset(s_masks_p, 0, f->size);
			*s_masks_p &= ~f->field_mask;
		} else {
			u32 zero = 0;

			cmd  = MLX5_ACTION_TYPE_ADD;
			mask = a_mask;
			vals_p = (void *)add_vals + f->offset;
			/* add 0 is no change */
			if (!memcmp(vals_p, &zero, f->size))
			if ((*(u32 *)vals_p & f->field_mask) == 0)
				skip = true;
			/* clear to denote we consumed this field */
			memset(a_masks_p, 0, f->size);
			*a_masks_p &= ~f->field_mask;
		}
		if (skip)
			continue;

		field_bsize = f->size * BITS_PER_BYTE;

		if (field_bsize == 32) {
		if (f->field_bsize == 32) {
			mask_be32 = *(__be32 *)&mask;
			mask = (__force unsigned long)cpu_to_le32(be32_to_cpu(mask_be32));
		} else if (field_bsize == 16) {
		} else if (f->field_bsize == 16) {
			mask_be16 = *(__be16 *)&mask;
			mask = (__force unsigned long)cpu_to_le16(be16_to_cpu(mask_be16));
		}

		first = find_first_bit(&mask, field_bsize);
		next_z = find_next_zero_bit(&mask, field_bsize, first);
		last  = find_last_bit(&mask, field_bsize);
		first = find_first_bit(&mask, f->field_bsize);
		next_z = find_next_zero_bit(&mask, f->field_bsize, first);
		last  = find_last_bit(&mask, f->field_bsize);
		if (first < next_z && next_z < last) {
			NL_SET_ERR_MSG_MOD(extack,
					   "rewrite of few sub-fields isn't supported");
@@ -2443,16 +2440,22 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs,
		MLX5_SET(set_action_in, action, field, f->field);

		if (cmd == MLX5_ACTION_TYPE_SET) {
			MLX5_SET(set_action_in, action, offset, first);
			int start;

			/* if field is bit sized it can start not from first bit */
			start = find_first_bit((unsigned long *)&f->field_mask,
					       f->field_bsize);

			MLX5_SET(set_action_in, action, offset, first - start);
			/* length is num of bits to be written, zero means length of 32 */
			MLX5_SET(set_action_in, action, length, (last - first + 1));
		}

		if (field_bsize == 32)
		if (f->field_bsize == 32)
			MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p) >> first);
		else if (field_bsize == 16)
		else if (f->field_bsize == 16)
			MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p) >> first);
		else if (field_bsize == 8)
		else if (f->field_bsize == 8)
			MLX5_SET(set_action_in, action, data, *(u8 *)vals_p >> first);

		action += action_size;
@@ -3443,6 +3446,12 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
		attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
	}

	if (!(attr->action &
	      (MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_DROP))) {
		NL_SET_ERR_MSG(extack, "Rule must have at least one forward/drop action");
		return -EOPNOTSUPP;
	}

	if (attr->split_count > 0 && !mlx5_esw_has_fwd_fdb(priv->mdev)) {
		NL_SET_ERR_MSG_MOD(extack,
				   "current firmware doesn't support split rule for port mirroring");
+6 −0
Original line number Diff line number Diff line
@@ -461,8 +461,14 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget)
		if (unlikely(get_cqe_opcode(cqe) == MLX5_CQE_REQ_ERR)) {
			if (!test_and_set_bit(MLX5E_SQ_STATE_RECOVERING,
					      &sq->state)) {
				struct mlx5e_tx_wqe_info *wi;
				u16 ci;

				ci = mlx5_wq_cyc_ctr2ix(&sq->wq, sqcc);
				wi = &sq->db.wqe_info[ci];
				mlx5e_dump_error_cqe(sq,
						     (struct mlx5_err_cqe *)cqe);
				mlx5_wq_cyc_wqe_dump(&sq->wq, ci, wi->num_wqebbs);
				queue_work(cq->channel->priv->wq,
					   &sq->recover_work);
			}
+12 −1
Original line number Diff line number Diff line
@@ -1831,6 +1831,15 @@ static void mlx5_eswitch_event_handlers_unregister(struct mlx5_eswitch *esw)
	flush_workqueue(esw->work_queue);
}

static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw)
{
	struct mlx5_vport *vport;
	int i;

	mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
		memset(&vport->info, 0, sizeof(vport->info));
}

/* Public E-Switch API */
#define ESW_ALLOWED(esw) ((esw) && MLX5_ESWITCH_MANAGER((esw)->dev))

@@ -1923,7 +1932,7 @@ abort:
	return err;
}

void mlx5_eswitch_disable(struct mlx5_eswitch *esw)
void mlx5_eswitch_disable(struct mlx5_eswitch *esw, bool clear_vf)
{
	int old_mode;

@@ -1952,6 +1961,8 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw)
		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
	}
	if (clear_vf)
		mlx5_eswitch_clear_vf_vports_info(esw);
}

int mlx5_eswitch_init(struct mlx5_core_dev *dev)
Loading