From 8c455dff18acd5d69130222b447ab622c1c31736 Mon Sep 17 00:00:00 2001 From: Ramesh Mylavarapu Date: Tue, 7 Sep 2021 19:04:56 +0530 Subject: [PATCH] gpu: nvgpu: add sequence support for gsp cmd/msg implemented sequence support which is needed for cmd/msg for sequencing all the commands sent from NVGPU to gsp and also to handle cmd responses with respect to correspondind assigned sequences. NVGPU-6784 Signed-off-by: Ramesh Mylavarapu Change-Id: I7d0bb015227c11512ec3c7a5ef7117e149704206 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2590607 Tested-by: mobile promotions Reviewed-by: mobile promotions --- arch/nvgpu-common.yaml | 5 +- drivers/gpu/nvgpu/Makefile | 3 +- drivers/gpu/nvgpu/Makefile.sources | 3 +- drivers/gpu/nvgpu/common/gsp/gsp_init.c | 11 ++ drivers/gpu/nvgpu/common/gsp/gsp_priv.h | 4 + drivers/gpu/nvgpu/common/gsp/ipc/gsp_seq.c | 182 +++++++++++++++++++++ drivers/gpu/nvgpu/common/gsp/ipc/gsp_seq.h | 74 +++++++++ 7 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/nvgpu/common/gsp/ipc/gsp_seq.c create mode 100644 drivers/gpu/nvgpu/common/gsp/ipc/gsp_seq.h diff --git a/arch/nvgpu-common.yaml b/arch/nvgpu-common.yaml index 4ef880f15..7ca2b730b 100644 --- a/arch/nvgpu-common.yaml +++ b/arch/nvgpu-common.yaml @@ -311,7 +311,10 @@ gsp: common/gsp/gsp_bootstrap.h, common/gsp/gsp_test.c, include/nvgpu/gsp.h, - include/nvgpu/gsp/gsp_test.h ] + include/nvgpu/gsp/gsp_test.h, + common/gsp/ipc/gsp_seq.c, + common/gsp/ipc/gsp_seq.h, + include/nvgpu/gsp.h ] engine_queues: owner: Sagar K diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index 313c8bd8b..0dffbe160 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -410,7 +410,8 @@ nvgpu-y += \ ifeq ($(CONFIG_NVGPU_GSP_SCHEDULER),y) nvgpu-$(CONFIG_NVGPU_GSP_SCHEDULER) += \ common/gsp/gsp_init.o \ - common/gsp/gsp_bootstrap.o + common/gsp/gsp_bootstrap.o \ + common/gsp/ipc/gsp_seq.o endif ifeq ($(CONFIG_NVGPU_GSP_STRESS_TEST),y) diff --git a/drivers/gpu/nvgpu/Makefile.sources b/drivers/gpu/nvgpu/Makefile.sources index d389e5940..2c4902f52 100644 --- a/drivers/gpu/nvgpu/Makefile.sources +++ b/drivers/gpu/nvgpu/Makefile.sources @@ -180,7 +180,8 @@ srcs += common/device.c \ ifeq ($(CONFIG_NVGPU_GSP_SCHEDULER),1) srcs += common/gsp/gsp_init.c \ - common/gsp/gsp_bootstrap.c + common/gsp/gsp_bootstrap.c \ + common/gsp/ipc/gsp_seq.c endif # Source files below are functionaly safe (FuSa) and must always be included. diff --git a/drivers/gpu/nvgpu/common/gsp/gsp_init.c b/drivers/gpu/nvgpu/common/gsp/gsp_init.c index 7744a5a51..d05fa4e31 100644 --- a/drivers/gpu/nvgpu/common/gsp/gsp_init.c +++ b/drivers/gpu/nvgpu/common/gsp/gsp_init.c @@ -29,6 +29,7 @@ #include #endif +#include "ipc/gsp_seq.h" #include "gsp_priv.h" #include "gsp_bootstrap.h" @@ -58,6 +59,8 @@ void nvgpu_gsp_sw_deinit(struct gk20a *g) #ifdef CONFIG_NVGPU_GSP_STRESS_TEST nvgpu_dma_free(g, &g->gsp->gsp_test.gsp_test_sysmem_block); #endif + nvgpu_gsp_sequences_free(g, g->gsp->sequences); + nvgpu_kfree(g, g->gsp); g->gsp = NULL; } @@ -99,6 +102,14 @@ int nvgpu_gsp_sw_init(struct gk20a *g) /* Init isr mutex */ nvgpu_mutex_init(&gsp->isr_mutex); + err = nvgpu_gsp_sequences_init(g, g->gsp); + if (err != 0) { + nvgpu_err(g, "GSP sequences init failed"); + nvgpu_mutex_destroy(&gsp->isr_mutex); + nvgpu_kfree(g, g->gsp); + g->gsp = NULL; + } + exit: return err; } diff --git a/drivers/gpu/nvgpu/common/gsp/gsp_priv.h b/drivers/gpu/nvgpu/common/gsp/gsp_priv.h index 4df234e5f..314116ce6 100644 --- a/drivers/gpu/nvgpu/common/gsp/gsp_priv.h +++ b/drivers/gpu/nvgpu/common/gsp/gsp_priv.h @@ -24,6 +24,7 @@ #define NVGPU_GSP_PRIV #include +#include #define GSP_DEBUG_BUFFER_QUEUE 3U #define GSP_DMESG_BUFFER_SIZE 0xC00U @@ -54,6 +55,9 @@ struct nvgpu_gsp { bool isr_enabled; struct nvgpu_mutex isr_mutex; + + struct gsp_sequences *sequences; + #ifdef CONFIG_NVGPU_GSP_STRESS_TEST struct gsp_stress_test gsp_test; #endif diff --git a/drivers/gpu/nvgpu/common/gsp/ipc/gsp_seq.c b/drivers/gpu/nvgpu/common/gsp/ipc/gsp_seq.c new file mode 100644 index 000000000..361df21c2 --- /dev/null +++ b/drivers/gpu/nvgpu/common/gsp/ipc/gsp_seq.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 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"), + * 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 "../gsp_priv.h" +#include "gsp_seq.h" + +static void gsp_sequences_init(struct gk20a *g, + struct gsp_sequences *sequences) +{ + u16 i = 0; + + nvgpu_log_fn(g, " "); + + (void) memset(sequences->seq, 0, + sizeof(*sequences->seq) * GSP_MAX_NUM_SEQUENCES); + + (void) memset(sequences->gsp_seq_tbl, 0, + sizeof(sequences->gsp_seq_tbl)); + + for (i = 0; i < GSP_MAX_NUM_SEQUENCES; i++) { + sequences->seq[i].id = (u8)i; + } +} + +int nvgpu_gsp_sequences_init(struct gk20a *g, struct nvgpu_gsp *gsp) +{ + int err = 0; + struct gsp_sequences *seqs; + + nvgpu_log_fn(g, " "); + + seqs = (struct gsp_sequences *) nvgpu_kzalloc(g, sizeof(*seqs->seq)); + if (seqs == NULL) { + nvgpu_err(g, "GSP sequences allocation failed"); + return -ENOMEM; + } + + seqs->seq = nvgpu_kzalloc(g, + GSP_MAX_NUM_SEQUENCES * sizeof(*seqs->seq)); + if (seqs->seq == NULL) { + nvgpu_err(g, "GSP sequence allocation failed"); + nvgpu_kfree(g, seqs); + return -ENOMEM; + } + + gsp->sequences = seqs; + gsp->sequences->seq = seqs->seq; + + nvgpu_mutex_init(&seqs->gsp_seq_lock); + + gsp_sequences_init(g, seqs); + + return err; +} + +void nvgpu_gsp_sequences_free(struct gk20a *g, + struct gsp_sequences *sequences) +{ + nvgpu_mutex_destroy(&sequences->gsp_seq_lock); + nvgpu_kfree(g, sequences->seq); + nvgpu_kfree(g, sequences); +} + +int nvgpu_gsp_seq_acquire(struct gk20a *g, + struct gsp_sequences *sequences, + struct gsp_sequence **pseq, + gsp_callback callback, void *cb_params) +{ + struct gsp_sequence *seq; + u16 size_of_seq_tbl = 0; + u32 index = 0; + int err = 0; + + nvgpu_log_fn(g, " "); + + nvgpu_mutex_acquire(&sequences->gsp_seq_lock); + + size_of_seq_tbl = sizeof(sequences->gsp_seq_tbl) * + sizeof(sequences->gsp_seq_tbl[0]); + + index = find_first_zero_bit(sequences->gsp_seq_tbl, + GSP_MAX_NUM_SEQUENCES); + + if (index >= GSP_MAX_NUM_SEQUENCES) { + nvgpu_err(g, "no free sequence available"); + nvgpu_mutex_release(&sequences->gsp_seq_lock); + err = -EAGAIN; + goto exit; + } + + nvgpu_assert(index < U64(INT_MAX)); + nvgpu_set_bit(index, sequences->gsp_seq_tbl); + + nvgpu_mutex_release(&sequences->gsp_seq_lock); + + seq = &sequences->seq[index]; + + seq->state = GSP_SEQ_STATE_PENDING; + seq->callback = callback; + seq->cb_params = cb_params; + seq->out_payload = NULL; + + *pseq = seq; + +exit: + return err; +} + +void gsp_seq_release(struct gsp_sequences *sequences, + struct gsp_sequence *seq) +{ + seq->state = GSP_SEQ_STATE_FREE; + seq->callback = NULL; + seq->cb_params = NULL; + seq->out_payload = NULL; + + nvgpu_mutex_acquire(&sequences->gsp_seq_lock); + nvgpu_clear_bit(seq->id, sequences->gsp_seq_tbl); + nvgpu_mutex_release(&sequences->gsp_seq_lock); +} + +int nvgpu_gsp_seq_response_handle(struct gk20a *g, + struct gsp_sequences *sequences, + struct nv_flcn_msg_gsp *msg, u32 seq_id) +{ + struct gsp_sequence *seq; + + nvgpu_log_fn(g, " "); + + /* get the sequence info data associated with this message */ + seq = &sequences->seq[seq_id]; + + + if (seq->state != GSP_SEQ_STATE_USED) { + nvgpu_err(g, "msg for an unknown sequence %d", seq->id); + return -EINVAL; + } + + if (seq->callback != NULL) { + seq->callback(g, msg, seq->cb_params, 0); + } + + /* release the sequence so that it may be used for other commands */ + gsp_seq_release(sequences, seq); + + return 0; +} + +u8 nvgpu_gsp_seq_get_id(struct gsp_sequence *seq) +{ + return seq->id; +} + +void nvgpu_gsp_seq_set_state(struct gsp_sequence *seq, enum gsp_seq_state state) +{ + seq->state = state; +} diff --git a/drivers/gpu/nvgpu/common/gsp/ipc/gsp_seq.h b/drivers/gpu/nvgpu/common/gsp/ipc/gsp_seq.h new file mode 100644 index 000000000..b4064a7c6 --- /dev/null +++ b/drivers/gpu/nvgpu/common/gsp/ipc/gsp_seq.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 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"), + * 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_GSP_SEQ_H +#define NVGPU_GSP_SEQ_H + +#include +#include + +struct gk20a; +struct nv_flcn_msg_gsp; + +#define GSP_MAX_NUM_SEQUENCES 256U +#define GSP_SEQ_BIT_SHIFT 5U +#define GSP_SEQ_TBL_SIZE (GSP_MAX_NUM_SEQUENCES >> GSP_SEQ_BIT_SHIFT) + +enum gsp_seq_state { + GSP_SEQ_STATE_FREE = 0U, + GSP_SEQ_STATE_PENDING, + GSP_SEQ_STATE_USED +}; + +typedef void (*gsp_callback)(struct gk20a *g, struct nv_flcn_msg_gsp *msg, + void *param, u32 status); + +struct gsp_sequence { + u8 id; + enum gsp_seq_state state; + u8 *out_payload; + gsp_callback callback; + void *cb_params; +}; + +struct gsp_sequences { + struct gsp_sequence *seq; + unsigned long gsp_seq_tbl[GSP_SEQ_TBL_SIZE]; + struct nvgpu_mutex gsp_seq_lock; +}; + +int nvgpu_gsp_sequences_init(struct gk20a *g, struct nvgpu_gsp *gsp); +void nvgpu_gsp_sequences_free(struct gk20a *g, + struct gsp_sequences *sequences); +int nvgpu_gsp_seq_acquire(struct gk20a *g, + struct gsp_sequences *sequences, + struct gsp_sequence **pseq, + gsp_callback callback, void *cb_params); +int nvgpu_gsp_seq_response_handle(struct gk20a *g, + struct gsp_sequences *sequences, + struct nv_flcn_msg_gsp *msg, u32 seq_id); +u8 nvgpu_gsp_seq_get_id(struct gsp_sequence *seq); +void nvgpu_gsp_seq_set_state(struct gsp_sequence *seq, + enum gsp_seq_state state); +void gsp_seq_release(struct gsp_sequences *sequences, + struct gsp_sequence *seq); +#endif /* NVGPU_GSP_SEQ_H */