@@ -423,9 +423,11 @@ static int mlx4_RESOURCE_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vh
struct mlx4_cmd_mailbox *inbox,
struct mlx4_cmd_mailbox *outbox)
{
+ struct mlx4_priv *priv = mlx4_priv(dev);
u32 param1 = *((u32 *) &vhcr->in_param);
u32 param2 = *(((u32 *) &vhcr->in_param) + 1);
int ret;
+ u8 pf_num = priv->mfunc.master.slave_state[slave].pf_num;
#if 0
char *res[] = {"QP", "CQ", "SRQ", "MPT", "MTT"};
@@ -508,6 +510,7 @@ static int mlx4_RESOURCE_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vh
mlx4_free_mtt_range(dev, param1 /* first */, param2 /* order */);
break;
case RES_MAC:
+ vhcr->in_param |= (u64) (pf_num) << 48;
switch (vhcr->op) {
case MLX4_CMD_ALLOC_RES:
ret = mlx4_register_mac(dev, vhcr->op_modifier,
@@ -1096,6 +1099,11 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, u16 para
if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR2)
goto reset_slave;
slave_state[slave].vhcr_dma |= param;
+ if (mlx4_QUERY_FUNC(dev, slave, &slave_state[slave].pf_num)) {
+ mlx4_err(dev, "Failed to determine physical function "
+ "number for slave %d\n", slave);
+ goto reset_slave;
+ }
break;
case MLX4_COMM_CMD_VHCR_POST:
if ((slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_EN) &&
@@ -152,9 +152,13 @@ int mlx4_QUERY_SLAVE_CAP_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vh
memcpy(caps, &dev->caps, sizeof *caps);
+ /* Ports are activated according to physical function number */
+ mlx4_set_port_mask(dev, caps, slave);
+
/* PDs have the same range in every guest; the distinction is in the msbs,
* which contains the guest ID (vf + 1) */
caps->pd_base = slave + 1;
+ caps->function = slave;
/* All other resources are allocated by the master, but we still report
* 'num' and 'reserved' capabilities as follows:
@@ -596,6 +600,7 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
#define QUERY_FW_OUT_SIZE 0x100
#define QUERY_FW_VER_OFFSET 0x00
+#define QUERY_FW_PPF_ID 0x09
#define QUERY_FW_CMD_IF_REV_OFFSET 0x0a
#define QUERY_FW_MAX_CMD_OFFSET 0x0f
#define QUERY_FW_ERR_START_OFFSET 0x30
@@ -628,6 +633,9 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
((fw_ver & 0xffff0000ull) >> 16) |
((fw_ver & 0x0000ffffull) << 16);
+ MLX4_GET(lg, outbox, QUERY_FW_PPF_ID);
+ dev->caps.function = lg;
+
MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET);
if (cmd_if_rev < MLX4_COMMAND_INTERFACE_MIN_REV ||
cmd_if_rev > MLX4_COMMAND_INTERFACE_MAX_REV) {
@@ -938,7 +946,8 @@ int mlx4_INIT_PORT(struct mlx4_dev *dev, int port)
mlx4_free_cmd_mailbox(dev, mailbox);
} else {
if (mlx4_is_master(dev))
- err = mlx4_common_init_port(dev, 0, port);
+ err = mlx4_common_init_port(dev, dev->caps.function,
+ port);
else
err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
MLX4_CMD_TIME_CLASS_A);
@@ -978,7 +987,7 @@ int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *v
int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port)
{
if (mlx4_is_master(dev))
- return mlx4_common_close_port(dev, 0, port);
+ return mlx4_common_close_port(dev, dev->caps.function, port);
else
return mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 1000);
}
@@ -1012,3 +1021,26 @@ int mlx4_NOP(struct mlx4_dev *dev)
/* Input modifier of 0x1f means "finish as soon as possible." */
return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100);
}
+
+int mlx4_QUERY_FUNC(struct mlx4_dev *dev, int func, u8 *pf_num)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ u8 *outbox;
+ int ret;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+ outbox = mailbox->buf;
+
+ ret = mlx4_cmd_box(dev, 0, mailbox->dma, func & 0xff, 0,
+ MLX4_CMD_QUERY_FUNC, MLX4_CMD_TIME_CLASS_A);
+ if (ret)
+ goto out;
+
+ *pf_num = outbox[3];
+
+out:
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return ret;
+}
@@ -178,5 +178,6 @@ int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm);
int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev);
int mlx4_NOP(struct mlx4_dev *dev);
int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg);
+int mlx4_QUERY_FUNC(struct mlx4_dev *dev, int func, u8 *pf_num);
#endif /* MLX4_FW_H */
@@ -150,15 +150,18 @@ int mlx4_check_port_params(struct mlx4_dev *dev,
return 0;
}
-static void mlx4_set_port_mask(struct mlx4_dev *dev)
+void mlx4_set_port_mask(struct mlx4_dev *dev, struct mlx4_caps *caps, int function)
{
int i;
+ int active = (function & 1) + 1;
- dev->caps.port_mask = 0;
- for (i = 1; i <= dev->caps.num_ports; ++i)
- if (dev->caps.port_type[i] == MLX4_PORT_TYPE_IB)
- dev->caps.port_mask |= 1 << (i - 1);
+ for (i = 1; i <= caps->num_ports; ++i) {
+ caps->port_mask[i] = caps->port_type[i];
+ if (dev->caps.pf_num > 1 && i != active)
+ caps->port_mask[i] = 0;
+ }
}
+
static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
{
int err;
@@ -271,7 +274,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
}
}
- mlx4_set_port_mask(dev);
+ mlx4_set_port_mask(dev, &dev->caps, dev->caps.function);
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] = dev_cap->reserved_qps;
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] =
@@ -382,7 +385,7 @@ int mlx4_change_port_types(struct mlx4_dev *dev,
goto out;
}
}
- mlx4_set_port_mask(dev);
+ mlx4_set_port_mask(dev, &dev->caps, dev->caps.function);
err = mlx4_register_device(dev);
}
@@ -922,6 +925,8 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
}
}
+ mlx4_set_port_mask(dev, &dev->caps, dev->caps.function);
+
err = mlx4_QUERY_ADAPTER(dev, &adapter);
if (err) {
mlx4_err(dev, "QUERY_ADAPTER command failed, aborting.\n");
@@ -228,6 +228,8 @@ struct mlx4_slave_state {
u8 comm_toggle;
u8 last_cmd;
u8 init_port_mask;
+ u8 pf_num;
+ u8 function;
dma_addr_t vhcr_dma;
u16 mtu[MLX4_MAX_PORTS + 1];
__be32 ib_cap_mask[MLX4_MAX_PORTS + 1];
@@ -528,6 +530,7 @@ int mlx4_check_port_params(struct mlx4_dev *dev,
enum mlx4_port_type *port_type);
int mlx4_change_port_types(struct mlx4_dev *dev,
enum mlx4_port_type *port_types);
+void mlx4_set_port_mask(struct mlx4_dev *dev, struct mlx4_caps *caps, int function);
void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table);
void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
@@ -39,7 +39,7 @@
#include "en_port.h"
#define MLX4_MAC_VALID (1ull << 63)
-#define MLX4_MAC_MASK 0xffffffffffffULL
+#define MLX4_MAC_MASK 0x7fffffffffffffffULL
#define MLX4_VLAN_VALID (1u << 31)
#define MLX4_VLAN_MASK 0xfff
@@ -103,18 +103,19 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn)
if (!err)
*qpn = out_param;
return err;
- }
+ } else
+ mac |= (u64) (dev->caps.function) << 48;
mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac);
mutex_lock(&table->mutex);
- for (i = 0; i < MLX4_MAX_MAC_NUM - 1; i++) {
+ for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
if (free < 0 && !table->entries[i]) {
free = i;
continue;
}
if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
- /* MAC already registered, Must not have duplicates */
+ /* MAC + PF already registered, Must not have duplicates */
err = -EEXIST;
goto out;
}
@@ -57,6 +57,7 @@ enum {
MLX4_CMD_QUERY_PORT = 0x43,
MLX4_CMD_SENSE_PORT = 0x4d,
MLX4_CMD_SET_PORT = 0xc,
+ MLX4_CMD_QUERY_FUNC = 0x56,
MLX4_CMD_ACCESS_DDR = 0x2e,
MLX4_CMD_MAP_ICM = 0xffa,
MLX4_CMD_UNMAP_ICM = 0xff9,
@@ -183,6 +183,7 @@ static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor)
struct mlx4_caps {
u64 fw_ver;
+ int function;
int pf_num;
int num_ports;
int vl_cap[MLX4_MAX_PORTS + 1];
@@ -249,7 +250,7 @@ struct mlx4_caps {
int log_num_prios;
enum mlx4_port_type port_type[MLX4_MAX_PORTS + 1];
u8 supported_type[MLX4_MAX_PORTS + 1];
- u32 port_mask;
+ enum mlx4_port_type port_mask[MLX4_MAX_PORTS + 1];
enum mlx4_port_type possible_type[MLX4_MAX_PORTS + 1];
};
@@ -409,8 +410,7 @@ struct mlx4_init_port_param {
#define mlx4_foreach_port(port, dev, type) \
for ((port) = 1; (port) <= (dev)->caps.num_ports; (port)++) \
- if (((type) == MLX4_PORT_TYPE_IB ? (dev)->caps.port_mask : \
- ~(dev)->caps.port_mask) & 1 << ((port) - 1))
+ if ((type) == (dev)->caps.port_mask[(port)])
static inline int mlx4_is_slave(struct mlx4_dev *dev)
{