Commit 0ff1fb65 authored by Hadar Hen Zion's avatar Hadar Hen Zion Committed by David S. Miller

{NET, IB}/mlx4: Add device managed flow steering firmware API

The driver is modified to support three operation modes.

If supported by firmware use the device managed flow steering
API, that which we call device managed steering mode. Else, if
the firmware supports the B0 steering mode use it, and finally,
if none of the above, use the A0 steering mode.

When the steering mode is device managed, the code is modified
such that L2 based rules set by the mlx4_en driver for Ethernet
unicast and multicast, and the IB stack multicast attach calls
done through the mlx4_ib driver are all routed to use the device
managed API.

When attaching rule using device managed flow steering API,
the firmware returns a 64 bit registration id, which is to be
provided during detach.

Currently the firmware is always programmed during HCA initialization
to use standard L2 hashing. Future work should be done to allow
configuring the flow-steering hash function with common, non
proprietary means.
Signed-off-by: default avatarHadar Hen Zion <hadarh@mellanox.co.il>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8fcfb4db
...@@ -718,26 +718,53 @@ int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp, ...@@ -718,26 +718,53 @@ int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
return ret; return ret;
} }
struct mlx4_ib_steering {
struct list_head list;
u64 reg_id;
union ib_gid gid;
};
static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
{ {
int err; int err;
struct mlx4_ib_dev *mdev = to_mdev(ibqp->device); struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
struct mlx4_ib_qp *mqp = to_mqp(ibqp); struct mlx4_ib_qp *mqp = to_mqp(ibqp);
u64 reg_id;
struct mlx4_ib_steering *ib_steering = NULL;
if (mdev->dev->caps.steering_mode ==
MLX4_STEERING_MODE_DEVICE_MANAGED) {
ib_steering = kmalloc(sizeof(*ib_steering), GFP_KERNEL);
if (!ib_steering)
return -ENOMEM;
}
err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, mqp->port,
!!(mqp->flags & MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK), !!(mqp->flags &
MLX4_PROT_IB_IPV6); MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK),
MLX4_PROT_IB_IPV6, &reg_id);
if (err) if (err)
return err; goto err_malloc;
err = add_gid_entry(ibqp, gid); err = add_gid_entry(ibqp, gid);
if (err) if (err)
goto err_add; goto err_add;
if (ib_steering) {
memcpy(ib_steering->gid.raw, gid->raw, 16);
ib_steering->reg_id = reg_id;
mutex_lock(&mqp->mutex);
list_add(&ib_steering->list, &mqp->steering_rules);
mutex_unlock(&mqp->mutex);
}
return 0; return 0;
err_add: err_add:
mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, MLX4_PROT_IB_IPV6); mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw,
MLX4_PROT_IB_IPV6, reg_id);
err_malloc:
kfree(ib_steering);
return err; return err;
} }
...@@ -765,9 +792,30 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) ...@@ -765,9 +792,30 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
u8 mac[6]; u8 mac[6];
struct net_device *ndev; struct net_device *ndev;
struct mlx4_ib_gid_entry *ge; struct mlx4_ib_gid_entry *ge;
u64 reg_id = 0;
if (mdev->dev->caps.steering_mode ==
MLX4_STEERING_MODE_DEVICE_MANAGED) {
struct mlx4_ib_steering *ib_steering;
mutex_lock(&mqp->mutex);
list_for_each_entry(ib_steering, &mqp->steering_rules, list) {
if (!memcmp(ib_steering->gid.raw, gid->raw, 16)) {
list_del(&ib_steering->list);
break;
}
}
mutex_unlock(&mqp->mutex);
if (&ib_steering->list == &mqp->steering_rules) {
pr_err("Couldn't find reg_id for mgid. Steering rule is left attached\n");
return -EINVAL;
}
reg_id = ib_steering->reg_id;
kfree(ib_steering);
}
err = mlx4_multicast_detach(mdev->dev, err = mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw,
&mqp->mqp, gid->raw, MLX4_PROT_IB_IPV6); MLX4_PROT_IB_IPV6, reg_id);
if (err) if (err)
return err; return err;
......
...@@ -163,6 +163,7 @@ struct mlx4_ib_qp { ...@@ -163,6 +163,7 @@ struct mlx4_ib_qp {
u8 state; u8 state;
int mlx_type; int mlx_type;
struct list_head gid_list; struct list_head gid_list;
struct list_head steering_rules;
}; };
struct mlx4_ib_srq { struct mlx4_ib_srq {
......
...@@ -495,6 +495,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, ...@@ -495,6 +495,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
spin_lock_init(&qp->sq.lock); spin_lock_init(&qp->sq.lock);
spin_lock_init(&qp->rq.lock); spin_lock_init(&qp->rq.lock);
INIT_LIST_HEAD(&qp->gid_list); INIT_LIST_HEAD(&qp->gid_list);
INIT_LIST_HEAD(&qp->steering_rules);
qp->state = IB_QPS_RESET; qp->state = IB_QPS_RESET;
if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
......
...@@ -463,7 +463,8 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) ...@@ -463,7 +463,8 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
err = mlx4_multicast_detach(mdev->dev, err = mlx4_multicast_detach(mdev->dev,
&priv->rss_map.indir_qp, &priv->rss_map.indir_qp,
mc_list, mc_list,
MLX4_PROT_ETH); MLX4_PROT_ETH,
mclist->reg_id);
if (err) if (err)
en_err(priv, "Fail to detach multicast address\n"); en_err(priv, "Fail to detach multicast address\n");
...@@ -475,11 +476,14 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) ...@@ -475,11 +476,14 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
if (mclist->action == MCLIST_ADD) { if (mclist->action == MCLIST_ADD) {
/* attach the address */ /* attach the address */
memcpy(&mc_list[10], mclist->addr, ETH_ALEN); memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
/* needed for B0 steering support */
mc_list[5] = priv->port; mc_list[5] = priv->port;
err = mlx4_multicast_attach(mdev->dev, err = mlx4_multicast_attach(mdev->dev,
&priv->rss_map.indir_qp, &priv->rss_map.indir_qp,
mc_list, 0, mc_list,
MLX4_PROT_ETH); priv->port, 0,
MLX4_PROT_ETH,
&mclist->reg_id);
if (err) if (err)
en_err(priv, "Fail to attach multicast address\n"); en_err(priv, "Fail to attach multicast address\n");
...@@ -827,9 +831,10 @@ int mlx4_en_start_port(struct net_device *dev) ...@@ -827,9 +831,10 @@ int mlx4_en_start_port(struct net_device *dev)
/* Attach rx QP to bradcast address */ /* Attach rx QP to bradcast address */
memset(&mc_list[10], 0xff, ETH_ALEN); memset(&mc_list[10], 0xff, ETH_ALEN);
mc_list[5] = priv->port; mc_list[5] = priv->port; /* needed for B0 steering support */
if (mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, mc_list, if (mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
0, MLX4_PROT_ETH)) priv->port, 0, MLX4_PROT_ETH,
&priv->broadcast_id))
mlx4_warn(mdev, "Failed Attaching Broadcast\n"); mlx4_warn(mdev, "Failed Attaching Broadcast\n");
/* Must redo promiscuous mode setup. */ /* Must redo promiscuous mode setup. */
...@@ -886,14 +891,14 @@ void mlx4_en_stop_port(struct net_device *dev) ...@@ -886,14 +891,14 @@ void mlx4_en_stop_port(struct net_device *dev)
/* Detach All multicasts */ /* Detach All multicasts */
memset(&mc_list[10], 0xff, ETH_ALEN); memset(&mc_list[10], 0xff, ETH_ALEN);
mc_list[5] = priv->port; mc_list[5] = priv->port; /* needed for B0 steering support */
mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list, mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
MLX4_PROT_ETH); MLX4_PROT_ETH, priv->broadcast_id);
list_for_each_entry(mclist, &priv->curr_list, list) { list_for_each_entry(mclist, &priv->curr_list, list) {
memcpy(&mc_list[10], mclist->addr, ETH_ALEN); memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
mc_list[5] = priv->port; mc_list[5] = priv->port;
mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
mc_list, MLX4_PROT_ETH); mc_list, MLX4_PROT_ETH, mclist->reg_id);
} }
mlx4_en_clear_list(dev); mlx4_en_clear_list(dev);
list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) { list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) {
......
...@@ -123,7 +123,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) ...@@ -123,7 +123,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
static const char * const fname[] = { static const char * const fname[] = {
[0] = "RSS support", [0] = "RSS support",
[1] = "RSS Toeplitz Hash Function support", [1] = "RSS Toeplitz Hash Function support",
[2] = "RSS XOR Hash Function support" [2] = "RSS XOR Hash Function support",
[3] = "Device manage flow steering support"
}; };
int i; int i;
...@@ -391,6 +392,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) ...@@ -391,6 +392,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_RSVD_XRC_OFFSET 0x66 #define QUERY_DEV_CAP_RSVD_XRC_OFFSET 0x66
#define QUERY_DEV_CAP_MAX_XRC_OFFSET 0x67 #define QUERY_DEV_CAP_MAX_XRC_OFFSET 0x67
#define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET 0x68 #define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET 0x68
#define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET 0x76
#define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET 0x77
#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80 #define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80
#define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82 #define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82
#define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84 #define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84
...@@ -474,6 +477,12 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) ...@@ -474,6 +477,12 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->num_ports = field & 0xf; dev_cap->num_ports = field & 0xf;
MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET); MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET);
dev_cap->max_msg_sz = 1 << (field & 0x1f); dev_cap->max_msg_sz = 1 << (field & 0x1f);
MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
if (field & 0x80)
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FS_EN;
dev_cap->fs_log_max_ucast_qp_range_size = field & 0x1f;
MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET);
dev_cap->fs_max_num_qp_per_entry = field;
MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET); MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
dev_cap->stat_rate_support = stat_rate; dev_cap->stat_rate_support = stat_rate;
MLX4_GET(ext_flags, outbox, QUERY_DEV_CAP_EXT_FLAGS_OFFSET); MLX4_GET(ext_flags, outbox, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
...@@ -1061,6 +1070,15 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) ...@@ -1061,6 +1070,15 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
#define INIT_HCA_LOG_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16) #define INIT_HCA_LOG_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16)
#define INIT_HCA_UC_STEERING_OFFSET (INIT_HCA_MCAST_OFFSET + 0x18) #define INIT_HCA_UC_STEERING_OFFSET (INIT_HCA_MCAST_OFFSET + 0x18)
#define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b) #define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b)
#define INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN 0x6
#define INIT_HCA_FS_PARAM_OFFSET 0x1d0
#define INIT_HCA_FS_BASE_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x00)
#define INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x12)
#define INIT_HCA_FS_LOG_TABLE_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x1b)
#define INIT_HCA_FS_ETH_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x21)
#define INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x22)
#define INIT_HCA_FS_IB_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x25)
#define INIT_HCA_FS_IB_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x26)
#define INIT_HCA_TPT_OFFSET 0x0f0 #define INIT_HCA_TPT_OFFSET 0x0f0
#define INIT_HCA_DMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00) #define INIT_HCA_DMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00)
#define INIT_HCA_LOG_MPT_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x0b) #define INIT_HCA_LOG_MPT_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x0b)
...@@ -1119,14 +1137,44 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) ...@@ -1119,14 +1137,44 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
MLX4_PUT(inbox, param->rdmarc_base, INIT_HCA_RDMARC_BASE_OFFSET); MLX4_PUT(inbox, param->rdmarc_base, INIT_HCA_RDMARC_BASE_OFFSET);
MLX4_PUT(inbox, param->log_rd_per_qp, INIT_HCA_LOG_RD_OFFSET); MLX4_PUT(inbox, param->log_rd_per_qp, INIT_HCA_LOG_RD_OFFSET);
/* multicast attributes */ /* steering attributes */
if (dev->caps.steering_mode ==
MLX4_STEERING_MODE_DEVICE_MANAGED) {
*(inbox + INIT_HCA_FLAGS_OFFSET / 4) |=
cpu_to_be32(1 <<
INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN);
MLX4_PUT(inbox, param->mc_base, INIT_HCA_FS_BASE_OFFSET);
MLX4_PUT(inbox, param->log_mc_entry_sz,
INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
MLX4_PUT(inbox, param->log_mc_table_sz,
INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
/* Enable Ethernet flow steering
* with udp unicast and tcp unicast
*/
MLX4_PUT(inbox, param->fs_hash_enable_bits,
INIT_HCA_FS_ETH_BITS_OFFSET);
MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR,
INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET);
/* Enable IPoIB flow steering
* with udp unicast and tcp unicast
*/
MLX4_PUT(inbox, param->fs_hash_enable_bits,
INIT_HCA_FS_IB_BITS_OFFSET);
MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR,
INIT_HCA_FS_IB_NUM_ADDRS_OFFSET);
} else {
MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET); MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET);
MLX4_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); MLX4_PUT(inbox, param->log_mc_entry_sz,
MLX4_PUT(inbox, param->log_mc_hash_sz, INIT_HCA_LOG_MC_HASH_SZ_OFFSET); INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
MLX4_PUT(inbox, param->log_mc_hash_sz,
INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
MLX4_PUT(inbox, param->log_mc_table_sz,
INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0) if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0)
MLX4_PUT(inbox, (u8) (1 << 3), INIT_HCA_UC_STEERING_OFFSET); MLX4_PUT(inbox, (u8) (1 << 3),
MLX4_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); INIT_HCA_UC_STEERING_OFFSET);
}
/* TPT attributes */ /* TPT attributes */
...@@ -1188,8 +1236,16 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, ...@@ -1188,8 +1236,16 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET); MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET);
MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET); MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET);
/* multicast attributes */ /* steering attributes */
if (dev->caps.steering_mode ==
MLX4_STEERING_MODE_DEVICE_MANAGED) {
MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET);
MLX4_GET(param->log_mc_entry_sz, outbox,
INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
MLX4_GET(param->log_mc_table_sz, outbox,
INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
} else {
MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET); MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET);
MLX4_GET(param->log_mc_entry_sz, outbox, MLX4_GET(param->log_mc_entry_sz, outbox,
INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
...@@ -1197,6 +1253,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, ...@@ -1197,6 +1253,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
INIT_HCA_LOG_MC_HASH_SZ_OFFSET); INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
MLX4_GET(param->log_mc_table_sz, outbox, MLX4_GET(param->log_mc_table_sz, outbox,
INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
}
/* TPT attributes */ /* TPT attributes */
......
...@@ -78,6 +78,8 @@ struct mlx4_dev_cap { ...@@ -78,6 +78,8 @@ struct mlx4_dev_cap {
u16 wavelength[MLX4_MAX_PORTS + 1]; u16 wavelength[MLX4_MAX_PORTS + 1];
u64 trans_code[MLX4_MAX_PORTS + 1]; u64 trans_code[MLX4_MAX_PORTS + 1];
u16 stat_rate_support; u16 stat_rate_support;
int fs_log_max_ucast_qp_range_size;
int fs_max_num_qp_per_entry;
u64 flags; u64 flags;
u64 flags2; u64 flags2;
int reserved_uars; int reserved_uars;
...@@ -165,6 +167,7 @@ struct mlx4_init_hca_param { ...@@ -165,6 +167,7 @@ struct mlx4_init_hca_param {
u8 log_mpt_sz; u8 log_mpt_sz;
u8 log_uar_sz; u8 log_uar_sz;
u8 uar_page_sz; /* log pg sz in 4k chunks */ u8 uar_page_sz; /* log pg sz in 4k chunks */
u8 fs_hash_enable_bits;
}; };
struct mlx4_init_ib_param { struct mlx4_init_ib_param {
......
...@@ -91,7 +91,9 @@ module_param_named(log_num_mgm_entry_size, ...@@ -91,7 +91,9 @@ module_param_named(log_num_mgm_entry_size,
MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num" MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num"
" of qp per mcg, for example:" " of qp per mcg, for example:"
" 10 gives 248.range: 9<=" " 10 gives 248.range: 9<="
" log_num_mgm_entry_size <= 12"); " log_num_mgm_entry_size <= 12."
" Not in use with device managed"
" flow steering");
#define MLX4_VF (1 << 0) #define MLX4_VF (1 << 0)
...@@ -274,6 +276,12 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) ...@@ -274,6 +276,12 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.max_gso_sz = dev_cap->max_gso_sz; dev->caps.max_gso_sz = dev_cap->max_gso_sz;
dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz; dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz;
if (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN) {
dev->caps.steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED;
dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry;
dev->caps.fs_log_max_ucast_qp_range_size =
dev_cap->fs_log_max_ucast_qp_range_size;
} else {
if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER && if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER &&
dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) { dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) {
dev->caps.steering_mode = MLX4_STEERING_MODE_B0; dev->caps.steering_mode = MLX4_STEERING_MODE_B0;
...@@ -285,9 +293,10 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) ...@@ -285,9 +293,10 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
mlx4_warn(dev, "Must have UC_STEER and MC_STEER flags " mlx4_warn(dev, "Must have UC_STEER and MC_STEER flags "
"set to use B0 steering. Falling back to A0 steering mode.\n"); "set to use B0 steering. Falling back to A0 steering mode.\n");
} }
dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev);
}
mlx4_dbg(dev, "Steering mode is: %s\n", mlx4_dbg(dev, "Steering mode is: %s\n",
mlx4_steering_mode_str(dev->caps.steering_mode)); mlx4_steering_mode_str(dev->caps.steering_mode));
dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev);
/* Sense port always allowed on supported devices for ConnectX1 and 2 */ /* Sense port always allowed on supported devices for ConnectX1 and 2 */
if (dev->pdev->device != 0x1003) if (dev->pdev->device != 0x1003)
...@@ -982,9 +991,11 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, ...@@ -982,9 +991,11 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap,
} }
/* /*
* It's not strictly required, but for simplicity just map the * For flow steering device managed mode it is required to use
* whole multicast group table now. The table isn't very big * mlx4_init_icm_table. For B0 steering mode it's not strictly
* and it's a lot easier than trying to track ref counts. * required, but for simplicity just map the whole multicast
* group table now. The table isn't very big and it's a lot
* easier than trying to track ref counts.
*/ */
err = mlx4_init_icm_table(dev, &priv->mcg_table.table, err = mlx4_init_icm_table(dev, &priv->mcg_table.table,
init_hca->mc_base, init_hca->mc_base,
...@@ -1220,7 +1231,26 @@ static int mlx4_init_hca(struct mlx4_dev *dev) ...@@ -1220,7 +1231,26 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
goto err_stop_fw; goto err_stop_fw;
} }
priv->fs_hash_mode = MLX4_FS_L2_HASH;
switch (priv->fs_hash_mode) {
case MLX4_FS_L2_HASH:
init_hca.fs_hash_enable_bits = 0;
break;
case MLX4_FS_L2_L3_L4_HASH:
/* Enable flow steering with
* udp unicast and tcp unicast
*/
init_hca.fs_hash_enable_bits =
MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN;
break;
}
profile = default_profile; profile = default_profile;
if (dev->caps.steering_mode ==
MLX4_STEERING_MODE_DEVICE_MANAGED)
profile.num_mcg = MLX4_FS_NUM_MCG;
icm_size = mlx4_make_profile(dev, &profile, &dev_cap, icm_size = mlx4_make_profile(dev, &profile, &dev_cap,
&init_hca); &init_hca);
......
This diff is collapsed.
...@@ -54,6 +54,17 @@ ...@@ -54,6 +54,17 @@
#define DRV_VERSION "1.1" #define DRV_VERSION "1.1"
#define DRV_RELDATE "Dec, 2011" #define DRV_RELDATE "Dec, 2011"
#define MLX4_FS_UDP_UC_EN (1 << 1)
#define MLX4_FS_TCP_UC_EN (1 << 2)
#define MLX4_FS_NUM_OF_L2_ADDR 8
#define MLX4_FS_MGM_LOG_ENTRY_SIZE 7
#define MLX4_FS_NUM_MCG (1 << 17)
enum {
MLX4_FS_L2_HASH = 0,
MLX4_FS_L2_L3_L4_HASH,
};
#define MLX4_NUM_UP 8 #define MLX4_NUM_UP 8
#define MLX4_NUM_TC 8 #define MLX4_NUM_TC 8
#define MLX4_RATELIMIT_UNITS 3 /* 100 Mbps */ #define MLX4_RATELIMIT_UNITS 3 /* 100 Mbps */
...@@ -704,6 +715,7 @@ struct mlx4_set_port_rqp_calc_context { ...@@ -704,6 +715,7 @@ struct mlx4_set_port_rqp_calc_context {
struct mlx4_mac_entry { struct mlx4_mac_entry {
u64 mac; u64 mac;
u64 reg_id;
}; };
struct mlx4_port_info { struct mlx4_port_info {
...@@ -777,6 +789,7 @@ struct mlx4_priv { ...@@ -777,6 +789,7 @@ struct mlx4_priv {
struct mutex bf_mutex; struct mutex bf_mutex;
struct io_mapping *bf_mapping; struct io_mapping *bf_mapping;
int reserved_mtts; int reserved_mtts;
int fs_hash_mode;
}; };
static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev) static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
......
...@@ -414,6 +414,7 @@ struct mlx4_en_mc_list { ...@@ -414,6 +414,7 @@ struct mlx4_en_mc_list {
struct list_head list; struct list_head list;
enum mlx4_en_mclist_act action; enum mlx4_en_mclist_act action;
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
u64 reg_id;
}; };
struct mlx4_en_frag_info { struct mlx4_en_frag_info {
...@@ -503,6 +504,7 @@ struct mlx4_en_priv { ...@@ -503,6 +504,7 @@ struct mlx4_en_priv {
u64 stats_bitmap; u64 stats_bitmap;
struct list_head mc_list; struct list_head mc_list;
struct list_head curr_list; struct list_head curr_list;
u64 broadcast_id;
struct mlx4_en_stat_out_mbox hw_stats; struct mlx4_en_stat_out_mbox hw_stats;
int vids[128]; int vids[128];
bool wol; bool wol;
......
...@@ -75,21 +75,54 @@ void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table) ...@@ -75,21 +75,54 @@ void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table)
table->total = 0; table->total = 0;
} }
static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port,
u64 mac, int *qpn, u64 *reg_id)
{ {
struct mlx4_qp qp;
u8 gid[16] = {0};
__be64 be_mac; __be64 be_mac;
int err; int err;
qp.qpn = *qpn; mac &= MLX4_MAC_MASK;
mac &= 0xffffffffffffULL;
be_mac = cpu_to_be64(mac << 16); be_mac = cpu_to_be64(mac << 16);
switch (dev->caps.steering_mode) {
case MLX4_STEERING_MODE_B0: {
struct mlx4_qp qp;
u8 gid[16] = {0};
qp.qpn = *qpn;
memcpy(&gid[10], &be_mac, ETH_ALEN); memcpy(&gid[10], &be_mac, ETH_ALEN);
gid[5] = port; gid[5] = port;
err = mlx4_unicast_attach(dev, &qp, gid, 0, MLX4_PROT_ETH); err = mlx4_unicast_attach(dev, &qp, gid, 0, MLX4_PROT_ETH);
break;
}
case MLX4_STEERING_MODE_DEVICE_MANAGED: {
struct mlx4_spec_list spec_eth = { {NULL} };
__be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
struct mlx4_net_trans_rule rule = {
.queue_mode = MLX4_NET_TRANS_Q_FIFO,
.exclusive = 0,
.allow_loopback = 1,
.promisc_mode = MLX4_FS_PROMISC_NONE,
.priority = MLX4_DOMAIN_NIC,
};
rule.port = port;
rule.qpn = *qpn;
INIT_LIST_HEAD(&rule.list);
spec_eth.id = MLX4_NET_TRANS_RULE_ID_ETH;
memcpy(spec_eth.eth.dst_mac, &be_mac, ETH_ALEN);
memcpy(spec_eth.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
list_add_tail(&spec_eth.list, &rule.list);
err = mlx4_flow_attach(dev, &rule, reg_id);
break;
}
default:
return -EINVAL;
}
if (err) if (err)
mlx4_warn(dev, "Failed Attaching Unicast\n"); mlx4_warn(dev, "Failed Attaching Unicast\n");
...@@ -97,19 +130,30 @@ static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) ...@@ -97,19 +130,30 @@ static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn)
} }
static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port, static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port,
u64 mac, int qpn) u64 mac, int qpn, u64 reg_id)
{ {
switch (dev->caps.steering_mode) {
case MLX4_STEERING_MODE_B0: {
struct mlx4_qp qp; struct mlx4_qp qp;
u8 gid[16] = {0}; u8 gid[16] = {0};
__be64 be_mac; __be64 be_mac;
qp.qpn = qpn; qp.qpn = qpn;
mac &= 0xffffffffffffULL; mac &= MLX4_MAC_MASK;
be_mac = cpu_to_be64(mac << 16); be_mac = cpu_to_be64(mac << 16);
memcpy(&gid[10], &be_mac, ETH_ALEN); memcpy(&gid[10], &be_mac, ETH_ALEN);
gid[5] = port; gid[5] = port;
mlx4_unicast_detach(dev, &qp, gid, MLX4_PROT_ETH); mlx4_unicast_detach(dev, &qp, gid, MLX4_PROT_ETH);
break;
}
case MLX4_STEERING_MODE_DEVICE_MANAGED: {
mlx4_flow_detach(dev, reg_id);
break;
}
default:
mlx4_err(dev, "Invalid steering mode.\n");
}
} }
static int validate_index(struct mlx4_dev *dev, static int validate_index(struct mlx4_dev *dev,
...@@ -144,6 +188,7 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) ...@@ -144,6 +188,7 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn)
struct mlx4_mac_entry *entry; struct mlx4_mac_entry *entry;
int index = 0; int index = 0;
int err = 0; int err = 0;
u64 reg_id;
mlx4_dbg(dev, "Registering MAC: 0x%llx for adding\n", mlx4_dbg(dev, "Registering MAC: 0x%llx for adding\n",
(unsigned long long) mac); (unsigned long long) mac);
...@@ -167,7 +212,7 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) ...@@ -167,7 +212,7 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn)
goto qp_err; goto qp_err;
} }
err = mlx4_uc_steer_add(dev, port, mac, qpn); err = mlx4_uc_steer_add(dev, port, mac, qpn, &reg_id);
if (err) if (err)
goto steer_err; goto steer_err;
...@@ -177,6 +222,7 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) ...@@ -177,6 +222,7 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn)
goto alloc_err; goto alloc_err;
} }
entry->mac = mac; entry->mac = mac;
entry->reg_id = reg_id;
err = radix_tree_insert(&info->mac_tree, *qpn, entry); err = radix_tree_insert(&info->mac_tree, *qpn, entry);
if (err) if (err)
goto insert_err; goto insert_err;
...@@ -186,7 +232,7 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) ...@@ -186,7 +232,7 @@ int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn)
kfree(entry); kfree(entry);
alloc_err: alloc_err:
mlx4_uc_steer_release(dev, port, mac, *qpn); mlx4_uc_steer_release(dev, port, mac, *qpn, reg_id);
steer_err: steer_err:
mlx4_qp_release_range(dev, *qpn, 1); mlx4_qp_release_range(dev, *qpn, 1);
...@@ -212,7 +258,8 @@ void mlx4_put_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int qpn) ...@@ -212,7 +258,8 @@ void mlx4_put_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int qpn)
mlx4_dbg(dev, "Releasing qp: port %d, mac 0x%llx," mlx4_dbg(dev, "Releasing qp: port %d, mac 0x%llx,"
" qpn %d\n", port, " qpn %d\n", port,
(unsigned long long) mac, qpn); (unsigned long long) mac, qpn);
mlx4_uc_steer_release(dev, port, entry->mac, qpn); mlx4_uc_steer_release(dev, port, entry->mac,
qpn, entry->reg_id);
mlx4_qp_release_range(dev, qpn, 1); mlx4_qp_release_range(dev, qpn, 1);
radix_tree_delete(&info->mac_tree, qpn); radix_tree_delete(&info->mac_tree, qpn);
kfree(entry); kfree(entry);
...@@ -363,11 +410,14 @@ int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac) ...@@ -363,11 +410,14 @@ int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac)
entry = radix_tree_lookup(&info->mac_tree, qpn); entry = radix_tree_lookup(&info->mac_tree, qpn);
if (!entry) if (!entry)
return -EINVAL; return -EINVAL;
mlx4_uc_steer_release(dev, port, entry->mac, qpn); mlx4_uc_steer_release(dev, port, entry->mac,
qpn, entry->reg_id);
mlx4_unregister_mac(dev, port, entry->mac); mlx4_unregister_mac(dev, port, entry->mac);
entry->mac = new_mac; entry->mac = new_mac;
entry->reg_id = 0;
mlx4_register_mac(dev, port, new_mac); mlx4_register_mac(dev, port, new_mac);
err = mlx4_uc_steer_add(dev, port, entry->mac, &qpn); err = mlx4_uc_steer_add(dev, port, entry->mac,
&qpn, &entry->reg_id);
return err; return err;
} }
......
...@@ -237,13 +237,19 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, ...@@ -237,13 +237,19 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
init_hca->mtt_base = profile[i].start; init_hca->mtt_base = profile[i].start;
break; break;
case MLX4_RES_MCG: case MLX4_RES_MCG:
dev->caps.num_mgms = profile[i].num >> 1;
dev->caps.num_amgms = profile[i].num >> 1;
init_hca->mc_base = profile[i].start; init_hca->mc_base = profile[i].start;
init_hca->log_mc_entry_sz = init_hca->log_mc_entry_sz =
ilog2(mlx4_get_mgm_entry_size(dev)); ilog2(mlx4_get_mgm_entry_size(dev));
init_hca->log_mc_table_sz = profile[i].log_num; init_hca->log_mc_table_sz = profile[i].log_num;
init_hca->log_mc_hash_sz = profile[i].log_num - 1; if (dev->caps.steering_mode ==
MLX4_STEERING_MODE_DEVICE_MANAGED) {
dev->caps.num_mgms = profile[i].num;
} else {
init_hca->log_mc_hash_sz =
profile[i].log_num - 1;
dev->caps.num_mgms = profile[i].num >> 1;
dev->caps.num_amgms = profile[i].num >> 1;
}
break; break;
default: default:
break; break;
......
...@@ -2744,6 +2744,9 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, ...@@ -2744,6 +2744,9 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_cmd_mailbox *outbox, struct mlx4_cmd_mailbox *outbox,
struct mlx4_cmd_info *cmd) struct mlx4_cmd_info *cmd)
{ {
if (dev->caps.steering_mode !=
MLX4_STEERING_MODE_DEVICE_MANAGED)
return -EOPNOTSUPP;
return mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, return mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param,
vhcr->in_modifier, 0, vhcr->in_modifier, 0,
MLX4_QP_FLOW_STEERING_ATTACH, MLX4_QP_FLOW_STEERING_ATTACH,
...@@ -2757,6 +2760,9 @@ int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave, ...@@ -2757,6 +2760,9 @@ int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_cmd_mailbox *outbox, struct mlx4_cmd_mailbox *outbox,
struct mlx4_cmd_info *cmd) struct mlx4_cmd_info *cmd)
{ {
if (dev->caps.steering_mode !=
MLX4_STEERING_MODE_DEVICE_MANAGED)
return -EOPNOTSUPP;
return mlx4_cmd(dev, vhcr->in_param, 0, 0, return mlx4_cmd(dev, vhcr->in_param, 0, 0,
MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_NATIVE); MLX4_CMD_NATIVE);
......
...@@ -70,14 +70,17 @@ enum { ...@@ -70,14 +70,17 @@ enum {
MLX4_MFUNC_EQE_MASK = (MLX4_MFUNC_MAX_EQES - 1) MLX4_MFUNC_EQE_MASK = (MLX4_MFUNC_MAX_EQES - 1)
}; };
/* Driver supports 2 diffrent device methods to manage traffic steering: /* Driver supports 3 diffrent device methods to manage traffic steering:
* -device managed - High level API for ib and eth flow steering. FW is
* managing flow steering tables.
* - B0 steering mode - Common low level API for ib and (if supported) eth. * - B0 steering mode - Common low level API for ib and (if supported) eth.
* - A0 steering mode - Limited low level API for eth. In case of IB, * - A0 steering mode - Limited low level API for eth. In case of IB,
* B0 mode is in use. * B0 mode is in use.
*/ */
enum { enum {
MLX4_STEERING_MODE_A0, MLX4_STEERING_MODE_A0,
MLX4_STEERING_MODE_B0 MLX4_STEERING_MODE_B0,
MLX4_STEERING_MODE_DEVICE_MANAGED
}; };
static inline const char *mlx4_steering_mode_str(int steering_mode) static inline const char *mlx4_steering_mode_str(int steering_mode)
...@@ -88,6 +91,10 @@ static inline const char *mlx4_steering_mode_str(int steering_mode) ...@@ -88,6 +91,10 @@ static inline const char *mlx4_steering_mode_str(int steering_mode)
case MLX4_STEERING_MODE_B0: case MLX4_STEERING_MODE_B0:
return "B0 steering"; return "B0 steering";
case MLX4_STEERING_MODE_DEVICE_MANAGED:
return "Device managed flow steering";
default: default:
return "Unrecognize steering mode"; return "Unrecognize steering mode";
} }
...@@ -125,7 +132,8 @@ enum { ...@@ -125,7 +132,8 @@ enum {
enum { enum {
MLX4_DEV_CAP_FLAG2_RSS = 1LL << 0, MLX4_DEV_CAP_FLAG2_RSS = 1LL << 0,
MLX4_DEV_CAP_FLAG2_RSS_TOP = 1LL << 1, MLX4_DEV_CAP_FLAG2_RSS_TOP = 1LL << 1,
MLX4_DEV_CAP_FLAG2_RSS_XOR = 1LL << 2 MLX4_DEV_CAP_FLAG2_RSS_XOR = 1LL << 2,
MLX4_DEV_CAP_FLAG2_FS_EN = 1LL << 3
}; };
#define MLX4_ATTR_EXTENDED_PORT_INFO cpu_to_be16(0xff90) #define MLX4_ATTR_EXTENDED_PORT_INFO cpu_to_be16(0xff90)
...@@ -319,6 +327,7 @@ struct mlx4_caps { ...@@ -319,6 +327,7 @@ struct mlx4_caps {
int reserved_mcgs; int reserved_mcgs;
int num_qp_per_mgm; int num_qp_per_mgm;
int steering_mode; int steering_mode;
int fs_log_max_ucast_qp_range_size;
int num_pds; int num_pds;
int reserved_pds; int reserved_pds;
int max_xrcds; int max_xrcds;
...@@ -647,9 +656,94 @@ int mlx4_unicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], ...@@ -647,9 +656,94 @@ int mlx4_unicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
enum mlx4_protocol prot); enum mlx4_protocol prot);
int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
int block_mcast_loopback, enum mlx4_protocol protocol); u8 port, int block_mcast_loopback,
enum mlx4_protocol protocol, u64 *reg_id);
int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
enum mlx4_protocol protocol); enum mlx4_protocol protocol, u64 reg_id);
enum {
MLX4_DOMAIN_UVERBS = 0x1000,
MLX4_DOMAIN_ETHTOOL = 0x2000,
MLX4_DOMAIN_RFS = 0x3000,
MLX4_DOMAIN_NIC = 0x5000,
};
enum mlx4_net_trans_rule_id {
MLX4_NET_TRANS_RULE_ID_ETH = 0,
MLX4_NET_TRANS_RULE_ID_IB,
MLX4_NET_TRANS_RULE_ID_IPV6,
MLX4_NET_TRANS_RULE_ID_IPV4,
MLX4_NET_TRANS_RULE_ID_TCP,
MLX4_NET_TRANS_RULE_ID_UDP,
MLX4_NET_TRANS_RULE_NUM, /* should be last */
};
enum mlx4_net_trans_promisc_mode {
MLX4_FS_PROMISC_NONE = 0,
MLX4_FS_PROMISC_UPLINK,
MLX4_FS_PROMISC_FUNCTION_PORT,
MLX4_FS_PROMISC_ALL_MULTI,
};
struct mlx4_spec_eth {
u8 dst_mac[6];
u8 dst_mac_msk[6];
u8 src_mac[6];
u8 src_mac_msk[6];
u8 ether_type_enable;
__be16 ether_type;
__be16 vlan_id_msk;
__be16 vlan_id;
};
struct mlx4_spec_tcp_udp {
__be16 dst_port;
__be16 dst_port_msk;
__be16 src_port;
__be16 src_port_msk;
};
struct mlx4_spec_ipv4 {
__be32 dst_ip;
__be32 dst_ip_msk;
__be32 src_ip;
__be32 src_ip_msk;
};
struct mlx4_spec_ib {
__be32 r_qpn;
__be32 qpn_msk;
u8 dst_gid[16];
u8 dst_gid_msk[16];
};
struct mlx4_spec_list {
struct list_head list;
enum mlx4_net_trans_rule_id id;
union {
struct mlx4_spec_eth eth;
struct mlx4_spec_ib ib;
struct mlx4_spec_ipv4 ipv4;
struct mlx4_spec_tcp_udp tcp_udp;
};
};
enum mlx4_net_trans_hw_rule_queue {
MLX4_NET_TRANS_Q_FIFO,
MLX4_NET_TRANS_Q_LIFO,
};
struct mlx4_net_trans_rule {
struct list_head list;
enum mlx4_net_trans_hw_rule_queue queue_mode;
bool exclusive;
bool allow_loopback;
enum mlx4_net_trans_promisc_mode promisc_mode;
u8 port;
u16 priority;
u32 qpn;
};
int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port); int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port);
int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port); int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port);
int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port); int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port);
...@@ -692,4 +786,8 @@ int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port); ...@@ -692,4 +786,8 @@ int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port);
int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx); int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx);
void mlx4_counter_free(struct mlx4_dev *dev, u32 idx); void mlx4_counter_free(struct mlx4_dev *dev, u32 idx);
int mlx4_flow_attach(struct mlx4_dev *dev,
struct mlx4_net_trans_rule *rule, u64 *reg_id);
int mlx4_flow_detach(struct mlx4_dev *dev, u64 reg_id);
#endif /* MLX4_DEVICE_H */ #endif /* MLX4_DEVICE_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment