From 11110465df1c46e536eca477273184048cd8e5fb Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Wed, 24 Apr 2019 16:09:34 +0530 Subject: [PATCH] gpu: nvgpu: create common.cyclestats unit Separate out cyclestats handling code into separate unit common.cyclestats This unit now exposes new API nvgpu_cyclestats_exec() to perform cyclestats operation. Call this API from common.gr.intr unit Extract out all the private data structures from gk20a.h to cyclestats_priv.h Rename struct gk20a_cyclestate_buffer_elem to nvgpu_cyclestate_buffer_elem Jira NVGPU-1103 Change-Id: Id362675228fe23d03d6d277ff320bcc1066c3c64 Signed-off-by: Deepak Nibade Reviewed-on: https://git-master.nvidia.com/r/2104202 Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-misra GVS: Gerrit_Virtual_Submit Reviewed-by: Vinod Gopalakrishnakurup Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/Makefile | 3 +- drivers/gpu/nvgpu/Makefile.sources | 1 + .../gpu/nvgpu/common/cyclestats/cyclestats.c | 169 ++++++++++++++++++ .../nvgpu/common/cyclestats/cyclestats_priv.h | 60 +++++++ drivers/gpu/nvgpu/common/gr/gr_intr.c | 149 +-------------- drivers/gpu/nvgpu/include/nvgpu/cyclestats.h | 34 ++++ drivers/gpu/nvgpu/include/nvgpu/gk20a.h | 31 ---- 7 files changed, 274 insertions(+), 173 deletions(-) create mode 100644 drivers/gpu/nvgpu/common/cyclestats/cyclestats.c create mode 100644 drivers/gpu/nvgpu/common/cyclestats/cyclestats_priv.h create mode 100644 drivers/gpu/nvgpu/include/nvgpu/cyclestats.h diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index d9749a80d..b779246f0 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -561,7 +561,8 @@ nvgpu-$(CONFIG_TEGRA_GR_VIRTUALIZATION) += \ common/vgpu/gv11b/vgpu_tsg_gv11b.o \ nvgpu-$(CONFIG_GK20A_CYCLE_STATS) += \ - common/perf/cyclestats_snapshot.o + common/perf/cyclestats_snapshot.o \ + common/cyclestats/cyclestats.o nvgpu-y += \ gp10b/gr_gp10b.o \ diff --git a/drivers/gpu/nvgpu/Makefile.sources b/drivers/gpu/nvgpu/Makefile.sources index 9c044f196..6f9aaf211 100644 --- a/drivers/gpu/nvgpu/Makefile.sources +++ b/drivers/gpu/nvgpu/Makefile.sources @@ -82,6 +82,7 @@ srcs += common/sim/sim.c \ common/therm/therm.c \ common/perf/perfbuf.c \ common/perf/cyclestats_snapshot.c \ + common/cyclestats/cyclestats.c \ common/top/top_gm20b.c \ common/top/top_gp10b.c \ common/top/top_gv100.c \ diff --git a/drivers/gpu/nvgpu/common/cyclestats/cyclestats.c b/drivers/gpu/nvgpu/common/cyclestats/cyclestats.c new file mode 100644 index 000000000..fff429307 --- /dev/null +++ b/drivers/gpu/nvgpu/common/cyclestats/cyclestats.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2019, 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "cyclestats_priv.h" + +static inline bool is_valid_cyclestats_bar0_offset_gk20a(struct gk20a *g, + u32 offset) +{ + /* support only 24-bit 4-byte aligned offsets */ + bool valid = !(offset & 0xFF000003U); + + if (g->allow_all) { + return true; + } + + /* whitelist check */ + valid = valid && + is_bar0_global_offset_whitelisted_gk20a(g, offset); + /* resource size check in case there was a problem + * with allocating the assumed size of bar0 */ + valid = valid && nvgpu_io_valid_reg(g, offset); + return valid; +} + +void nvgpu_cyclestats_exec(struct gk20a *g, + struct channel_gk20a *ch, u32 offset) +{ + void *virtual_address; + u32 buffer_size; + bool exit; + + /* GL will never use payload 0 for cycle state */ + if ((ch->cyclestate.cyclestate_buffer == NULL) || (offset == 0U)) { + return; + } + + nvgpu_mutex_acquire(&ch->cyclestate.cyclestate_buffer_mutex); + + virtual_address = ch->cyclestate.cyclestate_buffer; + buffer_size = ch->cyclestate.cyclestate_buffer_size; + exit = false; + + while (!exit) { + struct share_buffer_head *sh_hdr; + u32 min_element_size; + + /* validate offset */ + if (offset + sizeof(struct share_buffer_head) > buffer_size || + offset + sizeof(struct share_buffer_head) < offset) { + nvgpu_err(g, + "cyclestats buffer overrun at offset 0x%x", + offset); + break; + } + + sh_hdr = (struct share_buffer_head *) + ((char *)virtual_address + offset); + + min_element_size = + U32(sh_hdr->operation == OP_END ? + sizeof(struct share_buffer_head) : + sizeof(struct nvgpu_cyclestate_buffer_elem)); + + /* validate sh_hdr->size */ + if (sh_hdr->size < min_element_size || + offset + sh_hdr->size > buffer_size || + offset + sh_hdr->size < offset) { + nvgpu_err(g, + "bad cyclestate buffer header size at offset 0x%x", + offset); + sh_hdr->failed = U32(true); + break; + } + + switch (sh_hdr->operation) { + case OP_END: + exit = true; + break; + + case BAR0_READ32: + case BAR0_WRITE32: + { + struct nvgpu_cyclestate_buffer_elem *op_elem = + (struct nvgpu_cyclestate_buffer_elem *)sh_hdr; + bool valid = is_valid_cyclestats_bar0_offset_gk20a( + g, op_elem->offset_bar0); + u32 raw_reg; + u64 mask_orig; + u64 v; + + if (!valid) { + nvgpu_err(g, + "invalid cycletstats op offset: 0x%x", + op_elem->offset_bar0); + + exit = true; + sh_hdr->failed = U32(exit); + break; + } + + mask_orig = + ((1ULL << (op_elem->last_bit + 1)) - 1) & + ~((1ULL << op_elem->first_bit) - 1); + + raw_reg = nvgpu_readl(g, op_elem->offset_bar0); + + switch (sh_hdr->operation) { + case BAR0_READ32: + op_elem->data = ((raw_reg & mask_orig) + >> op_elem->first_bit); + break; + + case BAR0_WRITE32: + v = 0; + if ((unsigned int)mask_orig != + ~((unsigned int)0)) { + v = (unsigned int) + (raw_reg & ~mask_orig); + } + + v |= ((op_elem->data << op_elem->first_bit) + & mask_orig); + nvgpu_writel(g,op_elem->offset_bar0, + (unsigned int)v); + break; + default: + /* nop ok?*/ + break; + } + } + break; + + default: + /* no operation content case */ + exit = true; + break; + } + sh_hdr->completed = U32(true); + offset += sh_hdr->size; + } + nvgpu_mutex_release(&ch->cyclestate.cyclestate_buffer_mutex); +} diff --git a/drivers/gpu/nvgpu/common/cyclestats/cyclestats_priv.h b/drivers/gpu/nvgpu/common/cyclestats/cyclestats_priv.h new file mode 100644 index 000000000..1358ec712 --- /dev/null +++ b/drivers/gpu/nvgpu/common/cyclestats/cyclestats_priv.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019, 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef NVGPU_CYCLESTATS_PRIV_H +#define NVGPU_CYCLESTATS_PRIV_H + +#include + +#define MULTICHAR_TAG(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) + +enum BAR0_DEBUG_OPERATION { + BARO_ZERO_NOP = 0, + OP_END = MULTICHAR_TAG('D', 'O', 'N', 'E'), + BAR0_READ32 = MULTICHAR_TAG('0', 'R', '3', '2'), + BAR0_WRITE32 = MULTICHAR_TAG('0', 'W', '3', '2'), +}; + +struct share_buffer_head { + enum BAR0_DEBUG_OPERATION operation; +/* size of the operation item */ + u32 size; + u32 completed; + u32 failed; + u64 context; + u64 completion_callback; +}; + +struct nvgpu_cyclestate_buffer_elem { + struct share_buffer_head head; +/* in */ + u64 p_data; + u64 p_done; + u32 offset_bar0; + u16 first_bit; + u16 last_bit; +/* out */ +/* keep 64 bits to be consistent */ + u64 data; +}; + +#endif /* NVGPU_CYCLESTATS_PRIV_H */ diff --git a/drivers/gpu/nvgpu/common/gr/gr_intr.c b/drivers/gpu/nvgpu/common/gr/gr_intr.c index 8f04b114b..6d9371abc 100644 --- a/drivers/gpu/nvgpu/common/gr/gr_intr.c +++ b/drivers/gpu/nvgpu/common/gr/gr_intr.c @@ -23,10 +23,12 @@ #include #include #include -#include #include #include #include +#if defined(CONFIG_GK20A_CYCLE_STATS) +#include +#endif #include #include @@ -628,156 +630,21 @@ int nvgpu_gr_intr_handle_gpc_exception(struct gk20a *g, bool *post_event, return ret; } -#if defined(CONFIG_GK20A_CYCLE_STATS) -static inline bool is_valid_cyclestats_bar0_offset_gk20a(struct gk20a *g, - u32 offset) -{ - /* support only 24-bit 4-byte aligned offsets */ - bool valid = !(offset & 0xFF000003U); - - if (g->allow_all) { - return true; - } - - /* whitelist check */ - valid = valid && - is_bar0_global_offset_whitelisted_gk20a(g, offset); - /* resource size check in case there was a problem - * with allocating the assumed size of bar0 */ - valid = valid && nvgpu_io_valid_reg(g, offset); - return valid; -} -#endif - void nvgpu_gr_intr_handle_notify_pending(struct gk20a *g, struct nvgpu_gr_isr_data *isr_data) { struct channel_gk20a *ch = isr_data->ch; -#if defined(CONFIG_GK20A_CYCLE_STATS) - void *virtual_address; - u32 buffer_size; - u32 offset; - bool exit; -#endif if (ch == NULL || tsg_gk20a_from_ch(ch) == NULL) { return; } -#if defined(CONFIG_GK20A_CYCLE_STATS) - /* GL will never use payload 0 for cycle state */ - if ((ch->cyclestate.cyclestate_buffer == NULL) || - (isr_data->data_lo == 0)) { - return; - } - - nvgpu_mutex_acquire(&ch->cyclestate.cyclestate_buffer_mutex); - - virtual_address = ch->cyclestate.cyclestate_buffer; - buffer_size = ch->cyclestate.cyclestate_buffer_size; - offset = isr_data->data_lo; - exit = false; - while (!exit) { - struct share_buffer_head *sh_hdr; - u32 min_element_size; - - /* validate offset */ - if (offset + sizeof(struct share_buffer_head) > buffer_size || - offset + sizeof(struct share_buffer_head) < offset) { - nvgpu_err(g, - "cyclestats buffer overrun at offset 0x%x", - offset); - break; - } - - sh_hdr = (struct share_buffer_head *) - ((char *)virtual_address + offset); - - min_element_size = - U32(sh_hdr->operation == OP_END ? - sizeof(struct share_buffer_head) : - sizeof(struct gk20a_cyclestate_buffer_elem)); - - /* validate sh_hdr->size */ - if (sh_hdr->size < min_element_size || - offset + sh_hdr->size > buffer_size || - offset + sh_hdr->size < offset) { - nvgpu_err(g, - "bad cyclestate buffer header size at offset 0x%x", - offset); - sh_hdr->failed = U32(true); - break; - } - - switch (sh_hdr->operation) { - case OP_END: - exit = true; - break; - - case BAR0_READ32: - case BAR0_WRITE32: - { - struct gk20a_cyclestate_buffer_elem *op_elem = - (struct gk20a_cyclestate_buffer_elem *)sh_hdr; - bool valid = is_valid_cyclestats_bar0_offset_gk20a( - g, op_elem->offset_bar0); - u32 raw_reg; - u64 mask_orig; - u64 v; - - if (!valid) { - nvgpu_err(g, - "invalid cycletstats op offset: 0x%x", - op_elem->offset_bar0); - - exit = true; - sh_hdr->failed = U32(exit); - break; - } - - mask_orig = - ((1ULL << (op_elem->last_bit + 1)) - 1) & - ~((1ULL << op_elem->first_bit) - 1); - - raw_reg = nvgpu_readl(g, op_elem->offset_bar0); - - switch (sh_hdr->operation) { - case BAR0_READ32: - op_elem->data = ((raw_reg & mask_orig) - >> op_elem->first_bit); - break; - - case BAR0_WRITE32: - v = 0; - if ((unsigned int)mask_orig != - ~((unsigned int)0)) { - v = (unsigned int) - (raw_reg & ~mask_orig); - } - - v |= ((op_elem->data << op_elem->first_bit) - & mask_orig); - nvgpu_writel(g,op_elem->offset_bar0, - (unsigned int)v); - break; - default: - /* nop ok?*/ - break; - } - } - break; - - default: - /* no operation content case */ - exit = true; - break; - } - sh_hdr->completed = U32(true); - offset += sh_hdr->size; - } - nvgpu_mutex_release(&ch->cyclestate.cyclestate_buffer_mutex); -#endif nvgpu_log_fn(g, " "); + +#if defined(CONFIG_GK20A_CYCLE_STATS) + nvgpu_cyclestats_exec(g, ch, isr_data->data_lo); +#endif + nvgpu_cond_broadcast_interruptible(&ch->notifier_wq); } diff --git a/drivers/gpu/nvgpu/include/nvgpu/cyclestats.h b/drivers/gpu/nvgpu/include/nvgpu/cyclestats.h new file mode 100644 index 000000000..745f95aed --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/cyclestats.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef NVGPU_CYCLESTATS_H +#define NVGPU_CYCLESTATS_H + +#include + +struct gk20a; +struct channel_gk20a; + +void nvgpu_cyclestats_exec(struct gk20a *g, + struct channel_gk20a *ch, u32 offset); + +#endif diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index ce4ffaf5c..61633ef36 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -2221,37 +2221,6 @@ static inline u32 nvgpu_get_poll_timeout(struct gk20a *g) g->poll_timeout_default : U32_MAX; } -#define MULTICHAR_TAG(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) -enum BAR0_DEBUG_OPERATION { - BARO_ZERO_NOP = 0, - OP_END = MULTICHAR_TAG('D', 'O', 'N', 'E'), - BAR0_READ32 = MULTICHAR_TAG('0', 'R', '3', '2'), - BAR0_WRITE32 = MULTICHAR_TAG('0', 'W', '3', '2'), -}; - -struct share_buffer_head { - enum BAR0_DEBUG_OPERATION operation; -/* size of the operation item */ - u32 size; - u32 completed; - u32 failed; - u64 context; - u64 completion_callback; -}; - -struct gk20a_cyclestate_buffer_elem { - struct share_buffer_head head; -/* in */ - u64 p_data; - u64 p_done; - u32 offset_bar0; - u16 first_bit; - u16 last_bit; -/* out */ -/* keep 64 bits to be consistent */ - u64 data; -}; - /* operations that will need to be executed on non stall workqueue */ #define GK20A_NONSTALL_OPS_WAKEUP_SEMAPHORE BIT32(0) #define GK20A_NONSTALL_OPS_POST_EVENTS BIT32(1)