mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 17:12:06 +00:00
habanalabs: support clock gating enable/disable
In Gaudi there is a feature of clock gating certain engines. Therefore, add this property to the device structure. In addition, due to a limitation of this feature, the driver needs to dynamically enable or disable this feature during run-time. Therefore, add ASIC interface functions to enable/disable this function from the common code. Moreover, this feature must be turned off when the user wishes to debug the ASIC by reading/writing registers and/or memory through the driver's debugfs. Therefore, add an option to enable/disable clock gating via the debugfs interface. Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
This commit is contained in:
parent
803917f960
commit
ca62433f53
@ -8,6 +8,16 @@ Description: Sets the device address to be used for read or write through
|
|||||||
only when the IOMMU is disabled.
|
only when the IOMMU is disabled.
|
||||||
The acceptable value is a string that starts with "0x"
|
The acceptable value is a string that starts with "0x"
|
||||||
|
|
||||||
|
What: /sys/kernel/debug/habanalabs/hl<n>/clk_gate
|
||||||
|
Date: May 2020
|
||||||
|
KernelVersion: 5.8
|
||||||
|
Contact: oded.gabbay@gmail.com
|
||||||
|
Description: Allow the root user to disable/enable in runtime the clock
|
||||||
|
gating mechanism in Gaudi. Due to how Gaudi is built, the
|
||||||
|
clock gating needs to be disabled in order to access the
|
||||||
|
registers of the TPC and MME engines. This is sometimes needed
|
||||||
|
during debug by the user and hence the user needs this option
|
||||||
|
|
||||||
What: /sys/kernel/debug/habanalabs/hl<n>/command_buffers
|
What: /sys/kernel/debug/habanalabs/hl<n>/command_buffers
|
||||||
Date: Jan 2019
|
Date: Jan 2019
|
||||||
KernelVersion: 5.1
|
KernelVersion: 5.1
|
||||||
|
@ -970,6 +970,55 @@ static ssize_t hl_device_write(struct file *f, const char __user *buf,
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t hl_clk_gate_read(struct file *f, char __user *buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
|
||||||
|
struct hl_device *hdev = entry->hdev;
|
||||||
|
char tmp_buf[200];
|
||||||
|
ssize_t rc;
|
||||||
|
|
||||||
|
if (*ppos)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sprintf(tmp_buf, "%d\n", hdev->clock_gating);
|
||||||
|
rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,
|
||||||
|
strlen(tmp_buf) + 1);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t hl_clk_gate_write(struct file *f, const char __user *buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
|
||||||
|
struct hl_device *hdev = entry->hdev;
|
||||||
|
u32 value;
|
||||||
|
ssize_t rc;
|
||||||
|
|
||||||
|
if (atomic_read(&hdev->in_reset)) {
|
||||||
|
dev_warn_ratelimited(hdev->dev,
|
||||||
|
"Can't change clock gating during reset\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = kstrtouint_from_user(buf, count, 10, &value);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
hdev->clock_gating = 1;
|
||||||
|
if (hdev->asic_funcs->enable_clock_gating)
|
||||||
|
hdev->asic_funcs->enable_clock_gating(hdev);
|
||||||
|
} else {
|
||||||
|
if (hdev->asic_funcs->disable_clock_gating)
|
||||||
|
hdev->asic_funcs->disable_clock_gating(hdev);
|
||||||
|
hdev->clock_gating = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t hl_stop_on_err_read(struct file *f, char __user *buf,
|
static ssize_t hl_stop_on_err_read(struct file *f, char __user *buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
@ -1058,6 +1107,12 @@ static const struct file_operations hl_device_fops = {
|
|||||||
.write = hl_device_write
|
.write = hl_device_write
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct file_operations hl_clk_gate_fops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.read = hl_clk_gate_read,
|
||||||
|
.write = hl_clk_gate_write
|
||||||
|
};
|
||||||
|
|
||||||
static const struct file_operations hl_stop_on_err_fops = {
|
static const struct file_operations hl_stop_on_err_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.read = hl_stop_on_err_read,
|
.read = hl_stop_on_err_read,
|
||||||
@ -1201,6 +1256,12 @@ void hl_debugfs_add_device(struct hl_device *hdev)
|
|||||||
dev_entry,
|
dev_entry,
|
||||||
&hl_device_fops);
|
&hl_device_fops);
|
||||||
|
|
||||||
|
debugfs_create_file("clk_gate",
|
||||||
|
0200,
|
||||||
|
dev_entry->root,
|
||||||
|
dev_entry,
|
||||||
|
&hl_clk_gate_fops);
|
||||||
|
|
||||||
debugfs_create_file("stop_on_err",
|
debugfs_create_file("stop_on_err",
|
||||||
0644,
|
0644,
|
||||||
dev_entry->root,
|
dev_entry->root,
|
||||||
|
@ -603,6 +603,9 @@ int hl_device_set_debug_mode(struct hl_device *hdev, bool enable)
|
|||||||
|
|
||||||
hdev->in_debug = 0;
|
hdev->in_debug = 0;
|
||||||
|
|
||||||
|
if (!hdev->hard_reset_pending)
|
||||||
|
hdev->asic_funcs->enable_clock_gating(hdev);
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,6 +616,7 @@ int hl_device_set_debug_mode(struct hl_device *hdev, bool enable)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hdev->asic_funcs->disable_clock_gating(hdev);
|
||||||
hdev->in_debug = 1;
|
hdev->in_debug = 1;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -5018,6 +5018,16 @@ int goya_armcp_info_get(struct hl_device *hdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void goya_enable_clock_gating(struct hl_device *hdev)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void goya_disable_clock_gating(struct hl_device *hdev)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static bool goya_is_device_idle(struct hl_device *hdev, u32 *mask,
|
static bool goya_is_device_idle(struct hl_device *hdev, u32 *mask,
|
||||||
struct seq_file *s)
|
struct seq_file *s)
|
||||||
{
|
{
|
||||||
@ -5239,6 +5249,8 @@ static const struct hl_asic_funcs goya_funcs = {
|
|||||||
.mmu_invalidate_cache = goya_mmu_invalidate_cache,
|
.mmu_invalidate_cache = goya_mmu_invalidate_cache,
|
||||||
.mmu_invalidate_cache_range = goya_mmu_invalidate_cache_range,
|
.mmu_invalidate_cache_range = goya_mmu_invalidate_cache_range,
|
||||||
.send_heartbeat = goya_send_heartbeat,
|
.send_heartbeat = goya_send_heartbeat,
|
||||||
|
.enable_clock_gating = goya_enable_clock_gating,
|
||||||
|
.disable_clock_gating = goya_disable_clock_gating,
|
||||||
.debug_coresight = goya_debug_coresight,
|
.debug_coresight = goya_debug_coresight,
|
||||||
.is_device_idle = goya_is_device_idle,
|
.is_device_idle = goya_is_device_idle,
|
||||||
.soft_reset_late_init = goya_soft_reset_late_init,
|
.soft_reset_late_init = goya_soft_reset_late_init,
|
||||||
|
@ -578,6 +578,8 @@ enum hl_pll_frequency {
|
|||||||
* @mmu_invalidate_cache_range: flush specific MMU STLB cache lines with
|
* @mmu_invalidate_cache_range: flush specific MMU STLB cache lines with
|
||||||
* ASID-VA-size mask.
|
* ASID-VA-size mask.
|
||||||
* @send_heartbeat: send is-alive packet to ArmCP and verify response.
|
* @send_heartbeat: send is-alive packet to ArmCP and verify response.
|
||||||
|
* @enable_clock_gating: enable clock gating for reducing power consumption.
|
||||||
|
* @disable_clock_gating: disable clock for accessing registers on HBW.
|
||||||
* @debug_coresight: perform certain actions on Coresight for debugging.
|
* @debug_coresight: perform certain actions on Coresight for debugging.
|
||||||
* @is_device_idle: return true if device is idle, false otherwise.
|
* @is_device_idle: return true if device is idle, false otherwise.
|
||||||
* @soft_reset_late_init: perform certain actions needed after soft reset.
|
* @soft_reset_late_init: perform certain actions needed after soft reset.
|
||||||
@ -678,6 +680,8 @@ struct hl_asic_funcs {
|
|||||||
void (*mmu_invalidate_cache_range)(struct hl_device *hdev, bool is_hard,
|
void (*mmu_invalidate_cache_range)(struct hl_device *hdev, bool is_hard,
|
||||||
u32 asid, u64 va, u64 size);
|
u32 asid, u64 va, u64 size);
|
||||||
int (*send_heartbeat)(struct hl_device *hdev);
|
int (*send_heartbeat)(struct hl_device *hdev);
|
||||||
|
void (*enable_clock_gating)(struct hl_device *hdev);
|
||||||
|
void (*disable_clock_gating)(struct hl_device *hdev);
|
||||||
int (*debug_coresight)(struct hl_device *hdev, void *data);
|
int (*debug_coresight)(struct hl_device *hdev, void *data);
|
||||||
bool (*is_device_idle)(struct hl_device *hdev, u32 *mask,
|
bool (*is_device_idle)(struct hl_device *hdev, u32 *mask,
|
||||||
struct seq_file *s);
|
struct seq_file *s);
|
||||||
@ -1408,6 +1412,7 @@ struct hl_device_idle_busy_ts {
|
|||||||
* huge pages.
|
* huge pages.
|
||||||
* @init_done: is the initialization of the device done.
|
* @init_done: is the initialization of the device done.
|
||||||
* @mmu_enable: is MMU enabled.
|
* @mmu_enable: is MMU enabled.
|
||||||
|
* @clock_gating: is clock gating enabled.
|
||||||
* @device_cpu_disabled: is the device CPU disabled (due to timeouts)
|
* @device_cpu_disabled: is the device CPU disabled (due to timeouts)
|
||||||
* @dma_mask: the dma mask that was set for this device
|
* @dma_mask: the dma mask that was set for this device
|
||||||
* @in_debug: is device under debug. This, together with fpriv_list, enforces
|
* @in_debug: is device under debug. This, together with fpriv_list, enforces
|
||||||
@ -1494,6 +1499,7 @@ struct hl_device {
|
|||||||
u8 dram_default_page_mapping;
|
u8 dram_default_page_mapping;
|
||||||
u8 pmmu_huge_range;
|
u8 pmmu_huge_range;
|
||||||
u8 init_done;
|
u8 init_done;
|
||||||
|
u8 clock_gating;
|
||||||
u8 device_cpu_disabled;
|
u8 device_cpu_disabled;
|
||||||
u8 dma_mask;
|
u8 dma_mask;
|
||||||
u8 in_debug;
|
u8 in_debug;
|
||||||
|
@ -231,6 +231,7 @@ static void set_driver_behavior_per_device(struct hl_device *hdev)
|
|||||||
hdev->fw_loading = 1;
|
hdev->fw_loading = 1;
|
||||||
hdev->cpu_queues_enable = 1;
|
hdev->cpu_queues_enable = 1;
|
||||||
hdev->heartbeat = 1;
|
hdev->heartbeat = 1;
|
||||||
|
hdev->clock_gating = 1;
|
||||||
|
|
||||||
hdev->reset_pcilink = 0;
|
hdev->reset_pcilink = 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user