Commit ddd8a6c1 authored by Eugenia Emantayev's avatar Eugenia Emantayev Committed by David S. Miller

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: default avatarEugenia Emantayev <eugenia@mellanox.com>
Signed-off-by: default avatarAmir Vadai <amirv@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d998735f
...@@ -1013,6 +1013,9 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 {
......
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