Commit f15cde64 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/flcn: rework falcon reset

Mostly preparation to fit in Ampere changes, but should result in reset
sequences a lot closer to RM's, and perhaps help out with the issues we
sometimes see reported in this area.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent c7c0aac7
......@@ -5,6 +5,13 @@
int nvkm_falcon_ctor(const struct nvkm_falcon_func *, struct nvkm_subdev *owner,
const char *name, u32 addr, struct nvkm_falcon *);
void nvkm_falcon_dtor(struct nvkm_falcon *);
int nvkm_falcon_reset(struct nvkm_falcon *);
int gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *);
int gm200_flcn_disable(struct nvkm_falcon *);
int gm200_flcn_enable(struct nvkm_falcon *);
int gp102_flcn_reset_eng(struct nvkm_falcon *);
void nvkm_falcon_v1_load_imem(struct nvkm_falcon *,
void *, u32, u32, u16, u8, bool);
......@@ -15,11 +22,8 @@ int nvkm_falcon_v1_wait_for_halt(struct nvkm_falcon *, u32);
int nvkm_falcon_v1_clear_interrupt(struct nvkm_falcon *, u32);
void nvkm_falcon_v1_set_start_addr(struct nvkm_falcon *, u32 start_addr);
void nvkm_falcon_v1_start(struct nvkm_falcon *);
int nvkm_falcon_v1_enable(struct nvkm_falcon *);
void nvkm_falcon_v1_disable(struct nvkm_falcon *);
void gp102_sec2_flcn_bind_context(struct nvkm_falcon *, struct nvkm_memory *);
int gp102_sec2_flcn_enable(struct nvkm_falcon *);
#define FLCN_PRINTK(f,l,p,fmt,a...) ({ \
if ((f)->owner->name != (f)->name) \
......
......@@ -57,6 +57,12 @@ int nvkm_falcon_new_(const struct nvkm_falcon_func *, struct nvkm_device *,
enum nvkm_subdev_type, int inst, bool enable, u32 addr, struct nvkm_engine **);
struct nvkm_falcon_func {
int (*disable)(struct nvkm_falcon *);
int (*enable)(struct nvkm_falcon *);
bool reset_pmc;
int (*reset_eng)(struct nvkm_falcon *);
int (*reset_wait_mem_scrubbing)(struct nvkm_falcon *);
struct {
u32 *data;
u32 size;
......@@ -80,9 +86,6 @@ struct nvkm_falcon_func {
int (*clear_interrupt)(struct nvkm_falcon *, u32);
void (*set_start_addr)(struct nvkm_falcon *, u32 start_addr);
void (*start)(struct nvkm_falcon *);
int (*enable)(struct nvkm_falcon *falcon);
void (*disable)(struct nvkm_falcon *falcon);
int (*reset)(struct nvkm_falcon *);
struct {
u32 head;
......@@ -122,7 +125,4 @@ void nvkm_falcon_set_start_addr(struct nvkm_falcon *, u32);
void nvkm_falcon_start(struct nvkm_falcon *);
int nvkm_falcon_wait_for_halt(struct nvkm_falcon *, u32);
int nvkm_falcon_clear_interrupt(struct nvkm_falcon *, u32);
int nvkm_falcon_enable(struct nvkm_falcon *);
void nvkm_falcon_disable(struct nvkm_falcon *);
int nvkm_falcon_reset(struct nvkm_falcon *);
#endif
......@@ -2073,17 +2073,9 @@ gf100_gr_ = {
static const struct nvkm_falcon_func
gf100_gr_flcn = {
.fbif = 0x600,
.load_imem = nvkm_falcon_v1_load_imem,
.load_dmem = nvkm_falcon_v1_load_dmem,
.read_dmem = nvkm_falcon_v1_read_dmem,
.bind_context = nvkm_falcon_v1_bind_context,
.wait_for_halt = nvkm_falcon_v1_wait_for_halt,
.clear_interrupt = nvkm_falcon_v1_clear_interrupt,
.set_start_addr = nvkm_falcon_v1_set_start_addr,
.start = nvkm_falcon_v1_start,
.enable = nvkm_falcon_v1_enable,
.disable = nvkm_falcon_v1_disable,
};
int
......
......@@ -23,6 +23,10 @@
static const struct nvkm_falcon_func
gm107_nvdec_flcn = {
.disable = gm200_flcn_disable,
.enable = gm200_flcn_enable,
.reset_pmc = true,
.reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
.debug = 0xd00,
.fbif = 0x600,
.load_imem = nvkm_falcon_v1_load_imem,
......@@ -33,8 +37,6 @@ gm107_nvdec_flcn = {
.clear_interrupt = nvkm_falcon_v1_clear_interrupt,
.set_start_addr = nvkm_falcon_v1_set_start_addr,
.start = nvkm_falcon_v1_start,
.enable = nvkm_falcon_v1_enable,
.disable = nvkm_falcon_v1_disable,
};
static const struct nvkm_nvdec_func
......
......@@ -24,17 +24,6 @@
static const struct nvkm_falcon_func
gm107_nvenc_flcn = {
.fbif = 0x800,
.load_imem = nvkm_falcon_v1_load_imem,
.load_dmem = nvkm_falcon_v1_load_dmem,
.read_dmem = nvkm_falcon_v1_read_dmem,
.bind_context = nvkm_falcon_v1_bind_context,
.wait_for_halt = nvkm_falcon_v1_wait_for_halt,
.clear_interrupt = nvkm_falcon_v1_clear_interrupt,
.set_start_addr = nvkm_falcon_v1_set_start_addr,
.start = nvkm_falcon_v1_start,
.enable = nvkm_falcon_v1_enable,
.disable = nvkm_falcon_v1_disable,
};
static const struct nvkm_nvenc_func
......
......@@ -190,15 +190,6 @@ gp102_sec2_intr(struct nvkm_inth *inth)
return IRQ_HANDLED;
}
int
gp102_sec2_flcn_enable(struct nvkm_falcon *falcon)
{
nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000001);
udelay(10);
nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000000);
return nvkm_falcon_v1_enable(falcon);
}
void
gp102_sec2_flcn_bind_context(struct nvkm_falcon *falcon,
struct nvkm_memory *ctx)
......@@ -240,6 +231,11 @@ gp102_sec2_flcn_bind_context(struct nvkm_falcon *falcon,
static const struct nvkm_falcon_func
gp102_sec2_flcn = {
.disable = gm200_flcn_disable,
.enable = gm200_flcn_enable,
.reset_pmc = true,
.reset_eng = gp102_flcn_reset_eng,
.reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
.debug = 0x408,
.fbif = 0x600,
.load_imem = nvkm_falcon_v1_load_imem,
......@@ -251,8 +247,6 @@ gp102_sec2_flcn = {
.clear_interrupt = nvkm_falcon_v1_clear_interrupt,
.set_start_addr = nvkm_falcon_v1_set_start_addr,
.start = nvkm_falcon_v1_start,
.enable = gp102_sec2_flcn_enable,
.disable = nvkm_falcon_v1_disable,
.cmdq = { 0xa00, 0xa04, 8 },
.msgq = { 0xa30, 0xa34, 8 },
};
......
......@@ -26,6 +26,11 @@
static const struct nvkm_falcon_func
tu102_sec2_flcn = {
.disable = gm200_flcn_disable,
.enable = gm200_flcn_enable,
.reset_pmc = true,
.reset_eng = gp102_flcn_reset_eng,
.reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
.debug = 0x408,
.fbif = 0x600,
.load_imem = nvkm_falcon_v1_load_imem,
......@@ -37,8 +42,6 @@ tu102_sec2_flcn = {
.clear_interrupt = nvkm_falcon_v1_clear_interrupt,
.set_start_addr = nvkm_falcon_v1_set_start_addr,
.start = nvkm_falcon_v1_start,
.enable = nvkm_falcon_v1_enable,
.disable = nvkm_falcon_v1_disable,
.cmdq = { 0xc00, 0xc04, 8 },
.msgq = { 0xc80, 0xc84, 8 },
};
......
......@@ -4,3 +4,6 @@ nvkm-y += nvkm/falcon/cmdq.o
nvkm-y += nvkm/falcon/msgq.o
nvkm-y += nvkm/falcon/qmgr.o
nvkm-y += nvkm/falcon/v1.o
nvkm-y += nvkm/falcon/gm200.o
nvkm-y += nvkm/falcon/gp102.o
......@@ -85,44 +85,15 @@ nvkm_falcon_start(struct nvkm_falcon *falcon)
}
int
nvkm_falcon_enable(struct nvkm_falcon *falcon)
nvkm_falcon_reset(struct nvkm_falcon *falcon)
{
struct nvkm_device *device = falcon->owner->device;
int ret;
nvkm_mc_enable(device, falcon->owner->type, falcon->owner->inst);
ret = falcon->func->enable(falcon);
if (ret) {
nvkm_mc_disable(device, falcon->owner->type, falcon->owner->inst);
ret = falcon->func->disable(falcon);
if (WARN_ON(ret))
return ret;
}
return 0;
}
void
nvkm_falcon_disable(struct nvkm_falcon *falcon)
{
struct nvkm_device *device = falcon->owner->device;
/* already disabled, return or wait_idle will timeout */
if (!nvkm_mc_enabled(device, falcon->owner->type, falcon->owner->inst))
return;
falcon->func->disable(falcon);
nvkm_mc_disable(device, falcon->owner->type, falcon->owner->inst);
}
int
nvkm_falcon_reset(struct nvkm_falcon *falcon)
{
if (!falcon->func->reset) {
nvkm_falcon_disable(falcon);
return nvkm_falcon_enable(falcon);
}
return falcon->func->reset(falcon);
return nvkm_falcon_enable(falcon);
}
int
......
/*
* Copyright 2022 Red Hat Inc.
*
* 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 "priv.h"
#include <subdev/mc.h>
#include <subdev/timer.h>
int
gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *falcon)
{
nvkm_falcon_mask(falcon, 0x040, 0x00000000, 0x00000000);
if (nvkm_msec(falcon->owner->device, 10,
if (!(nvkm_falcon_rd32(falcon, 0x10c) & 0x00000006))
break;
) < 0)
return -ETIMEDOUT;
return 0;
}
int
gm200_flcn_enable(struct nvkm_falcon *falcon)
{
struct nvkm_device *device = falcon->owner->device;
int ret;
if (falcon->func->reset_eng) {
ret = falcon->func->reset_eng(falcon);
if (ret)
return ret;
}
if (falcon->func->reset_pmc)
nvkm_mc_enable(device, falcon->owner->type, falcon->owner->inst);
ret = falcon->func->reset_wait_mem_scrubbing(falcon);
if (ret)
return ret;
nvkm_falcon_wr32(falcon, 0x084, nvkm_rd32(device, 0x000000));
return 0;
}
int
gm200_flcn_disable(struct nvkm_falcon *falcon)
{
struct nvkm_device *device = falcon->owner->device;
int ret;
nvkm_falcon_mask(falcon, 0x048, 0x00000003, 0x00000000);
nvkm_falcon_wr32(falcon, 0x014, 0xffffffff);
if (falcon->func->reset_pmc)
nvkm_mc_disable(device, falcon->owner->type, falcon->owner->inst);
if (falcon->func->reset_eng) {
ret = falcon->func->reset_eng(falcon);
if (ret)
return ret;
}
return 0;
}
/*
* Copyright 2022 Red Hat Inc.
*
* 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 "priv.h"
int
gp102_flcn_reset_eng(struct nvkm_falcon *falcon)
{
nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000001);
udelay(10);
nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000000);
return falcon->func->reset_wait_mem_scrubbing(falcon);
}
......@@ -2,4 +2,12 @@
#ifndef __NVKM_FALCON_PRIV_H__
#define __NVKM_FALCON_PRIV_H__
#include <core/falcon.h>
static inline int
nvkm_falcon_enable(struct nvkm_falcon *falcon)
{
if (falcon->func->enable)
return falcon->func->enable(falcon);
return 0;
}
#endif
......@@ -266,46 +266,3 @@ nvkm_falcon_v1_clear_interrupt(struct nvkm_falcon *falcon, u32 mask)
return 0;
}
static int
falcon_v1_wait_idle(struct nvkm_falcon *falcon)
{
struct nvkm_device *device = falcon->owner->device;
int ret;
ret = nvkm_wait_msec(device, 10, falcon->addr + 0x04c, 0xffff, 0x0);
if (ret < 0)
return ret;
return 0;
}
int
nvkm_falcon_v1_enable(struct nvkm_falcon *falcon)
{
struct nvkm_device *device = falcon->owner->device;
int ret;
ret = nvkm_wait_msec(device, 10, falcon->addr + 0x10c, 0x6, 0x0);
if (ret < 0) {
nvkm_error(falcon->user, "Falcon mem scrubbing timeout\n");
return ret;
}
ret = falcon_v1_wait_idle(falcon);
if (ret)
return ret;
/* enable IRQs */
nvkm_falcon_wr32(falcon, 0x010, 0xff);
return 0;
}
void
nvkm_falcon_v1_disable(struct nvkm_falcon *falcon)
{
/* disable IRQs and wait for any previous code to complete */
nvkm_falcon_wr32(falcon, 0x014, 0xff);
falcon_v1_wait_idle(falcon);
}
......@@ -23,6 +23,10 @@
static const struct nvkm_falcon_func
gv100_gsp_flcn = {
.disable = gm200_flcn_disable,
.enable = gm200_flcn_enable,
.reset_eng = gp102_flcn_reset_eng,
.reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
.fbif = 0x600,
.load_imem = nvkm_falcon_v1_load_imem,
.load_dmem = nvkm_falcon_v1_load_dmem,
......@@ -32,8 +36,6 @@ gv100_gsp_flcn = {
.clear_interrupt = nvkm_falcon_v1_clear_interrupt,
.set_start_addr = nvkm_falcon_v1_set_start_addr,
.start = nvkm_falcon_v1_start,
.enable = gp102_sec2_flcn_enable,
.disable = nvkm_falcon_v1_disable,
};
static const struct nvkm_gsp_func
......
......@@ -23,18 +23,12 @@
*/
#include "priv.h"
static int
gm200_pmu_flcn_reset(struct nvkm_falcon *falcon)
{
struct nvkm_pmu *pmu = container_of(falcon, typeof(*pmu), falcon);
nvkm_falcon_wr32(falcon, 0x014, 0x0000ffff);
pmu->func->reset(pmu);
return nvkm_falcon_enable(falcon);
}
const struct nvkm_falcon_func
gm200_pmu_flcn = {
.disable = gm200_flcn_disable,
.enable = gm200_flcn_enable,
.reset_pmc = true,
.reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
.debug = 0xc08,
.fbif = 0xe00,
.load_imem = nvkm_falcon_v1_load_imem,
......@@ -45,9 +39,6 @@ gm200_pmu_flcn = {
.clear_interrupt = nvkm_falcon_v1_clear_interrupt,
.set_start_addr = nvkm_falcon_v1_set_start_addr,
.start = nvkm_falcon_v1_start,
.enable = nvkm_falcon_v1_enable,
.disable = nvkm_falcon_v1_disable,
.reset = gm200_pmu_flcn_reset,
.cmdq = { 0x4a0, 0x4b0, 4 },
.msgq = { 0x4c8, 0x4cc, 0 },
};
......
......@@ -23,18 +23,29 @@
*/
#include "priv.h"
void
gp102_pmu_reset(struct nvkm_pmu *pmu)
{
struct nvkm_device *device = pmu->subdev.device;
nvkm_mask(device, 0x10a3c0, 0x00000001, 0x00000001);
nvkm_mask(device, 0x10a3c0, 0x00000001, 0x00000000);
}
static const struct nvkm_falcon_func
gp102_pmu_flcn = {
.disable = gm200_flcn_disable,
.enable = gm200_flcn_enable,
.reset_eng = gp102_flcn_reset_eng,
.reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
.debug = 0xc08,
.fbif = 0xe00,
.load_imem = nvkm_falcon_v1_load_imem,
.load_dmem = nvkm_falcon_v1_load_dmem,
.read_dmem = nvkm_falcon_v1_read_dmem,
.bind_context = nvkm_falcon_v1_bind_context,
.wait_for_halt = nvkm_falcon_v1_wait_for_halt,
.clear_interrupt = nvkm_falcon_v1_clear_interrupt,
.set_start_addr = nvkm_falcon_v1_set_start_addr,
.start = nvkm_falcon_v1_start,
.cmdq = { 0x4a0, 0x4b0, 4 },
.msgq = { 0x4c8, 0x4cc, 0 },
};
static const struct nvkm_pmu_func
gp102_pmu = {
.flcn = &gm200_pmu_flcn,
.reset = gp102_pmu_reset,
.flcn = &gp102_pmu_flcn,
};
static const struct nvkm_pmu_fwif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment