Commit 0ec2c0f8 authored by Eugenia Emantayev's avatar Eugenia Emantayev Committed by David S. Miller

mlx4: Traffic steering management support for SRIOV

Let multicast/unicast attaching flow go through resource tracker.
The PF is the one responsible for managing all the steering entries.
Define and use module parameter that determines the number of qps
per multicast group.
Minor changes in function calls according to changed prototype.
Signed-off-by: default avatarEugenia Emantayev <eugenia@mellanox.co.il>
Signed-off-by: default avatarYevgeny Petrilin <yevgenyp@mellanox.co.il>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8e59d254
...@@ -996,6 +996,15 @@ static struct mlx4_cmd_info cmd_info[] = { ...@@ -996,6 +996,15 @@ static struct mlx4_cmd_info cmd_info[] = {
.verify = NULL, .verify = NULL,
.wrapper = mlx4_QP_ATTACH_wrapper .wrapper = mlx4_QP_ATTACH_wrapper
}, },
{
.opcode = MLX4_CMD_PROMISC,
.has_inbox = false,
.has_outbox = false,
.out_is_imm = false,
.encode_slave_id = false,
.verify = NULL,
.wrapper = mlx4_PROMISC_wrapper
},
{ {
.opcode = MLX4_CMD_INFORM_FLR_DONE, .opcode = MLX4_CMD_INFORM_FLR_DONE,
.has_inbox = false, .has_inbox = false,
......
...@@ -75,6 +75,14 @@ MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero"); ...@@ -75,6 +75,14 @@ MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero");
#endif /* CONFIG_PCI_MSI */ #endif /* CONFIG_PCI_MSI */
int mlx4_log_num_mgm_entry_size = 10;
module_param_named(log_num_mgm_entry_size,
mlx4_log_num_mgm_entry_size, int, 0444);
MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num"
" of qp per mcg, for example:"
" 10 gives 248.range: 9<="
" log_num_mgm_entry_size <= 12");
static char mlx4_version[] __devinitdata = static char mlx4_version[] __devinitdata =
DRV_NAME ": Mellanox ConnectX core driver v" DRV_NAME ": Mellanox ConnectX core driver v"
DRV_VERSION " (" DRV_RELDATE ")\n"; DRV_VERSION " (" DRV_RELDATE ")\n";
...@@ -205,7 +213,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) ...@@ -205,7 +213,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.reserved_srqs = dev_cap->reserved_srqs; dev->caps.reserved_srqs = dev_cap->reserved_srqs;
dev->caps.max_sq_desc_sz = dev_cap->max_sq_desc_sz; dev->caps.max_sq_desc_sz = dev_cap->max_sq_desc_sz;
dev->caps.max_rq_desc_sz = dev_cap->max_rq_desc_sz; dev->caps.max_rq_desc_sz = dev_cap->max_rq_desc_sz;
dev->caps.num_qp_per_mgm = MLX4_QP_PER_MGM; dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev);
/* /*
* Subtract 1 from the limit because we need to allocate a * Subtract 1 from the limit because we need to allocate a
* spare CQE so the HCA HW can tell the difference between an * spare CQE so the HCA HW can tell the difference between an
...@@ -648,7 +656,8 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, ...@@ -648,7 +656,8 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap,
* and it's a lot easier than trying to track ref counts. * 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, MLX4_MGM_ENTRY_SIZE, init_hca->mc_base,
mlx4_get_mgm_entry_size(dev),
dev->caps.num_mgms + dev->caps.num_amgms, dev->caps.num_mgms + dev->caps.num_amgms,
dev->caps.num_mgms + dev->caps.num_amgms, dev->caps.num_mgms + dev->caps.num_amgms,
0, 0); 0, 0);
......
...@@ -44,6 +44,24 @@ ...@@ -44,6 +44,24 @@
static const u8 zero_gid[16]; /* automatically initialized to 0 */ static const u8 zero_gid[16]; /* automatically initialized to 0 */
struct mlx4_mgm {
__be32 next_gid_index;
__be32 members_count;
u32 reserved[2];
u8 gid[16];
__be32 qp[MLX4_MAX_QP_PER_MGM];
};
int mlx4_get_mgm_entry_size(struct mlx4_dev *dev)
{
return min((1 << mlx4_log_num_mgm_entry_size), MLX4_MAX_MGM_ENTRY_SIZE);
}
int mlx4_get_qp_per_mgm(struct mlx4_dev *dev)
{
return 4 * (mlx4_get_mgm_entry_size(dev) / 16 - 2);
}
static int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index, static int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index,
struct mlx4_cmd_mailbox *mailbox) struct mlx4_cmd_mailbox *mailbox)
{ {
...@@ -58,12 +76,12 @@ static int mlx4_WRITE_ENTRY(struct mlx4_dev *dev, int index, ...@@ -58,12 +76,12 @@ static int mlx4_WRITE_ENTRY(struct mlx4_dev *dev, int index,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
} }
static int mlx4_WRITE_PROMISC(struct mlx4_dev *dev, u8 vep_num, u8 port, u8 steer, static int mlx4_WRITE_PROMISC(struct mlx4_dev *dev, u8 port, u8 steer,
struct mlx4_cmd_mailbox *mailbox) struct mlx4_cmd_mailbox *mailbox)
{ {
u32 in_mod; u32 in_mod;
in_mod = (u32) vep_num << 24 | (u32) port << 16 | steer << 1; in_mod = (u32) port << 16 | steer << 1;
return mlx4_cmd(dev, mailbox->dma, in_mod, 0x1, return mlx4_cmd(dev, mailbox->dma, in_mod, 0x1,
MLX4_CMD_WRITE_MCG, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRITE_MCG, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_NATIVE); MLX4_CMD_NATIVE);
...@@ -104,7 +122,7 @@ static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num, ...@@ -104,7 +122,7 @@ static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num,
* Add new entry to steering data structure. * Add new entry to steering data structure.
* All promisc QPs should be added as well * All promisc QPs should be added as well
*/ */
static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, static int new_steering_entry(struct mlx4_dev *dev, u8 port,
enum mlx4_steer_type steer, enum mlx4_steer_type steer,
unsigned int index, u32 qpn) unsigned int index, u32 qpn)
{ {
...@@ -117,10 +135,8 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -117,10 +135,8 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
struct mlx4_promisc_qp *dqp = NULL; struct mlx4_promisc_qp *dqp = NULL;
u32 prot; u32 prot;
int err; int err;
u8 pf_num;
pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); s_steer = &mlx4_priv(dev)->steer[0];
s_steer = &mlx4_priv(dev)->steer[pf_num];
new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL); new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL);
if (!new_entry) if (!new_entry)
return -ENOMEM; return -ENOMEM;
...@@ -132,7 +148,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -132,7 +148,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
/* If the given qpn is also a promisc qp, /* If the given qpn is also a promisc qp,
* it should be inserted to duplicates list * it should be inserted to duplicates list
*/ */
pqp = get_promisc_qp(dev, pf_num, steer, qpn); pqp = get_promisc_qp(dev, 0, steer, qpn);
if (pqp) { if (pqp) {
dqp = kmalloc(sizeof *dqp, GFP_KERNEL); dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
if (!dqp) { if (!dqp) {
...@@ -167,7 +183,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -167,7 +183,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
/* don't add already existing qpn */ /* don't add already existing qpn */
if (pqp->qpn == qpn) if (pqp->qpn == qpn)
continue; continue;
if (members_count == MLX4_QP_PER_MGM) { if (members_count == dev->caps.num_qp_per_mgm) {
/* out of space */ /* out of space */
err = -ENOMEM; err = -ENOMEM;
goto out_mailbox; goto out_mailbox;
...@@ -195,7 +211,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -195,7 +211,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
} }
/* update the data structures with existing steering entry */ /* update the data structures with existing steering entry */
static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, static int existing_steering_entry(struct mlx4_dev *dev, u8 port,
enum mlx4_steer_type steer, enum mlx4_steer_type steer,
unsigned int index, u32 qpn) unsigned int index, u32 qpn)
{ {
...@@ -203,12 +219,10 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -203,12 +219,10 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
struct mlx4_steer_index *tmp_entry, *entry = NULL; struct mlx4_steer_index *tmp_entry, *entry = NULL;
struct mlx4_promisc_qp *pqp; struct mlx4_promisc_qp *pqp;
struct mlx4_promisc_qp *dqp; struct mlx4_promisc_qp *dqp;
u8 pf_num;
pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); s_steer = &mlx4_priv(dev)->steer[0];
s_steer = &mlx4_priv(dev)->steer[pf_num];
pqp = get_promisc_qp(dev, pf_num, steer, qpn); pqp = get_promisc_qp(dev, 0, steer, qpn);
if (!pqp) if (!pqp)
return 0; /* nothing to do */ return 0; /* nothing to do */
...@@ -227,7 +241,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -227,7 +241,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
* we need to add it as a duplicate to this entry * we need to add it as a duplicate to this entry
* for future references */ * for future references */
list_for_each_entry(dqp, &entry->duplicates, list) { list_for_each_entry(dqp, &entry->duplicates, list) {
if (qpn == dqp->qpn) if (qpn == pqp->qpn)
return 0; /* qp is already duplicated */ return 0; /* qp is already duplicated */
} }
...@@ -243,20 +257,18 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -243,20 +257,18 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
/* Check whether a qpn is a duplicate on steering entry /* Check whether a qpn is a duplicate on steering entry
* If so, it should not be removed from mgm */ * If so, it should not be removed from mgm */
static bool check_duplicate_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port,
enum mlx4_steer_type steer, enum mlx4_steer_type steer,
unsigned int index, u32 qpn) unsigned int index, u32 qpn)
{ {
struct mlx4_steer *s_steer; struct mlx4_steer *s_steer;
struct mlx4_steer_index *tmp_entry, *entry = NULL; struct mlx4_steer_index *tmp_entry, *entry = NULL;
struct mlx4_promisc_qp *dqp, *tmp_dqp; struct mlx4_promisc_qp *dqp, *tmp_dqp;
u8 pf_num;
pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); s_steer = &mlx4_priv(dev)->steer[0];
s_steer = &mlx4_priv(dev)->steer[pf_num];
/* if qp is not promisc, it cannot be duplicated */ /* if qp is not promisc, it cannot be duplicated */
if (!get_promisc_qp(dev, pf_num, steer, qpn)) if (!get_promisc_qp(dev, 0, steer, qpn))
return false; return false;
/* The qp is promisc qp so it is a duplicate on this index /* The qp is promisc qp so it is a duplicate on this index
...@@ -281,7 +293,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -281,7 +293,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
} }
/* I a steering entry contains only promisc QPs, it can be removed. */ /* I a steering entry contains only promisc QPs, it can be removed. */
static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
enum mlx4_steer_type steer, enum mlx4_steer_type steer,
unsigned int index, u32 tqpn) unsigned int index, u32 tqpn)
{ {
...@@ -293,10 +305,8 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -293,10 +305,8 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
u32 members_count; u32 members_count;
bool ret = false; bool ret = false;
int i; int i;
u8 pf_num;
pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); s_steer = &mlx4_priv(dev)->steer[0];
s_steer = &mlx4_priv(dev)->steer[pf_num];
mailbox = mlx4_alloc_cmd_mailbox(dev); mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox)) if (IS_ERR(mailbox))
...@@ -308,7 +318,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -308,7 +318,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
members_count = be32_to_cpu(mgm->members_count) & 0xffffff; members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
for (i = 0; i < members_count; i++) { for (i = 0; i < members_count; i++) {
qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK; qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
if (!get_promisc_qp(dev, pf_num, steer, qpn) && qpn != tqpn) { if (!get_promisc_qp(dev, 0, steer, qpn) && qpn != tqpn) {
/* the qp is not promisc, the entry can't be removed */ /* the qp is not promisc, the entry can't be removed */
goto out; goto out;
} }
...@@ -334,7 +344,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -334,7 +344,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
return ret; return ret;
} }
static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, static int add_promisc_qp(struct mlx4_dev *dev, u8 port,
enum mlx4_steer_type steer, u32 qpn) enum mlx4_steer_type steer, u32 qpn)
{ {
struct mlx4_steer *s_steer; struct mlx4_steer *s_steer;
...@@ -349,14 +359,13 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -349,14 +359,13 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port,
bool found; bool found;
int last_index; int last_index;
int err; int err;
u8 pf_num;
struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_priv *priv = mlx4_priv(dev);
pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
s_steer = &mlx4_priv(dev)->steer[pf_num]; s_steer = &mlx4_priv(dev)->steer[0];
mutex_lock(&priv->mcg_table.mutex); mutex_lock(&priv->mcg_table.mutex);
if (get_promisc_qp(dev, pf_num, steer, qpn)) { if (get_promisc_qp(dev, 0, steer, qpn)) {
err = 0; /* Noting to do, already exists */ err = 0; /* Noting to do, already exists */
goto out_mutex; goto out_mutex;
} }
...@@ -399,7 +408,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -399,7 +408,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port,
} }
if (!found) { if (!found) {
/* Need to add the qpn to mgm */ /* Need to add the qpn to mgm */
if (members_count == MLX4_QP_PER_MGM) { if (members_count == dev->caps.num_qp_per_mgm) {
/* entry is full */ /* entry is full */
err = -ENOMEM; err = -ENOMEM;
goto out_mailbox; goto out_mailbox;
...@@ -422,7 +431,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -422,7 +431,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port,
mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK); mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30); mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
err = mlx4_WRITE_PROMISC(dev, vep_num, port, steer, mailbox); err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox);
if (err) if (err)
goto out_list; goto out_list;
...@@ -441,7 +450,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -441,7 +450,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port,
return err; return err;
} }
static int remove_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
enum mlx4_steer_type steer, u32 qpn) enum mlx4_steer_type steer, u32 qpn)
{ {
struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_priv *priv = mlx4_priv(dev);
...@@ -456,13 +465,11 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -456,13 +465,11 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port,
bool back_to_list = false; bool back_to_list = false;
int loc, i; int loc, i;
int err; int err;
u8 pf_num;
pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); s_steer = &mlx4_priv(dev)->steer[0];
s_steer = &mlx4_priv(dev)->steer[pf_num];
mutex_lock(&priv->mcg_table.mutex); mutex_lock(&priv->mcg_table.mutex);
pqp = get_promisc_qp(dev, pf_num, steer, qpn); pqp = get_promisc_qp(dev, 0, steer, qpn);
if (unlikely(!pqp)) { if (unlikely(!pqp)) {
mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn); mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn);
/* nothing to do */ /* nothing to do */
...@@ -481,12 +488,13 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, ...@@ -481,12 +488,13 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port,
goto out_list; goto out_list;
} }
mgm = mailbox->buf; mgm = mailbox->buf;
memset(mgm, 0, sizeof *mgm);
members_count = 0; members_count = 0;
list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list) list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list)
mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK); mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30); mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
err = mlx4_WRITE_PROMISC(dev, vep_num, port, steer, mailbox); err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox);
if (err) if (err)
goto out_mailbox; goto out_mailbox;
...@@ -651,12 +659,13 @@ int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], ...@@ -651,12 +659,13 @@ int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
} }
index += dev->caps.num_mgms; index += dev->caps.num_mgms;
new_entry = 1;
memset(mgm, 0, sizeof *mgm); memset(mgm, 0, sizeof *mgm);
memcpy(mgm->gid, gid, 16); memcpy(mgm->gid, gid, 16);
} }
members_count = be32_to_cpu(mgm->members_count) & 0xffffff; members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
if (members_count == MLX4_QP_PER_MGM) { if (members_count == dev->caps.num_qp_per_mgm) {
mlx4_err(dev, "MGM at index %x is full.\n", index); mlx4_err(dev, "MGM at index %x is full.\n", index);
err = -ENOMEM; err = -ENOMEM;
goto out; goto out;
...@@ -698,9 +707,9 @@ int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], ...@@ -698,9 +707,9 @@ int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
if (prot == MLX4_PROT_ETH) { if (prot == MLX4_PROT_ETH) {
/* manage the steering entry for promisc mode */ /* manage the steering entry for promisc mode */
if (new_entry) if (new_entry)
new_steering_entry(dev, 0, port, steer, index, qp->qpn); new_steering_entry(dev, port, steer, index, qp->qpn);
else else
existing_steering_entry(dev, 0, port, steer, existing_steering_entry(dev, port, steer,
index, qp->qpn); index, qp->qpn);
} }
if (err && link && index != -1) { if (err && link && index != -1) {
...@@ -751,7 +760,7 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], ...@@ -751,7 +760,7 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
/* if this pq is also a promisc qp, it shouldn't be removed */ /* if this pq is also a promisc qp, it shouldn't be removed */
if (prot == MLX4_PROT_ETH && if (prot == MLX4_PROT_ETH &&
check_duplicate_entry(dev, 0, port, steer, index, qp->qpn)) check_duplicate_entry(dev, port, steer, index, qp->qpn))
goto out; goto out;
members_count = be32_to_cpu(mgm->members_count) & 0xffffff; members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
...@@ -771,7 +780,8 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], ...@@ -771,7 +780,8 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
mgm->qp[i - 1] = 0; mgm->qp[i - 1] = 0;
if (prot == MLX4_PROT_ETH) if (prot == MLX4_PROT_ETH)
removed_entry = can_remove_steering_entry(dev, 0, port, steer, index, qp->qpn); removed_entry = can_remove_steering_entry(dev, port, steer,
index, qp->qpn);
if (i != 1 && (prot != MLX4_PROT_ETH || !removed_entry)) { if (i != 1 && (prot != MLX4_PROT_ETH || !removed_entry)) {
err = mlx4_WRITE_ENTRY(dev, index, mailbox); err = mlx4_WRITE_ENTRY(dev, index, mailbox);
goto out; goto out;
...@@ -830,6 +840,34 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], ...@@ -830,6 +840,34 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
return err; return err;
} }
static int mlx4_QP_ATTACH(struct mlx4_dev *dev, struct mlx4_qp *qp,
u8 gid[16], u8 attach, u8 block_loopback,
enum mlx4_protocol prot)
{
struct mlx4_cmd_mailbox *mailbox;
int err = 0;
int qpn;
if (!mlx4_is_mfunc(dev))
return -EBADF;
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
memcpy(mailbox->buf, gid, 16);
qpn = qp->qpn;
qpn |= (prot << 28);
if (attach && block_loopback)
qpn |= (1 << 31);
err = mlx4_cmd(dev, mailbox->dma, qpn, attach,
MLX4_CMD_QP_ATTACH, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_WRAPPED);
mlx4_free_cmd_mailbox(dev, mailbox);
return err;
}
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 prot) int block_mcast_loopback, enum mlx4_protocol prot)
...@@ -845,9 +883,12 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], ...@@ -845,9 +883,12 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
if (prot == MLX4_PROT_ETH) if (prot == MLX4_PROT_ETH)
gid[7] |= (steer << 1); gid[7] |= (steer << 1);
return mlx4_qp_attach_common(dev, qp, gid, if (mlx4_is_mfunc(dev))
block_mcast_loopback, prot, return mlx4_QP_ATTACH(dev, qp, gid, 1,
steer); block_mcast_loopback, prot);
return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback,
prot, steer);
} }
EXPORT_SYMBOL_GPL(mlx4_multicast_attach); EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
...@@ -862,22 +903,90 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], ...@@ -862,22 +903,90 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
return 0; return 0;
if (prot == MLX4_PROT_ETH) { if (prot == MLX4_PROT_ETH)
gid[7] |= (steer << 1); gid[7] |= (steer << 1);
}
if (mlx4_is_mfunc(dev))
return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot);
return mlx4_qp_detach_common(dev, qp, gid, prot, steer); return mlx4_qp_detach_common(dev, qp, gid, prot, steer);
} }
EXPORT_SYMBOL_GPL(mlx4_multicast_detach); EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
static int mlx4_unicast_attach(struct mlx4_dev *dev,
struct mlx4_qp *qp, u8 gid[16],
int block_mcast_loopback, enum mlx4_protocol prot)
{
if (prot == MLX4_PROT_ETH &&
!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
return 0;
if (prot == MLX4_PROT_ETH)
gid[7] |= (MLX4_UC_STEER << 1);
if (mlx4_is_mfunc(dev))
return mlx4_QP_ATTACH(dev, qp, gid, 1,
block_mcast_loopback, prot);
return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback,
prot, MLX4_UC_STEER);
}
EXPORT_SYMBOL_GPL(mlx4_unicast_attach);
static int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp,
u8 gid[16], enum mlx4_protocol prot)
{
if (prot == MLX4_PROT_ETH &&
!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))
return 0;
if (prot == MLX4_PROT_ETH)
gid[7] |= (MLX4_UC_STEER << 1);
if (mlx4_is_mfunc(dev))
return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot);
return mlx4_qp_detach_common(dev, qp, gid, prot, MLX4_UC_STEER);
}
EXPORT_SYMBOL_GPL(mlx4_unicast_detach);
int mlx4_PROMISC_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
struct mlx4_cmd_mailbox *outbox,
struct mlx4_cmd_info *cmd)
{
u32 qpn = (u32) vhcr->in_param & 0xffffffff;
u8 port = vhcr->in_param >> 62;
enum mlx4_steer_type steer = vhcr->in_modifier;
/* Promiscuous unicast is not allowed in mfunc */
if (mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)
return 0;
if (vhcr->op_modifier)
return add_promisc_qp(dev, port, steer, qpn);
else
return remove_promisc_qp(dev, port, steer, qpn);
}
static int mlx4_PROMISC(struct mlx4_dev *dev, u32 qpn,
enum mlx4_steer_type steer, u8 add, u8 port)
{
return mlx4_cmd(dev, (u64) qpn | (u64) port << 62, (u32) steer, add,
MLX4_CMD_PROMISC, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_WRAPPED);
}
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)
{ {
if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
return 0; return 0;
if (mlx4_is_mfunc(dev))
return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 1, port);
return add_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn); return add_promisc_qp(dev, port, MLX4_MC_STEER, qpn);
} }
EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add); EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add);
...@@ -886,8 +995,10 @@ int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port) ...@@ -886,8 +995,10 @@ int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
return 0; return 0;
if (mlx4_is_mfunc(dev))
return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 0, port);
return remove_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn); return remove_promisc_qp(dev, port, MLX4_MC_STEER, qpn);
} }
EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove); EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);
...@@ -896,8 +1007,10 @@ int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port) ...@@ -896,8 +1007,10 @@ int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
return 0; return 0;
if (mlx4_is_mfunc(dev))
return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 1, port);
return add_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn); return add_promisc_qp(dev, port, MLX4_UC_STEER, qpn);
} }
EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add); EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);
...@@ -906,7 +1019,10 @@ int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port) ...@@ -906,7 +1019,10 @@ int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER))
return 0; return 0;
return remove_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn); if (mlx4_is_mfunc(dev))
return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 0, port);
return remove_promisc_qp(dev, port, MLX4_UC_STEER, qpn);
} }
EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_remove); EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_remove);
......
...@@ -61,9 +61,9 @@ enum { ...@@ -61,9 +61,9 @@ enum {
}; };
enum { enum {
MLX4_MGM_ENTRY_SIZE = 0x100, MLX4_MAX_MGM_ENTRY_SIZE = 0x1000,
MLX4_QP_PER_MGM = 4 * (MLX4_MGM_ENTRY_SIZE / 16 - 2), MLX4_MAX_QP_PER_MGM = 4 * (MLX4_MAX_MGM_ENTRY_SIZE / 16 - 2),
MLX4_MTT_ENTRY_PER_SEG = 8 MLX4_MTT_ENTRY_PER_SEG = 8,
}; };
enum { enum {
...@@ -190,6 +190,8 @@ do { \ ...@@ -190,6 +190,8 @@ do { \
#define mlx4_warn(mdev, format, arg...) \ #define mlx4_warn(mdev, format, arg...) \
dev_warn(&mdev->pdev->dev, format, ##arg) dev_warn(&mdev->pdev->dev, format, ##arg)
extern int mlx4_log_num_mgm_entry_size;
#define MLX4_MAX_NUM_SLAVES (MLX4_MAX_NUM_PF + MLX4_MAX_NUM_VF) #define MLX4_MAX_NUM_SLAVES (MLX4_MAX_NUM_PF + MLX4_MAX_NUM_VF)
#define ALL_SLAVES 0xff #define ALL_SLAVES 0xff
...@@ -417,9 +419,6 @@ struct mlx4_comm { ...@@ -417,9 +419,6 @@ struct mlx4_comm {
u32 slave_read; u32 slave_read;
}; };
#define MGM_QPN_MASK 0x00FFFFFF
#define MGM_BLCK_LB_BIT 30
#define VLAN_FLTR_SIZE 128 #define VLAN_FLTR_SIZE 128
struct mlx4_vlan_fltr { struct mlx4_vlan_fltr {
...@@ -437,14 +436,6 @@ struct mlx4_steer_index { ...@@ -437,14 +436,6 @@ struct mlx4_steer_index {
struct list_head duplicates; struct list_head duplicates;
}; };
struct mlx4_mgm {
__be32 next_gid_index;
__be32 members_count;
u32 reserved[2];
u8 gid[16];
__be32 qp[MLX4_QP_PER_MGM];
};
struct mlx4_slave_state { struct mlx4_slave_state {
u8 comm_toggle; u8 comm_toggle;
u8 last_cmd; u8 last_cmd;
...@@ -1021,6 +1012,9 @@ int mlx4_QUERY_IF_STAT_wrapper(struct mlx4_dev *dev, int slave, ...@@ -1021,6 +1012,9 @@ int mlx4_QUERY_IF_STAT_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);
int mlx4_get_mgm_entry_size(struct mlx4_dev *dev);
int mlx4_get_qp_per_mgm(struct mlx4_dev *dev);
static inline void set_param_l(u64 *arg, u32 val) static inline void set_param_l(u64 *arg, u32 val)
{ {
*((u32 *)arg) = val; *((u32 *)arg) = val;
......
...@@ -99,7 +99,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, ...@@ -99,7 +99,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
profile[MLX4_RES_DMPT].size = dev_cap->dmpt_entry_sz; profile[MLX4_RES_DMPT].size = dev_cap->dmpt_entry_sz;
profile[MLX4_RES_CMPT].size = dev_cap->cmpt_entry_sz; profile[MLX4_RES_CMPT].size = dev_cap->cmpt_entry_sz;
profile[MLX4_RES_MTT].size = dev->caps.mtts_per_seg * dev_cap->mtt_entry_sz; profile[MLX4_RES_MTT].size = dev->caps.mtts_per_seg * dev_cap->mtt_entry_sz;
profile[MLX4_RES_MCG].size = MLX4_MGM_ENTRY_SIZE; profile[MLX4_RES_MCG].size = mlx4_get_mgm_entry_size(dev);
profile[MLX4_RES_QP].num = request->num_qp; profile[MLX4_RES_QP].num = request->num_qp;
profile[MLX4_RES_RDMARC].num = request->num_qp * request->rdmarc_per_qp; profile[MLX4_RES_RDMARC].num = request->num_qp * request->rdmarc_per_qp;
...@@ -218,7 +218,8 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, ...@@ -218,7 +218,8 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
dev->caps.num_mgms = profile[i].num >> 1; dev->caps.num_mgms = profile[i].num >> 1;
dev->caps.num_amgms = 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 = ilog2(MLX4_MGM_ENTRY_SIZE); init_hca->log_mc_entry_sz =
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; init_hca->log_mc_hash_sz = profile[i].log_num - 1;
break; break;
......
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