From 7685f60d9dd6ed062f3037d4e72ea124c103d211 Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Thu, 28 Sep 2017 12:32:18 -0700 Subject: gpu: nvgpu: Abstract rw_semaphore implementation Abstract implementation of rw_semaphore. In Linux it's implemented in terms of rw_semaphore. Change deterministic_busy to use the new implementation. JIRA NVGPU-259 Change-Id: Ia9c1b6e397581bff7711c5ab6fb76ef6d23cff87 Signed-off-by: Terje Bergstrom Reviewed-on: https://git-master.nvidia.com/r/1570405 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/Makefile.nvgpu | 1 + drivers/gpu/nvgpu/common/linux/driver_common.c | 2 +- drivers/gpu/nvgpu/common/linux/rwsem.c | 39 +++++++++++++++++++++++ drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 24 +++++++------- drivers/gpu/nvgpu/gk20a/gk20a.h | 3 +- drivers/gpu/nvgpu/include/nvgpu/linux/rwsem.h | 26 +++++++++++++++ drivers/gpu/nvgpu/include/nvgpu/rwsem.h | 44 ++++++++++++++++++++++++++ 7 files changed, 125 insertions(+), 14 deletions(-) create mode 100644 drivers/gpu/nvgpu/common/linux/rwsem.c create mode 100644 drivers/gpu/nvgpu/include/nvgpu/linux/rwsem.h create mode 100644 drivers/gpu/nvgpu/include/nvgpu/rwsem.h diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu b/drivers/gpu/nvgpu/Makefile.nvgpu index e059002a..02fb8529 100644 --- a/drivers/gpu/nvgpu/Makefile.nvgpu +++ b/drivers/gpu/nvgpu/Makefile.nvgpu @@ -47,6 +47,7 @@ nvgpu-y := \ common/linux/sysfs.o \ common/linux/cde.o \ common/linux/io.o \ + common/linux/rwsem.o \ common/mm/nvgpu_allocator.o \ common/mm/bitmap_allocator.o \ common/mm/buddy_allocator.o \ diff --git a/drivers/gpu/nvgpu/common/linux/driver_common.c b/drivers/gpu/nvgpu/common/linux/driver_common.c index 734bc1d2..295297b6 100644 --- a/drivers/gpu/nvgpu/common/linux/driver_common.c +++ b/drivers/gpu/nvgpu/common/linux/driver_common.c @@ -44,7 +44,7 @@ static void nvgpu_init_vars(struct gk20a *g) gk20a_init_gr(g); init_rwsem(&l->busy_lock); - init_rwsem(&g->deterministic_busy); + nvgpu_rwsem_init(&g->deterministic_busy); nvgpu_spinlock_init(&g->mc_enable_lock); diff --git a/drivers/gpu/nvgpu/common/linux/rwsem.c b/drivers/gpu/nvgpu/common/linux/rwsem.c new file mode 100644 index 00000000..297ddf11 --- /dev/null +++ b/drivers/gpu/nvgpu/common/linux/rwsem.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include + +void nvgpu_rwsem_init(struct nvgpu_rwsem *rwsem) +{ + init_rwsem(&rwsem->rwsem); +} + +void nvgpu_rwsem_up_read(struct nvgpu_rwsem *rwsem) +{ + up_read(&rwsem->rwsem); +} + +void nvgpu_rwsem_down_read(struct nvgpu_rwsem *rwsem) +{ + down_read(&rwsem->rwsem); +} + +void nvgpu_rwsem_up_write(struct nvgpu_rwsem *rwsem) +{ + up_write(&rwsem->rwsem); +} + +void nvgpu_rwsem_down_write(struct nvgpu_rwsem *rwsem) +{ + down_write(&rwsem->rwsem); +} diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index e3937afd..713c4215 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -602,10 +602,10 @@ unbind: /* put back the channel-wide submit ref from init */ if (ch->deterministic) { - down_read(&g->deterministic_busy); + nvgpu_rwsem_down_read(&g->deterministic_busy); ch->deterministic = false; gk20a_idle(g); - up_read(&g->deterministic_busy); + nvgpu_rwsem_up_read(&g->deterministic_busy); } ch->vpr = false; @@ -1268,7 +1268,7 @@ int gk20a_channel_alloc_gpfifo(struct channel_gk20a *c, c->vpr = true; if (flags & NVGPU_ALLOC_GPFIFO_EX_FLAGS_DETERMINISTIC) { - down_read(&g->deterministic_busy); + nvgpu_rwsem_down_read(&g->deterministic_busy); /* * Railgating isn't deterministic; instead of disallowing * railgating globally, take a power refcount for this @@ -1280,12 +1280,12 @@ int gk20a_channel_alloc_gpfifo(struct channel_gk20a *c, */ err = gk20a_busy(g); if (err) { - up_read(&g->deterministic_busy); + nvgpu_rwsem_up_read(&g->deterministic_busy); return err; } c->deterministic = true; - up_read(&g->deterministic_busy); + nvgpu_rwsem_up_read(&g->deterministic_busy); } /* an address space needs to have been bound at this point. */ @@ -1397,10 +1397,10 @@ clean_up: memset(&c->gpfifo, 0, sizeof(struct gpfifo_desc)); clean_up_idle: if (c->deterministic) { - down_read(&g->deterministic_busy); + nvgpu_rwsem_down_read(&g->deterministic_busy); gk20a_idle(g); c->deterministic = false; - up_read(&g->deterministic_busy); + nvgpu_rwsem_up_read(&g->deterministic_busy); } nvgpu_err(g, "fail"); return err; @@ -2661,7 +2661,7 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, /* Grab access to HW to deal with do_idle */ if (c->deterministic) - down_read(&g->deterministic_busy); + nvgpu_rwsem_down_read(&g->deterministic_busy); trace_gk20a_channel_submit_gpfifo(g->name, c->chid, @@ -2741,7 +2741,7 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, /* No hw access beyond this point */ if (c->deterministic) - up_read(&g->deterministic_busy); + nvgpu_rwsem_up_read(&g->deterministic_busy); trace_gk20a_channel_submitted_gpfifo(g->name, c->chid, @@ -2765,7 +2765,7 @@ clean_up: gk20a_fence_put(pre_fence); gk20a_fence_put(post_fence); if (c->deterministic) - up_read(&g->deterministic_busy); + nvgpu_rwsem_up_read(&g->deterministic_busy); else if (need_deferred_cleanup) gk20a_idle(g); @@ -2787,7 +2787,7 @@ void gk20a_channel_deterministic_idle(struct gk20a *g) u32 chid; /* Grab exclusive access to the hw to block new submits */ - down_write(&g->deterministic_busy); + nvgpu_rwsem_down_write(&g->deterministic_busy); for (chid = 0; chid < f->num_channels; chid++) { struct channel_gk20a *ch = &f->channel[chid]; @@ -2845,7 +2845,7 @@ void gk20a_channel_deterministic_unidle(struct gk20a *g) } /* Release submits, new deterministic channels and frees */ - up_write(&g->deterministic_busy); + nvgpu_rwsem_up_write(&g->deterministic_busy); } int gk20a_init_channel_support(struct gk20a *g, u32 chid) diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index cf13999a..b6f6a97b 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -58,6 +58,7 @@ struct nvgpu_mem_sgt; #include #include #include +#include #include "clk_gk20a.h" #include "ce2_gk20a.h" @@ -1082,7 +1083,7 @@ struct gk20a { * for submits and held for channel lifetime but dropped for an ongoing * gk20a_do_idle(). */ - struct rw_semaphore deterministic_busy; + struct nvgpu_rwsem deterministic_busy; struct nvgpu_falcon pmu_flcn; struct nvgpu_falcon sec2_flcn; diff --git a/drivers/gpu/nvgpu/include/nvgpu/linux/rwsem.h b/drivers/gpu/nvgpu/include/nvgpu/linux/rwsem.h new file mode 100644 index 00000000..7d073d39 --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/linux/rwsem.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __NVGPU_RWSEM_LINUX_H__ +#define __NVGPU_RWSEM_LINUX_H__ + +#include + +struct nvgpu_rwsem { + struct rw_semaphore rwsem; +}; + +#endif diff --git a/drivers/gpu/nvgpu/include/nvgpu/rwsem.h b/drivers/gpu/nvgpu/include/nvgpu/rwsem.h new file mode 100644 index 00000000..d37c11a8 --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/rwsem.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, 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_RWSEM_H__ +#define __NVGPU_RWSEM_H__ + +#ifdef __KERNEL__ +#include +#endif + +/* + * struct nvgpu_rwsem + * + * Should be implemented per-OS in a separate library + * But implementation should adhere to rw_semaphore implementation + * as specified in Linux Documentation + */ +struct nvgpu_rwsem; + +void nvgpu_rwsem_init(struct nvgpu_rwsem *rwsem); +void nvgpu_rwsem_up_read(struct nvgpu_rwsem *rwsem); +void nvgpu_rwsem_down_read(struct nvgpu_rwsem *rwsem); +void nvgpu_rwsem_up_write(struct nvgpu_rwsem *rwsem); +void nvgpu_rwsem_down_write(struct nvgpu_rwsem *rwsem); + +#endif -- cgit v1.2.2