From eef3ef77733cdcbf4b0d03b2ed86f1462deb78b2 Mon Sep 17 00:00:00 2001 From: Sagar Kamble Date: Thu, 28 Mar 2019 10:10:42 +0530 Subject: [PATCH] gpu: nvgpu: prepare sec2 sequences unit SEC2 commands and messages management is based on sharing the data through sequences. Functions for sending commands/allocating payload update sequence data acquiring lock and those for working on received messages read/free the sequence data releasing lock. JIRA NVGPU-2075 Change-Id: I988662d6ce6f9a15d67bab2a58d3f2689ffd804a Signed-off-by: Sagar Kamble Reviewed-on: https://git-master.nvidia.com/r/2085748 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/Makefile | 1 + drivers/gpu/nvgpu/Makefile.sources | 1 + drivers/gpu/nvgpu/common/sec2/sec2.c | 41 ++---- drivers/gpu/nvgpu/common/sec2/sec2_ipc.c | 80 +---------- drivers/gpu/nvgpu/common/sec2/sec2_seq.c | 160 +++++++++++++++++++++ drivers/gpu/nvgpu/include/nvgpu/sec2.h | 25 +--- drivers/gpu/nvgpu/include/nvgpu/sec2/seq.h | 77 ++++++++++ 7 files changed, 256 insertions(+), 129 deletions(-) create mode 100644 drivers/gpu/nvgpu/common/sec2/sec2_seq.c create mode 100644 drivers/gpu/nvgpu/include/nvgpu/sec2/seq.h diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index 55793ba7d..44936e098 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -450,6 +450,7 @@ nvgpu-y += \ common/sec2/sec2.o \ common/sec2/sec2_ipc.o \ common/sec2/sec2_queue.o \ + common/sec2/sec2_seq.o \ common/io/io.o \ common/power_features/power_features.o \ common/power_features/cg/cg.o \ diff --git a/drivers/gpu/nvgpu/Makefile.sources b/drivers/gpu/nvgpu/Makefile.sources index 384cf2638..e149cf131 100644 --- a/drivers/gpu/nvgpu/Makefile.sources +++ b/drivers/gpu/nvgpu/Makefile.sources @@ -162,6 +162,7 @@ srcs += common/sim.c \ common/sec2/sec2.c \ common/sec2/sec2_ipc.c \ common/sec2/sec2_queue.c \ + common/sec2/sec2_seq.c \ common/ptimer/ptimer.c \ common/sync/channel_sync.c \ common/sync/channel_sync_syncpt.c \ diff --git a/drivers/gpu/nvgpu/common/sec2/sec2.c b/drivers/gpu/nvgpu/common/sec2/sec2.c index a1d894b79..592c9789c 100644 --- a/drivers/gpu/nvgpu/common/sec2/sec2.c +++ b/drivers/gpu/nvgpu/common/sec2/sec2.c @@ -26,33 +26,17 @@ #include #include #include +#include #include #include -static void sec2_seq_init(struct nvgpu_sec2 *sec2) -{ - u32 i = 0; - - nvgpu_log_fn(sec2->g, " "); - - (void) memset(sec2->seq, 0, - sizeof(struct sec2_sequence) * SEC2_MAX_NUM_SEQUENCES); - - (void) memset(sec2->sec2_seq_tbl, 0, sizeof(sec2->sec2_seq_tbl)); - - for (i = 0; i < SEC2_MAX_NUM_SEQUENCES; i++) { - sec2->seq[i].id = (u8)i; - } -} - static void nvgpu_remove_sec2_support(struct nvgpu_sec2 *sec2) { struct gk20a *g = sec2->g; nvgpu_log_fn(g, " "); - nvgpu_kfree(g, sec2->seq); - nvgpu_mutex_destroy(&sec2->sec2_seq_lock); + nvgpu_sec2_sequences_free(g, &sec2->sequences); nvgpu_mutex_destroy(&sec2->isr_mutex); } @@ -64,33 +48,24 @@ int nvgpu_init_sec2_setup_sw(struct gk20a *g, struct nvgpu_sec2 *sec2) sec2->g = g; - sec2->seq = nvgpu_kzalloc(g, SEC2_MAX_NUM_SEQUENCES * - sizeof(struct sec2_sequence)); - if (sec2->seq == NULL) { - err = -ENOMEM; + err = nvgpu_sec2_sequences_alloc(g, &sec2->sequences); + if (err != 0) { goto exit; } - err = nvgpu_mutex_init(&sec2->sec2_seq_lock); - if (err != 0) { - goto free_seq_alloc; - } - - sec2_seq_init(sec2); + nvgpu_sec2_sequences_init(g, &sec2->sequences); err = nvgpu_mutex_init(&sec2->isr_mutex); if (err != 0) { - goto free_seq_mutex; + goto free_sequences; } sec2->remove_support = nvgpu_remove_sec2_support; goto exit; -free_seq_mutex: - nvgpu_mutex_destroy(&sec2->sec2_seq_lock); -free_seq_alloc: - nvgpu_kfree(g, sec2->seq); +free_sequences: + nvgpu_sec2_sequences_free(g, &sec2->sequences); exit: return err; diff --git a/drivers/gpu/nvgpu/common/sec2/sec2_ipc.c b/drivers/gpu/nvgpu/common/sec2/sec2_ipc.c index cff36f0be..66ab590d4 100644 --- a/drivers/gpu/nvgpu/common/sec2/sec2_ipc.c +++ b/drivers/gpu/nvgpu/common/sec2/sec2_ipc.c @@ -32,52 +32,6 @@ #include #include -static int sec2_seq_acquire(struct nvgpu_sec2 *sec2, - struct sec2_sequence **pseq) -{ - struct gk20a *g = sec2->g; - struct sec2_sequence *seq; - u64 index = 0; - int err = 0; - - nvgpu_mutex_acquire(&sec2->sec2_seq_lock); - - index = find_first_zero_bit(sec2->sec2_seq_tbl, - sizeof(sec2->sec2_seq_tbl)); - - if (index >= sizeof(sec2->sec2_seq_tbl)) { - nvgpu_err(g, "no free sequence available"); - nvgpu_mutex_release(&sec2->sec2_seq_lock); - err = -EAGAIN; - goto exit; - } - - nvgpu_assert(index < U64(INT_MAX)); - set_bit((int)index, sec2->sec2_seq_tbl); - - nvgpu_mutex_release(&sec2->sec2_seq_lock); - - seq = &sec2->seq[index]; - - seq->state = SEC2_SEQ_STATE_PENDING; - - *pseq = seq; - -exit: - return err; -} - -static void sec2_seq_release(struct nvgpu_sec2 *sec2, - struct sec2_sequence *seq) -{ - seq->state = SEC2_SEQ_STATE_FREE; - seq->callback = NULL; - seq->cb_params = NULL; - seq->out_payload = NULL; - - clear_bit((int)seq->id, sec2->sec2_seq_tbl); -} - /* command post operation functions */ static bool sec2_validate_cmd(struct nvgpu_sec2 *sec2, struct nv_flcn_cmd_sec2 *cmd, u32 queue_id) @@ -168,26 +122,23 @@ int nvgpu_sec2_cmd_post(struct gk20a *g, struct nv_flcn_cmd_sec2 *cmd, } /* Attempt to reserve a sequence for this command. */ - err = sec2_seq_acquire(sec2, &seq); + err = nvgpu_sec2_seq_acquire(g, &sec2->sequences, &seq, + callback, cb_param); if (err != 0) { goto exit; } /* Set the sequence number in the command header. */ - cmd->hdr.seq_id = seq->id; + cmd->hdr.seq_id = nvgpu_sec2_seq_get_id(seq); cmd->hdr.ctrl_flags = 0U; cmd->hdr.ctrl_flags = PMU_CMD_FLAGS_STATUS; - seq->callback = callback; - seq->cb_params = cb_param; - seq->out_payload = NULL; - - seq->state = SEC2_SEQ_STATE_USED; + nvgpu_sec2_seq_set_state(seq, SEC2_SEQ_STATE_USED); err = sec2_write_cmd(sec2, cmd, queue_id, timeout); if (err != 0) { - seq->state = SEC2_SEQ_STATE_PENDING; + nvgpu_sec2_seq_set_state(seq, SEC2_SEQ_STATE_PENDING); } exit: @@ -199,26 +150,9 @@ static int sec2_response_handle(struct nvgpu_sec2 *sec2, struct nv_flcn_msg_sec2 *msg) { struct gk20a *g = sec2->g; - struct sec2_sequence *seq; - int ret = 0; - /* get the sequence info data associated with this message */ - seq = &sec2->seq[msg->hdr.seq_id]; - - if (seq->state != SEC2_SEQ_STATE_USED && - seq->state != SEC2_SEQ_STATE_CANCELLED) { - nvgpu_err(g, "msg for an unknown sequence %d", seq->id); - return -EINVAL; - } - - if (seq->callback != NULL) { - seq->callback(g, msg, seq->cb_params, ret); - } - - /* release the sequence so that it may be used for other commands */ - sec2_seq_release(sec2, seq); - - return 0; + return nvgpu_sec2_seq_response_handle(g, &sec2->sequences, + msg, msg->hdr.seq_id); } static int sec2_handle_event(struct nvgpu_sec2 *sec2, diff --git a/drivers/gpu/nvgpu/common/sec2/sec2_seq.c b/drivers/gpu/nvgpu/common/sec2/sec2_seq.c new file mode 100644 index 000000000..0676b34ae --- /dev/null +++ b/drivers/gpu/nvgpu/common/sec2/sec2_seq.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2018-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 + +int nvgpu_sec2_sequences_alloc(struct gk20a *g, + struct sec2_sequences *sequences) +{ + int err; + + sequences->seq = nvgpu_kzalloc(g, SEC2_MAX_NUM_SEQUENCES * + sizeof(struct sec2_sequence)); + if (sequences->seq == NULL) { + return -ENOMEM; + } + + err = nvgpu_mutex_init(&sequences->sec2_seq_lock); + if (err != 0) { + nvgpu_kfree(g, sequences->seq); + return err; + } + + return 0; +} + +void nvgpu_sec2_sequences_init(struct gk20a *g, + struct sec2_sequences *sequences) +{ + u32 i = 0; + + nvgpu_log_fn(g, " "); + + (void) memset(sequences->seq, 0, + sizeof(struct sec2_sequence) * SEC2_MAX_NUM_SEQUENCES); + + (void) memset(sequences->sec2_seq_tbl, 0, + sizeof(sequences->sec2_seq_tbl)); + + for (i = 0; i < SEC2_MAX_NUM_SEQUENCES; i++) { + sequences->seq[i].id = (u8)i; + } +} + +void nvgpu_sec2_sequences_free(struct gk20a *g, + struct sec2_sequences *sequences) +{ + nvgpu_mutex_destroy(&sequences->sec2_seq_lock); + nvgpu_kfree(g, sequences->seq); +} + +int nvgpu_sec2_seq_acquire(struct gk20a *g, + struct sec2_sequences *sequences, + struct sec2_sequence **pseq, + sec2_callback callback, void *cb_params) +{ + struct sec2_sequence *seq; + u32 index = 0; + int err = 0; + + nvgpu_mutex_acquire(&sequences->sec2_seq_lock); + + index = find_first_zero_bit(sequences->sec2_seq_tbl, + sizeof(sequences->sec2_seq_tbl)); + + if (index >= sizeof(sequences->sec2_seq_tbl)) { + nvgpu_err(g, "no free sequence available"); + nvgpu_mutex_release(&sequences->sec2_seq_lock); + err = -EAGAIN; + goto exit; + } + + nvgpu_assert(index < U64(INT_MAX)); + set_bit(index, sequences->sec2_seq_tbl); + + nvgpu_mutex_release(&sequences->sec2_seq_lock); + + seq = &sequences->seq[index]; + + seq->state = SEC2_SEQ_STATE_PENDING; + seq->callback = callback; + seq->cb_params = cb_params; + seq->out_payload = NULL; + + *pseq = seq; + +exit: + return err; +} + +static void sec2_seq_release(struct sec2_sequences *sequences, + struct sec2_sequence *seq) +{ + seq->state = SEC2_SEQ_STATE_FREE; + seq->callback = NULL; + seq->cb_params = NULL; + seq->out_payload = NULL; + + nvgpu_mutex_acquire(&sequences->sec2_seq_lock); + clear_bit(seq->id, sequences->sec2_seq_tbl); + nvgpu_mutex_release(&sequences->sec2_seq_lock); +} + +int nvgpu_sec2_seq_response_handle(struct gk20a *g, + struct sec2_sequences *sequences, + struct nv_flcn_msg_sec2 *msg, u32 seq_id) +{ + struct sec2_sequence *seq; + + /* get the sequence info data associated with this message */ + seq = &sequences->seq[seq_id]; + + + if (seq->state != SEC2_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 */ + sec2_seq_release(sequences, seq); + + return 0; +} + +u8 nvgpu_sec2_seq_get_id(struct sec2_sequence *seq) +{ + return seq->id; +} + +void nvgpu_sec2_seq_set_state(struct sec2_sequence *seq, + enum sec2_seq_state state) +{ + seq->state = state; +} diff --git a/drivers/gpu/nvgpu/include/nvgpu/sec2.h b/drivers/gpu/nvgpu/include/nvgpu/sec2.h index e21b08ea0..950c58a83 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/sec2.h +++ b/drivers/gpu/nvgpu/include/nvgpu/sec2.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -40,29 +41,9 @@ #define NVGPU_SEC2_TRACE_BUFSIZE (32U*1024U) -#define SEC2_MAX_NUM_SEQUENCES (256U) -#define SEC2_SEQ_BIT_SHIFT (5U) -#define SEC2_SEQ_TBL_SIZE \ - (SEC2_MAX_NUM_SEQUENCES >> SEC2_SEQ_BIT_SHIFT) - -enum sec2_seq_state { - SEC2_SEQ_STATE_FREE = 0U, - SEC2_SEQ_STATE_PENDING, - SEC2_SEQ_STATE_USED, - SEC2_SEQ_STATE_CANCELLED -}; - typedef void (*sec2_callback)(struct gk20a *g, struct nv_flcn_msg_sec2 *msg, void *param, u32 status); -struct sec2_sequence { - u8 id; - enum sec2_seq_state state; - u8 *out_payload; - sec2_callback callback; - void *cb_params; -}; - struct nvgpu_sec2 { struct gk20a *g; struct nvgpu_falcon flcn; @@ -70,9 +51,7 @@ struct nvgpu_sec2 { struct nvgpu_engine_mem_queue *queues[SEC2_QUEUE_NUM]; - struct sec2_sequence *seq; - unsigned long sec2_seq_tbl[SEC2_SEQ_TBL_SIZE]; - struct nvgpu_mutex sec2_seq_lock; + struct sec2_sequences sequences; bool isr_enabled; struct nvgpu_mutex isr_mutex; diff --git a/drivers/gpu/nvgpu/include/nvgpu/sec2/seq.h b/drivers/gpu/nvgpu/include/nvgpu/sec2/seq.h new file mode 100644 index 000000000..6d21fc53a --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/sec2/seq.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018-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_SEC2_SEQ_H +#define NVGPU_SEC2_SEQ_H + +#include +#include + +struct gk20a; +struct nv_flcn_msg_sec2; + +#define SEC2_MAX_NUM_SEQUENCES (256U) +#define SEC2_SEQ_BIT_SHIFT (5U) +#define SEC2_SEQ_TBL_SIZE \ + (SEC2_MAX_NUM_SEQUENCES >> SEC2_SEQ_BIT_SHIFT) + +enum sec2_seq_state { + SEC2_SEQ_STATE_FREE = 0U, + SEC2_SEQ_STATE_PENDING, + SEC2_SEQ_STATE_USED +}; + +typedef void (*sec2_callback)(struct gk20a *g, struct nv_flcn_msg_sec2 *msg, + void *param, u32 status); + +struct sec2_sequence { + u8 id; + enum sec2_seq_state state; + u8 *out_payload; + sec2_callback callback; + void *cb_params; +}; + +struct sec2_sequences { + struct sec2_sequence *seq; + unsigned long sec2_seq_tbl[SEC2_SEQ_TBL_SIZE]; + struct nvgpu_mutex sec2_seq_lock; +}; + +int nvgpu_sec2_sequences_alloc(struct gk20a *g, + struct sec2_sequences *sequences); +void nvgpu_sec2_sequences_init(struct gk20a *g, + struct sec2_sequences *sequences); +void nvgpu_sec2_sequences_free(struct gk20a *g, + struct sec2_sequences *sequences); +int nvgpu_sec2_seq_acquire(struct gk20a *g, + struct sec2_sequences *sequences, + struct sec2_sequence **pseq, + sec2_callback callback, void *cb_params); +int nvgpu_sec2_seq_response_handle(struct gk20a *g, + struct sec2_sequences *sequences, + struct nv_flcn_msg_sec2 *msg, u32 seq_id); +u8 nvgpu_sec2_seq_get_id(struct sec2_sequence *seq); +void nvgpu_sec2_seq_set_state(struct sec2_sequence *seq, + enum sec2_seq_state state); + +#endif /* NVGPU_SEC2_SEQ_H */