[5] = "Time stamping support",
                [6] = "VST (control vlan insertion/stripping) 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;
 
 #define QUERY_DEV_CAP_RSVD_LKEY_OFFSET         0x98
 #define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET                0xa0
 #define QUERY_DEV_CAP_FW_REASSIGN_MAC          0x9d
+#define QUERY_DEV_CAP_VXLAN                    0x9e
 
        dev_cap->flags2 = 0;
        mailbox = mlx4_alloc_cmd_mailbox(dev);
        MLX4_GET(field, outbox, QUERY_DEV_CAP_FW_REASSIGN_MAC);
        if (field & 1<<6)
                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,
                 QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET);
        if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS)
        field &= 0x7f;
        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 */
        MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_BF_OFFSET);
        field &= 0x7f;
 #define INIT_HCA_IN_SIZE                0x200
 #define INIT_HCA_VERSION_OFFSET                 0x000
 #define         INIT_HCA_VERSION                2
+#define INIT_HCA_VXLAN_OFFSET           0x0c
 #define INIT_HCA_CACHELINE_SZ_OFFSET    0x0e
 #define INIT_HCA_FLAGS_OFFSET           0x014
 #define INIT_HCA_QPC_OFFSET             0x020
        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);
 
+       /* 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,
                       MLX4_CMD_NATIVE);
 
 
                 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)
 {
        struct mlx4_priv          *priv = mlx4_priv(dev);
                }
 
                choose_steering_mode(dev, &dev_cap);
+               choose_tunnel_offload_mode(dev, &dev_cap);
 
                err = mlx4_get_phys_port_id(dev);
                if (err)
 
        [MLX4_NET_TRANS_RULE_ID_IPV6]    = 0xE003,
        [MLX4_NET_TRANS_RULE_ID_IPV4]    = 0xE002,
        [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,
        [MLX4_NET_TRANS_RULE_ID_TCP] =
                sizeof(struct mlx4_net_trans_rule_hw_tcp_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,
                rule_hw->tcp_udp.src_port_msk = spec->tcp_udp.src_port_msk;
                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:
                return -EINVAL;
        }
 
 }
 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,
                                struct mlx4_vhcr *vhcr,
                                struct mlx4_cmd_mailbox *inbox,
 
        MLX4_SET_PORT_GID_TABLE = 0x5,
        MLX4_SET_PORT_PRIO2TC   = 0x8,
        MLX4_SET_PORT_SCHEDULER = 0x9,
+       MLX4_SET_PORT_VXLAN     = 0xB
 };
 
 enum {
 
 } __packed;
 
 enum {
+       MLX4_CQE_L2_TUNNEL_IPOK         = 1 << 31,
        MLX4_CQE_VLAN_PRESENT_MASK      = 1 << 29,
+       MLX4_CQE_L2_TUNNEL              = 1 << 27,
+       MLX4_CQE_L2_TUNNEL_CSUM         = 1 << 26,
+       MLX4_CQE_L2_TUNNEL_IPV4         = 1 << 25,
+
        MLX4_CQE_QPN_MASK               = 0xffffff,
 };
 
 
        }
 }
 
+enum {
+       MLX4_TUNNEL_OFFLOAD_MODE_NONE,
+       MLX4_TUNNEL_OFFLOAD_MODE_VXLAN
+};
+
 enum {
        MLX4_DEV_CAP_FLAG_RC            = 1LL <<  0,
        MLX4_DEV_CAP_FLAG_UC            = 1LL <<  1,
        MLX4_DEV_CAP_FLAG2_TS                   = 1LL <<  5,
        MLX4_DEV_CAP_FLAG2_VLAN_CONTROL         = 1LL <<  6,
        MLX4_DEV_CAP_FLAG2_FSM                  = 1LL <<  7,
-       MLX4_DEV_CAP_FLAG2_UPDATE_QP            = 1LL <<  8
+       MLX4_DEV_CAP_FLAG2_UPDATE_QP            = 1LL <<  8,
+       MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS       = 1LL <<  9
 };
 
 enum {
        u32                     function_caps;  /* VFs must be aware of these */
        u16                     hca_core_clock;
        u64                     phys_port_id[MLX4_MAX_PORTS + 1];
+       int                     tunnel_offload_mode;
 };
 
 struct mlx4_buf_list {
        MLX4_NET_TRANS_RULE_ID_IPV4,
        MLX4_NET_TRANS_RULE_ID_TCP,
        MLX4_NET_TRANS_RULE_ID_UDP,
+       MLX4_NET_TRANS_RULE_ID_VXLAN,
        MLX4_NET_TRANS_RULE_NUM, /* should be last */
 };
 
        u8      dst_gid_msk[16];
 };
 
+struct mlx4_spec_vxlan {
+       __be32 vni;
+       __be32 vni_mask;
+
+};
+
 struct mlx4_spec_list {
        struct  list_head list;
        enum    mlx4_net_trans_rule_id id;
                struct mlx4_spec_ib ib;
                struct mlx4_spec_ipv4 ipv4;
                struct mlx4_spec_tcp_udp tcp_udp;
+               struct mlx4_spec_vxlan vxlan;
        };
 };
 
        __be32  src_ip_msk;
 } __packed;
 
+struct mlx4_net_trans_rule_hw_vxlan {
+       u8      size;
+       u8      rsvd;
+       __be16  id;
+       __be32  rsvd1;
+       __be32  vni;
+       __be32  vni_mask;
+} __packed;
+
 struct _rule_hw {
        union {
                struct {
                struct mlx4_net_trans_rule_hw_ib ib;
                struct mlx4_net_trans_rule_hw_ipv4 ipv4;
                struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp;
+               struct mlx4_net_trans_rule_hw_vxlan vxlan;
        };
 };
 
+enum {
+       VXLAN_STEER_BY_OUTER_MAC        = 1 << 0,
+       VXLAN_STEER_BY_OUTER_VLAN       = 1 << 1,
+       VXLAN_STEER_BY_VSID_VNI         = 1 << 2,
+       VXLAN_STEER_BY_INNER_MAC        = 1 << 3,
+       VXLAN_STEER_BY_INNER_VLAN       = 1 << 4,
+};
+
+
 int mlx4_flow_steer_promisc_add(struct mlx4_dev *dev, u8 port, u32 qpn,
                                enum mlx4_net_trans_promisc_mode mode);
 int mlx4_flow_steer_promisc_remove(struct mlx4_dev *dev, u8 port,
 int mlx4_SET_PORT_PRIO2TC(struct mlx4_dev *dev, u8 port, u8 *prio2tc);
 int mlx4_SET_PORT_SCHEDULER(struct mlx4_dev *dev, u8 port, u8 *tc_tx_bw,
                u8 *pg, u16 *ratelimit);
+int mlx4_SET_PORT_VXLAN(struct mlx4_dev *dev, u8 port, u8 steering);
 int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx);
 int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
 void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan);
 
        MLX4_RSS_TCP_IPV4                       = 1 << 4,
        MLX4_RSS_IPV4                           = 1 << 5,
 
+       MLX4_RSS_BY_OUTER_HEADERS               = 0 << 6,
+       MLX4_RSS_BY_INNER_HEADERS               = 2 << 6,
+       MLX4_RSS_BY_INNER_HEADERS_IPONLY        = 3 << 6,
+
        /* offset of mlx4_rss_context within mlx4_qp_context.pri_path */
        MLX4_RSS_OFFSET_IN_QPC_PRI_PATH         = 0x24,
        /* offset of being RSS indirection QP within mlx4_qp_context.flags */
 
 enum {
        MLX4_WQE_CTRL_NEC               = 1 << 29,
+       MLX4_WQE_CTRL_IIP               = 1 << 28,
+       MLX4_WQE_CTRL_ILP               = 1 << 27,
        MLX4_WQE_CTRL_FENCE             = 1 << 6,
        MLX4_WQE_CTRL_CQ_UPDATE         = 3 << 2,
        MLX4_WQE_CTRL_SOLICITED         = 1 << 1,