net/mlx4_core: Read HCA frequency and map internal clock
Read HCA frequency, read PCI clock bar and offset, map internal clock to PCI bar. Signed-off-by: Eugenia Emantayev <eugenia@mellanox.com> Signed-off-by: Amir Vadai <amirv@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
					parent
					
						
							
								d998735f44
							
						
					
				
			
			
				commit
				
					
						ddd8a6c12d
					
				
			
		
					 5 changed files with 75 additions and 1 deletions
				
			
		| 
						 | 
					@ -1013,6 +1013,9 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
 | 
				
			||||||
#define QUERY_FW_COMM_BASE_OFFSET      0x40
 | 
					#define QUERY_FW_COMM_BASE_OFFSET      0x40
 | 
				
			||||||
#define QUERY_FW_COMM_BAR_OFFSET       0x48
 | 
					#define QUERY_FW_COMM_BAR_OFFSET       0x48
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define QUERY_FW_CLOCK_OFFSET	       0x50
 | 
				
			||||||
 | 
					#define QUERY_FW_CLOCK_BAR	       0x58
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mailbox = mlx4_alloc_cmd_mailbox(dev);
 | 
						mailbox = mlx4_alloc_cmd_mailbox(dev);
 | 
				
			||||||
	if (IS_ERR(mailbox))
 | 
						if (IS_ERR(mailbox))
 | 
				
			||||||
		return PTR_ERR(mailbox);
 | 
							return PTR_ERR(mailbox);
 | 
				
			||||||
| 
						 | 
					@ -1087,6 +1090,12 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
 | 
				
			||||||
		 fw->comm_bar, fw->comm_base);
 | 
							 fw->comm_bar, fw->comm_base);
 | 
				
			||||||
	mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2);
 | 
						mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MLX4_GET(fw->clock_offset, outbox, QUERY_FW_CLOCK_OFFSET);
 | 
				
			||||||
 | 
						MLX4_GET(fw->clock_bar,    outbox, QUERY_FW_CLOCK_BAR);
 | 
				
			||||||
 | 
						fw->clock_bar = (fw->clock_bar >> 6) * 2;
 | 
				
			||||||
 | 
						mlx4_dbg(dev, "Internal clock bar:%d offset:0x%llx\n",
 | 
				
			||||||
 | 
							 fw->clock_bar, fw->clock_offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Round up number of system pages needed in case
 | 
						 * Round up number of system pages needed in case
 | 
				
			||||||
	 * MLX4_ICM_PAGE_SIZE < PAGE_SIZE.
 | 
						 * MLX4_ICM_PAGE_SIZE < PAGE_SIZE.
 | 
				
			||||||
| 
						 | 
					@ -1374,6 +1383,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 | 
				
			||||||
	u8 byte_field;
 | 
						u8 byte_field;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define QUERY_HCA_GLOBAL_CAPS_OFFSET	0x04
 | 
					#define QUERY_HCA_GLOBAL_CAPS_OFFSET	0x04
 | 
				
			||||||
 | 
					#define QUERY_HCA_CORE_CLOCK_OFFSET	0x0c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mailbox = mlx4_alloc_cmd_mailbox(dev);
 | 
						mailbox = mlx4_alloc_cmd_mailbox(dev);
 | 
				
			||||||
	if (IS_ERR(mailbox))
 | 
						if (IS_ERR(mailbox))
 | 
				
			||||||
| 
						 | 
					@ -1388,6 +1398,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MLX4_GET(param->global_caps, outbox, QUERY_HCA_GLOBAL_CAPS_OFFSET);
 | 
						MLX4_GET(param->global_caps, outbox, QUERY_HCA_GLOBAL_CAPS_OFFSET);
 | 
				
			||||||
 | 
						MLX4_GET(param->hca_core_clock, outbox, QUERY_HCA_CORE_CLOCK_OFFSET);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* QPC/EEC/CQC/EQC/RDMARC attributes */
 | 
						/* QPC/EEC/CQC/EQC/RDMARC attributes */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -162,6 +162,7 @@ struct mlx4_init_hca_param {
 | 
				
			||||||
	u64 global_caps;
 | 
						u64 global_caps;
 | 
				
			||||||
	u16 log_mc_entry_sz;
 | 
						u16 log_mc_entry_sz;
 | 
				
			||||||
	u16 log_mc_hash_sz;
 | 
						u16 log_mc_hash_sz;
 | 
				
			||||||
 | 
						u16 hca_core_clock; /* Internal Clock Frequency (in MHz) */
 | 
				
			||||||
	u8  log_num_qps;
 | 
						u8  log_num_qps;
 | 
				
			||||||
	u8  log_num_srqs;
 | 
						u8  log_num_srqs;
 | 
				
			||||||
	u8  log_num_cqs;
 | 
						u8  log_num_cqs;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -513,6 +513,8 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mlx4_log_num_mgm_entry_size = hca_param.log_mc_entry_sz;
 | 
						mlx4_log_num_mgm_entry_size = hca_param.log_mc_entry_sz;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev->caps.hca_core_clock = hca_param.hca_core_clock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(&dev_cap, 0, sizeof(dev_cap));
 | 
						memset(&dev_cap, 0, sizeof(dev_cap));
 | 
				
			||||||
	dev->caps.max_qp_dest_rdma = 1 << hca_param.log_rd_per_qp;
 | 
						dev->caps.max_qp_dest_rdma = 1 << hca_param.log_rd_per_qp;
 | 
				
			||||||
	err = mlx4_dev_cap(dev, &dev_cap);
 | 
						err = mlx4_dev_cap(dev, &dev_cap);
 | 
				
			||||||
| 
						 | 
					@ -1226,8 +1228,31 @@ static void unmap_bf_area(struct mlx4_dev *dev)
 | 
				
			||||||
		io_mapping_free(mlx4_priv(dev)->bf_mapping);
 | 
							io_mapping_free(mlx4_priv(dev)->bf_mapping);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int map_internal_clock(struct mlx4_dev *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mlx4_priv *priv = mlx4_priv(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv->clock_mapping =
 | 
				
			||||||
 | 
							ioremap(pci_resource_start(dev->pdev, priv->fw.clock_bar) +
 | 
				
			||||||
 | 
								priv->fw.clock_offset, MLX4_CLOCK_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!priv->clock_mapping)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void unmap_internal_clock(struct mlx4_dev *dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct mlx4_priv *priv = mlx4_priv(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (priv->clock_mapping)
 | 
				
			||||||
 | 
							iounmap(priv->clock_mapping);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void mlx4_close_hca(struct mlx4_dev *dev)
 | 
					static void mlx4_close_hca(struct mlx4_dev *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						unmap_internal_clock(dev);
 | 
				
			||||||
	unmap_bf_area(dev);
 | 
						unmap_bf_area(dev);
 | 
				
			||||||
	if (mlx4_is_slave(dev))
 | 
						if (mlx4_is_slave(dev))
 | 
				
			||||||
		mlx4_slave_exit(dev);
 | 
							mlx4_slave_exit(dev);
 | 
				
			||||||
| 
						 | 
					@ -1445,6 +1470,37 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
 | 
				
			||||||
			mlx4_err(dev, "INIT_HCA command failed, aborting.\n");
 | 
								mlx4_err(dev, "INIT_HCA command failed, aborting.\n");
 | 
				
			||||||
			goto err_free_icm;
 | 
								goto err_free_icm;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * If TS is supported by FW
 | 
				
			||||||
 | 
							 * read HCA frequency by QUERY_HCA command
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) {
 | 
				
			||||||
 | 
								memset(&init_hca, 0, sizeof(init_hca));
 | 
				
			||||||
 | 
								err = mlx4_QUERY_HCA(dev, &init_hca);
 | 
				
			||||||
 | 
								if (err) {
 | 
				
			||||||
 | 
									mlx4_err(dev, "QUERY_HCA command failed, disable timestamp.\n");
 | 
				
			||||||
 | 
									dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									dev->caps.hca_core_clock =
 | 
				
			||||||
 | 
										init_hca.hca_core_clock;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* In case we got HCA frequency 0 - disable timestamping
 | 
				
			||||||
 | 
								 * to avoid dividing by zero
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								if (!dev->caps.hca_core_clock) {
 | 
				
			||||||
 | 
									dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
 | 
				
			||||||
 | 
									mlx4_err(dev,
 | 
				
			||||||
 | 
										 "HCA frequency is 0. Timestamping is not supported.");
 | 
				
			||||||
 | 
								} else if (map_internal_clock(dev)) {
 | 
				
			||||||
 | 
									/*
 | 
				
			||||||
 | 
									 * Map internal clock,
 | 
				
			||||||
 | 
									 * in case of failure disable timestamping
 | 
				
			||||||
 | 
									 */
 | 
				
			||||||
 | 
									dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
 | 
				
			||||||
 | 
									mlx4_err(dev, "Failed to map internal clock. Timestamping is not supported.\n");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		err = mlx4_init_slave(dev);
 | 
							err = mlx4_init_slave(dev);
 | 
				
			||||||
		if (err) {
 | 
							if (err) {
 | 
				
			||||||
| 
						 | 
					@ -1478,6 +1534,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unmap_bf:
 | 
					unmap_bf:
 | 
				
			||||||
 | 
						unmap_internal_clock(dev);
 | 
				
			||||||
	unmap_bf_area(dev);
 | 
						unmap_bf_area(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_close:
 | 
					err_close:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,7 +87,8 @@ enum {
 | 
				
			||||||
	MLX4_HCR_SIZE		= 0x0001c,
 | 
						MLX4_HCR_SIZE		= 0x0001c,
 | 
				
			||||||
	MLX4_CLR_INT_SIZE	= 0x00008,
 | 
						MLX4_CLR_INT_SIZE	= 0x00008,
 | 
				
			||||||
	MLX4_SLAVE_COMM_BASE	= 0x0,
 | 
						MLX4_SLAVE_COMM_BASE	= 0x0,
 | 
				
			||||||
	MLX4_COMM_PAGESIZE	= 0x1000
 | 
						MLX4_COMM_PAGESIZE	= 0x1000,
 | 
				
			||||||
 | 
						MLX4_CLOCK_SIZE		= 0x00008
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
| 
						 | 
					@ -403,6 +404,7 @@ struct mlx4_fw {
 | 
				
			||||||
	u64			clr_int_base;
 | 
						u64			clr_int_base;
 | 
				
			||||||
	u64			catas_offset;
 | 
						u64			catas_offset;
 | 
				
			||||||
	u64			comm_base;
 | 
						u64			comm_base;
 | 
				
			||||||
 | 
						u64			clock_offset;
 | 
				
			||||||
	struct mlx4_icm	       *fw_icm;
 | 
						struct mlx4_icm	       *fw_icm;
 | 
				
			||||||
	struct mlx4_icm	       *aux_icm;
 | 
						struct mlx4_icm	       *aux_icm;
 | 
				
			||||||
	u32			catas_size;
 | 
						u32			catas_size;
 | 
				
			||||||
| 
						 | 
					@ -410,6 +412,7 @@ struct mlx4_fw {
 | 
				
			||||||
	u8			clr_int_bar;
 | 
						u8			clr_int_bar;
 | 
				
			||||||
	u8			catas_bar;
 | 
						u8			catas_bar;
 | 
				
			||||||
	u8			comm_bar;
 | 
						u8			comm_bar;
 | 
				
			||||||
 | 
						u8			clock_bar;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mlx4_comm {
 | 
					struct mlx4_comm {
 | 
				
			||||||
| 
						 | 
					@ -826,6 +829,7 @@ struct mlx4_priv {
 | 
				
			||||||
	struct list_head	bf_list;
 | 
						struct list_head	bf_list;
 | 
				
			||||||
	struct mutex		bf_mutex;
 | 
						struct mutex		bf_mutex;
 | 
				
			||||||
	struct io_mapping	*bf_mapping;
 | 
						struct io_mapping	*bf_mapping;
 | 
				
			||||||
 | 
						void __iomem            *clock_mapping;
 | 
				
			||||||
	int			reserved_mtts;
 | 
						int			reserved_mtts;
 | 
				
			||||||
	int			fs_hash_mode;
 | 
						int			fs_hash_mode;
 | 
				
			||||||
	u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS];
 | 
						u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -445,6 +445,7 @@ struct mlx4_caps {
 | 
				
			||||||
	u8			eqe_factor;
 | 
						u8			eqe_factor;
 | 
				
			||||||
	u32			userspace_caps; /* userspace must be aware of these */
 | 
						u32			userspace_caps; /* userspace must be aware of these */
 | 
				
			||||||
	u32			function_caps;  /* VFs must be aware of these */
 | 
						u32			function_caps;  /* VFs must be aware of these */
 | 
				
			||||||
 | 
						u16			hca_core_clock;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mlx4_buf_list {
 | 
					struct mlx4_buf_list {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue