mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
gpu: nvgpu: Make trigger mmu fault GPU specific
Add abstraction for triggering fake MMU fault, and a gk20a implementation. Also adds recovery to FE hardware warning exception to make testing easier. Bug 1495967 Change-Id: I6703cff37900a4c4592023423f9c0b31a8928db2 Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
committed by
Dan Willemsen
parent
542f729aa9
commit
3df84a13d1
@@ -1953,7 +1953,7 @@ clean_up:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gk20a_init_fifo(struct gpu_ops *gops)
|
void gk20a_init_channel(struct gpu_ops *gops)
|
||||||
{
|
{
|
||||||
gops->fifo.bind_channel = channel_gk20a_bind;
|
gops->fifo.bind_channel = channel_gk20a_bind;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,6 +167,6 @@ int gk20a_channel_release(struct inode *inode, struct file *filp);
|
|||||||
struct channel_gk20a *gk20a_get_channel_from_file(int fd);
|
struct channel_gk20a *gk20a_get_channel_from_file(int fd);
|
||||||
void gk20a_channel_update(struct channel_gk20a *c, int nr_completed);
|
void gk20a_channel_update(struct channel_gk20a *c, int nr_completed);
|
||||||
|
|
||||||
void gk20a_init_fifo(struct gpu_ops *gops);
|
void gk20a_init_channel(struct gpu_ops *gops);
|
||||||
|
|
||||||
#endif /*__CHANNEL_GK20A_H__*/
|
#endif /*__CHANNEL_GK20A_H__*/
|
||||||
|
|||||||
@@ -1092,43 +1092,15 @@ static void gk20a_fifo_get_faulty_channel(struct gk20a *g, int engine_id,
|
|||||||
fifo_engine_status_id_v(status);
|
fifo_engine_status_id_v(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gk20a_fifo_recover(struct gk20a *g, u32 __engine_ids,
|
static void gk20a_fifo_trigger_mmu_fault(struct gk20a *g,
|
||||||
bool verbose)
|
unsigned long engine_ids)
|
||||||
{
|
{
|
||||||
unsigned long end_jiffies = jiffies +
|
unsigned long end_jiffies = jiffies +
|
||||||
msecs_to_jiffies(gk20a_get_gr_idle_timeout(g));
|
msecs_to_jiffies(gk20a_get_gr_idle_timeout(g));
|
||||||
unsigned long delay = GR_IDLE_CHECK_DEFAULT;
|
unsigned long delay = GR_IDLE_CHECK_DEFAULT;
|
||||||
unsigned long engine_id, i;
|
unsigned long engine_id;
|
||||||
unsigned long _engine_ids = __engine_ids;
|
|
||||||
unsigned long engine_ids = 0;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
gk20a_debug_dump(g->dev);
|
|
||||||
|
|
||||||
/* store faulted engines in advance */
|
|
||||||
g->fifo.mmu_fault_engines = 0;
|
|
||||||
for_each_set_bit(engine_id, &_engine_ids, 32) {
|
|
||||||
bool ref_type_ch;
|
|
||||||
int ref_chid;
|
|
||||||
gk20a_fifo_get_faulty_channel(g, engine_id, &ref_chid,
|
|
||||||
&ref_type_ch);
|
|
||||||
|
|
||||||
/* Reset *all* engines that use the
|
|
||||||
* same channel as faulty engine */
|
|
||||||
for (i = 0; i < g->fifo.max_engines; i++) {
|
|
||||||
bool type_ch;
|
|
||||||
u32 chid;
|
|
||||||
gk20a_fifo_get_faulty_channel(g, i, &chid, &type_ch);
|
|
||||||
if (ref_type_ch == type_ch && ref_chid == chid) {
|
|
||||||
engine_ids |= BIT(i);
|
|
||||||
g->fifo.mmu_fault_engines |=
|
|
||||||
BIT(gk20a_engine_id_to_mmu_id(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* trigger faults for all bad engines */
|
/* trigger faults for all bad engines */
|
||||||
for_each_set_bit(engine_id, &engine_ids, 32) {
|
for_each_set_bit(engine_id, &engine_ids, 32) {
|
||||||
if (engine_id > g->fifo.max_engines) {
|
if (engine_id > g->fifo.max_engines) {
|
||||||
@@ -1164,6 +1136,42 @@ void gk20a_fifo_recover(struct gk20a *g, u32 __engine_ids,
|
|||||||
gk20a_writel(g, fifo_trigger_mmu_fault_r(engine_id), 0);
|
gk20a_writel(g, fifo_trigger_mmu_fault_r(engine_id), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gk20a_fifo_recover(struct gk20a *g, u32 __engine_ids,
|
||||||
|
bool verbose)
|
||||||
|
{
|
||||||
|
unsigned long engine_id, i;
|
||||||
|
unsigned long _engine_ids = __engine_ids;
|
||||||
|
unsigned long engine_ids = 0;
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
gk20a_debug_dump(g->dev);
|
||||||
|
|
||||||
|
/* store faulted engines in advance */
|
||||||
|
g->fifo.mmu_fault_engines = 0;
|
||||||
|
for_each_set_bit(engine_id, &_engine_ids, 32) {
|
||||||
|
bool ref_type_ch;
|
||||||
|
int ref_chid;
|
||||||
|
gk20a_fifo_get_faulty_channel(g, engine_id, &ref_chid,
|
||||||
|
&ref_type_ch);
|
||||||
|
|
||||||
|
/* Reset *all* engines that use the
|
||||||
|
* same channel as faulty engine */
|
||||||
|
for (i = 0; i < g->fifo.max_engines; i++) {
|
||||||
|
bool type_ch;
|
||||||
|
u32 chid;
|
||||||
|
gk20a_fifo_get_faulty_channel(g, i, &chid, &type_ch);
|
||||||
|
if (ref_type_ch == type_ch && ref_chid == chid) {
|
||||||
|
engine_ids |= BIT(i);
|
||||||
|
g->fifo.mmu_fault_engines |=
|
||||||
|
BIT(gk20a_engine_id_to_mmu_id(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
g->ops.fifo.trigger_mmu_fault(g, engine_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool gk20a_fifo_handle_sched_error(struct gk20a *g)
|
static bool gk20a_fifo_handle_sched_error(struct gk20a *g)
|
||||||
{
|
{
|
||||||
@@ -1834,3 +1842,9 @@ bool gk20a_fifo_mmu_fault_pending(struct gk20a *g)
|
|||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gk20a_init_fifo(struct gpu_ops *gops)
|
||||||
|
{
|
||||||
|
gk20a_init_channel(gops);
|
||||||
|
gops->fifo.trigger_mmu_fault = gk20a_fifo_trigger_mmu_fault;
|
||||||
|
}
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ int gk20a_fifo_suspend(struct gk20a *g);
|
|||||||
bool gk20a_fifo_mmu_fault_pending(struct gk20a *g);
|
bool gk20a_fifo_mmu_fault_pending(struct gk20a *g);
|
||||||
void gk20a_fifo_recover(struct gk20a *g, u32 engine_ids, bool verbose);
|
void gk20a_fifo_recover(struct gk20a *g, u32 engine_ids, bool verbose);
|
||||||
int gk20a_init_fifo_reset_enable_hw(struct gk20a *g);
|
int gk20a_init_fifo_reset_enable_hw(struct gk20a *g);
|
||||||
|
void gk20a_init_fifo(struct gpu_ops *gops);
|
||||||
|
|
||||||
void fifo_gk20a_finish_mmu_fault_handling(struct gk20a *g,
|
void fifo_gk20a_finish_mmu_fault_handling(struct gk20a *g,
|
||||||
unsigned long fault_id);
|
unsigned long fault_id);
|
||||||
|
|||||||
@@ -137,6 +137,8 @@ struct gpu_ops {
|
|||||||
} clock_gating;
|
} clock_gating;
|
||||||
struct {
|
struct {
|
||||||
void (*bind_channel)(struct channel_gk20a *ch_gk20a);
|
void (*bind_channel)(struct channel_gk20a *ch_gk20a);
|
||||||
|
void (*trigger_mmu_fault)(struct gk20a *g,
|
||||||
|
unsigned long engine_ids);
|
||||||
} fifo;
|
} fifo;
|
||||||
struct pmu_v {
|
struct pmu_v {
|
||||||
/*used for change of enum zbc update cmd id from ver 0 to ver1*/
|
/*used for change of enum zbc update cmd id from ver 0 to ver1*/
|
||||||
|
|||||||
@@ -5333,6 +5333,7 @@ int gk20a_gr_isr(struct gk20a *g)
|
|||||||
u32 fe = gk20a_readl(g, gr_fe_hww_esr_r());
|
u32 fe = gk20a_readl(g, gr_fe_hww_esr_r());
|
||||||
gk20a_dbg(gpu_dbg_intr, "fe warning %08x\n", fe);
|
gk20a_dbg(gpu_dbg_intr, "fe warning %08x\n", fe);
|
||||||
gk20a_writel(g, gr_fe_hww_esr_r(), fe);
|
gk20a_writel(g, gr_fe_hww_esr_r(), fe);
|
||||||
|
need_reset |= -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if a gpc exception has occurred */
|
/* check if a gpc exception has occurred */
|
||||||
|
|||||||
Reference in New Issue
Block a user