Commit 32f69e4b authored by Daniel Jurgens's avatar Daniel Jurgens Committed by Jason Gunthorpe

{net, IB}/mlx5: Manage port association for multiport RoCE

When mlx5_ib_add is called determine if the mlx5 core device being
added is capable of dual port RoCE operation. If it is, determine
whether it is a master device or a slave device using the
num_vhca_ports and affiliate_nic_vport_criteria capabilities.

If the device is a slave, attempt to find a master device to affiliate it
with. Devices that can be affiliated will share a system image guid. If
none are found place it on a list of unaffiliated ports. If a master is
found bind the port to it by configuring the port affiliation in the NIC
vport context.

Similarly when mlx5_ib_remove is called determine the port type. If it's
a slave port, unaffiliate it from the master device, otherwise just
remove it from the unaffiliated port list.

The IB device is registered as a multiport device, even if a 2nd port is
not available for affiliation. When the 2nd port is affiliated later the
GID cache must be refreshed in order to get the default GIDs for the 2nd
port in the cache. Export roce_rescan_device to provide a mechanism to
refresh the cache after a new port is bound.

In a multiport configuration all IB object (QP, MR, PD, etc) related
commands should flow through the master mlx5_core_dev, other commands
must be sent to the slave port mlx5_core_mdev, an interface is provide
to get the correct mdev for non IB object commands.
Signed-off-by: default avatarDaniel Jurgens <danielj@mellanox.com>
Reviewed-by: default avatarParav Pandit <parav@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 7fd8aefb
...@@ -821,7 +821,7 @@ static int gid_table_setup_one(struct ib_device *ib_dev) ...@@ -821,7 +821,7 @@ static int gid_table_setup_one(struct ib_device *ib_dev)
if (err) if (err)
return err; return err;
roce_rescan_device(ib_dev); rdma_roce_rescan_device(ib_dev);
return err; return err;
} }
......
...@@ -137,7 +137,6 @@ int ib_cache_gid_del_all_netdev_gids(struct ib_device *ib_dev, u8 port, ...@@ -137,7 +137,6 @@ int ib_cache_gid_del_all_netdev_gids(struct ib_device *ib_dev, u8 port,
int roce_gid_mgmt_init(void); int roce_gid_mgmt_init(void);
void roce_gid_mgmt_cleanup(void); void roce_gid_mgmt_cleanup(void);
void roce_rescan_device(struct ib_device *ib_dev);
unsigned long roce_gid_type_mask_support(struct ib_device *ib_dev, u8 port); unsigned long roce_gid_type_mask_support(struct ib_device *ib_dev, u8 port);
int ib_cache_setup_one(struct ib_device *device); int ib_cache_setup_one(struct ib_device *device);
......
...@@ -410,13 +410,18 @@ static void enum_all_gids_of_dev_cb(struct ib_device *ib_dev, ...@@ -410,13 +410,18 @@ static void enum_all_gids_of_dev_cb(struct ib_device *ib_dev,
rtnl_unlock(); rtnl_unlock();
} }
/* This function will rescan all of the network devices in the system /**
* and add their gids, as needed, to the relevant RoCE devices. */ * rdma_roce_rescan_device - Rescan all of the network devices in the system
void roce_rescan_device(struct ib_device *ib_dev) * and add their gids, as needed, to the relevant RoCE devices.
*
* @device: the rdma device
*/
void rdma_roce_rescan_device(struct ib_device *ib_dev)
{ {
ib_enum_roce_netdev(ib_dev, pass_all_filter, NULL, ib_enum_roce_netdev(ib_dev, pass_all_filter, NULL,
enum_all_gids_of_dev_cb, NULL); enum_all_gids_of_dev_cb, NULL);
} }
EXPORT_SYMBOL(rdma_roce_rescan_device);
static void callback_for_addr_gid_device_scan(struct ib_device *device, static void callback_for_addr_gid_device_scan(struct ib_device *device,
u8 port, u8 port,
......
This diff is collapsed.
...@@ -654,8 +654,17 @@ struct mlx5_ib_counters { ...@@ -654,8 +654,17 @@ struct mlx5_ib_counters {
u16 set_id; u16 set_id;
}; };
struct mlx5_ib_multiport_info;
struct mlx5_ib_multiport {
struct mlx5_ib_multiport_info *mpi;
/* To be held when accessing the multiport info */
spinlock_t mpi_lock;
};
struct mlx5_ib_port { struct mlx5_ib_port {
struct mlx5_ib_counters cnts; struct mlx5_ib_counters cnts;
struct mlx5_ib_multiport mp;
}; };
struct mlx5_roce { struct mlx5_roce {
...@@ -756,6 +765,17 @@ struct mlx5_ib_profile { ...@@ -756,6 +765,17 @@ struct mlx5_ib_profile {
struct mlx5_ib_stage stage[MLX5_IB_STAGE_MAX]; struct mlx5_ib_stage stage[MLX5_IB_STAGE_MAX];
}; };
struct mlx5_ib_multiport_info {
struct list_head list;
struct mlx5_ib_dev *ibdev;
struct mlx5_core_dev *mdev;
struct completion unref_comp;
u64 sys_image_guid;
u32 mdev_refcnt;
bool is_master;
bool unaffiliate;
};
struct mlx5_ib_dev { struct mlx5_ib_dev {
struct ib_device ib_dev; struct ib_device ib_dev;
struct mlx5_core_dev *mdev; struct mlx5_core_dev *mdev;
...@@ -800,6 +820,8 @@ struct mlx5_ib_dev { ...@@ -800,6 +820,8 @@ struct mlx5_ib_dev {
struct mutex lb_mutex; struct mutex lb_mutex;
u32 user_td; u32 user_td;
u8 umr_fence; u8 umr_fence;
struct list_head ib_dev_list;
u64 sys_image_guid;
}; };
static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq) static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq)
...@@ -1071,6 +1093,12 @@ int mlx5_ib_generate_wc(struct ib_cq *ibcq, struct ib_wc *wc); ...@@ -1071,6 +1093,12 @@ int mlx5_ib_generate_wc(struct ib_cq *ibcq, struct ib_wc *wc);
void mlx5_ib_free_bfreg(struct mlx5_ib_dev *dev, struct mlx5_bfreg_info *bfregi, void mlx5_ib_free_bfreg(struct mlx5_ib_dev *dev, struct mlx5_bfreg_info *bfregi,
int bfregn); int bfregn);
struct mlx5_ib_dev *mlx5_ib_get_ibdev_from_mpi(struct mlx5_ib_multiport_info *mpi);
struct mlx5_core_dev *mlx5_ib_get_native_port_mdev(struct mlx5_ib_dev *dev,
u8 ib_port_num,
u8 *native_port_num);
void mlx5_ib_put_native_port_mdev(struct mlx5_ib_dev *dev,
u8 port_num);
static inline void init_query_mad(struct ib_smp *mad) static inline void init_query_mad(struct ib_smp *mad)
{ {
......
...@@ -688,7 +688,7 @@ static inline int mlx5_fpga_conn_init_qp(struct mlx5_fpga_conn *conn) ...@@ -688,7 +688,7 @@ static inline int mlx5_fpga_conn_init_qp(struct mlx5_fpga_conn *conn)
MLX5_SET(qpc, qpc, st, MLX5_QP_ST_RC); MLX5_SET(qpc, qpc, st, MLX5_QP_ST_RC);
MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED); MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED);
MLX5_SET(qpc, qpc, primary_address_path.pkey_index, MLX5_FPGA_PKEY_INDEX); MLX5_SET(qpc, qpc, primary_address_path.pkey_index, MLX5_FPGA_PKEY_INDEX);
MLX5_SET(qpc, qpc, primary_address_path.port, MLX5_FPGA_PORT_NUM); MLX5_SET(qpc, qpc, primary_address_path.vhca_port_num, MLX5_FPGA_PORT_NUM);
MLX5_SET(qpc, qpc, pd, conn->fdev->conn_res.pdn); MLX5_SET(qpc, qpc, pd, conn->fdev->conn_res.pdn);
MLX5_SET(qpc, qpc, cqn_snd, conn->cq.mcq.cqn); MLX5_SET(qpc, qpc, cqn_snd, conn->cq.mcq.cqn);
MLX5_SET(qpc, qpc, cqn_rcv, conn->cq.mcq.cqn); MLX5_SET(qpc, qpc, cqn_rcv, conn->cq.mcq.cqn);
...@@ -727,7 +727,7 @@ static inline int mlx5_fpga_conn_rtr_qp(struct mlx5_fpga_conn *conn) ...@@ -727,7 +727,7 @@ static inline int mlx5_fpga_conn_rtr_qp(struct mlx5_fpga_conn *conn)
MLX5_SET(qpc, qpc, next_rcv_psn, MLX5_SET(qpc, qpc, next_rcv_psn,
MLX5_GET(fpga_qpc, conn->fpga_qpc, next_send_psn)); MLX5_GET(fpga_qpc, conn->fpga_qpc, next_send_psn));
MLX5_SET(qpc, qpc, primary_address_path.pkey_index, MLX5_FPGA_PKEY_INDEX); MLX5_SET(qpc, qpc, primary_address_path.pkey_index, MLX5_FPGA_PKEY_INDEX);
MLX5_SET(qpc, qpc, primary_address_path.port, MLX5_FPGA_PORT_NUM); MLX5_SET(qpc, qpc, primary_address_path.vhca_port_num, MLX5_FPGA_PORT_NUM);
ether_addr_copy(MLX5_ADDR_OF(qpc, qpc, primary_address_path.rmac_47_32), ether_addr_copy(MLX5_ADDR_OF(qpc, qpc, primary_address_path.rmac_47_32),
MLX5_ADDR_OF(fpga_qpc, conn->fpga_qpc, fpga_mac_47_32)); MLX5_ADDR_OF(fpga_qpc, conn->fpga_qpc, fpga_mac_47_32));
MLX5_SET(qpc, qpc, primary_address_path.udp_sport, MLX5_SET(qpc, qpc, primary_address_path.udp_sport,
......
...@@ -187,7 +187,7 @@ int mlx5i_create_underlay_qp(struct mlx5_core_dev *mdev, struct mlx5_core_qp *qp ...@@ -187,7 +187,7 @@ int mlx5i_create_underlay_qp(struct mlx5_core_dev *mdev, struct mlx5_core_qp *qp
MLX5_QP_ENHANCED_ULP_STATELESS_MODE); MLX5_QP_ENHANCED_ULP_STATELESS_MODE);
addr_path = MLX5_ADDR_OF(qpc, qpc, primary_address_path); addr_path = MLX5_ADDR_OF(qpc, qpc, primary_address_path);
MLX5_SET(ads, addr_path, port, 1); MLX5_SET(ads, addr_path, vhca_port_num, 1);
MLX5_SET(ads, addr_path, grh, 1); MLX5_SET(ads, addr_path, grh, 1);
ret = mlx5_core_create_qp(mdev, qp, in, inlen); ret = mlx5_core_create_qp(mdev, qp, in, inlen);
......
...@@ -1121,3 +1121,61 @@ int mlx5_core_modify_hca_vport_context(struct mlx5_core_dev *dev, ...@@ -1121,3 +1121,61 @@ int mlx5_core_modify_hca_vport_context(struct mlx5_core_dev *dev,
return err; return err;
} }
EXPORT_SYMBOL_GPL(mlx5_core_modify_hca_vport_context); EXPORT_SYMBOL_GPL(mlx5_core_modify_hca_vport_context);
int mlx5_nic_vport_affiliate_multiport(struct mlx5_core_dev *master_mdev,
struct mlx5_core_dev *port_mdev)
{
int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
void *in;
int err;
in = kvzalloc(inlen, GFP_KERNEL);
if (!in)
return -ENOMEM;
err = mlx5_nic_vport_enable_roce(port_mdev);
if (err)
goto free;
MLX5_SET(modify_nic_vport_context_in, in, field_select.affiliation, 1);
MLX5_SET(modify_nic_vport_context_in, in,
nic_vport_context.affiliated_vhca_id,
MLX5_CAP_GEN(master_mdev, vhca_id));
MLX5_SET(modify_nic_vport_context_in, in,
nic_vport_context.affiliation_criteria,
MLX5_CAP_GEN(port_mdev, affiliate_nic_vport_criteria));
err = mlx5_modify_nic_vport_context(port_mdev, in, inlen);
if (err)
mlx5_nic_vport_disable_roce(port_mdev);
free:
kvfree(in);
return err;
}
EXPORT_SYMBOL_GPL(mlx5_nic_vport_affiliate_multiport);
int mlx5_nic_vport_unaffiliate_multiport(struct mlx5_core_dev *port_mdev)
{
int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
void *in;
int err;
in = kvzalloc(inlen, GFP_KERNEL);
if (!in)
return -ENOMEM;
MLX5_SET(modify_nic_vport_context_in, in, field_select.affiliation, 1);
MLX5_SET(modify_nic_vport_context_in, in,
nic_vport_context.affiliated_vhca_id, 0);
MLX5_SET(modify_nic_vport_context_in, in,
nic_vport_context.affiliation_criteria, 0);
err = mlx5_modify_nic_vport_context(port_mdev, in, inlen);
if (!err)
mlx5_nic_vport_disable_roce(port_mdev);
kvfree(in);
return err;
}
EXPORT_SYMBOL_GPL(mlx5_nic_vport_unaffiliate_multiport);
...@@ -1234,9 +1234,29 @@ static inline bool mlx5_rl_is_supported(struct mlx5_core_dev *dev) ...@@ -1234,9 +1234,29 @@ static inline bool mlx5_rl_is_supported(struct mlx5_core_dev *dev)
return !!(dev->priv.rl_table.max_size); return !!(dev->priv.rl_table.max_size);
} }
static inline int mlx5_core_is_mp_slave(struct mlx5_core_dev *dev)
{
return MLX5_CAP_GEN(dev, affiliate_nic_vport_criteria) &&
MLX5_CAP_GEN(dev, num_vhca_ports) <= 1;
}
static inline int mlx5_core_is_mp_master(struct mlx5_core_dev *dev)
{
return MLX5_CAP_GEN(dev, num_vhca_ports) > 1;
}
static inline int mlx5_core_mp_enabled(struct mlx5_core_dev *dev)
{
return mlx5_core_is_mp_slave(dev) ||
mlx5_core_is_mp_master(dev);
}
static inline int mlx5_core_native_port_num(struct mlx5_core_dev *dev) static inline int mlx5_core_native_port_num(struct mlx5_core_dev *dev)
{ {
return 1; if (!mlx5_core_mp_enabled(dev))
return 1;
return MLX5_CAP_GEN(dev, native_port_num);
} }
enum { enum {
......
...@@ -502,7 +502,7 @@ struct mlx5_ifc_ads_bits { ...@@ -502,7 +502,7 @@ struct mlx5_ifc_ads_bits {
u8 dei_cfi[0x1]; u8 dei_cfi[0x1];
u8 eth_prio[0x3]; u8 eth_prio[0x3];
u8 sl[0x4]; u8 sl[0x4];
u8 port[0x8]; u8 vhca_port_num[0x8];
u8 rmac_47_32[0x10]; u8 rmac_47_32[0x10];
u8 rmac_31_0[0x20]; u8 rmac_31_0[0x20];
...@@ -794,7 +794,10 @@ enum { ...@@ -794,7 +794,10 @@ enum {
}; };
struct mlx5_ifc_cmd_hca_cap_bits { struct mlx5_ifc_cmd_hca_cap_bits {
u8 reserved_at_0[0x80]; u8 reserved_at_0[0x30];
u8 vhca_id[0x10];
u8 reserved_at_40[0x40];
u8 log_max_srq_sz[0x8]; u8 log_max_srq_sz[0x8];
u8 log_max_qp_sz[0x8]; u8 log_max_qp_sz[0x8];
...@@ -1066,8 +1069,11 @@ struct mlx5_ifc_cmd_hca_cap_bits { ...@@ -1066,8 +1069,11 @@ struct mlx5_ifc_cmd_hca_cap_bits {
u8 reserved_at_5f8[0x3]; u8 reserved_at_5f8[0x3];
u8 log_max_xrq[0x5]; u8 log_max_xrq[0x5];
u8 reserved_at_600[0x1e]; u8 affiliate_nic_vport_criteria[0x8];
u8 sw_owner_id; u8 native_port_num[0x8];
u8 num_vhca_ports[0x8];
u8 reserved_at_618[0x6];
u8 sw_owner_id[0x1];
u8 reserved_at_61f[0x1e1]; u8 reserved_at_61f[0x1e1];
}; };
...@@ -2617,7 +2623,12 @@ struct mlx5_ifc_nic_vport_context_bits { ...@@ -2617,7 +2623,12 @@ struct mlx5_ifc_nic_vport_context_bits {
u8 event_on_mc_address_change[0x1]; u8 event_on_mc_address_change[0x1];
u8 event_on_uc_address_change[0x1]; u8 event_on_uc_address_change[0x1];
u8 reserved_at_40[0xf0]; u8 reserved_at_40[0xc];
u8 affiliation_criteria[0x4];
u8 affiliated_vhca_id[0x10];
u8 reserved_at_60[0xd0];
u8 mtu[0x10]; u8 mtu[0x10];
...@@ -3260,7 +3271,8 @@ struct mlx5_ifc_set_roce_address_in_bits { ...@@ -3260,7 +3271,8 @@ struct mlx5_ifc_set_roce_address_in_bits {
u8 op_mod[0x10]; u8 op_mod[0x10];
u8 roce_address_index[0x10]; u8 roce_address_index[0x10];
u8 reserved_at_50[0x10]; u8 reserved_at_50[0xc];
u8 vhca_port_num[0x4];
u8 reserved_at_60[0x20]; u8 reserved_at_60[0x20];
...@@ -3880,7 +3892,8 @@ struct mlx5_ifc_query_roce_address_in_bits { ...@@ -3880,7 +3892,8 @@ struct mlx5_ifc_query_roce_address_in_bits {
u8 op_mod[0x10]; u8 op_mod[0x10];
u8 roce_address_index[0x10]; u8 roce_address_index[0x10];
u8 reserved_at_50[0x10]; u8 reserved_at_50[0xc];
u8 vhca_port_num[0x4];
u8 reserved_at_60[0x20]; u8 reserved_at_60[0x20];
}; };
...@@ -5312,7 +5325,9 @@ struct mlx5_ifc_modify_nic_vport_context_out_bits { ...@@ -5312,7 +5325,9 @@ struct mlx5_ifc_modify_nic_vport_context_out_bits {
}; };
struct mlx5_ifc_modify_nic_vport_field_select_bits { struct mlx5_ifc_modify_nic_vport_field_select_bits {
u8 reserved_at_0[0x14]; u8 reserved_at_0[0x12];
u8 affiliation[0x1];
u8 reserved_at_e[0x1];
u8 disable_uc_local_lb[0x1]; u8 disable_uc_local_lb[0x1];
u8 disable_mc_local_lb[0x1]; u8 disable_mc_local_lb[0x1];
u8 node_guid[0x1]; u8 node_guid[0x1];
......
...@@ -116,4 +116,8 @@ int mlx5_core_modify_hca_vport_context(struct mlx5_core_dev *dev, ...@@ -116,4 +116,8 @@ int mlx5_core_modify_hca_vport_context(struct mlx5_core_dev *dev,
struct mlx5_hca_vport_context *req); struct mlx5_hca_vport_context *req);
int mlx5_nic_vport_update_local_lb(struct mlx5_core_dev *mdev, bool enable); int mlx5_nic_vport_update_local_lb(struct mlx5_core_dev *mdev, bool enable);
int mlx5_nic_vport_query_local_lb(struct mlx5_core_dev *mdev, bool *status); int mlx5_nic_vport_query_local_lb(struct mlx5_core_dev *mdev, bool *status);
int mlx5_nic_vport_affiliate_multiport(struct mlx5_core_dev *master_mdev,
struct mlx5_core_dev *port_mdev);
int mlx5_nic_vport_unaffiliate_multiport(struct mlx5_core_dev *port_mdev);
#endif /* __MLX5_VPORT_H__ */ #endif /* __MLX5_VPORT_H__ */
...@@ -3850,4 +3850,12 @@ ib_get_vector_affinity(struct ib_device *device, int comp_vector) ...@@ -3850,4 +3850,12 @@ ib_get_vector_affinity(struct ib_device *device, int comp_vector)
} }
/**
* rdma_roce_rescan_device - Rescan all of the network devices in the system
* and add their gids, as needed, to the relevant RoCE devices.
*
* @device: the rdma device
*/
void rdma_roce_rescan_device(struct ib_device *ibdev);
#endif /* IB_VERBS_H */ #endif /* IB_VERBS_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