Files
linux-nvgpu/drivers/gpu/nvgpu/common/linux/vgpu/tsg_vgpu.c
Richard Zhao b386768d32 gpu: nvgpu: make .tsg_unbind_channel one layer lower
The message to tell RM server to unbind channel has to be sent after
client unbinds the channel and before client calls tsg release. The
channel has to belong to a tsg on RM server before client submit a
runlist to remove the channel. Or there's a bare channel problem.

By moving .tsg_unbind_channl one layer lower, gk20a_tsg_unbind_channel()
will be common functions for all chip, and it'll call tsg release after
call .tsg_unbind_channel. So vgpu won't need to worry about tsg was
released before sending msg to RM server.

Bug 200382695
Bug 200382785

Change-Id: I32acc122f3f9d5d0628049ccf673225f9e90c87a
Signed-off-by: Richard Zhao <rizhao@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1645383
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Konsta Holtta <kholtta@nvidia.com>
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2018-01-31 02:40:48 -08:00

157 lines
3.8 KiB
C

/*
* Copyright (c) 2016-2018, 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/>.
*/
#include <linux/tegra_vgpu.h>
#include "gk20a/gk20a.h"
#include "gk20a/channel_gk20a.h"
#include "gk20a/tsg_gk20a.h"
#include "common/linux/platform_gk20a.h"
#include "vgpu.h"
#include "fifo_vgpu.h"
#include <nvgpu/bug.h>
int vgpu_tsg_open(struct tsg_gk20a *tsg)
{
struct tegra_vgpu_cmd_msg msg = {};
struct tegra_vgpu_tsg_open_rel_params *p =
&msg.params.tsg_open;
int err;
gk20a_dbg_fn("");
msg.cmd = TEGRA_VGPU_CMD_TSG_OPEN;
msg.handle = vgpu_get_handle(tsg->g);
p->tsg_id = tsg->tsgid;
err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
err = err ? err : msg.ret;
if (err) {
nvgpu_err(tsg->g,
"vgpu_tsg_open failed, tsgid %d", tsg->tsgid);
}
return err;
}
void vgpu_tsg_release(struct tsg_gk20a *tsg)
{
struct tegra_vgpu_cmd_msg msg = {};
struct tegra_vgpu_tsg_open_rel_params *p =
&msg.params.tsg_release;
int err;
gk20a_dbg_fn("");
msg.cmd = TEGRA_VGPU_CMD_TSG_RELEASE;
msg.handle = vgpu_get_handle(tsg->g);
p->tsg_id = tsg->tsgid;
err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
err = err ? err : msg.ret;
if (err) {
nvgpu_err(tsg->g,
"vgpu_tsg_release failed, tsgid %d", tsg->tsgid);
}
}
int vgpu_enable_tsg(struct tsg_gk20a *tsg)
{
struct gk20a *g = tsg->g;
struct channel_gk20a *ch;
nvgpu_rwsem_down_read(&tsg->ch_list_lock);
nvgpu_list_for_each_entry(ch, &tsg->ch_list, channel_gk20a, ch_entry)
g->ops.fifo.enable_channel(ch);
nvgpu_rwsem_up_read(&tsg->ch_list_lock);
return 0;
}
int vgpu_tsg_bind_channel(struct tsg_gk20a *tsg,
struct channel_gk20a *ch)
{
struct tegra_vgpu_cmd_msg msg = {};
struct tegra_vgpu_tsg_bind_unbind_channel_params *p =
&msg.params.tsg_bind_unbind_channel;
int err;
gk20a_dbg_fn("");
err = gk20a_tsg_bind_channel(tsg, ch);
if (err)
return err;
msg.cmd = TEGRA_VGPU_CMD_TSG_BIND_CHANNEL;
msg.handle = vgpu_get_handle(tsg->g);
p->tsg_id = tsg->tsgid;
p->ch_handle = ch->virt_ctx;
err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
err = err ? err : msg.ret;
if (err) {
nvgpu_err(tsg->g,
"vgpu_tsg_bind_channel failed, ch %d tsgid %d",
ch->chid, tsg->tsgid);
gk20a_tsg_unbind_channel(ch);
}
return err;
}
int vgpu_tsg_unbind_channel(struct channel_gk20a *ch)
{
struct tegra_vgpu_cmd_msg msg = {};
struct tegra_vgpu_tsg_bind_unbind_channel_params *p =
&msg.params.tsg_bind_unbind_channel;
int err;
gk20a_dbg_fn("");
err = gk20a_fifo_tsg_unbind_channel(ch);
if (err)
return err;
msg.cmd = TEGRA_VGPU_CMD_TSG_UNBIND_CHANNEL;
msg.handle = vgpu_get_handle(ch->g);
p->ch_handle = ch->virt_ctx;
err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
err = err ? err : msg.ret;
WARN_ON(err);
return err;
}
int vgpu_tsg_set_timeslice(struct tsg_gk20a *tsg, u32 timeslice)
{
struct tegra_vgpu_cmd_msg msg = {0};
struct tegra_vgpu_tsg_timeslice_params *p =
&msg.params.tsg_timeslice;
int err;
gk20a_dbg_fn("");
msg.cmd = TEGRA_VGPU_CMD_TSG_SET_TIMESLICE;
msg.handle = vgpu_get_handle(tsg->g);
p->tsg_id = tsg->tsgid;
p->timeslice_us = timeslice;
err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
err = err ? err : msg.ret;
WARN_ON(err);
if (!err)
tsg->timeslice_us = timeslice;
return err;
}