Commit db491e4f authored by Ofir Bitton's avatar Ofir Bitton Committed by Oded Gabbay

habanalabs: Add dropped cs statistics info struct

Add command submission statistics structure which can be obtained
through the info ioctl. Each drop counter describes the reason for
which the command submission was dropped.
This information is needed for the user to be aware of the specific
reason for which the submitted work was dropped. The user can then
utilize the driver more efficiently.
Signed-off-by: default avatarOfir Bitton <obitton@habana.ai>
Reviewed-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
parent c8f9b49d
...@@ -246,6 +246,18 @@ static void free_job(struct hl_device *hdev, struct hl_cs_job *job) ...@@ -246,6 +246,18 @@ static void free_job(struct hl_device *hdev, struct hl_cs_job *job)
kfree(job); kfree(job);
} }
static void cs_counters_aggregate(struct hl_device *hdev, struct hl_ctx *ctx)
{
hdev->aggregated_cs_counters.device_in_reset_drop_cnt +=
ctx->cs_counters.device_in_reset_drop_cnt;
hdev->aggregated_cs_counters.out_of_mem_drop_cnt +=
ctx->cs_counters.out_of_mem_drop_cnt;
hdev->aggregated_cs_counters.parsing_drop_cnt +=
ctx->cs_counters.parsing_drop_cnt;
hdev->aggregated_cs_counters.queue_full_drop_cnt +=
ctx->cs_counters.queue_full_drop_cnt;
}
static void cs_do_release(struct kref *ref) static void cs_do_release(struct kref *ref)
{ {
struct hl_cs *cs = container_of(ref, struct hl_cs, struct hl_cs *cs = container_of(ref, struct hl_cs,
...@@ -349,6 +361,8 @@ static void cs_do_release(struct kref *ref) ...@@ -349,6 +361,8 @@ static void cs_do_release(struct kref *ref)
dma_fence_signal(cs->fence); dma_fence_signal(cs->fence);
dma_fence_put(cs->fence); dma_fence_put(cs->fence);
cs_counters_aggregate(hdev, cs->ctx);
kfree(cs); kfree(cs);
} }
...@@ -632,12 +646,15 @@ static int cs_ioctl_default(struct hl_fpriv *hpriv, void __user *chunks, ...@@ -632,12 +646,15 @@ static int cs_ioctl_default(struct hl_fpriv *hpriv, void __user *chunks,
rc = validate_queue_index(hdev, chunk, &queue_type, rc = validate_queue_index(hdev, chunk, &queue_type,
&is_kernel_allocated_cb); &is_kernel_allocated_cb);
if (rc) if (rc) {
hpriv->ctx->cs_counters.parsing_drop_cnt++;
goto free_cs_object; goto free_cs_object;
}
if (is_kernel_allocated_cb) { if (is_kernel_allocated_cb) {
cb = get_cb_from_cs_chunk(hdev, &hpriv->cb_mgr, chunk); cb = get_cb_from_cs_chunk(hdev, &hpriv->cb_mgr, chunk);
if (!cb) { if (!cb) {
hpriv->ctx->cs_counters.parsing_drop_cnt++;
rc = -EINVAL; rc = -EINVAL;
goto free_cs_object; goto free_cs_object;
} }
...@@ -651,6 +668,7 @@ static int cs_ioctl_default(struct hl_fpriv *hpriv, void __user *chunks, ...@@ -651,6 +668,7 @@ static int cs_ioctl_default(struct hl_fpriv *hpriv, void __user *chunks,
job = hl_cs_allocate_job(hdev, queue_type, job = hl_cs_allocate_job(hdev, queue_type,
is_kernel_allocated_cb); is_kernel_allocated_cb);
if (!job) { if (!job) {
hpriv->ctx->cs_counters.out_of_mem_drop_cnt++;
dev_err(hdev->dev, "Failed to allocate a new job\n"); dev_err(hdev->dev, "Failed to allocate a new job\n");
rc = -ENOMEM; rc = -ENOMEM;
if (is_kernel_allocated_cb) if (is_kernel_allocated_cb)
...@@ -683,6 +701,7 @@ static int cs_ioctl_default(struct hl_fpriv *hpriv, void __user *chunks, ...@@ -683,6 +701,7 @@ static int cs_ioctl_default(struct hl_fpriv *hpriv, void __user *chunks,
rc = cs_parser(hpriv, job); rc = cs_parser(hpriv, job);
if (rc) { if (rc) {
hpriv->ctx->cs_counters.parsing_drop_cnt++;
dev_err(hdev->dev, dev_err(hdev->dev,
"Failed to parse JOB %d.%llu.%d, err %d, rejecting the CS\n", "Failed to parse JOB %d.%llu.%d, err %d, rejecting the CS\n",
cs->ctx->asid, cs->sequence, job->id, rc); cs->ctx->asid, cs->sequence, job->id, rc);
...@@ -691,6 +710,7 @@ static int cs_ioctl_default(struct hl_fpriv *hpriv, void __user *chunks, ...@@ -691,6 +710,7 @@ static int cs_ioctl_default(struct hl_fpriv *hpriv, void __user *chunks,
} }
if (int_queues_only) { if (int_queues_only) {
hpriv->ctx->cs_counters.parsing_drop_cnt++;
dev_err(hdev->dev, dev_err(hdev->dev,
"Reject CS %d.%llu because only internal queues jobs are present\n", "Reject CS %d.%llu because only internal queues jobs are present\n",
cs->ctx->asid, cs->sequence); cs->ctx->asid, cs->sequence);
...@@ -875,6 +895,7 @@ static int cs_ioctl_signal_wait(struct hl_fpriv *hpriv, enum hl_cs_type cs_type, ...@@ -875,6 +895,7 @@ static int cs_ioctl_signal_wait(struct hl_fpriv *hpriv, enum hl_cs_type cs_type,
job = hl_cs_allocate_job(hdev, q_type, true); job = hl_cs_allocate_job(hdev, q_type, true);
if (!job) { if (!job) {
ctx->cs_counters.out_of_mem_drop_cnt++;
dev_err(hdev->dev, "Failed to allocate a new job\n"); dev_err(hdev->dev, "Failed to allocate a new job\n");
rc = -ENOMEM; rc = -ENOMEM;
goto put_cs; goto put_cs;
...@@ -882,6 +903,7 @@ static int cs_ioctl_signal_wait(struct hl_fpriv *hpriv, enum hl_cs_type cs_type, ...@@ -882,6 +903,7 @@ static int cs_ioctl_signal_wait(struct hl_fpriv *hpriv, enum hl_cs_type cs_type,
cb = hl_cb_kernel_create(hdev, PAGE_SIZE); cb = hl_cb_kernel_create(hdev, PAGE_SIZE);
if (!cb) { if (!cb) {
ctx->cs_counters.out_of_mem_drop_cnt++;
kfree(job); kfree(job);
rc = -EFAULT; rc = -EFAULT;
goto put_cs; goto put_cs;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "include/armcp_if.h" #include "include/armcp_if.h"
#include "include/qman_if.h" #include "include/qman_if.h"
#include <uapi/misc/habanalabs.h>
#include <linux/cdev.h> #include <linux/cdev.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
...@@ -787,6 +788,7 @@ struct hl_ctx { ...@@ -787,6 +788,7 @@ struct hl_ctx {
struct mutex mem_hash_lock; struct mutex mem_hash_lock;
struct mutex mmu_lock; struct mutex mmu_lock;
struct list_head debugfs_list; struct list_head debugfs_list;
struct hl_cs_counters cs_counters;
u64 cs_sequence; u64 cs_sequence;
u64 *dram_default_hops; u64 *dram_default_hops;
spinlock_t cs_lock; spinlock_t cs_lock;
...@@ -1391,6 +1393,7 @@ struct hl_device_idle_busy_ts { ...@@ -1391,6 +1393,7 @@ struct hl_device_idle_busy_ts {
* @compute_ctx: current compute context executing. * @compute_ctx: current compute context executing.
* @idle_busy_ts_arr: array to hold time stamps of transitions from idle to busy * @idle_busy_ts_arr: array to hold time stamps of transitions from idle to busy
* and vice-versa * and vice-versa
* @aggregated_cs_counters: aggregated cs counters among all contexts
* @dram_used_mem: current DRAM memory consumption. * @dram_used_mem: current DRAM memory consumption.
* @timeout_jiffies: device CS timeout value. * @timeout_jiffies: device CS timeout value.
* @max_power: the max power of the device, as configured by the sysadmin. This * @max_power: the max power of the device, as configured by the sysadmin. This
...@@ -1489,6 +1492,8 @@ struct hl_device { ...@@ -1489,6 +1492,8 @@ struct hl_device {
struct hl_device_idle_busy_ts *idle_busy_ts_arr; struct hl_device_idle_busy_ts *idle_busy_ts_arr;
struct hl_cs_counters aggregated_cs_counters;
atomic64_t dram_used_mem; atomic64_t dram_used_mem;
u64 timeout_jiffies; u64 timeout_jiffies;
u64 max_power; u64 max_power;
......
...@@ -276,6 +276,27 @@ static int time_sync_info(struct hl_device *hdev, struct hl_info_args *args) ...@@ -276,6 +276,27 @@ static int time_sync_info(struct hl_device *hdev, struct hl_info_args *args)
min((size_t) max_size, sizeof(time_sync))) ? -EFAULT : 0; min((size_t) max_size, sizeof(time_sync))) ? -EFAULT : 0;
} }
static int cs_counters_info(struct hl_fpriv *hpriv, struct hl_info_args *args)
{
struct hl_device *hdev = hpriv->hdev;
struct hl_info_cs_counters cs_counters = {0};
u32 max_size = args->return_size;
void __user *out = (void __user *) (uintptr_t) args->return_pointer;
if ((!max_size) || (!out))
return -EINVAL;
memcpy(&cs_counters.cs_counters, &hdev->aggregated_cs_counters,
sizeof(struct hl_cs_counters));
if (hpriv->ctx)
memcpy(&cs_counters.ctx_cs_counters, &hpriv->ctx->cs_counters,
sizeof(struct hl_cs_counters));
return copy_to_user(out, &cs_counters,
min((size_t) max_size, sizeof(cs_counters))) ? -EFAULT : 0;
}
static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data, static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data,
struct device *dev) struct device *dev)
{ {
...@@ -336,6 +357,9 @@ static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data, ...@@ -336,6 +357,9 @@ static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data,
case HL_INFO_TIME_SYNC: case HL_INFO_TIME_SYNC:
return time_sync_info(hdev, args); return time_sync_info(hdev, args);
case HL_INFO_CS_COUNTERS:
return cs_counters_info(hpriv, args);
default: default:
dev_err(dev, "Invalid request %d\n", args->op); dev_err(dev, "Invalid request %d\n", args->op);
rc = -ENOTTY; rc = -ENOTTY;
......
...@@ -514,6 +514,7 @@ int hl_hw_queue_schedule_cs(struct hl_cs *cs) ...@@ -514,6 +514,7 @@ int hl_hw_queue_schedule_cs(struct hl_cs *cs)
hdev->asic_funcs->hw_queues_lock(hdev); hdev->asic_funcs->hw_queues_lock(hdev);
if (hl_device_disabled_or_in_reset(hdev)) { if (hl_device_disabled_or_in_reset(hdev)) {
ctx->cs_counters.device_in_reset_drop_cnt++;
dev_err(hdev->dev, dev_err(hdev->dev,
"device is disabled or in reset, CS rejected!\n"); "device is disabled or in reset, CS rejected!\n");
rc = -EPERM; rc = -EPERM;
...@@ -543,8 +544,10 @@ int hl_hw_queue_schedule_cs(struct hl_cs *cs) ...@@ -543,8 +544,10 @@ int hl_hw_queue_schedule_cs(struct hl_cs *cs)
break; break;
} }
if (rc) if (rc) {
ctx->cs_counters.queue_full_drop_cnt++;
goto unroll_cq_resv; goto unroll_cq_resv;
}
if (q->queue_type == QUEUE_TYPE_EXT || if (q->queue_type == QUEUE_TYPE_EXT ||
q->queue_type == QUEUE_TYPE_HW) q->queue_type == QUEUE_TYPE_HW)
......
...@@ -263,6 +263,7 @@ enum hl_device_status { ...@@ -263,6 +263,7 @@ enum hl_device_status {
* time the driver was loaded. * time the driver was loaded.
* HL_INFO_TIME_SYNC - Retrieve the device's time alongside the host's time * HL_INFO_TIME_SYNC - Retrieve the device's time alongside the host's time
* for synchronization. * for synchronization.
* HL_INFO_CS_COUNTERS - Retrieve command submission counters
*/ */
#define HL_INFO_HW_IP_INFO 0 #define HL_INFO_HW_IP_INFO 0
#define HL_INFO_HW_EVENTS 1 #define HL_INFO_HW_EVENTS 1
...@@ -274,6 +275,7 @@ enum hl_device_status { ...@@ -274,6 +275,7 @@ enum hl_device_status {
#define HL_INFO_CLK_RATE 8 #define HL_INFO_CLK_RATE 8
#define HL_INFO_RESET_COUNT 9 #define HL_INFO_RESET_COUNT 9
#define HL_INFO_TIME_SYNC 10 #define HL_INFO_TIME_SYNC 10
#define HL_INFO_CS_COUNTERS 11
#define HL_INFO_VERSION_MAX_LEN 128 #define HL_INFO_VERSION_MAX_LEN 128
#define HL_INFO_CARD_NAME_MAX_LEN 16 #define HL_INFO_CARD_NAME_MAX_LEN 16
...@@ -338,6 +340,25 @@ struct hl_info_time_sync { ...@@ -338,6 +340,25 @@ struct hl_info_time_sync {
__u64 host_time; __u64 host_time;
}; };
/**
* struct hl_info_cs_counters - command submission counters
* @out_of_mem_drop_cnt: dropped due to memory allocation issue
* @parsing_drop_cnt: dropped due to error in packet parsing
* @queue_full_drop_cnt: dropped due to queue full
* @device_in_reset_drop_cnt: dropped due to device in reset
*/
struct hl_cs_counters {
__u64 out_of_mem_drop_cnt;
__u64 parsing_drop_cnt;
__u64 queue_full_drop_cnt;
__u64 device_in_reset_drop_cnt;
};
struct hl_info_cs_counters {
struct hl_cs_counters cs_counters;
struct hl_cs_counters ctx_cs_counters;
};
struct hl_info_args { struct hl_info_args {
/* Location of relevant struct in userspace */ /* Location of relevant struct in userspace */
__u64 return_pointer; __u64 return_pointer;
......
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