Commit af2922fa authored by Dave Airlie's avatar Dave Airlie

Merge branch 'linux-5.12' of git://github.com/skeggsb/linux into drm-next

Nothing too major here, I actually thought I'd sent most of these
right before the new year, but that apparently got lost in the bustle:
- Turing MMU fault recovery fixes
- Fix mDP connectors being reported as eDP to userspace
- Fixes for audio locking, and other bit-rot from DRM changes since
atomic support was written
- Misc other minor fixes.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Ben Skeggs <skeggsb@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CACAvsv7yLfhuVbYa-4g0vxVt93OaC7Sodiz2R-TDHu-MoofEdw@mail.gmail.com
parents 32c3d9b0 d1f5a3fc
...@@ -36,7 +36,7 @@ core507d_update(struct nv50_core *core, u32 *interlock, bool ntfy) ...@@ -36,7 +36,7 @@ core507d_update(struct nv50_core *core, u32 *interlock, bool ntfy)
struct nvif_push *push = core->chan.push; struct nvif_push *push = core->chan.push;
int ret; int ret;
if ((ret = PUSH_WAIT(push, 5))) if ((ret = PUSH_WAIT(push, (ntfy ? 2 : 0) + 3)))
return ret; return ret;
if (ntfy) { if (ntfy) {
......
...@@ -54,7 +54,7 @@ corec37d_update(struct nv50_core *core, u32 *interlock, bool ntfy) ...@@ -54,7 +54,7 @@ corec37d_update(struct nv50_core *core, u32 *interlock, bool ntfy)
struct nvif_push *push = core->chan.push; struct nvif_push *push = core->chan.push;
int ret; int ret;
if ((ret = PUSH_WAIT(push, 9))) if ((ret = PUSH_WAIT(push, (ntfy ? 2 * 2 : 0) + 5)))
return ret; return ret;
if (ntfy) { if (ntfy) {
......
This diff is collapsed.
...@@ -322,7 +322,7 @@ head907d_mode(struct nv50_head *head, struct nv50_head_atom *asyh) ...@@ -322,7 +322,7 @@ head907d_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
const int i = head->base.index; const int i = head->base.index;
int ret; int ret;
if ((ret = PUSH_WAIT(push, 14))) if ((ret = PUSH_WAIT(push, 13)))
return ret; return ret;
PUSH_MTHD(push, NV907D, HEAD_SET_OVERSCAN_COLOR(i), PUSH_MTHD(push, NV907D, HEAD_SET_OVERSCAN_COLOR(i),
...@@ -353,14 +353,7 @@ head907d_mode(struct nv50_head *head, struct nv50_head_atom *asyh) ...@@ -353,14 +353,7 @@ head907d_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
PUSH_MTHD(push, NV907D, HEAD_SET_DEFAULT_BASE_COLOR(i), PUSH_MTHD(push, NV907D, HEAD_SET_DEFAULT_BASE_COLOR(i),
NVVAL(NV907D, HEAD_SET_DEFAULT_BASE_COLOR, RED, 0) | NVVAL(NV907D, HEAD_SET_DEFAULT_BASE_COLOR, RED, 0) |
NVVAL(NV907D, HEAD_SET_DEFAULT_BASE_COLOR, GREEN, 0) | NVVAL(NV907D, HEAD_SET_DEFAULT_BASE_COLOR, GREEN, 0) |
NVVAL(NV907D, HEAD_SET_DEFAULT_BASE_COLOR, BLUE, 0), NVVAL(NV907D, HEAD_SET_DEFAULT_BASE_COLOR, BLUE, 0));
HEAD_SET_CRC_CONTROL(i),
NVDEF(NV907D, HEAD_SET_CRC_CONTROL, CONTROLLING_CHANNEL, CORE) |
NVDEF(NV907D, HEAD_SET_CRC_CONTROL, EXPECT_BUFFER_COLLAPSE, FALSE) |
NVDEF(NV907D, HEAD_SET_CRC_CONTROL, TIMESTAMP_MODE, FALSE) |
NVDEF(NV907D, HEAD_SET_CRC_CONTROL, PRIMARY_OUTPUT, NONE) |
NVDEF(NV907D, HEAD_SET_CRC_CONTROL, SECONDARY_OUTPUT, NONE));
PUSH_MTHD(push, NV907D, HEAD_SET_PIXEL_CLOCK_FREQUENCY(i), PUSH_MTHD(push, NV907D, HEAD_SET_PIXEL_CLOCK_FREQUENCY(i),
NVVAL(NV907D, HEAD_SET_PIXEL_CLOCK_FREQUENCY, HERTZ, m->clock * 1000) | NVVAL(NV907D, HEAD_SET_PIXEL_CLOCK_FREQUENCY, HERTZ, m->clock * 1000) |
......
...@@ -14,6 +14,7 @@ enum dcb_connector_type { ...@@ -14,6 +14,7 @@ enum dcb_connector_type {
DCB_CONNECTOR_LVDS_SPWG = 0x41, DCB_CONNECTOR_LVDS_SPWG = 0x41,
DCB_CONNECTOR_DP = 0x46, DCB_CONNECTOR_DP = 0x46,
DCB_CONNECTOR_eDP = 0x47, DCB_CONNECTOR_eDP = 0x47,
DCB_CONNECTOR_mDP = 0x48,
DCB_CONNECTOR_HDMI_0 = 0x60, DCB_CONNECTOR_HDMI_0 = 0x60,
DCB_CONNECTOR_HDMI_1 = 0x61, DCB_CONNECTOR_HDMI_1 = 0x61,
DCB_CONNECTOR_HDMI_C = 0x63, DCB_CONNECTOR_HDMI_C = 0x63,
......
...@@ -533,6 +533,7 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, ...@@ -533,6 +533,7 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
if (ret) { if (ret) {
NV_PRINTK(err, cli, "channel failed to initialise, %d\n", ret); NV_PRINTK(err, cli, "channel failed to initialise, %d\n", ret);
nouveau_channel_del(pchan); nouveau_channel_del(pchan);
goto done;
} }
ret = nouveau_svmm_join((*pchan)->vmm->svmm, (*pchan)->inst); ret = nouveau_svmm_join((*pchan)->vmm->svmm, (*pchan)->inst);
......
...@@ -1212,6 +1212,7 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb) ...@@ -1212,6 +1212,7 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb)
case DCB_CONNECTOR_DMS59_DP0: case DCB_CONNECTOR_DMS59_DP0:
case DCB_CONNECTOR_DMS59_DP1: case DCB_CONNECTOR_DMS59_DP1:
case DCB_CONNECTOR_DP : case DCB_CONNECTOR_DP :
case DCB_CONNECTOR_mDP :
case DCB_CONNECTOR_USB_C : return DRM_MODE_CONNECTOR_DisplayPort; case DCB_CONNECTOR_USB_C : return DRM_MODE_CONNECTOR_DisplayPort;
case DCB_CONNECTOR_eDP : return DRM_MODE_CONNECTOR_eDP; case DCB_CONNECTOR_eDP : return DRM_MODE_CONNECTOR_eDP;
case DCB_CONNECTOR_HDMI_0 : case DCB_CONNECTOR_HDMI_0 :
......
...@@ -221,6 +221,7 @@ struct nouveau_drm { ...@@ -221,6 +221,7 @@ struct nouveau_drm {
struct { struct {
struct drm_audio_component *component; struct drm_audio_component *component;
struct mutex lock;
bool component_registered; bool component_registered;
} audio; } audio;
}; };
......
...@@ -53,7 +53,12 @@ struct nouveau_encoder { ...@@ -53,7 +53,12 @@ struct nouveau_encoder {
* actually programmed on the hw, not the proposed crtc */ * actually programmed on the hw, not the proposed crtc */
struct drm_crtc *crtc; struct drm_crtc *crtc;
u32 ctrl; u32 ctrl;
bool audio;
/* Protected by nouveau_drm.audio.lock */
struct {
bool enabled;
struct drm_connector *connector;
} audio;
struct drm_display_mode mode; struct drm_display_mode mode;
int last_dpms; int last_dpms;
...@@ -141,11 +146,9 @@ enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *, ...@@ -141,11 +146,9 @@ enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *,
unsigned *clock); unsigned *clock);
struct nouveau_connector * struct nouveau_connector *
nv50_outp_get_new_connector(struct nouveau_encoder *outp, nv50_outp_get_new_connector(struct drm_atomic_state *state, struct nouveau_encoder *outp);
struct drm_atomic_state *state);
struct nouveau_connector * struct nouveau_connector *
nv50_outp_get_old_connector(struct nouveau_encoder *outp, nv50_outp_get_old_connector(struct drm_atomic_state *state, struct nouveau_encoder *outp);
struct drm_atomic_state *state);
int nv50_mstm_detect(struct nouveau_encoder *encoder); int nv50_mstm_detect(struct nouveau_encoder *encoder);
void nv50_mstm_remove(struct nv50_mstm *mstm); void nv50_mstm_remove(struct nv50_mstm *mstm);
......
...@@ -36,19 +36,7 @@ ...@@ -36,19 +36,7 @@
#include <nvif/class.h> #include <nvif/class.h>
#include <nvif/cl0080.h> #include <nvif/cl0080.h>
struct gk104_fifo_engine_status { void
bool busy;
bool faulted;
bool chsw;
bool save;
bool load;
struct {
bool tsg;
u32 id;
} prev, next, *chan;
};
static void
gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn,
struct gk104_fifo_engine_status *status) struct gk104_fifo_engine_status *status)
{ {
...@@ -95,7 +83,7 @@ gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn, ...@@ -95,7 +83,7 @@ gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn,
status->chan == &status->next ? "*" : " "); status->chan == &status->next ? "*" : " ");
} }
static int int
gk104_fifo_class_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, gk104_fifo_class_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
void *argv, u32 argc, struct nvkm_object **pobject) void *argv, u32 argc, struct nvkm_object **pobject)
{ {
...@@ -112,7 +100,7 @@ gk104_fifo_class_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, ...@@ -112,7 +100,7 @@ gk104_fifo_class_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
return -EINVAL; return -EINVAL;
} }
static int int
gk104_fifo_class_get(struct nvkm_fifo *base, int index, gk104_fifo_class_get(struct nvkm_fifo *base, int index,
struct nvkm_oclass *oclass) struct nvkm_oclass *oclass)
{ {
...@@ -134,14 +122,14 @@ gk104_fifo_class_get(struct nvkm_fifo *base, int index, ...@@ -134,14 +122,14 @@ gk104_fifo_class_get(struct nvkm_fifo *base, int index,
return c; return c;
} }
static void void
gk104_fifo_uevent_fini(struct nvkm_fifo *fifo) gk104_fifo_uevent_fini(struct nvkm_fifo *fifo)
{ {
struct nvkm_device *device = fifo->engine.subdev.device; struct nvkm_device *device = fifo->engine.subdev.device;
nvkm_mask(device, 0x002140, 0x80000000, 0x00000000); nvkm_mask(device, 0x002140, 0x80000000, 0x00000000);
} }
static void void
gk104_fifo_uevent_init(struct nvkm_fifo *fifo) gk104_fifo_uevent_init(struct nvkm_fifo *fifo)
{ {
struct nvkm_device *device = fifo->engine.subdev.device; struct nvkm_device *device = fifo->engine.subdev.device;
...@@ -556,7 +544,7 @@ gk104_fifo_bind_reason[] = { ...@@ -556,7 +544,7 @@ gk104_fifo_bind_reason[] = {
{} {}
}; };
static void void
gk104_fifo_intr_bind(struct gk104_fifo *fifo) gk104_fifo_intr_bind(struct gk104_fifo *fifo)
{ {
struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
...@@ -627,7 +615,7 @@ gk104_fifo_intr_sched(struct gk104_fifo *fifo) ...@@ -627,7 +615,7 @@ gk104_fifo_intr_sched(struct gk104_fifo *fifo)
} }
} }
static void void
gk104_fifo_intr_chsw(struct gk104_fifo *fifo) gk104_fifo_intr_chsw(struct gk104_fifo *fifo)
{ {
struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
...@@ -637,7 +625,7 @@ gk104_fifo_intr_chsw(struct gk104_fifo *fifo) ...@@ -637,7 +625,7 @@ gk104_fifo_intr_chsw(struct gk104_fifo *fifo)
nvkm_wr32(device, 0x00256c, stat); nvkm_wr32(device, 0x00256c, stat);
} }
static void void
gk104_fifo_intr_dropped_fault(struct gk104_fifo *fifo) gk104_fifo_intr_dropped_fault(struct gk104_fifo *fifo)
{ {
struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
...@@ -680,7 +668,7 @@ static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = { ...@@ -680,7 +668,7 @@ static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = {
{} {}
}; };
static void void
gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit) gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit)
{ {
struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
...@@ -729,7 +717,7 @@ static const struct nvkm_bitfield gk104_fifo_pbdma_intr_1[] = { ...@@ -729,7 +717,7 @@ static const struct nvkm_bitfield gk104_fifo_pbdma_intr_1[] = {
{} {}
}; };
static void void
gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit) gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit)
{ {
struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
...@@ -750,7 +738,7 @@ gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit) ...@@ -750,7 +738,7 @@ gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit)
nvkm_wr32(device, 0x040148 + (unit * 0x2000), stat); nvkm_wr32(device, 0x040148 + (unit * 0x2000), stat);
} }
static void void
gk104_fifo_intr_runlist(struct gk104_fifo *fifo) gk104_fifo_intr_runlist(struct gk104_fifo *fifo)
{ {
struct nvkm_device *device = fifo->base.engine.subdev.device; struct nvkm_device *device = fifo->base.engine.subdev.device;
...@@ -763,7 +751,7 @@ gk104_fifo_intr_runlist(struct gk104_fifo *fifo) ...@@ -763,7 +751,7 @@ gk104_fifo_intr_runlist(struct gk104_fifo *fifo)
} }
} }
static void void
gk104_fifo_intr_engine(struct gk104_fifo *fifo) gk104_fifo_intr_engine(struct gk104_fifo *fifo)
{ {
nvkm_fifo_uevent(&fifo->base); nvkm_fifo_uevent(&fifo->base);
...@@ -861,7 +849,7 @@ gk104_fifo_intr(struct nvkm_fifo *base) ...@@ -861,7 +849,7 @@ gk104_fifo_intr(struct nvkm_fifo *base)
} }
} }
static void void
gk104_fifo_fini(struct nvkm_fifo *base) gk104_fifo_fini(struct nvkm_fifo *base)
{ {
struct gk104_fifo *fifo = gk104_fifo(base); struct gk104_fifo *fifo = gk104_fifo(base);
...@@ -871,7 +859,7 @@ gk104_fifo_fini(struct nvkm_fifo *base) ...@@ -871,7 +859,7 @@ gk104_fifo_fini(struct nvkm_fifo *base)
nvkm_mask(device, 0x002140, 0x10000000, 0x10000000); nvkm_mask(device, 0x002140, 0x10000000, 0x10000000);
} }
static int int
gk104_fifo_info(struct nvkm_fifo *base, u64 mthd, u64 *data) gk104_fifo_info(struct nvkm_fifo *base, u64 mthd, u64 *data)
{ {
struct gk104_fifo *fifo = gk104_fifo(base); struct gk104_fifo *fifo = gk104_fifo(base);
...@@ -899,7 +887,7 @@ gk104_fifo_info(struct nvkm_fifo *base, u64 mthd, u64 *data) ...@@ -899,7 +887,7 @@ gk104_fifo_info(struct nvkm_fifo *base, u64 mthd, u64 *data)
} }
} }
static int int
gk104_fifo_oneinit(struct nvkm_fifo *base) gk104_fifo_oneinit(struct nvkm_fifo *base)
{ {
struct gk104_fifo *fifo = gk104_fifo(base); struct gk104_fifo *fifo = gk104_fifo(base);
...@@ -974,7 +962,7 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) ...@@ -974,7 +962,7 @@ gk104_fifo_oneinit(struct nvkm_fifo *base)
return nvkm_memory_map(fifo->user.mem, 0, bar, fifo->user.bar, NULL, 0); return nvkm_memory_map(fifo->user.mem, 0, bar, fifo->user.bar, NULL, 0);
} }
static void void
gk104_fifo_init(struct nvkm_fifo *base) gk104_fifo_init(struct nvkm_fifo *base)
{ {
struct gk104_fifo *fifo = gk104_fifo(base); struct gk104_fifo *fifo = gk104_fifo(base);
...@@ -1006,7 +994,7 @@ gk104_fifo_init(struct nvkm_fifo *base) ...@@ -1006,7 +994,7 @@ gk104_fifo_init(struct nvkm_fifo *base)
nvkm_wr32(device, 0x002140, 0x7fffffff); nvkm_wr32(device, 0x002140, 0x7fffffff);
} }
static void * void *
gk104_fifo_dtor(struct nvkm_fifo *base) gk104_fifo_dtor(struct nvkm_fifo *base)
{ {
struct gk104_fifo *fifo = gk104_fifo(base); struct gk104_fifo *fifo = gk104_fifo(base);
......
...@@ -87,11 +87,43 @@ struct gk104_fifo_func { ...@@ -87,11 +87,43 @@ struct gk104_fifo_func {
bool cgrp_force; bool cgrp_force;
}; };
struct gk104_fifo_engine_status {
bool busy;
bool faulted;
bool chsw;
bool save;
bool load;
struct {
bool tsg;
u32 id;
} prev, next, *chan;
};
int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *, int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *,
int index, int nr, struct nvkm_fifo **); int index, int nr, struct nvkm_fifo **);
void gk104_fifo_runlist_insert(struct gk104_fifo *, struct gk104_fifo_chan *); void gk104_fifo_runlist_insert(struct gk104_fifo *, struct gk104_fifo_chan *);
void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *); void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *);
void gk104_fifo_runlist_update(struct gk104_fifo *, int runl); void gk104_fifo_runlist_update(struct gk104_fifo *, int runl);
void gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn,
struct gk104_fifo_engine_status *status);
void gk104_fifo_intr_bind(struct gk104_fifo *fifo);
void gk104_fifo_intr_chsw(struct gk104_fifo *fifo);
void gk104_fifo_intr_dropped_fault(struct gk104_fifo *fifo);
void gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit);
void gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit);
void gk104_fifo_intr_runlist(struct gk104_fifo *fifo);
void gk104_fifo_intr_engine(struct gk104_fifo *fifo);
void *gk104_fifo_dtor(struct nvkm_fifo *base);
int gk104_fifo_oneinit(struct nvkm_fifo *base);
int gk104_fifo_info(struct nvkm_fifo *base, u64 mthd, u64 *data);
void gk104_fifo_init(struct nvkm_fifo *base);
void gk104_fifo_fini(struct nvkm_fifo *base);
int gk104_fifo_class_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
void *argv, u32 argc, struct nvkm_object **pobject);
int gk104_fifo_class_get(struct nvkm_fifo *base, int index,
struct nvkm_oclass *oclass);
void gk104_fifo_uevent_fini(struct nvkm_fifo *fifo);
void gk104_fifo_uevent_init(struct nvkm_fifo *fifo);
extern const struct gk104_fifo_pbdma_func gk104_fifo_pbdma; extern const struct gk104_fifo_pbdma_func gk104_fifo_pbdma;
int gk104_fifo_pbdma_nr(struct gk104_fifo *); int gk104_fifo_pbdma_nr(struct gk104_fifo *);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "priv.h" #include "priv.h"
#include <core/memory.h> #include <core/memory.h>
#include <subdev/mc.h>
#include <subdev/mmu.h> #include <subdev/mmu.h>
#include <engine/fifo.h> #include <engine/fifo.h>
...@@ -34,6 +35,9 @@ tu102_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable) ...@@ -34,6 +35,9 @@ tu102_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable)
* which don't appear to actually work anymore, but newer * which don't appear to actually work anymore, but newer
* versions of RM don't appear to touch anything at all.. * versions of RM don't appear to touch anything at all..
*/ */
struct nvkm_device *device = buffer->fault->subdev.device;
nvkm_mc_intr_mask(device, NVKM_SUBDEV_FAULT, enable);
} }
static void static void
...@@ -41,6 +45,11 @@ tu102_fault_buffer_fini(struct nvkm_fault_buffer *buffer) ...@@ -41,6 +45,11 @@ tu102_fault_buffer_fini(struct nvkm_fault_buffer *buffer)
{ {
struct nvkm_device *device = buffer->fault->subdev.device; struct nvkm_device *device = buffer->fault->subdev.device;
const u32 foff = buffer->id * 0x20; const u32 foff = buffer->id * 0x20;
/* Disable the fault interrupts */
nvkm_wr32(device, 0xb81408, 0x1);
nvkm_wr32(device, 0xb81410, 0x10);
nvkm_mask(device, 0xb83010 + foff, 0x80000000, 0x00000000); nvkm_mask(device, 0xb83010 + foff, 0x80000000, 0x00000000);
} }
...@@ -50,6 +59,10 @@ tu102_fault_buffer_init(struct nvkm_fault_buffer *buffer) ...@@ -50,6 +59,10 @@ tu102_fault_buffer_init(struct nvkm_fault_buffer *buffer)
struct nvkm_device *device = buffer->fault->subdev.device; struct nvkm_device *device = buffer->fault->subdev.device;
const u32 foff = buffer->id * 0x20; const u32 foff = buffer->id * 0x20;
/* Enable the fault interrupts */
nvkm_wr32(device, 0xb81208, 0x1);
nvkm_wr32(device, 0xb81210, 0x10);
nvkm_mask(device, 0xb83010 + foff, 0xc0000000, 0x40000000); nvkm_mask(device, 0xb83010 + foff, 0xc0000000, 0x40000000);
nvkm_wr32(device, 0xb83004 + foff, upper_32_bits(buffer->addr)); nvkm_wr32(device, 0xb83004 + foff, upper_32_bits(buffer->addr));
nvkm_wr32(device, 0xb83000 + foff, lower_32_bits(buffer->addr)); nvkm_wr32(device, 0xb83000 + foff, lower_32_bits(buffer->addr));
...@@ -109,14 +122,20 @@ tu102_fault_intr(struct nvkm_fault *fault) ...@@ -109,14 +122,20 @@ tu102_fault_intr(struct nvkm_fault *fault)
} }
if (stat & 0x00000200) { if (stat & 0x00000200) {
/* Clear the associated interrupt flag */
nvkm_wr32(device, 0xb81010, 0x10);
if (fault->buffer[0]) { if (fault->buffer[0]) {
nvkm_event_send(&fault->event, 1, 0, NULL, 0); nvkm_event_send(&fault->event, 1, 0, NULL, 0);
stat &= ~0x00000200; stat &= ~0x00000200;
} }
} }
/*XXX: guess, can't confirm until we get fw... */ /* Replayable MMU fault */
if (stat & 0x00000100) { if (stat & 0x00000100) {
/* Clear the associated interrupt flag */
nvkm_wr32(device, 0xb81008, 0x1);
if (fault->buffer[1]) { if (fault->buffer[1]) {
nvkm_event_send(&fault->event, 1, 1, NULL, 0); nvkm_event_send(&fault->event, 1, 1, NULL, 0);
stat &= ~0x00000100; stat &= ~0x00000100;
......
...@@ -108,9 +108,6 @@ nvkm_mc_intr(struct nvkm_device *device, bool *handled) ...@@ -108,9 +108,6 @@ nvkm_mc_intr(struct nvkm_device *device, bool *handled)
if (stat) if (stat)
nvkm_error(&mc->subdev, "intr %08x\n", stat); nvkm_error(&mc->subdev, "intr %08x\n", stat);
*handled = intr != 0; *handled = intr != 0;
if (mc->func->intr_hack)
mc->func->intr_hack(mc, handled);
} }
static u32 static u32
......
...@@ -26,7 +26,6 @@ struct nvkm_mc_func { ...@@ -26,7 +26,6 @@ struct nvkm_mc_func {
void (*intr_mask)(struct nvkm_mc *, u32 mask, u32 stat); void (*intr_mask)(struct nvkm_mc *, u32 mask, u32 stat);
/* retrieve pending interrupt mask (NV_PMC_INTR) */ /* retrieve pending interrupt mask (NV_PMC_INTR) */
u32 (*intr_stat)(struct nvkm_mc *); u32 (*intr_stat)(struct nvkm_mc *);
void (*intr_hack)(struct nvkm_mc *, bool *handled);
const struct nvkm_mc_map *reset; const struct nvkm_mc_map *reset;
void (*unk260)(struct nvkm_mc *, u32); void (*unk260)(struct nvkm_mc *, u32);
}; };
......
...@@ -19,37 +19,118 @@ ...@@ -19,37 +19,118 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE. * OTHER DEALINGS IN THE SOFTWARE.
*/ */
#define tu102_mc(p) container_of((p), struct tu102_mc, base)
#include "priv.h" #include "priv.h"
struct tu102_mc {
struct nvkm_mc base;
spinlock_t lock;
bool intr;
u32 mask;
};
static void static void
tu102_mc_intr_hack(struct nvkm_mc *mc, bool *handled) tu102_mc_intr_update(struct tu102_mc *mc)
{ {
struct nvkm_device *device = mc->subdev.device; struct nvkm_device *device = mc->base.subdev.device;
u32 stat = nvkm_rd32(device, 0xb81010); u32 mask = mc->intr ? mc->mask : 0, i;
if (stat & 0x00000050) {
struct nvkm_subdev *subdev = for (i = 0; i < 2; i++) {
nvkm_device_subdev(device, NVKM_SUBDEV_FAULT); nvkm_wr32(device, 0x000180 + (i * 0x04), ~mask);
nvkm_wr32(device, 0xb81010, stat & 0x00000050); nvkm_wr32(device, 0x000160 + (i * 0x04), mask);
if (subdev)
nvkm_subdev_intr(subdev);
*handled = true;
} }
if (mask & 0x00000200)
nvkm_wr32(device, 0xb81608, 0x6);
else
nvkm_wr32(device, 0xb81610, 0x6);
}
void
tu102_mc_intr_unarm(struct nvkm_mc *base)
{
struct tu102_mc *mc = tu102_mc(base);
unsigned long flags;
spin_lock_irqsave(&mc->lock, flags);
mc->intr = false;
tu102_mc_intr_update(mc);
spin_unlock_irqrestore(&mc->lock, flags);
}
void
tu102_mc_intr_rearm(struct nvkm_mc *base)
{
struct tu102_mc *mc = tu102_mc(base);
unsigned long flags;
spin_lock_irqsave(&mc->lock, flags);
mc->intr = true;
tu102_mc_intr_update(mc);
spin_unlock_irqrestore(&mc->lock, flags);
} }
void
tu102_mc_intr_mask(struct nvkm_mc *base, u32 mask, u32 intr)
{
struct tu102_mc *mc = tu102_mc(base);
unsigned long flags;
spin_lock_irqsave(&mc->lock, flags);
mc->mask = (mc->mask & ~mask) | intr;
tu102_mc_intr_update(mc);
spin_unlock_irqrestore(&mc->lock, flags);
}
static u32
tu102_mc_intr_stat(struct nvkm_mc *mc)
{
struct nvkm_device *device = mc->subdev.device;
u32 intr0 = nvkm_rd32(device, 0x000100);
u32 intr1 = nvkm_rd32(device, 0x000104);
u32 intr_top = nvkm_rd32(device, 0xb81600);
/* Turing and above route the MMU fault interrupts via a different
* interrupt tree with different control registers. For the moment remap
* them back to the old PMC vector.
*/
if (intr_top & 0x00000006)
intr0 |= 0x00000200;
return intr0 | intr1;
}
static const struct nvkm_mc_func static const struct nvkm_mc_func
tu102_mc = { tu102_mc = {
.init = nv50_mc_init, .init = nv50_mc_init,
.intr = gp100_mc_intr, .intr = gp100_mc_intr,
.intr_unarm = gp100_mc_intr_unarm, .intr_unarm = tu102_mc_intr_unarm,
.intr_rearm = gp100_mc_intr_rearm, .intr_rearm = tu102_mc_intr_rearm,
.intr_mask = gp100_mc_intr_mask, .intr_mask = tu102_mc_intr_mask,
.intr_stat = gf100_mc_intr_stat, .intr_stat = tu102_mc_intr_stat,
.intr_hack = tu102_mc_intr_hack,
.reset = gk104_mc_reset, .reset = gk104_mc_reset,
}; };
int
tu102_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device,
int index, struct nvkm_mc **pmc)
{
struct tu102_mc *mc;
if (!(mc = kzalloc(sizeof(*mc), GFP_KERNEL)))
return -ENOMEM;
nvkm_mc_ctor(func, device, index, &mc->base);
*pmc = &mc->base;
spin_lock_init(&mc->lock);
mc->intr = false;
mc->mask = 0x7fffffff;
return 0;
}
int int
tu102_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc) tu102_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc)
{ {
return gp100_mc_new_(&tu102_mc, device, index, pmc); return tu102_mc_new_(&tu102_mc, device, index, pmc);
} }
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