mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	IB/mlx5: Implement callbacks for manipulating VFs
Implement the IB defined callbacks used to manipulate the policy for the link state, set GUIDs or get statistics information. This functionality is added into a new file that will be used to add any SRIOV related functionality to the mlx5 IB layer. The following callbacks have been added: mlx5_ib_get_vf_config mlx5_ib_set_vf_link_state mlx5_ib_get_vf_stats mlx5_ib_set_vf_guid In addition, publish whether this device is based on a virtual function. In mlx5 supported devices, virtual functions are implemented as vHCAs. vHCAs have their own QP number space so it is possible that two vHCAs will use a QP with the same number at the same time. Signed-off-by: Eli Cohen <eli@mellanox.com> Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
		
							parent
							
								
									1f324bff9b
								
							
						
					
					
						commit
						eff901d30e
					
				| @ -1,4 +1,4 @@ | |||||||
| obj-$(CONFIG_MLX5_INFINIBAND)	+= mlx5_ib.o | obj-$(CONFIG_MLX5_INFINIBAND)	+= mlx5_ib.o | ||||||
| 
 | 
 | ||||||
| mlx5_ib-y :=	main.o cq.o doorbell.o qp.o mem.o srq.o mr.o ah.o mad.o gsi.o | mlx5_ib-y :=	main.o cq.o doorbell.o qp.o mem.o srq.o mr.o ah.o mad.o gsi.o ib_virt.o | ||||||
| mlx5_ib-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += odp.o | mlx5_ib-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += odp.o | ||||||
|  | |||||||
							
								
								
									
										194
									
								
								drivers/infiniband/hw/mlx5/ib_virt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								drivers/infiniband/hw/mlx5/ib_virt.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,194 @@ | |||||||
|  | /*
 | ||||||
|  |  * Copyright (c) 2016, Mellanox Technologies. All rights reserved. | ||||||
|  |  * | ||||||
|  |  * This software is available to you under a choice of one of two | ||||||
|  |  * licenses.  You may choose to be licensed under the terms of the GNU | ||||||
|  |  * General Public License (GPL) Version 2, available from the file | ||||||
|  |  * COPYING in the main directory of this source tree, or the | ||||||
|  |  * OpenIB.org BSD license below: | ||||||
|  |  * | ||||||
|  |  *     Redistribution and use in source and binary forms, with or | ||||||
|  |  *     without modification, are permitted provided that the following | ||||||
|  |  *     conditions are met: | ||||||
|  |  * | ||||||
|  |  *      - Redistributions of source code must retain the above | ||||||
|  |  *        copyright notice, this list of conditions and the following | ||||||
|  |  *        disclaimer. | ||||||
|  |  * | ||||||
|  |  *      - Redistributions in binary form must reproduce the above | ||||||
|  |  *        copyright notice, this list of conditions and the following | ||||||
|  |  *        disclaimer in the documentation and/or other materials | ||||||
|  |  *        provided with the distribution. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||||
|  |  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||||
|  |  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||||
|  |  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||||||
|  |  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||||||
|  |  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||||
|  |  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  * SOFTWARE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <linux/module.h> | ||||||
|  | #include <linux/mlx5/vport.h> | ||||||
|  | #include "mlx5_ib.h" | ||||||
|  | 
 | ||||||
|  | static inline u32 mlx_to_net_policy(enum port_state_policy mlx_policy) | ||||||
|  | { | ||||||
|  | 	switch (mlx_policy) { | ||||||
|  | 	case MLX5_POLICY_DOWN: | ||||||
|  | 		return IFLA_VF_LINK_STATE_DISABLE; | ||||||
|  | 	case MLX5_POLICY_UP: | ||||||
|  | 		return IFLA_VF_LINK_STATE_ENABLE; | ||||||
|  | 	case MLX5_POLICY_FOLLOW: | ||||||
|  | 		return IFLA_VF_LINK_STATE_AUTO; | ||||||
|  | 	default: | ||||||
|  | 		return __IFLA_VF_LINK_STATE_MAX; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int mlx5_ib_get_vf_config(struct ib_device *device, int vf, u8 port, | ||||||
|  | 			  struct ifla_vf_info *info) | ||||||
|  | { | ||||||
|  | 	struct mlx5_ib_dev *dev = to_mdev(device); | ||||||
|  | 	struct mlx5_core_dev *mdev = dev->mdev; | ||||||
|  | 	struct mlx5_hca_vport_context *rep; | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	rep = kzalloc(sizeof(*rep), GFP_KERNEL); | ||||||
|  | 	if (!rep) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	err = mlx5_query_hca_vport_context(mdev, 1, 1,  vf + 1, rep); | ||||||
|  | 	if (err) { | ||||||
|  | 		mlx5_ib_warn(dev, "failed to query port policy for vf %d (%d)\n", | ||||||
|  | 			     vf, err); | ||||||
|  | 		goto free; | ||||||
|  | 	} | ||||||
|  | 	memset(info, 0, sizeof(*info)); | ||||||
|  | 	info->linkstate = mlx_to_net_policy(rep->policy); | ||||||
|  | 	if (info->linkstate == __IFLA_VF_LINK_STATE_MAX) | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 
 | ||||||
|  | free: | ||||||
|  | 	kfree(rep); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline enum port_state_policy net_to_mlx_policy(int policy) | ||||||
|  | { | ||||||
|  | 	switch (policy) { | ||||||
|  | 	case IFLA_VF_LINK_STATE_DISABLE: | ||||||
|  | 		return MLX5_POLICY_DOWN; | ||||||
|  | 	case IFLA_VF_LINK_STATE_ENABLE: | ||||||
|  | 		return MLX5_POLICY_UP; | ||||||
|  | 	case IFLA_VF_LINK_STATE_AUTO: | ||||||
|  | 		return MLX5_POLICY_FOLLOW; | ||||||
|  | 	default: | ||||||
|  | 		return MLX5_POLICY_INVALID; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int mlx5_ib_set_vf_link_state(struct ib_device *device, int vf, | ||||||
|  | 			      u8 port, int state) | ||||||
|  | { | ||||||
|  | 	struct mlx5_ib_dev *dev = to_mdev(device); | ||||||
|  | 	struct mlx5_core_dev *mdev = dev->mdev; | ||||||
|  | 	struct mlx5_hca_vport_context *in; | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	in = kzalloc(sizeof(*in), GFP_KERNEL); | ||||||
|  | 	if (!in) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	in->policy = net_to_mlx_policy(state); | ||||||
|  | 	if (in->policy == MLX5_POLICY_INVALID) { | ||||||
|  | 		err = -EINVAL; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	in->field_select = MLX5_HCA_VPORT_SEL_STATE_POLICY; | ||||||
|  | 	err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in); | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	kfree(in); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int mlx5_ib_get_vf_stats(struct ib_device *device, int vf, | ||||||
|  | 			 u8 port, struct ifla_vf_stats *stats) | ||||||
|  | { | ||||||
|  | 	int out_sz = MLX5_ST_SZ_BYTES(query_vport_counter_out); | ||||||
|  | 	struct mlx5_core_dev *mdev; | ||||||
|  | 	struct mlx5_ib_dev *dev; | ||||||
|  | 	void *out; | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	dev = to_mdev(device); | ||||||
|  | 	mdev = dev->mdev; | ||||||
|  | 
 | ||||||
|  | 	out = kzalloc(out_sz, GFP_KERNEL); | ||||||
|  | 	if (!out) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	err = mlx5_core_query_vport_counter(mdev, true, vf, port, out, out_sz); | ||||||
|  | 	if (err) | ||||||
|  | 		goto ex; | ||||||
|  | 
 | ||||||
|  | 	stats->rx_packets = MLX5_GET64_PR(query_vport_counter_out, out, received_ib_unicast.packets); | ||||||
|  | 	stats->tx_packets = MLX5_GET64_PR(query_vport_counter_out, out, transmitted_ib_unicast.packets); | ||||||
|  | 	stats->rx_bytes = MLX5_GET64_PR(query_vport_counter_out, out, received_ib_unicast.octets); | ||||||
|  | 	stats->tx_bytes = MLX5_GET64_PR(query_vport_counter_out, out, transmitted_ib_unicast.octets); | ||||||
|  | 	stats->multicast = MLX5_GET64_PR(query_vport_counter_out, out, received_ib_multicast.packets); | ||||||
|  | 
 | ||||||
|  | ex: | ||||||
|  | 	kfree(out); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int set_vf_node_guid(struct ib_device *device, int vf, u8 port, u64 guid) | ||||||
|  | { | ||||||
|  | 	struct mlx5_ib_dev *dev = to_mdev(device); | ||||||
|  | 	struct mlx5_core_dev *mdev = dev->mdev; | ||||||
|  | 	struct mlx5_hca_vport_context *in; | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	in = kzalloc(sizeof(*in), GFP_KERNEL); | ||||||
|  | 	if (!in) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	in->field_select = MLX5_HCA_VPORT_SEL_NODE_GUID; | ||||||
|  | 	in->node_guid = guid; | ||||||
|  | 	err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in); | ||||||
|  | 	kfree(in); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int set_vf_port_guid(struct ib_device *device, int vf, u8 port, u64 guid) | ||||||
|  | { | ||||||
|  | 	struct mlx5_ib_dev *dev = to_mdev(device); | ||||||
|  | 	struct mlx5_core_dev *mdev = dev->mdev; | ||||||
|  | 	struct mlx5_hca_vport_context *in; | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	in = kzalloc(sizeof(*in), GFP_KERNEL); | ||||||
|  | 	if (!in) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	in->field_select = MLX5_HCA_VPORT_SEL_PORT_GUID; | ||||||
|  | 	in->port_guid = guid; | ||||||
|  | 	err = mlx5_core_modify_hca_vport_context(mdev, 1, 1, vf + 1, in); | ||||||
|  | 	kfree(in); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int mlx5_ib_set_vf_guid(struct ib_device *device, int vf, u8 port, | ||||||
|  | 			u64 guid, int type) | ||||||
|  | { | ||||||
|  | 	if (type == IFLA_VF_IB_NODE_GUID) | ||||||
|  | 		return set_vf_node_guid(device, vf, port, guid); | ||||||
|  | 	else if (type == IFLA_VF_IB_PORT_GUID) | ||||||
|  | 		return set_vf_port_guid(device, vf, port, guid); | ||||||
|  | 
 | ||||||
|  | 	return -EINVAL; | ||||||
|  | } | ||||||
| @ -562,6 +562,9 @@ static int mlx5_ib_query_device(struct ib_device *ibdev, | |||||||
| 	if (MLX5_CAP_GEN(mdev, cd)) | 	if (MLX5_CAP_GEN(mdev, cd)) | ||||||
| 		props->device_cap_flags |= IB_DEVICE_CROSS_CHANNEL; | 		props->device_cap_flags |= IB_DEVICE_CROSS_CHANNEL; | ||||||
| 
 | 
 | ||||||
|  | 	if (!mlx5_core_is_pf(mdev)) | ||||||
|  | 		props->device_cap_flags |= IB_DEVICE_VIRTUAL_FUNCTION; | ||||||
|  | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -699,6 +702,7 @@ static int mlx5_query_hca_port(struct ib_device *ibdev, u8 port, | |||||||
| 	props->qkey_viol_cntr	= rep->qkey_violation_counter; | 	props->qkey_viol_cntr	= rep->qkey_violation_counter; | ||||||
| 	props->subnet_timeout	= rep->subnet_timeout; | 	props->subnet_timeout	= rep->subnet_timeout; | ||||||
| 	props->init_type_reply	= rep->init_type_reply; | 	props->init_type_reply	= rep->init_type_reply; | ||||||
|  | 	props->grh_required	= rep->grh_required; | ||||||
| 
 | 
 | ||||||
| 	err = mlx5_query_port_link_width_oper(mdev, &ib_link_width_oper, port); | 	err = mlx5_query_port_link_width_oper(mdev, &ib_link_width_oper, port); | ||||||
| 	if (err) | 	if (err) | ||||||
| @ -2349,6 +2353,12 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev) | |||||||
| 	dev->ib_dev.map_mr_sg		= mlx5_ib_map_mr_sg; | 	dev->ib_dev.map_mr_sg		= mlx5_ib_map_mr_sg; | ||||||
| 	dev->ib_dev.check_mr_status	= mlx5_ib_check_mr_status; | 	dev->ib_dev.check_mr_status	= mlx5_ib_check_mr_status; | ||||||
| 	dev->ib_dev.get_port_immutable  = mlx5_port_immutable; | 	dev->ib_dev.get_port_immutable  = mlx5_port_immutable; | ||||||
|  | 	if (mlx5_core_is_pf(mdev)) { | ||||||
|  | 		dev->ib_dev.get_vf_config	= mlx5_ib_get_vf_config; | ||||||
|  | 		dev->ib_dev.set_vf_link_state	= mlx5_ib_set_vf_link_state; | ||||||
|  | 		dev->ib_dev.get_vf_stats	= mlx5_ib_get_vf_stats; | ||||||
|  | 		dev->ib_dev.set_vf_guid		= mlx5_ib_set_vf_guid; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	mlx5_ib_internal_fill_odp_caps(dev); | 	mlx5_ib_internal_fill_odp_caps(dev); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -776,6 +776,14 @@ void mlx5_ib_qp_disable_pagefaults(struct mlx5_ib_qp *qp); | |||||||
| void mlx5_ib_qp_enable_pagefaults(struct mlx5_ib_qp *qp); | void mlx5_ib_qp_enable_pagefaults(struct mlx5_ib_qp *qp); | ||||||
| void mlx5_ib_invalidate_range(struct ib_umem *umem, unsigned long start, | void mlx5_ib_invalidate_range(struct ib_umem *umem, unsigned long start, | ||||||
| 			      unsigned long end); | 			      unsigned long end); | ||||||
|  | int mlx5_ib_get_vf_config(struct ib_device *device, int vf, | ||||||
|  | 			  u8 port, struct ifla_vf_info *info); | ||||||
|  | int mlx5_ib_set_vf_link_state(struct ib_device *device, int vf, | ||||||
|  | 			      u8 port, int state); | ||||||
|  | int mlx5_ib_get_vf_stats(struct ib_device *device, int vf, | ||||||
|  | 			 u8 port, struct ifla_vf_stats *stats); | ||||||
|  | int mlx5_ib_set_vf_guid(struct ib_device *device, int vf, u8 port, | ||||||
|  | 			u64 guid, int type); | ||||||
| 
 | 
 | ||||||
| #else /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */ | #else /* CONFIG_INFINIBAND_ON_DEMAND_PAGING */ | ||||||
| static inline void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev) | static inline void mlx5_ib_internal_fill_odp_caps(struct mlx5_ib_dev *dev) | ||||||
|  | |||||||
| @ -613,7 +613,10 @@ struct mlx5_pas { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum port_state_policy { | enum port_state_policy { | ||||||
| 	MLX5_AAA_000 | 	MLX5_POLICY_DOWN	= 0, | ||||||
|  | 	MLX5_POLICY_UP		= 1, | ||||||
|  | 	MLX5_POLICY_FOLLOW	= 2, | ||||||
|  | 	MLX5_POLICY_INVALID	= 0xffffffff | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum phy_port_state { | enum phy_port_state { | ||||||
|  | |||||||
| @ -3696,6 +3696,12 @@ struct mlx5_ifc_query_hca_vport_pkey_in_bits { | |||||||
| 	u8         pkey_index[0x10]; | 	u8         pkey_index[0x10]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | enum { | ||||||
|  | 	MLX5_HCA_VPORT_SEL_PORT_GUID	= 1 << 0, | ||||||
|  | 	MLX5_HCA_VPORT_SEL_NODE_GUID	= 1 << 1, | ||||||
|  | 	MLX5_HCA_VPORT_SEL_STATE_POLICY	= 1 << 2, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct mlx5_ifc_query_hca_vport_gid_out_bits { | struct mlx5_ifc_query_hca_vport_gid_out_bits { | ||||||
| 	u8         status[0x8]; | 	u8         status[0x8]; | ||||||
| 	u8         reserved_at_8[0x18]; | 	u8         reserved_at_8[0x18]; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Eli Cohen
						Eli Cohen