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

Commit 7ffdf726 authored by Or Gerlitz's avatar Or Gerlitz Committed by David S. Miller
Browse files

net/mlx4_core: Add basic support for TCP/IP offloads under tunneling



Add the low-level device commands and definitions used for TCP/IP HW offloads
of tunneled/vxlan traffic which are supported by the ConnectX3-pro NIC.

This is done through the following elements:

 - read tunneling device caps in QUERY_DEV_CAP
 - add helper function to do SET_PORT for tunneling
 - add DMFS VXLAN steering rule definitions
 - add CQE and WQE checksum offload field definitions

Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 604d13c9
Loading
Loading
Loading
Loading
+18 −1
Original line number Original line Diff line number Diff line
@@ -134,7 +134,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
		[5] = "Time stamping support",
		[5] = "Time stamping support",
		[6] = "VST (control vlan insertion/stripping) support",
		[6] = "VST (control vlan insertion/stripping) support",
		[7] = "FSM (MAC anti-spoofing) support",
		[7] = "FSM (MAC anti-spoofing) support",
		[8] = "Dynamic QP updates support"
		[8] = "Dynamic QP updates support",
		[9] = "TCP/IP offloads/flow-steering for VXLAN support"
	};
	};
	int i;
	int i;


@@ -536,6 +537,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_RSVD_LKEY_OFFSET		0x98
#define QUERY_DEV_CAP_RSVD_LKEY_OFFSET		0x98
#define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET		0xa0
#define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET		0xa0
#define QUERY_DEV_CAP_FW_REASSIGN_MAC		0x9d
#define QUERY_DEV_CAP_FW_REASSIGN_MAC		0x9d
#define QUERY_DEV_CAP_VXLAN			0x9e


	dev_cap->flags2 = 0;
	dev_cap->flags2 = 0;
	mailbox = mlx4_alloc_cmd_mailbox(dev);
	mailbox = mlx4_alloc_cmd_mailbox(dev);
@@ -701,6 +703,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
	MLX4_GET(field, outbox, QUERY_DEV_CAP_FW_REASSIGN_MAC);
	MLX4_GET(field, outbox, QUERY_DEV_CAP_FW_REASSIGN_MAC);
	if (field & 1<<6)
	if (field & 1<<6)
		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_REASSIGN_MAC_EN;
		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_REASSIGN_MAC_EN;
	MLX4_GET(field, outbox, QUERY_DEV_CAP_VXLAN);
	if (field & 1<<3)
		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS;
	MLX4_GET(dev_cap->max_icm_sz, outbox,
	MLX4_GET(dev_cap->max_icm_sz, outbox,
		 QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET);
		 QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET);
	if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS)
	if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS)
@@ -849,6 +854,11 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
	field &= 0x7f;
	field &= 0x7f;
	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);


	/* For guests, disable vxlan tunneling */
	MLX4_GET(field, outbox, QUERY_DEV_CAP_VXLAN);
	field &= 0xf7;
	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_VXLAN);

	/* For guests, report Blueflame disabled */
	/* For guests, report Blueflame disabled */
	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_BF_OFFSET);
	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_BF_OFFSET);
	field &= 0x7f;
	field &= 0x7f;
@@ -1274,6 +1284,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
#define INIT_HCA_IN_SIZE		 0x200
#define INIT_HCA_IN_SIZE		 0x200
#define INIT_HCA_VERSION_OFFSET		 0x000
#define INIT_HCA_VERSION_OFFSET		 0x000
#define	 INIT_HCA_VERSION		 2
#define	 INIT_HCA_VERSION		 2
#define INIT_HCA_VXLAN_OFFSET		 0x0c
#define INIT_HCA_CACHELINE_SZ_OFFSET	 0x0e
#define INIT_HCA_CACHELINE_SZ_OFFSET	 0x0e
#define INIT_HCA_FLAGS_OFFSET		 0x014
#define INIT_HCA_FLAGS_OFFSET		 0x014
#define INIT_HCA_QPC_OFFSET		 0x020
#define INIT_HCA_QPC_OFFSET		 0x020
@@ -1432,6 +1443,12 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
	MLX4_PUT(inbox, param->uar_page_sz,	INIT_HCA_UAR_PAGE_SZ_OFFSET);
	MLX4_PUT(inbox, param->uar_page_sz,	INIT_HCA_UAR_PAGE_SZ_OFFSET);
	MLX4_PUT(inbox, param->log_uar_sz,      INIT_HCA_LOG_UAR_SZ_OFFSET);
	MLX4_PUT(inbox, param->log_uar_sz,      INIT_HCA_LOG_UAR_SZ_OFFSET);


	/* set parser VXLAN attributes */
	if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS) {
		u8 parser_params = 0;
		MLX4_PUT(inbox, parser_params,	INIT_HCA_VXLAN_OFFSET);
	}

	err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_INIT_HCA, 10000,
	err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_INIT_HCA, 10000,
		       MLX4_CMD_NATIVE);
		       MLX4_CMD_NATIVE);


+14 −0
Original line number Original line Diff line number Diff line
@@ -1444,6 +1444,19 @@ static void choose_steering_mode(struct mlx4_dev *dev,
		 mlx4_log_num_mgm_entry_size);
		 mlx4_log_num_mgm_entry_size);
}
}


static void choose_tunnel_offload_mode(struct mlx4_dev *dev,
				       struct mlx4_dev_cap *dev_cap)
{
	if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED &&
	    dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS)
		dev->caps.tunnel_offload_mode = MLX4_TUNNEL_OFFLOAD_MODE_VXLAN;
	else
		dev->caps.tunnel_offload_mode = MLX4_TUNNEL_OFFLOAD_MODE_NONE;

	mlx4_dbg(dev, "Tunneling offload mode is: %s\n",  (dev->caps.tunnel_offload_mode
		 == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) ? "vxlan" : "none");
}

static int mlx4_init_hca(struct mlx4_dev *dev)
static int mlx4_init_hca(struct mlx4_dev *dev)
{
{
	struct mlx4_priv	  *priv = mlx4_priv(dev);
	struct mlx4_priv	  *priv = mlx4_priv(dev);
@@ -1484,6 +1497,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
		}
		}


		choose_steering_mode(dev, &dev_cap);
		choose_steering_mode(dev, &dev_cap);
		choose_tunnel_offload_mode(dev, &dev_cap);


		err = mlx4_get_phys_port_id(dev);
		err = mlx4_get_phys_port_id(dev);
		if (err)
		if (err)
+12 −2
Original line number Original line Diff line number Diff line
@@ -697,7 +697,8 @@ const u16 __sw_id_hw[] = {
	[MLX4_NET_TRANS_RULE_ID_IPV6]    = 0xE003,
	[MLX4_NET_TRANS_RULE_ID_IPV6]    = 0xE003,
	[MLX4_NET_TRANS_RULE_ID_IPV4]    = 0xE002,
	[MLX4_NET_TRANS_RULE_ID_IPV4]    = 0xE002,
	[MLX4_NET_TRANS_RULE_ID_TCP]     = 0xE004,
	[MLX4_NET_TRANS_RULE_ID_TCP]     = 0xE004,
	[MLX4_NET_TRANS_RULE_ID_UDP]     = 0xE006
	[MLX4_NET_TRANS_RULE_ID_UDP]     = 0xE006,
	[MLX4_NET_TRANS_RULE_ID_VXLAN]	 = 0xE008
};
};


int mlx4_map_sw_to_hw_steering_id(struct mlx4_dev *dev,
int mlx4_map_sw_to_hw_steering_id(struct mlx4_dev *dev,
@@ -722,7 +723,9 @@ static const int __rule_hw_sz[] = {
	[MLX4_NET_TRANS_RULE_ID_TCP] =
	[MLX4_NET_TRANS_RULE_ID_TCP] =
		sizeof(struct mlx4_net_trans_rule_hw_tcp_udp),
		sizeof(struct mlx4_net_trans_rule_hw_tcp_udp),
	[MLX4_NET_TRANS_RULE_ID_UDP] =
	[MLX4_NET_TRANS_RULE_ID_UDP] =
		sizeof(struct mlx4_net_trans_rule_hw_tcp_udp)
		sizeof(struct mlx4_net_trans_rule_hw_tcp_udp),
	[MLX4_NET_TRANS_RULE_ID_VXLAN] =
		sizeof(struct mlx4_net_trans_rule_hw_vxlan)
};
};


int mlx4_hw_rule_sz(struct mlx4_dev *dev,
int mlx4_hw_rule_sz(struct mlx4_dev *dev,
@@ -787,6 +790,13 @@ static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec,
		rule_hw->tcp_udp.src_port_msk = spec->tcp_udp.src_port_msk;
		rule_hw->tcp_udp.src_port_msk = spec->tcp_udp.src_port_msk;
		break;
		break;


	case MLX4_NET_TRANS_RULE_ID_VXLAN:
		rule_hw->vxlan.vni =
			cpu_to_be32(be32_to_cpu(spec->vxlan.vni) << 8);
		rule_hw->vxlan.vni_mask =
			cpu_to_be32(be32_to_cpu(spec->vxlan.vni_mask) << 8);
		break;

	default:
	default:
		return -EINVAL;
		return -EINVAL;
	}
	}
+41 −0
Original line number Original line Diff line number Diff line
@@ -800,6 +800,47 @@ int mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw,
}
}
EXPORT_SYMBOL(mlx4_SET_PORT_SCHEDULER);
EXPORT_SYMBOL(mlx4_SET_PORT_SCHEDULER);


enum {
	VXLAN_ENABLE_MODIFY	= 1 << 7,
	VXLAN_STEERING_MODIFY	= 1 << 6,

	VXLAN_ENABLE		= 1 << 7,
};

struct mlx4_set_port_vxlan_context {
	u32	reserved1;
	u8	modify_flags;
	u8	reserved2;
	u8	enable_flags;
	u8	steering;
};

int mlx4_SET_PORT_VXLAN(struct mlx4_dev *dev, u8 port, u8 steering)
{
	int err;
	u32 in_mod;
	struct mlx4_cmd_mailbox *mailbox;
	struct mlx4_set_port_vxlan_context  *context;

	mailbox = mlx4_alloc_cmd_mailbox(dev);
	if (IS_ERR(mailbox))
		return PTR_ERR(mailbox);
	context = mailbox->buf;
	memset(context, 0, sizeof(*context));

	context->modify_flags = VXLAN_ENABLE_MODIFY | VXLAN_STEERING_MODIFY;
	context->enable_flags = VXLAN_ENABLE;
	context->steering  = steering;

	in_mod = MLX4_SET_PORT_VXLAN << 8 | port;
	err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
		       MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);

	mlx4_free_cmd_mailbox(dev, mailbox);
	return err;
}
EXPORT_SYMBOL(mlx4_SET_PORT_VXLAN);

int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave,
int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave,
				struct mlx4_vhcr *vhcr,
				struct mlx4_vhcr *vhcr,
				struct mlx4_cmd_mailbox *inbox,
				struct mlx4_cmd_mailbox *inbox,
+1 −0
Original line number Original line Diff line number Diff line
@@ -180,6 +180,7 @@ enum {
	MLX4_SET_PORT_GID_TABLE = 0x5,
	MLX4_SET_PORT_GID_TABLE = 0x5,
	MLX4_SET_PORT_PRIO2TC	= 0x8,
	MLX4_SET_PORT_PRIO2TC	= 0x8,
	MLX4_SET_PORT_SCHEDULER = 0x9,
	MLX4_SET_PORT_SCHEDULER = 0x9,
	MLX4_SET_PORT_VXLAN	= 0xB
};
};


enum {
enum {
Loading