habanalabs: Add INFO IOCTL opcode for time sync information
authorTomer Tayar <ttayar@habana.ai>
Tue, 31 Mar 2020 19:46:36 +0000 (22:46 +0300)
committerOded Gabbay <oded.gabbay@gmail.com>
Tue, 19 May 2020 11:48:41 +0000 (14:48 +0300)
Add a new opcode to the INFO IOCTL that retrieves the device time
alongside the host time, to allow a user application that want to measure
device time together with host time (such as a profiler) to synchronize
these times.

Signed-off-by: Tomer Tayar <ttayar@habana.ai>
Reviewed-by: Oded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
drivers/misc/habanalabs/goya/goya.c
drivers/misc/habanalabs/goya/goyaP.h
drivers/misc/habanalabs/habanalabs.h
drivers/misc/habanalabs/habanalabs_ioctl.c
drivers/misc/habanalabs/include/goya/asic_reg/goya_regs.h
drivers/misc/habanalabs/include/goya/asic_reg/psoc_timestamp_regs.h [new file with mode: 0644]
include/uapi/misc/habanalabs.h

index 19c3bdf..ddc506d 100644 (file)
@@ -5200,6 +5200,13 @@ static void goya_set_dma_mask_from_fw(struct hl_device *hdev)
        }
 }
 
+u64 goya_get_device_time(struct hl_device *hdev)
+{
+       u64 device_time = ((u64) RREG32(mmPSOC_TIMESTAMP_CNTCVU)) << 32;
+
+       return device_time | RREG32(mmPSOC_TIMESTAMP_CNTCVL);
+}
+
 static const struct hl_asic_funcs goya_funcs = {
        .early_init = goya_early_init,
        .early_fini = goya_early_fini,
@@ -5263,7 +5270,8 @@ static const struct hl_asic_funcs goya_funcs = {
        .get_queue_id_for_cq = goya_get_queue_id_for_cq,
        .read_device_fw_version = goya_read_device_fw_version,
        .load_firmware_to_device = goya_load_firmware_to_device,
-       .set_dma_mask_from_fw = goya_set_dma_mask_from_fw
+       .set_dma_mask_from_fw = goya_set_dma_mask_from_fw,
+       .get_device_time = goya_get_device_time
 };
 
 /*
index 86857cd..d36f8d9 100644 (file)
@@ -231,5 +231,6 @@ void goya_mmu_remove_device_cpu_mappings(struct hl_device *hdev);
 
 int goya_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk);
 u32 goya_get_queue_id_for_cq(struct hl_device *hdev, u32 cq_idx);
+u64 goya_get_device_time(struct hl_device *hdev);
 
 #endif /* GOYAP_H_ */
index 8db9554..a8ee241 100644 (file)
@@ -554,6 +554,7 @@ enum hl_pll_frequency {
  * @load_firmware_to_device: load the firmware to the device's memory
  * @set_dma_mask_from_fw: set the DMA mask in the driver according to the
  *                        firmware configuration
+ * @get_device_time: Get the device time.
  */
 struct hl_asic_funcs {
        int (*early_init)(struct hl_device *hdev);
@@ -646,6 +647,7 @@ struct hl_asic_funcs {
                                        enum hl_fw_component fwc);
        int (*load_firmware_to_device)(struct hl_device *hdev);
        void (*set_dma_mask_from_fw)(struct hl_device *hdev);
+       u64 (*get_device_time)(struct hl_device *hdev);
 };
 
 
index 6474b86..f599369 100644 (file)
@@ -258,6 +258,22 @@ static int get_reset_count(struct hl_device *hdev, struct hl_info_args *args)
                min((size_t) max_size, sizeof(reset_count))) ? -EFAULT : 0;
 }
 
+static int time_sync_info(struct hl_device *hdev, struct hl_info_args *args)
+{
+       struct hl_info_time_sync time_sync = {0};
+       u32 max_size = args->return_size;
+       void __user *out = (void __user *) (uintptr_t) args->return_pointer;
+
+       if ((!max_size) || (!out))
+               return -EINVAL;
+
+       time_sync.device_time = hdev->asic_funcs->get_device_time(hdev);
+       time_sync.host_time = ktime_get_raw_ns();
+
+       return copy_to_user(out, &time_sync,
+               min((size_t) max_size, sizeof(time_sync))) ? -EFAULT : 0;
+}
+
 static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data,
                                struct device *dev)
 {
@@ -315,6 +331,9 @@ static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data,
                rc = get_clk_rate(hdev, args);
                break;
 
+       case HL_INFO_TIME_SYNC:
+               return time_sync_info(hdev, args);
+
        default:
                dev_err(dev, "Invalid request %d\n", args->op);
                rc = -ENOTTY;
index fce490e..ce65c9d 100644 (file)
@@ -18,6 +18,7 @@
 #include "psoc_mme_pll_regs.h"
 #include "psoc_pci_pll_regs.h"
 #include "psoc_emmc_pll_regs.h"
+#include "psoc_timestamp_regs.h"
 #include "cpu_if_regs.h"
 #include "cpu_ca53_cfg_regs.h"
 #include "cpu_pll_regs.h"
diff --git a/drivers/misc/habanalabs/include/goya/asic_reg/psoc_timestamp_regs.h b/drivers/misc/habanalabs/include/goya/asic_reg/psoc_timestamp_regs.h
new file mode 100644 (file)
index 0000000..9ce2459
--- /dev/null
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright 2016-2018 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+/************************************
+ ** This is an auto-generated file **
+ **       DO NOT EDIT BELOW        **
+ ************************************/
+
+#ifndef ASIC_REG_PSOC_TIMESTAMP_REGS_H_
+#define ASIC_REG_PSOC_TIMESTAMP_REGS_H_
+
+/*
+ *****************************************
+ *   PSOC_TIMESTAMP (Prototype: TIMESTAMP)
+ *****************************************
+ */
+
+#define mmPSOC_TIMESTAMP_CNTCR                                       0xC49000
+
+#define mmPSOC_TIMESTAMP_CNTSR                                       0xC49004
+
+#define mmPSOC_TIMESTAMP_CNTCVL                                      0xC49008
+
+#define mmPSOC_TIMESTAMP_CNTCVU                                      0xC4900C
+
+#define mmPSOC_TIMESTAMP_CNTFID0                                     0xC49020
+
+#define mmPSOC_TIMESTAMP_PIDR4                                       0xC49FD0
+
+#define mmPSOC_TIMESTAMP_PIDR5                                       0xC49FD4
+
+#define mmPSOC_TIMESTAMP_PIDR6                                       0xC49FD8
+
+#define mmPSOC_TIMESTAMP_PIDR7                                       0xC49FDC
+
+#define mmPSOC_TIMESTAMP_PIDR0                                       0xC49FE0
+
+#define mmPSOC_TIMESTAMP_PIDR1                                       0xC49FE4
+
+#define mmPSOC_TIMESTAMP_PIDR2                                       0xC49FE8
+
+#define mmPSOC_TIMESTAMP_PIDR3                                       0xC49FEC
+
+#define mmPSOC_TIMESTAMP_CIDR0                                       0xC49FF0
+
+#define mmPSOC_TIMESTAMP_CIDR1                                       0xC49FF4
+
+#define mmPSOC_TIMESTAMP_CIDR2                                       0xC49FF8
+
+#define mmPSOC_TIMESTAMP_CIDR3                                       0xC49FFC
+
+#endif /* ASIC_REG_PSOC_TIMESTAMP_REGS_H_ */
index 4faa2c9..4d59305 100644 (file)
@@ -101,6 +101,8 @@ enum hl_device_status {
  * HL_INFO_RESET_COUNT   - Retrieve the counts of the soft and hard reset
  *                         operations performed on the device since the last
  *                         time the driver was loaded.
+ * HL_INFO_TIME_SYNC     - Retrieve the device's time alongside the host's time
+ *                         for synchronization.
  */
 #define HL_INFO_HW_IP_INFO             0
 #define HL_INFO_HW_EVENTS              1
@@ -111,6 +113,7 @@ enum hl_device_status {
 #define HL_INFO_HW_EVENTS_AGGREGATE    7
 #define HL_INFO_CLK_RATE               8
 #define HL_INFO_RESET_COUNT            9
+#define HL_INFO_TIME_SYNC              10
 
 #define HL_INFO_VERSION_MAX_LEN        128
 #define HL_INFO_CARD_NAME_MAX_LEN      16
@@ -169,6 +172,11 @@ struct hl_info_reset_count {
        __u32 soft_reset_cnt;
 };
 
+struct hl_info_time_sync {
+       __u64 device_time;
+       __u64 host_time;
+};
+
 struct hl_info_args {
        /* Location of relevant struct in userspace */
        __u64 return_pointer;