The information which is currently provided as a response to the "HL_INFO_HW_IDLE" IOCTL is merely a general boolean value. This patch extends it and provides also a bitmask that indicates which of the device engines are busy.
Unified · Split
| @@ -506,7 +506,7 @@ static int engines_show(struct seq_file *s, void *data) · 505 unmodified lines | ||
| 506 | 506 | struct hl_dbg_device_entry *dev_entry = entry->dev_entry; |
| 507 | 507 | struct hl_device *hdev = dev_entry->hdev; |
| 508 | 508 | |
| 509 | − hdev->asic_funcs->is_device_idle(hdev, s); | |
| 509 | + hdev->asic_funcs->is_device_idle(hdev, NULL, s); | |
| 510 | 510 | |
| 511 | 511 | return 0; |
| 512 | 512 | } |
| @@ -2828,7 +2828,7 @@ static int goya_send_job_on_qman0(struct hl_device *hdev, struct hl_cs_job *job) · 2827 unmodified lines | ||
| 2828 | 2828 | else |
| 2829 | 2829 | timeout = HL_DEVICE_TIMEOUT_USEC; |
| 2830 | 2830 | |
| 2831 | − if (!hdev->asic_funcs->is_device_idle(hdev, NULL)) { | |
| 2831 | + if (!hdev->asic_funcs->is_device_idle(hdev, NULL, NULL)) { | |
| 2832 | 2832 | dev_err_ratelimited(hdev->dev, |
| 2833 | 2833 | "Can't send KMD job on QMAN0 because the device is not idle\n"); |
| 2834 | 2834 | return -EBUSY; |
| @@ -4914,7 +4914,8 @@ int goya_armcp_info_get(struct hl_device *hdev) · 2079 unmodified lines | ||
| 4914 | 4914 | return 0; |
| 4915 | 4915 | } |
| 4916 | 4916 | |
| 4917 | −static bool goya_is_device_idle(struct hl_device *hdev, struct seq_file *s) | |
| 4917 | +static bool goya_is_device_idle(struct hl_device *hdev, u32 *mask, | |
| 4918 | + struct seq_file *s) | |
| 4918 | 4919 | { |
| 4919 | 4920 | const char *fmt = "%-5d%-9s%#-14x%#-16x%#x\n"; |
| 4920 | 4921 | const char *dma_fmt = "%-5d%-9s%#-14x%#x\n"; |
| @@ -4937,6 +4938,8 @@ static bool goya_is_device_idle(struct hl_device *hdev, struct seq_file *s) · 16 unmodified lines | ||
| 4937 | 4938 | IS_DMA_IDLE(dma_core_sts0); |
| 4938 | 4939 | is_idle &= is_eng_idle; |
| 4939 | 4940 | |
| 4941 | + if (mask) | |
| 4942 | + *mask |= !is_eng_idle << (GOYA_ENGINE_ID_DMA_0 + i); | |
| 4940 | 4943 | if (s) |
| 4941 | 4944 | seq_printf(s, dma_fmt, i, is_eng_idle ? "Y" : "N", |
| 4942 | 4945 | qm_glbl_sts0, dma_core_sts0); |
| @@ -4958,6 +4961,8 @@ static bool goya_is_device_idle(struct hl_device *hdev, struct seq_file *s) · 15 unmodified lines | ||
| 4958 | 4961 | IS_TPC_IDLE(tpc_cfg_sts); |
| 4959 | 4962 | is_idle &= is_eng_idle; |
| 4960 | 4963 | |
| 4964 | + if (mask) | |
| 4965 | + *mask |= !is_eng_idle << (GOYA_ENGINE_ID_TPC_0 + i); | |
| 4961 | 4966 | if (s) |
| 4962 | 4967 | seq_printf(s, fmt, i, is_eng_idle ? "Y" : "N", |
| 4963 | 4968 | qm_glbl_sts0, cmdq_glbl_sts0, tpc_cfg_sts); |
| @@ -4976,6 +4981,8 @@ static bool goya_is_device_idle(struct hl_device *hdev, struct seq_file *s) · 12 unmodified lines | ||
| 4976 | 4981 | IS_MME_IDLE(mme_arch_sts); |
| 4977 | 4982 | is_idle &= is_eng_idle; |
| 4978 | 4983 | |
| 4984 | + if (mask) | |
| 4985 | + *mask |= !is_eng_idle << GOYA_ENGINE_ID_MME_0; | |
| 4979 | 4986 | if (s) { |
| 4980 | 4987 | seq_printf(s, fmt, 0, is_eng_idle ? "Y" : "N", qm_glbl_sts0, |
| 4981 | 4988 | cmdq_glbl_sts0, mme_arch_sts); |
| @@ -557,7 +557,8 @@ struct hl_asic_funcs { · 556 unmodified lines | ||
| 557 | 557 | u32 asid, u64 va, u64 size); |
| 558 | 558 | int (*send_heartbeat)(struct hl_device *hdev); |
| 559 | 559 | int (*debug_coresight)(struct hl_device *hdev, void *data); |
| 560 | − bool (*is_device_idle)(struct hl_device *hdev, struct seq_file *s); | |
| 560 | + bool (*is_device_idle)(struct hl_device *hdev, u32 *mask, | |
| 561 | + struct seq_file *s); | |
| 561 | 562 | int (*soft_reset_late_init)(struct hl_device *hdev); |
| 562 | 563 | void (*hw_queues_lock)(struct hl_device *hdev); |
| 563 | 564 | void (*hw_queues_unlock)(struct hl_device *hdev); |
| @@ -119,7 +119,8 @@ static int hw_idle(struct hl_device *hdev, struct hl_info_args *args) · 118 unmodified lines | ||
| 119 | 119 | if ((!max_size) || (!out)) |
| 120 | 120 | return -EINVAL; |
| 121 | 121 | |
| 122 | − hw_idle.is_idle = hdev->asic_funcs->is_device_idle(hdev, NULL); | |
| 122 | + hw_idle.is_idle = hdev->asic_funcs->is_device_idle(hdev, | |
| 123 | + &hw_idle.busy_engines_mask, NULL); | |
| 123 | 124 | |
| 124 | 125 | return copy_to_user(out, &hw_idle, |
| 125 | 126 | min((size_t) max_size, sizeof(hw_idle))) ? -EFAULT : 0; |
| @@ -45,6 +45,30 @@ enum goya_queue_id { · 44 unmodified lines | ||
| 45 | 45 | GOYA_QUEUE_ID_SIZE |
| 46 | 46 | }; |
| 47 | 47 | |
| 48 | +/* | |
| 49 | + * Engine Numbering | |
| 50 | + * | |
| 51 | + * Used in the "busy_engines_mask" field in `struct hl_info_hw_idle' | |
| 52 | + */ | |
| 53 | + | |
| 54 | +enum goya_engine_id { | |
| 55 | + GOYA_ENGINE_ID_DMA_0 = 0, | |
| 56 | + GOYA_ENGINE_ID_DMA_1, | |
| 57 | + GOYA_ENGINE_ID_DMA_2, | |
| 58 | + GOYA_ENGINE_ID_DMA_3, | |
| 59 | + GOYA_ENGINE_ID_DMA_4, | |
| 60 | + GOYA_ENGINE_ID_MME_0, | |
| 61 | + GOYA_ENGINE_ID_TPC_0, | |
| 62 | + GOYA_ENGINE_ID_TPC_1, | |
| 63 | + GOYA_ENGINE_ID_TPC_2, | |
| 64 | + GOYA_ENGINE_ID_TPC_3, | |
| 65 | + GOYA_ENGINE_ID_TPC_4, | |
| 66 | + GOYA_ENGINE_ID_TPC_5, | |
| 67 | + GOYA_ENGINE_ID_TPC_6, | |
| 68 | + GOYA_ENGINE_ID_TPC_7, | |
| 69 | + GOYA_ENGINE_ID_SIZE | |
| 70 | +}; | |
| 71 | + | |
| 48 | 72 | enum hl_device_status { |
| 49 | 73 | HL_DEVICE_STATUS_OPERATIONAL, |
| 50 | 74 | HL_DEVICE_STATUS_IN_RESET, |
| @@ -86,7 +110,11 @@ struct hl_info_dram_usage { · 35 unmodified lines | ||
| 86 | 110 | |
| 87 | 111 | struct hl_info_hw_idle { |
| 88 | 112 | __u32 is_idle; |
| 89 | − __u32 pad; | |
| 113 | + /* | |
| 114 | + * Bitmask of busy engines. | |
| 115 | + * Bits definition is according to `enum <chip>_enging_id'. | |
| 116 | + */ | |
| 117 | + __u32 busy_engines_mask; | |
| 90 | 118 | }; |
| 91 | 119 | |
| 92 | 120 | struct hl_info_device_status { |