Users and sysadmins usually want to know what is the device utilization as a level 0 indication if they are efficiently using the device. Add a new opcode to the INFO IOCTL that will return the device utilization over the last period of 100-1000ms. The return value is 0-100, representing as percentage the total utilization rate.
Unified · Split
| @@ -178,11 +178,23 @@ static void cs_do_release(struct kref *ref) · 177 unmodified lines | |||
| 178 | 178 | ||
| 179 | /* We also need to update CI for internal queues */ | 179 | /* We also need to update CI for internal queues */ |
| 180 | if (cs->submitted) { | 180 | if (cs->submitted) { |
| 181 | int cs_cnt = atomic_dec_return(&hdev->cs_active_cnt); | 181 | hdev->asic_funcs->hw_queues_lock(hdev); |
| 182 | 182 | ||
| 183 | WARN_ONCE((cs_cnt < 0), | 183 | hdev->cs_active_cnt--; |
| 184 | "hl%d: error in CS active cnt %d\n", | 184 | if (!hdev->cs_active_cnt) { |
| 185 | hdev->id, cs_cnt); | 185 | struct hl_device_idle_busy_ts *ts; |
| 186 | |||
| 187 | ts = &hdev->idle_busy_ts_arr[hdev->idle_busy_ts_idx++]; | ||
| 188 | ts->busy_to_idle_ts = ktime_get(); | ||
| 189 | |||
| 190 | if (hdev->idle_busy_ts_idx == HL_IDLE_BUSY_TS_ARR_SIZE) | ||
| 191 | hdev->idle_busy_ts_idx = 0; | ||
| 192 | } else if (hdev->cs_active_cnt < 0) { | ||
| 193 | dev_crit(hdev->dev, "CS active cnt %d is negative\n", | ||
| 194 | hdev->cs_active_cnt); | ||
| 195 | } | ||
| 196 | |||
| 197 | hdev->asic_funcs->hw_queues_unlock(hdev); | ||
| 186 | 198 | ||
| 187 | hl_int_hw_queue_update_ci(cs); | 199 | hl_int_hw_queue_update_ci(cs); |
| 188 | 200 | ||
| @@ -293,6 +293,14 @@ static int device_early_init(struct hl_device *hdev) · 292 unmodified lines | |||
| 293 | goto free_eq_wq; | 293 | goto free_eq_wq; |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | hdev->idle_busy_ts_arr = kmalloc_array(HL_IDLE_BUSY_TS_ARR_SIZE, | ||
| 297 | sizeof(struct hl_device_idle_busy_ts), | ||
| 298 | (GFP_KERNEL | __GFP_ZERO)); | ||
| 299 | if (!hdev->idle_busy_ts_arr) { | ||
| 300 | rc = -ENOMEM; | ||
| 301 | goto free_chip_info; | ||
| 302 | } | ||
| 303 | |||
| 296 | hl_cb_mgr_init(&hdev->kernel_cb_mgr); | 304 | hl_cb_mgr_init(&hdev->kernel_cb_mgr); |
| 297 | 305 | ||
| 298 | mutex_init(&hdev->send_cpu_message_lock); | 306 | mutex_init(&hdev->send_cpu_message_lock); |
| @@ -303,10 +311,11 @@ static int device_early_init(struct hl_device *hdev) · 4 unmodified lines | |||
| 303 | INIT_LIST_HEAD(&hdev->fpriv_list); | 311 | INIT_LIST_HEAD(&hdev->fpriv_list); |
| 304 | mutex_init(&hdev->fpriv_list_lock); | 312 | mutex_init(&hdev->fpriv_list_lock); |
| 305 | atomic_set(&hdev->in_reset, 0); | 313 | atomic_set(&hdev->in_reset, 0); |
| 306 | atomic_set(&hdev->cs_active_cnt, 0); | ||
| 307 | 314 | ||
| 308 | return 0; | 315 | return 0; |
| 309 | 316 | ||
| 317 | free_chip_info: | ||
| 318 | kfree(hdev->hl_chip_info); | ||
| 310 | free_eq_wq: | 319 | free_eq_wq: |
| 311 | destroy_workqueue(hdev->eq_wq); | 320 | destroy_workqueue(hdev->eq_wq); |
| 312 | free_cq_wq: | 321 | free_cq_wq: |
| @@ -336,6 +345,7 @@ static void device_early_fini(struct hl_device *hdev) · 23 unmodified lines | |||
| 336 | 345 | ||
| 337 | hl_cb_mgr_fini(hdev, &hdev->kernel_cb_mgr); | 346 | hl_cb_mgr_fini(hdev, &hdev->kernel_cb_mgr); |
| 338 | 347 | ||
| 348 | kfree(hdev->idle_busy_ts_arr); | ||
| 339 | kfree(hdev->hl_chip_info); | 349 | kfree(hdev->hl_chip_info); |
| 340 | 350 | ||
| 341 | destroy_workqueue(hdev->eq_wq); | 351 | destroy_workqueue(hdev->eq_wq); |
| @@ -451,6 +461,102 @@ static void device_late_fini(struct hl_device *hdev) · 109 unmodified lines | |||
| 451 | hdev->late_init_done = false; | 461 | hdev->late_init_done = false; |
| 452 | } | 462 | } |
| 453 | 463 | ||
| 464 | uint32_t hl_device_utilization(struct hl_device *hdev, uint32_t period_ms) | ||
| 465 | { | ||
| 466 | struct hl_device_idle_busy_ts *ts; | ||
| 467 | ktime_t zero_ktime, curr = ktime_get(); | ||
| 468 | u32 overlap_cnt = 0, last_index = hdev->idle_busy_ts_idx; | ||
| 469 | s64 period_us, last_start_us, last_end_us, last_busy_time_us, | ||
| 470 | total_busy_time_us = 0, total_busy_time_ms; | ||
| 471 | |||
| 472 | zero_ktime = ktime_set(0, 0); | ||
| 473 | period_us = period_ms * USEC_PER_MSEC; | ||
| 474 | ts = &hdev->idle_busy_ts_arr[last_index]; | ||
| 475 | |||
| 476 | /* check case that device is currently in idle */ | ||
| 477 | if (!ktime_compare(ts->busy_to_idle_ts, zero_ktime) && | ||
| 478 | !ktime_compare(ts->idle_to_busy_ts, zero_ktime)) { | ||
| 479 | |||
| 480 | last_index--; | ||
| 481 | /* Handle case idle_busy_ts_idx was 0 */ | ||
| 482 | if (last_index > HL_IDLE_BUSY_TS_ARR_SIZE) | ||
| 483 | last_index = HL_IDLE_BUSY_TS_ARR_SIZE - 1; | ||
| 484 | |||
| 485 | ts = &hdev->idle_busy_ts_arr[last_index]; | ||
| 486 | } | ||
| 487 | |||
| 488 | while (overlap_cnt < HL_IDLE_BUSY_TS_ARR_SIZE) { | ||
| 489 | /* Check if we are in last sample case. i.e. if the sample | ||
| 490 | * begun before the sampling period. This could be a real | ||
| 491 | * sample or 0 so need to handle both cases | ||
| 492 | */ | ||
| 493 | last_start_us = ktime_to_us( | ||
| 494 | ktime_sub(curr, ts->idle_to_busy_ts)); | ||
| 495 | |||
| 496 | if (last_start_us > period_us) { | ||
| 497 | |||
| 498 | /* First check two cases: | ||
| 499 | * 1. If the device is currently busy | ||
| 500 | * 2. If the device was idle during the whole sampling | ||
| 501 | * period | ||
| 502 | */ | ||
| 503 | |||
| 504 | if (!ktime_compare(ts->busy_to_idle_ts, zero_ktime)) { | ||
| 505 | /* Check if the device is currently busy */ | ||
| 506 | if (ktime_compare(ts->idle_to_busy_ts, | ||
| 507 | zero_ktime)) | ||
| 508 | return 100; | ||
| 509 | |||
| 510 | /* We either didn't have any activity or we | ||
| 511 | * reached an entry which is 0. Either way, | ||
| 512 | * exit and return what was accumulated so far | ||
| 513 | */ | ||
| 514 | break; | ||
| 515 | } | ||
| 516 | |||
| 517 | /* If sample has finished, check it is relevant */ | ||
| 518 | last_end_us = ktime_to_us( | ||
| 519 | ktime_sub(curr, ts->busy_to_idle_ts)); | ||
| 520 | |||
| 521 | if (last_end_us > period_us) | ||
| 522 | break; | ||
| 523 | |||
| 524 | /* It is relevant so add it but with adjustment */ | ||
| 525 | last_busy_time_us = ktime_to_us( | ||
| 526 | ktime_sub(ts->busy_to_idle_ts, | ||
| 527 | ts->idle_to_busy_ts)); | ||
| 528 | total_busy_time_us += last_busy_time_us - | ||
| 529 | (last_start_us - period_us); | ||
| 530 | break; | ||
| 531 | } | ||
| 532 | |||
| 533 | /* Check if the sample is finished or still open */ | ||
| 534 | if (ktime_compare(ts->busy_to_idle_ts, zero_ktime)) | ||
| 535 | last_busy_time_us = ktime_to_us( | ||
| 536 | ktime_sub(ts->busy_to_idle_ts, | ||
| 537 | ts->idle_to_busy_ts)); | ||
| 538 | else | ||
| 539 | last_busy_time_us = ktime_to_us( | ||
| 540 | ktime_sub(curr, ts->idle_to_busy_ts)); | ||
| 541 | |||
| 542 | total_busy_time_us += last_busy_time_us; | ||
| 543 | |||
| 544 | last_index--; | ||
| 545 | /* Handle case idle_busy_ts_idx was 0 */ | ||
| 546 | if (last_index > HL_IDLE_BUSY_TS_ARR_SIZE) | ||
| 547 | last_index = HL_IDLE_BUSY_TS_ARR_SIZE - 1; | ||
| 548 | |||
| 549 | ts = &hdev->idle_busy_ts_arr[last_index]; | ||
| 550 | |||
| 551 | overlap_cnt++; | ||
| 552 | } | ||
| 553 | |||
| 554 | total_busy_time_ms = DIV_ROUND_UP_ULL(total_busy_time_us, | ||
| 555 | USEC_PER_MSEC); | ||
| 556 | |||
| 557 | return DIV_ROUND_UP_ULL(total_busy_time_ms * 100, period_ms); | ||
| 558 | } | ||
| 559 | |||
| 454 | /* | 560 | /* |
| 455 | * hl_device_set_frequency - set the frequency of the device | 561 | * hl_device_set_frequency - set the frequency of the device |
| 456 | * | 562 | * |
| @@ -808,6 +914,14 @@ again: · 351 unmodified lines | |||
| 808 | for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++) | 914 | for (i = 0 ; i < hdev->asic_prop.completion_queues_count ; i++) |
| 809 | hl_cq_reset(hdev, &hdev->completion_queue[i]); | 915 | hl_cq_reset(hdev, &hdev->completion_queue[i]); |
| 810 | 916 | ||
| 917 | hdev->idle_busy_ts_idx = 0; | ||
| 918 | hdev->idle_busy_ts_arr[0].busy_to_idle_ts = ktime_set(0, 0); | ||
| 919 | hdev->idle_busy_ts_arr[0].idle_to_busy_ts = ktime_set(0, 0); | ||
| 920 | |||
| 921 | if (hdev->cs_active_cnt) | ||
| 922 | dev_crit(hdev->dev, "CS active cnt %d is not 0 during reset\n", | ||
| 923 | hdev->cs_active_cnt); | ||
| 924 | |||
| 811 | mutex_lock(&hdev->fpriv_list_lock); | 925 | mutex_lock(&hdev->fpriv_list_lock); |
| 812 | 926 | ||
| 813 | /* Make sure the context switch phase will run again */ | 927 | /* Make sure the context switch phase will run again */ |
| @@ -45,6 +45,8 @@ · 44 unmodified lines | |||
| 45 | /* MUST BE POWER OF 2 and larger than 1 */ | 45 | /* MUST BE POWER OF 2 and larger than 1 */ |
| 46 | #define HL_MAX_PENDING_CS 64 | 46 | #define HL_MAX_PENDING_CS 64 |
| 47 | 47 | ||
| 48 | #define HL_IDLE_BUSY_TS_ARR_SIZE 4096 | ||
| 49 | |||
| 48 | /* Memory */ | 50 | /* Memory */ |
| 49 | #define MEM_HASH_TABLE_BITS 7 /* 1 << 7 buckets */ | 51 | #define MEM_HASH_TABLE_BITS 7 /* 1 << 7 buckets */ |
| 50 | 52 | ||
| @@ -1156,6 +1158,16 @@ struct hl_device_reset_work { · 1105 unmodified lines | |||
| 1156 | struct hl_device *hdev; | 1158 | struct hl_device *hdev; |
| 1157 | }; | 1159 | }; |
| 1158 | 1160 | ||
| 1161 | /** | ||
| 1162 | * struct hl_device_idle_busy_ts - used for calculating device utilization rate. | ||
| 1163 | * @idle_to_busy_ts: timestamp where device changed from idle to busy. | ||
| 1164 | * @busy_to_idle_ts: timestamp where device changed from busy to idle. | ||
| 1165 | */ | ||
| 1166 | struct hl_device_idle_busy_ts { | ||
| 1167 | ktime_t idle_to_busy_ts; | ||
| 1168 | ktime_t busy_to_idle_ts; | ||
| 1169 | }; | ||
| 1170 | |||
| 1159 | /** | 1171 | /** |
| 1160 | * struct hl_device - habanalabs device structure. | 1172 | * struct hl_device - habanalabs device structure. |
| 1161 | * @pdev: pointer to PCI device, can be NULL in case of simulator device. | 1173 | * @pdev: pointer to PCI device, can be NULL in case of simulator device. |
| @@ -1203,19 +1215,22 @@ struct hl_device_reset_work { · 41 unmodified lines | |||
| 1203 | * when a user opens the device | 1215 | * when a user opens the device |
| 1204 | * @fpriv_list_lock: protects the fpriv_list | 1216 | * @fpriv_list_lock: protects the fpriv_list |
| 1205 | * @compute_ctx: current compute context executing. | 1217 | * @compute_ctx: current compute context executing. |
| 1218 | * @idle_busy_ts_arr: array to hold time stamps of transitions from idle to busy | ||
| 1219 | * and vice-versa | ||
| 1206 | * @dram_used_mem: current DRAM memory consumption. | 1220 | * @dram_used_mem: current DRAM memory consumption. |
| 1207 | * @timeout_jiffies: device CS timeout value. | 1221 | * @timeout_jiffies: device CS timeout value. |
| 1208 | * @max_power: the max power of the device, as configured by the sysadmin. This | 1222 | * @max_power: the max power of the device, as configured by the sysadmin. This |
| 1209 | * value is saved so in case of hard-reset, KMD will restore this | 1223 | * value is saved so in case of hard-reset, KMD will restore this |
| 1210 | * value and update the F/W after the re-initialization | 1224 | * value and update the F/W after the re-initialization |
| 1211 | * @in_reset: is device in reset flow. | 1225 | * @in_reset: is device in reset flow. |
| 1226 | * @curr_pll_profile: current PLL profile. | ||
| 1212 | * @cs_active_cnt: number of active command submissions on this device (active | 1227 | * @cs_active_cnt: number of active command submissions on this device (active |
| 1213 | * means already in H/W queues) | 1228 | * means already in H/W queues) |
| 1214 | * @curr_pll_profile: current PLL profile. | ||
| 1215 | * @major: habanalabs KMD major. | 1229 | * @major: habanalabs KMD major. |
| 1216 | * @high_pll: high PLL profile frequency. | 1230 | * @high_pll: high PLL profile frequency. |
| 1217 | * @soft_reset_cnt: number of soft reset since KMD loading. | 1231 | * @soft_reset_cnt: number of soft reset since KMD loading. |
| 1218 | * @hard_reset_cnt: number of hard reset since KMD loading. | 1232 | * @hard_reset_cnt: number of hard reset since KMD loading. |
| 1233 | * @idle_busy_ts_idx: index of current entry in idle_busy_ts_arr | ||
| 1219 | * @id: device minor. | 1234 | * @id: device minor. |
| 1220 | * @id_control: minor of the control device | 1235 | * @id_control: minor of the control device |
| 1221 | * @disabled: is device disabled. | 1236 | * @disabled: is device disabled. |
| @@ -1285,16 +1300,19 @@ struct hl_device { · 63 unmodified lines | |||
| 1285 | 1300 | ||
| 1286 | struct hl_ctx *compute_ctx; | 1301 | struct hl_ctx *compute_ctx; |
| 1287 | 1302 | ||
| 1303 | struct hl_device_idle_busy_ts *idle_busy_ts_arr; | ||
| 1304 | |||
| 1288 | atomic64_t dram_used_mem; | 1305 | atomic64_t dram_used_mem; |
| 1289 | u64 timeout_jiffies; | 1306 | u64 timeout_jiffies; |
| 1290 | u64 max_power; | 1307 | u64 max_power; |
| 1291 | atomic_t in_reset; | 1308 | atomic_t in_reset; |
| 1292 | atomic_t cs_active_cnt; | ||
| 1293 | enum hl_pll_frequency curr_pll_profile; | 1309 | enum hl_pll_frequency curr_pll_profile; |
| 1310 | int cs_active_cnt; | ||
| 1294 | u32 major; | 1311 | u32 major; |
| 1295 | u32 high_pll; | 1312 | u32 high_pll; |
| 1296 | u32 soft_reset_cnt; | 1313 | u32 soft_reset_cnt; |
| 1297 | u32 hard_reset_cnt; | 1314 | u32 hard_reset_cnt; |
| 1315 | u32 idle_busy_ts_idx; | ||
| 1298 | u16 id; | 1316 | u16 id; |
| 1299 | u16 id_control; | 1317 | u16 id_control; |
| 1300 | u8 disabled; | 1318 | u8 disabled; |
| @@ -1457,6 +1475,7 @@ int hl_device_reset(struct hl_device *hdev, bool hard_reset, · 156 unmodified lines | |||
| 1457 | void hl_hpriv_get(struct hl_fpriv *hpriv); | 1475 | void hl_hpriv_get(struct hl_fpriv *hpriv); |
| 1458 | void hl_hpriv_put(struct hl_fpriv *hpriv); | 1476 | void hl_hpriv_put(struct hl_fpriv *hpriv); |
| 1459 | int hl_device_set_frequency(struct hl_device *hdev, enum hl_pll_frequency freq); | 1477 | int hl_device_set_frequency(struct hl_device *hdev, enum hl_pll_frequency freq); |
| 1478 | uint32_t hl_device_utilization(struct hl_device *hdev, uint32_t period_ms); | ||
| 1460 | 1479 | ||
| 1461 | int hl_build_hwmon_channel_info(struct hl_device *hdev, | 1480 | int hl_build_hwmon_channel_info(struct hl_device *hdev, |
| 1462 | struct armcp_sensor *sensors_arr); | 1481 | struct armcp_sensor *sensors_arr); |
| @@ -197,6 +197,29 @@ out: · 196 unmodified lines | |||
| 197 | return rc; | 197 | return rc; |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | static int device_utilization(struct hl_device *hdev, struct hl_info_args *args) | ||
| 201 | { | ||
| 202 | struct hl_info_device_utilization device_util = {0}; | ||
| 203 | u32 max_size = args->return_size; | ||
| 204 | void __user *out = (void __user *) (uintptr_t) args->return_pointer; | ||
| 205 | |||
| 206 | if ((!max_size) || (!out)) | ||
| 207 | return -EINVAL; | ||
| 208 | |||
| 209 | if ((args->period_ms < 100) || (args->period_ms > 1000) || | ||
| 210 | (args->period_ms % 100)) { | ||
| 211 | dev_err(hdev->dev, | ||
| 212 | "period %u must be between 100 - 1000 and must be divisible by 100\n", | ||
| 213 | args->period_ms); | ||
| 214 | return -EINVAL; | ||
| 215 | } | ||
| 216 | |||
| 217 | device_util.utilization = hl_device_utilization(hdev, args->period_ms); | ||
| 218 | |||
| 219 | return copy_to_user(out, &device_util, | ||
| 220 | min((size_t) max_size, sizeof(device_util))) ? -EFAULT : 0; | ||
| 221 | } | ||
| 222 | |||
| 200 | static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data, | 223 | static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data, |
| 201 | struct device *dev) | 224 | struct device *dev) |
| 202 | { | 225 | { |
| @@ -239,6 +262,10 @@ static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data, · 36 unmodified lines | |||
| 239 | rc = hw_idle(hdev, args); | 262 | rc = hw_idle(hdev, args); |
| 240 | break; | 263 | break; |
| 241 | 264 | ||
| 265 | case HL_INFO_DEVICE_UTILIZATION: | ||
| 266 | rc = device_utilization(hdev, args); | ||
| 267 | break; | ||
| 268 | |||
| 242 | default: | 269 | default: |
| 243 | dev_err(dev, "Invalid request %d\n", args->op); | 270 | dev_err(dev, "Invalid request %d\n", args->op); |
| 244 | rc = -ENOTTY; | 271 | rc = -ENOTTY; |
| @@ -364,7 +364,13 @@ int hl_hw_queue_schedule_cs(struct hl_cs *cs) · 363 unmodified lines | |||
| 364 | spin_unlock(&hdev->hw_queues_mirror_lock); | 364 | spin_unlock(&hdev->hw_queues_mirror_lock); |
| 365 | } | 365 | } |
| 366 | 366 | ||
| 367 | atomic_inc(&hdev->cs_active_cnt); | 367 | if (!hdev->cs_active_cnt++) { |
| 368 | struct hl_device_idle_busy_ts *ts; | ||
| 369 | |||
| 370 | ts = &hdev->idle_busy_ts_arr[hdev->idle_busy_ts_idx]; | ||
| 371 | ts->busy_to_idle_ts = ktime_set(0, 0); | ||
| 372 | ts->idle_to_busy_ts = ktime_get(); | ||
| 373 | } | ||
| 368 | 374 | ||
| 369 | list_for_each_entry_safe(job, tmp, &cs->job_list, cs_node) | 375 | list_for_each_entry_safe(job, tmp, &cs->job_list, cs_node) |
| 370 | if (job->ext_queue) | 376 | if (job->ext_queue) |
| @@ -38,4 +38,6 @@ · 37 unmodified lines | |||
| 38 | 38 | ||
| 39 | #define TPC_MAX_NUM 8 | 39 | #define TPC_MAX_NUM 8 |
| 40 | 40 | ||
| 41 | #define MME_MAX_NUM 1 | ||
| 42 | |||
| 41 | #endif /* GOYA_H */ | 43 | #endif /* GOYA_H */ |
| @@ -77,22 +77,29 @@ enum hl_device_status { · 76 unmodified lines | |||
| 77 | 77 | ||
| 78 | /* Opcode for management ioctl | 78 | /* Opcode for management ioctl |
| 79 | * | 79 | * |
| 80 | * HW_IP_INFO - Receive information about different IP blocks in the | 80 | * HW_IP_INFO - Receive information about different IP blocks in the |
| 81 | * device. | 81 | * device. |
| 82 | * HL_INFO_HW_EVENTS - Receive an array describing how many times each event | 82 | * HL_INFO_HW_EVENTS - Receive an array describing how many times each event |
| 83 | * occurred since the last hard reset. | 83 | * occurred since the last hard reset. |
| 84 | * HL_INFO_DRAM_USAGE - Retrieve the dram usage inside the device and of the | 84 | * HL_INFO_DRAM_USAGE - Retrieve the dram usage inside the device and of the |
| 85 | * specific context. This is relevant only for GOYA device. | 85 | * specific context. This is relevant only for devices |
| 86 | * HL_INFO_HW_IDLE - Retrieve information about the idle status of each | 86 | * where the dram is managed by the kernel driver |
| 87 | * internal engine. | 87 | * HL_INFO_HW_IDLE - Retrieve information about the idle status of each |
| 88 | * internal engine. | ||
| 88 | * HL_INFO_DEVICE_STATUS - Retrieve the device's status. This opcode doesn't | 89 | * HL_INFO_DEVICE_STATUS - Retrieve the device's status. This opcode doesn't |
| 89 | * require an open context. | 90 | * require an open context. |
| 91 | * HL_INFO_DEVICE_UTILIZATION - Retrieve the total utilization of the device | ||
| 92 | * over the last period specified by the user. | ||
| 93 | * The period can be between 100ms to 1s, in | ||
| 94 | * resolution of 100ms. The return value is a | ||
| 95 | * percentage of the utilization rate. | ||
| 90 | */ | 96 | */ |
| 91 | #define HL_INFO_HW_IP_INFO 0 | 97 | #define HL_INFO_HW_IP_INFO 0 |
| 92 | #define HL_INFO_HW_EVENTS 1 | 98 | #define HL_INFO_HW_EVENTS 1 |
| 93 | #define HL_INFO_DRAM_USAGE 2 | 99 | #define HL_INFO_DRAM_USAGE 2 |
| 94 | #define HL_INFO_HW_IDLE 3 | 100 | #define HL_INFO_HW_IDLE 3 |
| 95 | #define HL_INFO_DEVICE_STATUS 4 | 101 | #define HL_INFO_DEVICE_STATUS 4 |
| 102 | #define HL_INFO_DEVICE_UTILIZATION 6 | ||
| 96 | 103 | ||
| 97 | #define HL_INFO_VERSION_MAX_LEN 128 | 104 | #define HL_INFO_VERSION_MAX_LEN 128 |
| 98 | 105 | ||
| @@ -134,6 +141,11 @@ struct hl_info_device_status { · 35 unmodified lines | |||
| 134 | __u32 pad; | 141 | __u32 pad; |
| 135 | }; | 142 | }; |
| 136 | 143 | ||
| 144 | struct hl_info_device_utilization { | ||
| 145 | __u32 utilization; | ||
| 146 | __u32 pad; | ||
| 147 | }; | ||
| 148 | |||
| 137 | struct hl_info_args { | 149 | struct hl_info_args { |
| 138 | /* Location of relevant struct in userspace */ | 150 | /* Location of relevant struct in userspace */ |
| 139 | __u64 return_pointer; | 151 | __u64 return_pointer; |
| @@ -149,8 +161,15 @@ struct hl_info_args { · 9 unmodified lines | |||
| 149 | /* HL_INFO_* */ | 161 | /* HL_INFO_* */ |
| 150 | __u32 op; | 162 | __u32 op; |
| 151 | 163 | ||
| 152 | /* Context ID - Currently not in use */ | 164 | union { |
| 153 | __u32 ctx_id; | 165 | /* Context ID - Currently not in use */ |
| 166 | __u32 ctx_id; | ||
| 167 | /* Period value for utilization rate (100ms - 1000ms, in 100ms | ||
| 168 | * resolution. | ||
| 169 | */ | ||
| 170 | __u32 period_ms; | ||
| 171 | }; | ||
| 172 | |||
| 154 | __u32 pad; | 173 | __u32 pad; |
| 155 | }; | 174 | }; |
| 156 | 175 | ||