In devices with multiple physical functions, each function activates only one port, according to the function number. Even functions activate port 1, odd functions activate port2. For every virtual function we query the FW to which physical function it belongs, as all the functions are served by the master function.
Signed-off-by: Yevgeny Petrilin <[email protected]> --- drivers/net/mlx4/cmd.c | 8 ++++++++ drivers/net/mlx4/fw.c | 36 ++++++++++++++++++++++++++++++++++-- drivers/net/mlx4/fw.h | 1 + drivers/net/mlx4/main.c | 19 ++++++++++++------- drivers/net/mlx4/mlx4.h | 3 +++ drivers/net/mlx4/port.c | 9 +++++---- include/linux/mlx4/cmd.h | 1 + include/linux/mlx4/device.h | 6 +++--- 8 files changed, 67 insertions(+), 16 deletions(-) diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c index a4722e2..b25e40e 100644 --- a/drivers/net/mlx4/cmd.c +++ b/drivers/net/mlx4/cmd.c @@ -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) && diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c index d1427e5..55377c0 100644 --- a/drivers/net/mlx4/fw.c +++ b/drivers/net/mlx4/fw.c @@ -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; +} diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h index a9d7e55..9fd15f1 100644 --- a/drivers/net/mlx4/fw.h +++ b/drivers/net/mlx4/fw.h @@ -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 */ diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 9dca6f4..e670aa0 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c @@ -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"); diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index 351956d..1a37f63 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h @@ -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); diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c index dcbfd72..902bd94 100644 --- a/drivers/net/mlx4/port.c +++ b/drivers/net/mlx4/port.c @@ -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; } diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h index b8a2079..01a1873 100644 --- a/include/linux/mlx4/cmd.h +++ b/include/linux/mlx4/cmd.h @@ -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, diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index c543210..0765845 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -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) { -- 1.6.0.2 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
