Commit 4029685a authored by David S. Miller's avatar David S. Miller

Merge branch 'mlx4-next'

Or Gerlitz says:

====================
mlx4: Enable single ported VFs over IB ports

This series further enhances the support for mlx4 single ported VFs
introduced in 3.15 to work over IB ports too.

Just as quick reminder, the ConnectX3 device family exposes one PCI device
which serves both ports.

This can be non-optimal under virtualization schemes where the admin
would like the VF to expose one interface to the VM, etc.

Since all the VF interaction with the firmware passes through the PF
driver, we can emulate to the VF they have one port, and further create
a set of the VFs which act on port1 of the device and another set which
acts on port2.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 29044b58 be9b9eca
...@@ -189,7 +189,7 @@ void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev, ...@@ -189,7 +189,7 @@ void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev,
{ {
int i; int i;
u64 guid_indexes; u64 guid_indexes;
int slave_id; int slave_id, slave_port;
enum slave_port_state new_state; enum slave_port_state new_state;
enum slave_port_state prev_state; enum slave_port_state prev_state;
__be64 tmp_cur_ag, form_cache_ag; __be64 tmp_cur_ag, form_cache_ag;
...@@ -217,6 +217,11 @@ void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev, ...@@ -217,6 +217,11 @@ void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev,
slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ; slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
if (slave_id >= dev->dev->persist->num_vfs + 1) if (slave_id >= dev->dev->persist->num_vfs + 1)
return; return;
slave_port = mlx4_phys_to_slave_port(dev->dev, slave_id, port_num);
if (slave_port < 0) /* this port isn't available for the VF */
continue;
tmp_cur_ag = *(__be64 *)&p_data[i * GUID_REC_SIZE]; tmp_cur_ag = *(__be64 *)&p_data[i * GUID_REC_SIZE];
form_cache_ag = get_cached_alias_guid(dev, port_num, form_cache_ag = get_cached_alias_guid(dev, port_num,
(NUM_ALIAS_GUID_IN_REC * block_num) + i); (NUM_ALIAS_GUID_IN_REC * block_num) + i);
......
...@@ -1365,14 +1365,17 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc ...@@ -1365,14 +1365,17 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc
* stadard address handle by decoding the tunnelled mlx4_ah fields */ * stadard address handle by decoding the tunnelled mlx4_ah fields */
memcpy(&ah.av, &tunnel->hdr.av, sizeof (struct mlx4_av)); memcpy(&ah.av, &tunnel->hdr.av, sizeof (struct mlx4_av));
ah.ibah.device = ctx->ib_dev; ah.ibah.device = ctx->ib_dev;
port = be32_to_cpu(ah.av.ib.port_pd) >> 24;
port = mlx4_slave_convert_port(dev->dev, slave, port);
if (port < 0)
return;
ah.av.ib.port_pd = cpu_to_be32(port << 24 | (be32_to_cpu(ah.av.ib.port_pd) & 0xffffff));
mlx4_ib_query_ah(&ah.ibah, &ah_attr); mlx4_ib_query_ah(&ah.ibah, &ah_attr);
if (ah_attr.ah_flags & IB_AH_GRH) if (ah_attr.ah_flags & IB_AH_GRH)
fill_in_real_sgid_index(dev, slave, ctx->port, &ah_attr); fill_in_real_sgid_index(dev, slave, ctx->port, &ah_attr);
port = mlx4_slave_convert_port(dev->dev, slave, ah_attr.port_num);
if (port < 0)
return;
ah_attr.port_num = port;
memcpy(ah_attr.dmac, tunnel->hdr.mac, 6); memcpy(ah_attr.dmac, tunnel->hdr.mac, 6);
ah_attr.vlan_id = be16_to_cpu(tunnel->hdr.vlan); ah_attr.vlan_id = be16_to_cpu(tunnel->hdr.vlan);
/* if slave have default vlan use it */ /* if slave have default vlan use it */
......
...@@ -877,7 +877,7 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave, ...@@ -877,7 +877,7 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave,
{ {
struct ib_smp *smp = inbox->buf; struct ib_smp *smp = inbox->buf;
u32 index; u32 index;
u8 port; u8 port, slave_port;
u8 opcode_modifier; u8 opcode_modifier;
u16 *table; u16 *table;
int err; int err;
...@@ -889,7 +889,8 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave, ...@@ -889,7 +889,8 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave,
__be32 slave_cap_mask; __be32 slave_cap_mask;
__be64 slave_node_guid; __be64 slave_node_guid;
port = vhcr->in_modifier; slave_port = vhcr->in_modifier;
port = mlx4_slave_convert_port(dev, slave, slave_port);
/* network-view bit is for driver use only, and should not be passed to FW */ /* network-view bit is for driver use only, and should not be passed to FW */
opcode_modifier = vhcr->op_modifier & ~0x8; /* clear netw view bit */ opcode_modifier = vhcr->op_modifier & ~0x8; /* clear netw view bit */
...@@ -925,8 +926,9 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave, ...@@ -925,8 +926,9 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave,
if (smp->attr_id == IB_SMP_ATTR_PORT_INFO) { if (smp->attr_id == IB_SMP_ATTR_PORT_INFO) {
/*get the slave specific caps:*/ /*get the slave specific caps:*/
/*do the command */ /*do the command */
smp->attr_mod = cpu_to_be32(port);
err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, err = mlx4_cmd_box(dev, inbox->dma, outbox->dma,
vhcr->in_modifier, opcode_modifier, port, opcode_modifier,
vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE); vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
/* modify the response for slaves */ /* modify the response for slaves */
if (!err && slave != mlx4_master_func_num(dev)) { if (!err && slave != mlx4_master_func_num(dev)) {
...@@ -970,7 +972,7 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave, ...@@ -970,7 +972,7 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave,
} }
if (smp->attr_id == IB_SMP_ATTR_NODE_INFO) { if (smp->attr_id == IB_SMP_ATTR_NODE_INFO) {
err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, err = mlx4_cmd_box(dev, inbox->dma, outbox->dma,
vhcr->in_modifier, opcode_modifier, port, opcode_modifier,
vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE); vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
if (!err) { if (!err) {
slave_node_guid = mlx4_get_slave_node_guid(dev, slave); slave_node_guid = mlx4_get_slave_node_guid(dev, slave);
...@@ -3192,6 +3194,12 @@ int mlx4_vf_set_enable_smi_admin(struct mlx4_dev *dev, int slave, int port, ...@@ -3192,6 +3194,12 @@ int mlx4_vf_set_enable_smi_admin(struct mlx4_dev *dev, int slave, int port,
int enabled) int enabled)
{ {
struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_active_ports actv_ports = mlx4_get_active_ports(
&priv->dev, slave);
int min_port = find_first_bit(actv_ports.ports,
priv->dev.caps.num_ports) + 1;
int max_port = min_port - 1 +
bitmap_weight(actv_ports.ports, priv->dev.caps.num_ports);
if (slave == mlx4_master_func_num(dev)) if (slave == mlx4_master_func_num(dev))
return 0; return 0;
...@@ -3201,6 +3209,11 @@ int mlx4_vf_set_enable_smi_admin(struct mlx4_dev *dev, int slave, int port, ...@@ -3201,6 +3209,11 @@ int mlx4_vf_set_enable_smi_admin(struct mlx4_dev *dev, int slave, int port,
enabled < 0 || enabled > 1) enabled < 0 || enabled > 1)
return -EINVAL; return -EINVAL;
if (min_port == max_port && dev->caps.num_ports > 1) {
mlx4_info(dev, "SMI access disallowed for single ported VFs\n");
return -EPROTONOSUPPORT;
}
priv->mfunc.master.vf_admin[slave].enable_smi[port] = enabled; priv->mfunc.master.vf_admin[slave].enable_smi[port] = enabled;
return 0; return 0;
} }
......
...@@ -145,7 +145,7 @@ void mlx4_gen_slave_eqe(struct work_struct *work) ...@@ -145,7 +145,7 @@ void mlx4_gen_slave_eqe(struct work_struct *work)
struct mlx4_slave_event_eq *slave_eq = &mfunc->master.slave_eq; struct mlx4_slave_event_eq *slave_eq = &mfunc->master.slave_eq;
struct mlx4_eqe *eqe; struct mlx4_eqe *eqe;
u8 slave; u8 slave;
int i; int i, phys_port, slave_port;
for (eqe = next_slave_event_eqe(slave_eq); eqe; for (eqe = next_slave_event_eqe(slave_eq); eqe;
eqe = next_slave_event_eqe(slave_eq)) { eqe = next_slave_event_eqe(slave_eq)) {
...@@ -154,9 +154,20 @@ void mlx4_gen_slave_eqe(struct work_struct *work) ...@@ -154,9 +154,20 @@ void mlx4_gen_slave_eqe(struct work_struct *work)
/* All active slaves need to receive the event */ /* All active slaves need to receive the event */
if (slave == ALL_SLAVES) { if (slave == ALL_SLAVES) {
for (i = 0; i <= dev->persist->num_vfs; i++) { for (i = 0; i <= dev->persist->num_vfs; i++) {
phys_port = 0;
if (eqe->type == MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT &&
eqe->subtype == MLX4_DEV_PMC_SUBTYPE_PORT_INFO) {
phys_port = eqe->event.port_mgmt_change.port;
slave_port = mlx4_phys_to_slave_port(dev, i, phys_port);
if (slave_port < 0) /* VF doesn't have this port */
continue;
eqe->event.port_mgmt_change.port = slave_port;
}
if (mlx4_GEN_EQE(dev, i, eqe)) if (mlx4_GEN_EQE(dev, i, eqe))
mlx4_warn(dev, "Failed to generate event for slave %d\n", mlx4_warn(dev, "Failed to generate event for slave %d\n",
i); i);
if (phys_port)
eqe->event.port_mgmt_change.port = phys_port;
} }
} else { } else {
if (mlx4_GEN_EQE(dev, slave, eqe)) if (mlx4_GEN_EQE(dev, slave, eqe))
...@@ -224,7 +235,7 @@ int mlx4_gen_pkey_eqe(struct mlx4_dev *dev, int slave, u8 port) ...@@ -224,7 +235,7 @@ int mlx4_gen_pkey_eqe(struct mlx4_dev *dev, int slave, u8 port)
eqe.type = MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT; eqe.type = MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT;
eqe.subtype = MLX4_DEV_PMC_SUBTYPE_PKEY_TABLE; eqe.subtype = MLX4_DEV_PMC_SUBTYPE_PKEY_TABLE;
eqe.event.port_mgmt_change.port = port; eqe.event.port_mgmt_change.port = mlx4_phys_to_slave_port(dev, slave, port);
return mlx4_GEN_EQE(dev, slave, &eqe); return mlx4_GEN_EQE(dev, slave, &eqe);
} }
...@@ -241,7 +252,7 @@ int mlx4_gen_guid_change_eqe(struct mlx4_dev *dev, int slave, u8 port) ...@@ -241,7 +252,7 @@ int mlx4_gen_guid_change_eqe(struct mlx4_dev *dev, int slave, u8 port)
eqe.type = MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT; eqe.type = MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT;
eqe.subtype = MLX4_DEV_PMC_SUBTYPE_GUID_INFO; eqe.subtype = MLX4_DEV_PMC_SUBTYPE_GUID_INFO;
eqe.event.port_mgmt_change.port = port; eqe.event.port_mgmt_change.port = mlx4_phys_to_slave_port(dev, slave, port);
return mlx4_GEN_EQE(dev, slave, &eqe); return mlx4_GEN_EQE(dev, slave, &eqe);
} }
...@@ -251,6 +262,7 @@ int mlx4_gen_port_state_change_eqe(struct mlx4_dev *dev, int slave, u8 port, ...@@ -251,6 +262,7 @@ int mlx4_gen_port_state_change_eqe(struct mlx4_dev *dev, int slave, u8 port,
u8 port_subtype_change) u8 port_subtype_change)
{ {
struct mlx4_eqe eqe; struct mlx4_eqe eqe;
u8 slave_port = mlx4_phys_to_slave_port(dev, slave, port);
/*don't send if we don't have the that slave */ /*don't send if we don't have the that slave */
if (dev->persist->num_vfs < slave) if (dev->persist->num_vfs < slave)
...@@ -259,7 +271,7 @@ int mlx4_gen_port_state_change_eqe(struct mlx4_dev *dev, int slave, u8 port, ...@@ -259,7 +271,7 @@ int mlx4_gen_port_state_change_eqe(struct mlx4_dev *dev, int slave, u8 port,
eqe.type = MLX4_EVENT_TYPE_PORT_CHANGE; eqe.type = MLX4_EVENT_TYPE_PORT_CHANGE;
eqe.subtype = port_subtype_change; eqe.subtype = port_subtype_change;
eqe.event.port_change.port = cpu_to_be32(port << 28); eqe.event.port_change.port = cpu_to_be32(slave_port << 28);
mlx4_dbg(dev, "%s: sending: %d to slave: %d on port: %d\n", __func__, mlx4_dbg(dev, "%s: sending: %d to slave: %d on port: %d\n", __func__,
port_subtype_change, slave, port); port_subtype_change, slave, port);
...@@ -589,6 +601,10 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) ...@@ -589,6 +601,10 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
if (SLAVE_PORT_GEN_EVENT_DOWN == gen_event) { if (SLAVE_PORT_GEN_EVENT_DOWN == gen_event) {
if (i == mlx4_master_func_num(dev)) if (i == mlx4_master_func_num(dev))
continue; continue;
eqe->event.port_change.port =
cpu_to_be32(
(be32_to_cpu(eqe->event.port_change.port) & 0xFFFFFFF)
| (mlx4_phys_to_slave_port(dev, i, port) << 28));
mlx4_slave_event(dev, i, eqe); mlx4_slave_event(dev, i, eqe);
} }
} }
......
...@@ -2988,18 +2988,6 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, ...@@ -2988,18 +2988,6 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data,
/* In master functions, the communication channel must be initialized /* In master functions, the communication channel must be initialized
* after obtaining its address from fw */ * after obtaining its address from fw */
if (mlx4_is_master(dev)) { if (mlx4_is_master(dev)) {
int ib_ports = 0;
mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
ib_ports++;
if (ib_ports &&
(num_vfs_argc > 1 || probe_vfs_argc > 1)) {
mlx4_err(dev,
"Invalid syntax of num_vfs/probe_vfs with IB port - single port VFs syntax is only supported when all ports are configured as ethernet\n");
err = -EINVAL;
goto err_close;
}
if (dev->caps.num_ports < 2 && if (dev->caps.num_ports < 2 &&
num_vfs_argc > 1) { num_vfs_argc > 1) {
err = -EINVAL; err = -EINVAL;
......
...@@ -2703,6 +2703,10 @@ static void adjust_proxy_tun_qkey(struct mlx4_dev *dev, struct mlx4_vhcr *vhcr, ...@@ -2703,6 +2703,10 @@ static void adjust_proxy_tun_qkey(struct mlx4_dev *dev, struct mlx4_vhcr *vhcr,
context->qkey = cpu_to_be32(qkey); context->qkey = cpu_to_be32(qkey);
} }
static int adjust_qp_sched_queue(struct mlx4_dev *dev, int slave,
struct mlx4_qp_context *qpc,
struct mlx4_cmd_mailbox *inbox);
int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave, int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr, struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox, struct mlx4_cmd_mailbox *inbox,
...@@ -2725,6 +2729,10 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave, ...@@ -2725,6 +2729,10 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
struct res_srq *srq; struct res_srq *srq;
int local_qpn = be32_to_cpu(qpc->local_qpn) & 0xffffff; int local_qpn = be32_to_cpu(qpc->local_qpn) & 0xffffff;
err = adjust_qp_sched_queue(dev, slave, qpc, inbox);
if (err)
return err;
err = qp_res_start_move_to(dev, slave, qpn, RES_QP_HW, &qp, 0); err = qp_res_start_move_to(dev, slave, qpn, RES_QP_HW, &qp, 0);
if (err) if (err)
return err; return err;
...@@ -3526,8 +3534,8 @@ static int adjust_qp_sched_queue(struct mlx4_dev *dev, int slave, ...@@ -3526,8 +3534,8 @@ static int adjust_qp_sched_queue(struct mlx4_dev *dev, int slave,
pri_sched_queue = (qpc->pri_path.sched_queue & ~(1 << 6)) | pri_sched_queue = (qpc->pri_path.sched_queue & ~(1 << 6)) |
((port & 1) << 6); ((port & 1) << 6);
if (optpar & MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH || if (optpar & (MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH | MLX4_QP_OPTPAR_SCHED_QUEUE) ||
mlx4_is_eth(dev, port + 1)) { qpc->pri_path.sched_queue || mlx4_is_eth(dev, port + 1)) {
qpc->pri_path.sched_queue = pri_sched_queue; qpc->pri_path.sched_queue = pri_sched_queue;
} }
......
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