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 <tbergstrom@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1570405
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Terje Bergstrom
2017-09-28 12:32:18 -07:00
committed by mobile promotions
parent c7e0c7e7ce
commit 7685f60d9d
7 changed files with 125 additions and 14 deletions

View File

@@ -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 \

View File

@@ -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);

View File

@@ -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 <nvgpu/rwsem.h>
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);
}

View File

@@ -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)

View File

@@ -58,6 +58,7 @@ struct nvgpu_mem_sgt;
#include <nvgpu/pmu.h>
#include <nvgpu/atomic.h>
#include <nvgpu/barrier.h>
#include <nvgpu/rwsem.h>
#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;

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef __NVGPU_RWSEM_LINUX_H__
#define __NVGPU_RWSEM_LINUX_H__
#include <linux/rwsem.h>
struct nvgpu_rwsem {
struct rw_semaphore rwsem;
};
#endif

View File

@@ -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 <nvgpu/linux/rwsem.h>
#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