diff options
author | Eugenia Emantayev <eugenia@mellanox.com> | 2013-04-23 02:06:48 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-04-24 16:30:13 -0400 |
commit | ddd8a6c12d7e494902a9435a9a7a543ef730b2d8 (patch) | |
tree | 5dd526d9fef754d1de7fce210ee002e71cb1818d /drivers/net/ethernet/mellanox | |
parent | d998735f443427c1530cac5eeda0a45c8cb60a57 (diff) |
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>
Diffstat (limited to 'drivers/net/ethernet/mellanox')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.c | 11 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 57 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4.h | 6 |
4 files changed, 74 insertions, 1 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index f1e70979b4c1..6776c257bd34 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c | |||
@@ -1013,6 +1013,9 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) | |||
1013 | #define QUERY_FW_COMM_BASE_OFFSET 0x40 | 1013 | #define QUERY_FW_COMM_BASE_OFFSET 0x40 |
1014 | #define QUERY_FW_COMM_BAR_OFFSET 0x48 | 1014 | #define QUERY_FW_COMM_BAR_OFFSET 0x48 |
1015 | 1015 | ||
1016 | #define QUERY_FW_CLOCK_OFFSET 0x50 | ||
1017 | #define QUERY_FW_CLOCK_BAR 0x58 | ||
1018 | |||
1016 | mailbox = mlx4_alloc_cmd_mailbox(dev); | 1019 | mailbox = mlx4_alloc_cmd_mailbox(dev); |
1017 | if (IS_ERR(mailbox)) | 1020 | if (IS_ERR(mailbox)) |
1018 | return PTR_ERR(mailbox); | 1021 | return PTR_ERR(mailbox); |
@@ -1087,6 +1090,12 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) | |||
1087 | fw->comm_bar, fw->comm_base); | 1090 | fw->comm_bar, fw->comm_base); |
1088 | mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2); | 1091 | mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2); |
1089 | 1092 | ||
1093 | MLX4_GET(fw->clock_offset, outbox, QUERY_FW_CLOCK_OFFSET); | ||
1094 | MLX4_GET(fw->clock_bar, outbox, QUERY_FW_CLOCK_BAR); | ||
1095 | fw->clock_bar = (fw->clock_bar >> 6) * 2; | ||
1096 | mlx4_dbg(dev, "Internal clock bar:%d offset:0x%llx\n", | ||
1097 | fw->clock_bar, fw->clock_offset); | ||
1098 | |||
1090 | /* | 1099 | /* |
1091 | * Round up number of system pages needed in case | 1100 | * Round up number of system pages needed in case |
1092 | * MLX4_ICM_PAGE_SIZE < PAGE_SIZE. | 1101 | * MLX4_ICM_PAGE_SIZE < PAGE_SIZE. |
@@ -1374,6 +1383,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, | |||
1374 | u8 byte_field; | 1383 | u8 byte_field; |
1375 | 1384 | ||
1376 | #define QUERY_HCA_GLOBAL_CAPS_OFFSET 0x04 | 1385 | #define QUERY_HCA_GLOBAL_CAPS_OFFSET 0x04 |
1386 | #define QUERY_HCA_CORE_CLOCK_OFFSET 0x0c | ||
1377 | 1387 | ||
1378 | mailbox = mlx4_alloc_cmd_mailbox(dev); | 1388 | mailbox = mlx4_alloc_cmd_mailbox(dev); |
1379 | if (IS_ERR(mailbox)) | 1389 | if (IS_ERR(mailbox)) |
@@ -1388,6 +1398,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, | |||
1388 | goto out; | 1398 | goto out; |
1389 | 1399 | ||
1390 | MLX4_GET(param->global_caps, outbox, QUERY_HCA_GLOBAL_CAPS_OFFSET); | 1400 | MLX4_GET(param->global_caps, outbox, QUERY_HCA_GLOBAL_CAPS_OFFSET); |
1401 | MLX4_GET(param->hca_core_clock, outbox, QUERY_HCA_CORE_CLOCK_OFFSET); | ||
1391 | 1402 | ||
1392 | /* QPC/EEC/CQC/EQC/RDMARC attributes */ | 1403 | /* QPC/EEC/CQC/EQC/RDMARC attributes */ |
1393 | 1404 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h index 151c2bb380a6..fdf41665a059 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.h +++ b/drivers/net/ethernet/mellanox/mlx4/fw.h | |||
@@ -162,6 +162,7 @@ struct mlx4_init_hca_param { | |||
162 | u64 global_caps; | 162 | u64 global_caps; |
163 | u16 log_mc_entry_sz; | 163 | u16 log_mc_entry_sz; |
164 | u16 log_mc_hash_sz; | 164 | u16 log_mc_hash_sz; |
165 | u16 hca_core_clock; /* Internal Clock Frequency (in MHz) */ | ||
165 | u8 log_num_qps; | 166 | u8 log_num_qps; |
166 | u8 log_num_srqs; | 167 | u8 log_num_srqs; |
167 | u8 log_num_cqs; | 168 | u8 log_num_cqs; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 16abde20e1fc..e81840faa6c6 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -513,6 +513,8 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) | |||
513 | 513 | ||
514 | mlx4_log_num_mgm_entry_size = hca_param.log_mc_entry_sz; | 514 | mlx4_log_num_mgm_entry_size = hca_param.log_mc_entry_sz; |
515 | 515 | ||
516 | dev->caps.hca_core_clock = hca_param.hca_core_clock; | ||
517 | |||
516 | memset(&dev_cap, 0, sizeof(dev_cap)); | 518 | memset(&dev_cap, 0, sizeof(dev_cap)); |
517 | dev->caps.max_qp_dest_rdma = 1 << hca_param.log_rd_per_qp; | 519 | dev->caps.max_qp_dest_rdma = 1 << hca_param.log_rd_per_qp; |
518 | err = mlx4_dev_cap(dev, &dev_cap); | 520 | err = mlx4_dev_cap(dev, &dev_cap); |
@@ -1226,8 +1228,31 @@ static void unmap_bf_area(struct mlx4_dev *dev) | |||
1226 | io_mapping_free(mlx4_priv(dev)->bf_mapping); | 1228 | io_mapping_free(mlx4_priv(dev)->bf_mapping); |
1227 | } | 1229 | } |
1228 | 1230 | ||
1231 | static int map_internal_clock(struct mlx4_dev *dev) | ||
1232 | { | ||
1233 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
1234 | |||
1235 | priv->clock_mapping = | ||
1236 | ioremap(pci_resource_start(dev->pdev, priv->fw.clock_bar) + | ||
1237 | priv->fw.clock_offset, MLX4_CLOCK_SIZE); | ||
1238 | |||
1239 | if (!priv->clock_mapping) | ||
1240 | return -ENOMEM; | ||
1241 | |||
1242 | return 0; | ||
1243 | } | ||
1244 | |||
1245 | static void unmap_internal_clock(struct mlx4_dev *dev) | ||
1246 | { | ||
1247 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
1248 | |||
1249 | if (priv->clock_mapping) | ||
1250 | iounmap(priv->clock_mapping); | ||
1251 | } | ||
1252 | |||
1229 | static void mlx4_close_hca(struct mlx4_dev *dev) | 1253 | static void mlx4_close_hca(struct mlx4_dev *dev) |
1230 | { | 1254 | { |
1255 | unmap_internal_clock(dev); | ||
1231 | unmap_bf_area(dev); | 1256 | unmap_bf_area(dev); |
1232 | if (mlx4_is_slave(dev)) | 1257 | if (mlx4_is_slave(dev)) |
1233 | mlx4_slave_exit(dev); | 1258 | mlx4_slave_exit(dev); |
@@ -1445,6 +1470,37 @@ static int mlx4_init_hca(struct mlx4_dev *dev) | |||
1445 | mlx4_err(dev, "INIT_HCA command failed, aborting.\n"); | 1470 | mlx4_err(dev, "INIT_HCA command failed, aborting.\n"); |
1446 | goto err_free_icm; | 1471 | goto err_free_icm; |
1447 | } | 1472 | } |
1473 | /* | ||
1474 | * If TS is supported by FW | ||
1475 | * read HCA frequency by QUERY_HCA command | ||
1476 | */ | ||
1477 | if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) { | ||
1478 | memset(&init_hca, 0, sizeof(init_hca)); | ||
1479 | err = mlx4_QUERY_HCA(dev, &init_hca); | ||
1480 | if (err) { | ||
1481 | mlx4_err(dev, "QUERY_HCA command failed, disable timestamp.\n"); | ||
1482 | dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS; | ||
1483 | } else { | ||
1484 | dev->caps.hca_core_clock = | ||
1485 | init_hca.hca_core_clock; | ||
1486 | } | ||
1487 | |||
1488 | /* In case we got HCA frequency 0 - disable timestamping | ||
1489 | * to avoid dividing by zero | ||
1490 | */ | ||
1491 | if (!dev->caps.hca_core_clock) { | ||
1492 | dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS; | ||
1493 | mlx4_err(dev, | ||
1494 | "HCA frequency is 0. Timestamping is not supported."); | ||
1495 | } else if (map_internal_clock(dev)) { | ||
1496 | /* | ||
1497 | * Map internal clock, | ||
1498 | * in case of failure disable timestamping | ||
1499 | */ | ||
1500 | dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS; | ||
1501 | mlx4_err(dev, "Failed to map internal clock. Timestamping is not supported.\n"); | ||
1502 | } | ||
1503 | } | ||
1448 | } else { | 1504 | } else { |
1449 | err = mlx4_init_slave(dev); | 1505 | err = mlx4_init_slave(dev); |
1450 | if (err) { | 1506 | if (err) { |
@@ -1478,6 +1534,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev) | |||
1478 | return 0; | 1534 | return 0; |
1479 | 1535 | ||
1480 | unmap_bf: | 1536 | unmap_bf: |
1537 | unmap_internal_clock(dev); | ||
1481 | unmap_bf_area(dev); | 1538 | unmap_bf_area(dev); |
1482 | 1539 | ||
1483 | err_close: | 1540 | err_close: |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 252f4ba7f32c..0567f01938ed 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h | |||
@@ -87,7 +87,8 @@ enum { | |||
87 | MLX4_HCR_SIZE = 0x0001c, | 87 | MLX4_HCR_SIZE = 0x0001c, |
88 | MLX4_CLR_INT_SIZE = 0x00008, | 88 | MLX4_CLR_INT_SIZE = 0x00008, |
89 | MLX4_SLAVE_COMM_BASE = 0x0, | 89 | MLX4_SLAVE_COMM_BASE = 0x0, |
90 | MLX4_COMM_PAGESIZE = 0x1000 | 90 | MLX4_COMM_PAGESIZE = 0x1000, |
91 | MLX4_CLOCK_SIZE = 0x00008 | ||
91 | }; | 92 | }; |
92 | 93 | ||
93 | enum { | 94 | enum { |
@@ -403,6 +404,7 @@ struct mlx4_fw { | |||
403 | u64 clr_int_base; | 404 | u64 clr_int_base; |
404 | u64 catas_offset; | 405 | u64 catas_offset; |
405 | u64 comm_base; | 406 | u64 comm_base; |
407 | u64 clock_offset; | ||
406 | struct mlx4_icm *fw_icm; | 408 | struct mlx4_icm *fw_icm; |
407 | struct mlx4_icm *aux_icm; | 409 | struct mlx4_icm *aux_icm; |
408 | u32 catas_size; | 410 | u32 catas_size; |
@@ -410,6 +412,7 @@ struct mlx4_fw { | |||
410 | u8 clr_int_bar; | 412 | u8 clr_int_bar; |
411 | u8 catas_bar; | 413 | u8 catas_bar; |
412 | u8 comm_bar; | 414 | u8 comm_bar; |
415 | u8 clock_bar; | ||
413 | }; | 416 | }; |
414 | 417 | ||
415 | struct mlx4_comm { | 418 | struct mlx4_comm { |
@@ -826,6 +829,7 @@ struct mlx4_priv { | |||
826 | struct list_head bf_list; | 829 | struct list_head bf_list; |
827 | struct mutex bf_mutex; | 830 | struct mutex bf_mutex; |
828 | struct io_mapping *bf_mapping; | 831 | struct io_mapping *bf_mapping; |
832 | void __iomem *clock_mapping; | ||
829 | int reserved_mtts; | 833 | int reserved_mtts; |
830 | int fs_hash_mode; | 834 | int fs_hash_mode; |
831 | u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS]; | 835 | u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS]; |