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

Commit 2b3d7b75 authored by Shahed Shaikh's avatar Shahed Shaikh Committed by David S. Miller
Browse files

qlcnic: Add VXLAN Rx offload support



This patch adds Rx checksum offload support for VXLAN.
Implements .ndo_{add|del}_vxlan_port netdev ops.
Adapter supports only one VXLAN port, so program adapter with
very first UDP port which VXLAN driver is listening to.

Signed-off-by: default avatarShahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 381709de
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -535,6 +535,7 @@ struct qlcnic_hardware_context {
	u8 extend_lb_time;
	u8 phys_port_id[ETH_ALEN];
	u8 lb_mode;
	u16 vxlan_port;
};

struct qlcnic_adapter_stats {
@@ -551,6 +552,7 @@ struct qlcnic_adapter_stats {
	u64  lso_frames;
	u64  encap_lso_frames;
	u64  encap_tx_csummed;
	u64  encap_rx_csummed;
	u64  xmit_on;
	u64  xmit_off;
	u64  skb_alloc_failure;
@@ -912,6 +914,7 @@ struct qlcnic_mac_vlan_list {
#define QLCNIC_FW_CAPABILITY_2_BEACON		BIT_7
#define QLCNIC_FW_CAPABILITY_2_PER_PORT_ESWITCH_CFG	BIT_9

#define QLCNIC_83XX_FW_CAPAB_ENCAP_RX_OFFLOAD	BIT_0
#define QLCNIC_83XX_FW_CAPAB_ENCAP_TX_OFFLOAD	BIT_1
#define QLCNIC_83XX_FW_CAPAB_ENCAP_CKO_OFFLOAD	BIT_4

@@ -1008,6 +1011,8 @@ struct qlcnic_ipaddr {
#define QLCNIC_APP_CHANGED_FLAGS	0x20000
#define QLCNIC_HAS_PHYS_PORT_ID		0x40000
#define QLCNIC_TSS_RSS			0x80000
#define QLCNIC_ADD_VXLAN_PORT		0x100000
#define QLCNIC_DEL_VXLAN_PORT		0x200000

#define QLCNIC_IS_MSI_FAMILY(adapter) \
	((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
@@ -1828,6 +1833,12 @@ static inline bool qlcnic_encap_tx_offload(struct qlcnic_adapter *adapter)
	       QLCNIC_83XX_FW_CAPAB_ENCAP_TX_OFFLOAD;
}

static inline bool qlcnic_encap_rx_offload(struct qlcnic_adapter *adapter)
{
	return adapter->ahw->extra_capability[0] &
	       QLCNIC_83XX_FW_CAPAB_ENCAP_RX_OFFLOAD;
}

static inline int qlcnic_start_firmware(struct qlcnic_adapter *adapter)
{
	return adapter->nic_ops->start_firmware(adapter);
+2 −1
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
	{QLCNIC_CMD_GET_PORT_CONFIG, 2, 2},
	{QLCNIC_CMD_GET_LINK_STATUS, 2, 4},
	{QLCNIC_CMD_IDC_ACK, 5, 1},
	{QLCNIC_CMD_INIT_NIC_FUNC, 2, 1},
	{QLCNIC_CMD_INIT_NIC_FUNC, 3, 1},
	{QLCNIC_CMD_STOP_NIC_FUNC, 2, 1},
	{QLCNIC_CMD_SET_LED_CONFIG, 5, 1},
	{QLCNIC_CMD_GET_LED_CONFIG, 1, 5},
@@ -87,6 +87,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
	{QLCNIC_CMD_BC_EVENT_SETUP, 2, 1},
	{QLCNIC_CMD_DCB_QUERY_CAP, 1, 2},
	{QLCNIC_CMD_DCB_QUERY_PARAM, 1, 50},
	{QLCNIC_CMD_SET_INGRESS_ENCAP, 2, 1},
};

const u32 qlcnic_83xx_ext_reg_tbl[] = {
+2 −1
Original line number Diff line number Diff line
@@ -528,8 +528,9 @@ enum qlc_83xx_ext_regs {
};

/* Initialize/Stop NIC command bit definitions */
#define QLC_REGISTER_DCB_AEN		BIT_1
#define QLC_REGISTER_LB_IDC		BIT_0
#define QLC_REGISTER_DCB_AEN		BIT_1
#define QLC_83XX_MULTI_TENANCY_INFO	BIT_29
#define QLC_INIT_FW_RESOURCES		BIT_31

/* 83xx funcitons */
+87 −0
Original line number Diff line number Diff line
@@ -1020,10 +1020,97 @@ static int qlcnic_83xx_idc_check_state_validity(struct qlcnic_adapter *adapter,
	return 0;
}

#define QLC_83XX_ENCAP_TYPE_VXLAN	BIT_1
#define QLC_83XX_MATCH_ENCAP_ID		BIT_2
#define QLC_83XX_SET_VXLAN_UDP_DPORT	BIT_3
#define QLC_83XX_VXLAN_UDP_DPORT(PORT)	((PORT & 0xffff) << 16)

#define QLCNIC_ENABLE_INGRESS_ENCAP_PARSING 1
#define QLCNIC_DISABLE_INGRESS_ENCAP_PARSING 0

static int qlcnic_set_vxlan_port(struct qlcnic_adapter *adapter)
{
	u16 port = adapter->ahw->vxlan_port;
	struct qlcnic_cmd_args cmd;
	int ret = 0;

	memset(&cmd, 0, sizeof(cmd));

	ret = qlcnic_alloc_mbx_args(&cmd, adapter,
				    QLCNIC_CMD_INIT_NIC_FUNC);
	if (ret)
		return ret;

	cmd.req.arg[1] = QLC_83XX_MULTI_TENANCY_INFO;
	cmd.req.arg[2] = QLC_83XX_ENCAP_TYPE_VXLAN |
			 QLC_83XX_SET_VXLAN_UDP_DPORT |
			 QLC_83XX_VXLAN_UDP_DPORT(port);

	ret = qlcnic_issue_cmd(adapter, &cmd);
	if (ret)
		netdev_err(adapter->netdev,
			   "Failed to set VXLAN port %d in adapter\n",
			   port);

	qlcnic_free_mbx_args(&cmd);

	return ret;
}

static int qlcnic_set_vxlan_parsing(struct qlcnic_adapter *adapter,
				    bool state)
{
	u16 vxlan_port = adapter->ahw->vxlan_port;
	struct qlcnic_cmd_args cmd;
	int ret = 0;

	memset(&cmd, 0, sizeof(cmd));

	ret = qlcnic_alloc_mbx_args(&cmd, adapter,
				    QLCNIC_CMD_SET_INGRESS_ENCAP);
	if (ret)
		return ret;

	cmd.req.arg[1] = state ? QLCNIC_ENABLE_INGRESS_ENCAP_PARSING :
				 QLCNIC_DISABLE_INGRESS_ENCAP_PARSING;

	ret = qlcnic_issue_cmd(adapter, &cmd);
	if (ret)
		netdev_err(adapter->netdev,
			   "Failed to %s VXLAN parsing for port %d\n",
			   state ? "enable" : "disable", vxlan_port);
	else
		netdev_info(adapter->netdev,
			    "%s VXLAN parsing for port %d\n",
			    state ? "Enabled" : "Disabled", vxlan_port);

	qlcnic_free_mbx_args(&cmd);

	return ret;
}

static void qlcnic_83xx_periodic_tasks(struct qlcnic_adapter *adapter)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;

	if (adapter->fhash.fnum)
		qlcnic_prune_lb_filters(adapter);

	if (adapter->flags & QLCNIC_ADD_VXLAN_PORT) {
		if (qlcnic_set_vxlan_port(adapter))
			return;

		if (qlcnic_set_vxlan_parsing(adapter, true))
			return;

		adapter->flags &= ~QLCNIC_ADD_VXLAN_PORT;
	} else if (adapter->flags & QLCNIC_DEL_VXLAN_PORT) {
		if (qlcnic_set_vxlan_parsing(adapter, false))
			return;

		ahw->vxlan_port = 0;
		adapter->flags &= ~QLCNIC_DEL_VXLAN_PORT;
	}
}

/**
+2 −0
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@ static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
	 QLC_OFF(stats.encap_lso_frames)},
	{"encap_tx_csummed", QLC_SIZEOF(stats.encap_tx_csummed),
	 QLC_OFF(stats.encap_tx_csummed)},
	{"encap_rx_csummed", QLC_SIZEOF(stats.encap_rx_csummed),
	 QLC_OFF(stats.encap_rx_csummed)},
	{"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure),
	 QLC_OFF(stats.skb_alloc_failure)},
	{"mac_filter_limit_overrun", QLC_SIZEOF(stats.mac_filter_limit_overrun),
Loading