be2net: add FW cmds needed for VxLAN offloads

This patch adds support for the FW cmds needed for VxLAN offloads
on Skyhawk-R:
1) The VxLAN UDP port needs to be configured via the port-desc of
   SET_PROFILE_CONFIG_v1 cmd.
   This patch re-factors the be_set_profile_config() code (used so far
   only for setting VF QoS) to be used to set any type of descriptor.
2) The MANAGE_IFACE_FILTERS cmds is needed to convert a normal interface
   into a tunnel interface. This allows for RSS to work even on the inner
   TCP/UDP headers of VxLAN traffic.

Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index cf5afe7..d1ec15a 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -3503,14 +3503,11 @@
 	return status;
 }
 
-/* Currently only Lancer uses this command and it supports version 0 only
- * Uses sync mcc
- */
-int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps,
-			      u8 domain)
+int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
+			      int size, u8 version, u8 domain)
 {
-	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_set_profile_config *req;
+	struct be_mcc_wrb *wrb;
 	int status;
 
 	spin_lock_bh(&adapter->mcc_lock);
@@ -3522,44 +3519,116 @@
 	}
 
 	req = embedded_payload(wrb);
-
 	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 			       OPCODE_COMMON_SET_PROFILE_CONFIG, sizeof(*req),
 			       wrb, NULL);
+	req->hdr.version = version;
 	req->hdr.domain = domain;
 	req->desc_count = cpu_to_le32(1);
-	req->nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0;
-	req->nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0;
-	req->nic_desc.flags = (1 << QUN) | (1 << IMM) | (1 << NOSV);
-	req->nic_desc.pf_num = adapter->pf_number;
-	req->nic_desc.vf_num = domain;
+	memcpy(req->desc, desc, size);
 
-	/* Mark fields invalid */
-	req->nic_desc.unicast_mac_count = 0xFFFF;
-	req->nic_desc.mcc_count = 0xFFFF;
-	req->nic_desc.vlan_count = 0xFFFF;
-	req->nic_desc.mcast_mac_count = 0xFFFF;
-	req->nic_desc.txq_count = 0xFFFF;
-	req->nic_desc.rq_count = 0xFFFF;
-	req->nic_desc.rssq_count = 0xFFFF;
-	req->nic_desc.lro_count = 0xFFFF;
-	req->nic_desc.cq_count = 0xFFFF;
-	req->nic_desc.toe_conn_count = 0xFFFF;
-	req->nic_desc.eq_count = 0xFFFF;
-	req->nic_desc.link_param = 0xFF;
-	req->nic_desc.bw_min = 0xFFFFFFFF;
-	req->nic_desc.acpi_params = 0xFF;
-	req->nic_desc.wol_param = 0x0F;
-
-	/* Change BW */
-	req->nic_desc.bw_min = cpu_to_le32(bps);
-	req->nic_desc.bw_max = cpu_to_le32(bps);
 	status = be_mcc_notify_wait(adapter);
 err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
+/* Mark all fields invalid */
+void be_reset_nic_desc(struct be_nic_res_desc *nic)
+{
+	memset(nic, 0, sizeof(*nic));
+	nic->unicast_mac_count = 0xFFFF;
+	nic->mcc_count = 0xFFFF;
+	nic->vlan_count = 0xFFFF;
+	nic->mcast_mac_count = 0xFFFF;
+	nic->txq_count = 0xFFFF;
+	nic->rq_count = 0xFFFF;
+	nic->rssq_count = 0xFFFF;
+	nic->lro_count = 0xFFFF;
+	nic->cq_count = 0xFFFF;
+	nic->toe_conn_count = 0xFFFF;
+	nic->eq_count = 0xFFFF;
+	nic->link_param = 0xFF;
+	nic->acpi_params = 0xFF;
+	nic->wol_param = 0x0F;
+	nic->bw_min = 0xFFFFFFFF;
+	nic->bw_max = 0xFFFFFFFF;
+}
+
+int be_cmd_config_qos(struct be_adapter *adapter, u32 bps, u8 domain)
+{
+	if (lancer_chip(adapter)) {
+		struct be_nic_res_desc nic_desc;
+
+		be_reset_nic_desc(&nic_desc);
+		nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0;
+		nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0;
+		nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) |
+					(1 << NOSV_SHIFT);
+		nic_desc.pf_num = adapter->pf_number;
+		nic_desc.vf_num = domain;
+		nic_desc.bw_max = cpu_to_le32(bps);
+
+		return be_cmd_set_profile_config(adapter, &nic_desc,
+						 RESOURCE_DESC_SIZE_V0,
+						 0, domain);
+	} else {
+		return be_cmd_set_qos(adapter, bps, domain);
+	}
+}
+
+int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_manage_iface_filters *req;
+	int status;
+
+	if (iface == 0xFFFFFFFF)
+		return -1;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
+
+	be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			       OPCODE_COMMON_MANAGE_IFACE_FILTERS, sizeof(*req),
+			       wrb, NULL);
+	req->op = op;
+	req->target_iface_id = cpu_to_le32(iface);
+
+	status = be_mcc_notify_wait(adapter);
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
+int be_cmd_set_vxlan_port(struct be_adapter *adapter, __be16 port)
+{
+	struct be_port_res_desc port_desc;
+
+	memset(&port_desc, 0, sizeof(port_desc));
+	port_desc.hdr.desc_type = PORT_RESOURCE_DESC_TYPE_V1;
+	port_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
+	port_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
+	port_desc.link_num = adapter->hba_port_num;
+	if (port) {
+		port_desc.nv_flags = NV_TYPE_VXLAN | (1 << SOCVID_SHIFT) |
+					(1 << RCVID_SHIFT);
+		port_desc.nv_port = swab16(port);
+	} else {
+		port_desc.nv_flags = NV_TYPE_DISABLED;
+		port_desc.nv_port = 0;
+	}
+
+	return be_cmd_set_profile_config(adapter, &port_desc,
+					 RESOURCE_DESC_SIZE_V1, 1, 0);
+}
+
 int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg,
 		     int vf_num)
 {