diff --git a/drivers/gpu/nvgpu/common/utils/string.c b/drivers/gpu/nvgpu/common/utils/string.c index eb6260d13..503f21bec 100644 --- a/drivers/gpu/nvgpu/common/utils/string.c +++ b/drivers/gpu/nvgpu/common/utils/string.c @@ -88,3 +88,46 @@ bool nvgpu_mem_is_word_aligned(struct gk20a *g, u8 *addr) return true; } + +u32 nvgpu_str_join(char *dest, u32 dest_len, const char **src_str_list, + u32 str_list_len, const char *joiner) +{ + u64 dest_empty_len = nvgpu_safe_sub_u64(dest_len, 1ULL); + u64 joiner_len = strlen(joiner); + u32 i = 0U; + + /* Initialize destination buffer */ + *dest = '\0'; + + if (str_list_len == 0U) { + return 0; + } + + /* Copy first string */ + (void) strncat(dest, src_str_list[0], dest_empty_len); + + /* + * Calculate available size in destination buffer + * Subtract extra 1U for the NULL byte + */ + dest_empty_len = nvgpu_safe_sub_u64( + nvgpu_safe_sub_u64(dest_len, strlen(dest)), 1ULL); + + for (i = 1; i < str_list_len; i++) { + /* Make sure we are not writing beyond destination buffer */ + if (dest_empty_len < nvgpu_safe_add_u64(joiner_len, + strlen(src_str_list[i]))) { + goto ret; + } + + (void) strncat(dest, joiner, dest_empty_len); + (void) strncat(dest, src_str_list[i], dest_empty_len); + + dest_empty_len = nvgpu_safe_sub_u64( + nvgpu_safe_sub_u64(dest_len, strlen(dest)), 1ULL); + } + +ret: + /* Return number of bytes (or chars) copied */ + return nvgpu_safe_cast_u64_to_u32(strlen(dest)); +} diff --git a/drivers/gpu/nvgpu/hal/fifo/channel_ga10b_fusa.c b/drivers/gpu/nvgpu/hal/fifo/channel_ga10b_fusa.c index 8fb1ac77b..b8088aedb 100644 --- a/drivers/gpu/nvgpu/hal/fifo/channel_ga10b_fusa.c +++ b/drivers/gpu/nvgpu/hal/fifo/channel_ga10b_fusa.c @@ -27,6 +27,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include "channel_ga10b.h" @@ -139,45 +144,46 @@ void ga10b_channel_unbind(struct nvgpu_channel *ch) } } +#define NUM_STATUS_STR 8U + +static u32 ga10b_channel_status_mask(void) +{ + u32 mask = (runlist_chram_channel_on_pbdma_m() | + runlist_chram_channel_on_eng_m() | + runlist_chram_channel_pending_m() | + runlist_chram_channel_ctx_reload_m() | + runlist_chram_channel_pbdma_busy_m() | + runlist_chram_channel_eng_busy_m() | + runlist_chram_channel_acquire_fail_m()); + + return mask; +} + static const char * const chram_status_str[] = { - [runlist_chram_channel_status_idle_v()] = "idle", - [runlist_chram_channel_status_pending_v()] = "pending", - [runlist_chram_channel_status_pending_ctx_reload_v()] = - "pending_ctx_reload", - [runlist_chram_channel_status_pending_acquire_fail_v()] = - "pending_acquire_fail", - [runlist_chram_channel_status_pending_acquire_fail_ctx_reload_v()] = - "pending_acq_fail_ctx_reload", - [runlist_chram_channel_status_pbdma_busy_v()] = "pbdma_busy", - [runlist_chram_channel_status_pbdma_busy_and_eng_busy_v()] = - "pbdma_and_eng_busy", - [runlist_chram_channel_status_eng_busy_v()] = "eng_busy", - [runlist_chram_channel_status_eng_busy_pending_acquire_fail_v()] = - "eng_busy_pending_acquire_fail", - [runlist_chram_channel_status_eng_busy_pending_v()] = "eng_busy_pending", - [runlist_chram_channel_status_pbdma_busy_ctx_reload_v()] = - "pbdma_busy_ctx_reload", - [runlist_chram_channel_status_pbdma_busy_eng_busy_ctx_reload_v()] = - "pbdma_and_eng_busy_ctx_reload", - [runlist_chram_channel_status_busy_ctx_reload_v()] = "busy_ctx_reload", - [runlist_chram_channel_status_eng_busy_pending_ctx_reload_v()] = - "eng_busy_pending_ctx_reload", - [runlist_chram_channel_status_eng_busy_pending_acquire_fail_ctx_reload_v()] = - "eng_busy_pending_acq_fail_ctx_reload", + [runlist_chram_channel_on_pbdma_m()] = "on_pbdma", + [runlist_chram_channel_on_eng_m()] = "on_eng", + [runlist_chram_channel_pending_m()] = "pending", + [runlist_chram_channel_ctx_reload_m()] = "ctx_reload", + [runlist_chram_channel_pbdma_busy_m()] = "pbdma_busy", + [runlist_chram_channel_eng_busy_m()] = "eng_busy", + [runlist_chram_channel_acquire_fail_m()] = "acquire_fail", }; void ga10b_channel_read_state(struct gk20a *g, struct nvgpu_channel *ch, struct nvgpu_channel_hw_state *state) { - struct nvgpu_runlist *runlist = NULL; u32 reg = 0U; - u32 status = 0U; + unsigned long bit = 0UL; + unsigned long status_str_bits = 0UL; + u32 status_str_count = 0U; + bool idle = true; + struct nvgpu_runlist *runlist = NULL; + const char **chram_status_list = NULL; runlist = ch->runlist; reg = nvgpu_chram_bar0_readl(g, runlist, runlist_chram_channel_r(ch->chid)); - status = runlist_chram_channel_status_v(reg); state->next = runlist_chram_channel_next_v(reg) == runlist_chram_channel_next_true_v(); @@ -188,17 +194,47 @@ void ga10b_channel_read_state(struct gk20a *g, struct nvgpu_channel *ch, state->busy = runlist_chram_channel_busy_v(reg) == runlist_chram_channel_busy_true_v(); state->pending_acquire = - (status == - runlist_chram_channel_status_pending_acquire_fail_v()) || - (status == - runlist_chram_channel_status_eng_busy_pending_acquire_fail_ctx_reload_v()) || - (status == - runlist_chram_channel_status_pending_acquire_fail_ctx_reload_v()); + ((runlist_chram_channel_pending_v(reg) == + runlist_chram_channel_pending_true_v()) && + (runlist_chram_channel_acquire_fail_v(reg) == + runlist_chram_channel_acquire_fail_true_v())); state->eng_faulted = runlist_chram_channel_eng_faulted_v(reg) == runlist_chram_channel_eng_faulted_true_v(); - state->status_string = chram_status_str[status] == NULL ? "N/A" : - chram_status_str[status]; + + /* Construct status string for below status fields */ + status_str_bits = (u64)(reg & ga10b_channel_status_mask()); + + /* Allocate memory for status string list */ + chram_status_list = nvgpu_kzalloc(g, (sizeof(char *) * NUM_STATUS_STR)); + if (chram_status_list == NULL) { + nvgpu_err(g, "Status string list pointer allocation failed"); + state->status_string[0] = '\0'; + return; + } + + /* + * Status is true if the corresponding bit is set. + * Go through each set bit and copy status string to status string list. + */ + for_each_set_bit(bit, &status_str_bits, ilog2(U32_MAX)) { + chram_status_list[status_str_count] = + chram_status_str[BIT32(bit)]; + status_str_count = nvgpu_safe_add_u32(status_str_count, 1UL); + idle = false; + } + + if (idle) { + chram_status_list[status_str_count] = "idle"; + status_str_count = nvgpu_safe_add_u32(status_str_count, 1UL); + } + + /* Combine all status strings */ + (void) nvgpu_str_join(state->status_string, + NVGPU_CHANNEL_STATUS_STRING_LENGTH, chram_status_list, + status_str_count, ", "); + + nvgpu_err(g, "status_string %s", state->status_string); nvgpu_log_info(g, "Channel id:%d state next:%s enabled:%s ctx_reload:%s" " busy:%s pending_acquire:%s eng_faulted:%s status_string:%s", @@ -209,6 +245,8 @@ void ga10b_channel_read_state(struct gk20a *g, struct nvgpu_channel *ch, state->busy ? "true" : "false", state->pending_acquire ? "true" : "false", state->eng_faulted ? "true" : "false", state->status_string); + + nvgpu_kfree(g, chram_status_list); } void ga10b_channel_reset_faulted(struct gk20a *g, struct nvgpu_channel *ch, diff --git a/drivers/gpu/nvgpu/hal/fifo/channel_gk20a_fusa.c b/drivers/gpu/nvgpu/hal/fifo/channel_gk20a_fusa.c index 88f16a777..0c69cfab1 100644 --- a/drivers/gpu/nvgpu/hal/fifo/channel_gk20a_fusa.c +++ b/drivers/gpu/nvgpu/hal/fifo/channel_gk20a_fusa.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2020, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2021, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -97,5 +97,10 @@ void gk20a_channel_read_state(struct gk20a *g, struct nvgpu_channel *ch, state->pending_acquire = (status_v == ccsr_channel_status_pending_acquire_v()) || (status_v == ccsr_channel_status_on_eng_pending_acquire_v()); - state->status_string = ccsr_chan_status_str[status_v]; + + /* Copy at the most NVGPU_CHANNEL_STATUS_STRING_LENGTH characters */ + (void) strncpy(state->status_string, ccsr_chan_status_str[status_v], + NVGPU_CHANNEL_STATUS_STRING_LENGTH - 1U); + + state->status_string[NVGPU_CHANNEL_STATUS_STRING_LENGTH - 1U] = '\0'; } diff --git a/drivers/gpu/nvgpu/include/nvgpu/channel.h b/drivers/gpu/nvgpu/include/nvgpu/channel.h index 1277877fc..c8621ef14 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/channel.h +++ b/drivers/gpu/nvgpu/include/nvgpu/channel.h @@ -153,6 +153,8 @@ struct gpfifo_desc { #endif }; +#define NVGPU_CHANNEL_STATUS_STRING_LENGTH 120U + /** * Structure abstracting H/W state for channel. * Used when unbinding a channel from TSG. @@ -172,7 +174,7 @@ struct nvgpu_channel_hw_state { /** Channel has encountered an engine page fault. */ bool eng_faulted; /** Human-readable status string. */ - const char *status_string; + char status_string[NVGPU_CHANNEL_STATUS_STRING_LENGTH]; }; /** diff --git a/drivers/gpu/nvgpu/include/nvgpu/hw/ga100/hw_runlist_ga100.h b/drivers/gpu/nvgpu/include/nvgpu/hw/ga100/hw_runlist_ga100.h index 95e8793f6..1daed7908 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/hw/ga100/hw_runlist_ga100.h +++ b/drivers/gpu/nvgpu/include/nvgpu/hw/ga100/hw_runlist_ga100.h @@ -107,29 +107,27 @@ #define runlist_chram_channel_busy_true_v() (0x00000001U) #define runlist_chram_channel_eng_faulted_v(r) (((r) >> 5U) & 0x1U) #define runlist_chram_channel_eng_faulted_true_v() (0x00000001U) +#define runlist_chram_channel_on_pbdma_m() (U32(0x1U) << 6U) +#define runlist_chram_channel_on_pbdma_v(r) (((r) >> 6U) & 0x1U) +#define runlist_chram_channel_on_pbdma_true_v() (0x00000001U) +#define runlist_chram_channel_on_eng_m() (U32(0x1U) << 7U) +#define runlist_chram_channel_on_eng_v(r) (((r) >> 7U) & 0x1U) +#define runlist_chram_channel_on_eng_true_v() (0x00000001U) +#define runlist_chram_channel_pending_m() (U32(0x1U) << 8U) +#define runlist_chram_channel_pending_v(r) (((r) >> 8U) & 0x1U) +#define runlist_chram_channel_pending_true_v() (0x00000001U) +#define runlist_chram_channel_ctx_reload_m() (U32(0x1U) << 9U) #define runlist_chram_channel_ctx_reload_v(r) (((r) >> 9U) & 0x1U) #define runlist_chram_channel_ctx_reload_true_v() (0x00000001U) -#define runlist_chram_channel_status_v(r) (((r) >> 8U) & 0x1fU) -#define runlist_chram_channel_status_idle_v() (0x00000000U) -#define runlist_chram_channel_status_pending_v() (0x00000001U) -#define runlist_chram_channel_status_pending_ctx_reload_v() (0x00000003U) -#define runlist_chram_channel_status_pending_acquire_fail_v() (0x00000011U) -#define runlist_chram_channel_status_pending_acquire_fail_ctx_reload_v()\ - (0x00000013U) -#define runlist_chram_channel_status_pbdma_busy_v() (0x00000004U) -#define runlist_chram_channel_status_pbdma_busy_and_eng_busy_v() (0x0000000cU) -#define runlist_chram_channel_status_eng_busy_v() (0x00000008U) -#define runlist_chram_channel_status_eng_busy_pending_acquire_fail_v()\ - (0x00000019U) -#define runlist_chram_channel_status_eng_busy_pending_v() (0x00000009U) -#define runlist_chram_channel_status_pbdma_busy_ctx_reload_v() (0x00000006U) -#define runlist_chram_channel_status_pbdma_busy_eng_busy_ctx_reload_v()\ - (0x0000000eU) -#define runlist_chram_channel_status_busy_ctx_reload_v() (0x0000000aU) -#define runlist_chram_channel_status_eng_busy_pending_ctx_reload_v()\ - (0x0000000bU) -#define runlist_chram_channel_status_eng_busy_pending_acquire_fail_ctx_reload_v()\ - (0x0000001bU) +#define runlist_chram_channel_pbdma_busy_m() (U32(0x1U) << 10U) +#define runlist_chram_channel_pbdma_busy_v(r) (((r) >> 10U) & 0x1U) +#define runlist_chram_channel_pbdma_busy_true_v() (0x00000001U) +#define runlist_chram_channel_eng_busy_m() (U32(0x1U) << 11U) +#define runlist_chram_channel_eng_busy_v(r) (((r) >> 11U) & 0x1U) +#define runlist_chram_channel_eng_busy_true_v() (0x00000001U) +#define runlist_chram_channel_acquire_fail_m() (U32(0x1U) << 12U) +#define runlist_chram_channel_acquire_fail_v(r) (((r) >> 12U) & 0x1U) +#define runlist_chram_channel_acquire_fail_true_v() (0x00000001U) #define runlist_chram_channel_update_f(v) ((U32(v) & 0xffffffffU) << 0U) #define runlist_chram_channel_update_enable_channel_v() (0x00000002U) #define runlist_chram_channel_update_disable_channel_v() (0x00000003U) diff --git a/drivers/gpu/nvgpu/include/nvgpu/hw/ga10b/hw_runlist_ga10b.h b/drivers/gpu/nvgpu/include/nvgpu/hw/ga10b/hw_runlist_ga10b.h index 143ea6aec..16eae9794 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/hw/ga10b/hw_runlist_ga10b.h +++ b/drivers/gpu/nvgpu/include/nvgpu/hw/ga10b/hw_runlist_ga10b.h @@ -107,29 +107,27 @@ #define runlist_chram_channel_busy_true_v() (0x00000001U) #define runlist_chram_channel_eng_faulted_v(r) (((r) >> 5U) & 0x1U) #define runlist_chram_channel_eng_faulted_true_v() (0x00000001U) +#define runlist_chram_channel_on_pbdma_m() (U32(0x1U) << 6U) +#define runlist_chram_channel_on_pbdma_v(r) (((r) >> 6U) & 0x1U) +#define runlist_chram_channel_on_pbdma_true_v() (0x00000001U) +#define runlist_chram_channel_on_eng_m() (U32(0x1U) << 7U) +#define runlist_chram_channel_on_eng_v(r) (((r) >> 7U) & 0x1U) +#define runlist_chram_channel_on_eng_true_v() (0x00000001U) +#define runlist_chram_channel_pending_m() (U32(0x1U) << 8U) +#define runlist_chram_channel_pending_v(r) (((r) >> 8U) & 0x1U) +#define runlist_chram_channel_pending_true_v() (0x00000001U) +#define runlist_chram_channel_ctx_reload_m() (U32(0x1U) << 9U) #define runlist_chram_channel_ctx_reload_v(r) (((r) >> 9U) & 0x1U) #define runlist_chram_channel_ctx_reload_true_v() (0x00000001U) -#define runlist_chram_channel_status_v(r) (((r) >> 8U) & 0x1fU) -#define runlist_chram_channel_status_idle_v() (0x00000000U) -#define runlist_chram_channel_status_pending_v() (0x00000001U) -#define runlist_chram_channel_status_pending_ctx_reload_v() (0x00000003U) -#define runlist_chram_channel_status_pending_acquire_fail_v() (0x00000011U) -#define runlist_chram_channel_status_pending_acquire_fail_ctx_reload_v()\ - (0x00000013U) -#define runlist_chram_channel_status_pbdma_busy_v() (0x00000004U) -#define runlist_chram_channel_status_pbdma_busy_and_eng_busy_v() (0x0000000cU) -#define runlist_chram_channel_status_eng_busy_v() (0x00000008U) -#define runlist_chram_channel_status_eng_busy_pending_acquire_fail_v()\ - (0x00000019U) -#define runlist_chram_channel_status_eng_busy_pending_v() (0x00000009U) -#define runlist_chram_channel_status_pbdma_busy_ctx_reload_v() (0x00000006U) -#define runlist_chram_channel_status_pbdma_busy_eng_busy_ctx_reload_v()\ - (0x0000000eU) -#define runlist_chram_channel_status_busy_ctx_reload_v() (0x0000000aU) -#define runlist_chram_channel_status_eng_busy_pending_ctx_reload_v()\ - (0x0000000bU) -#define runlist_chram_channel_status_eng_busy_pending_acquire_fail_ctx_reload_v()\ - (0x0000001bU) +#define runlist_chram_channel_pbdma_busy_m() (U32(0x1U) << 10U) +#define runlist_chram_channel_pbdma_busy_v(r) (((r) >> 10U) & 0x1U) +#define runlist_chram_channel_pbdma_busy_true_v() (0x00000001U) +#define runlist_chram_channel_eng_busy_m() (U32(0x1U) << 11U) +#define runlist_chram_channel_eng_busy_v(r) (((r) >> 11U) & 0x1U) +#define runlist_chram_channel_eng_busy_true_v() (0x00000001U) +#define runlist_chram_channel_acquire_fail_m() (U32(0x1U) << 12U) +#define runlist_chram_channel_acquire_fail_v(r) (((r) >> 12U) & 0x1U) +#define runlist_chram_channel_acquire_fail_true_v() (0x00000001U) #define runlist_chram_channel_update_f(v) ((U32(v) & 0xffffffffU) << 0U) #define runlist_chram_channel_update_enable_channel_v() (0x00000002U) #define runlist_chram_channel_update_disable_channel_v() (0x00000003U) diff --git a/drivers/gpu/nvgpu/include/nvgpu/string.h b/drivers/gpu/nvgpu/include/nvgpu/string.h index 9b510e616..35689fbac 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/string.h +++ b/drivers/gpu/nvgpu/include/nvgpu/string.h @@ -114,4 +114,22 @@ int nvgpu_strnadd_u32(char *dst, const u32 value, size_t size, u32 radix); */ bool nvgpu_mem_is_word_aligned(struct gk20a *g, u8 *addr); +/** + * @brief Construct single string from multiple strings. + * + * Concatenates multiple source strings to generate single string. + * + * @param dest [in] Pointer to the destination string. + * @param dest_len [in] Maximum length of destination string + * including NULL character. + * @param src_str_list [in] Pointer to list of strings to be concatenated. + * @param str_list_len [in] Number of strings in \a src_str_list. + * @param joiner [in] Pointer to string used to join strings in + * \a src_str_list. + * + * @return Number of bytes copied to \a dest. + */ +u32 nvgpu_str_join(char *dest, u32 dest_len, const char **src_str_list, + u32 str_list_len, const char *joiner); + #endif /* NVGPU_STRING_H */