[Nouveau] [RFC PATCH 3/5] gk104: channel priority/timeslice support
Konsta Hölttä
kholtta at nvidia.com
Wed Aug 5 04:27:51 PDT 2015
Change channel "priorities" by modifying the runlist timeslice value,
thus giving more time for more important jobs before switching.
A new KEPLER_SET_CHANNEL_PRIORITY mthd on fifo channel objects sets the
priority to low, medium or high.
Disable channel and preempt it out, change the timeslice, and then
enable the channel again. The shift bit in the timeslice register is
left untouched (3) as is the enable bit.
Signed-off-by: Konsta Hölttä <kholtta at nvidia.com>
---
drm/nouveau/include/nvif/class.h | 10 +++++++
drm/nouveau/nvkm/engine/fifo/gk104.c | 58 ++++++++++++++++++++++++++++++++++++
2 files changed, 68 insertions(+)
diff --git a/drm/nouveau/include/nvif/class.h b/drm/nouveau/include/nvif/class.h
index 28176e6..381c72d 100644
--- a/drm/nouveau/include/nvif/class.h
+++ b/drm/nouveau/include/nvif/class.h
@@ -619,9 +619,19 @@ struct fermi_a_zbc_depth_v0 {
#define FERMI_A_ZBC_DEPTH_V0_FMT_FP32 0x01
__u8 format;
__u8 index;
__u8 pad03[5];
__u32 ds;
__u32 l2;
};
+#define KEPLER_SET_CHANNEL_PRIORITY 0x42 // XXX
+struct kepler_set_channel_priority_v0 {
+ __u8 version;
+#define KEPLER_SET_CHANNEL_PRIORITY_LOW 0x00
+#define KEPLER_SET_CHANNEL_PRIORITY_MEDIUM 0x01
+#define KEPLER_SET_CHANNEL_PRIORITY_HIGH 0x02
+ __u8 priority;
+ __u8 pad03[6];
+};
+
#endif
diff --git a/drm/nouveau/nvkm/engine/fifo/gk104.c b/drm/nouveau/nvkm/engine/fifo/gk104.c
index 659c05f..2bab45e 100644
--- a/drm/nouveau/nvkm/engine/fifo/gk104.c
+++ b/drm/nouveau/nvkm/engine/fifo/gk104.c
@@ -333,22 +333,80 @@ gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend)
gk104_fifo_runlist_update(priv, chan->engine);
}
gk104_fifo_chan_kick(chan);
nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000);
return nvkm_fifo_channel_fini(&chan->base, suspend);
}
+static int
+gk104_fifo_set_runlist_timeslice(struct gk104_fifo_priv *priv,
+ struct gk104_fifo_chan *chan, u8 slice)
+{
+ struct nvkm_gpuobj *base = nv_gpuobj(nv_object(chan)->parent);
+ u32 chid = chan->base.chid;
+
+ nv_mask(priv, 0x800004 + (chid * 8), 0x00000800, 0x00000800);
+ WARN_ON(gk104_fifo_chan_kick(chan));
+ nv_wo32(base, 0xf8, slice | 0x10003000);
+ nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
+ nv_info(chan, "timeslice set to %d for %d\n", slice, chid);
+
+ return 0;
+}
+
+int
+gk104_fifo_chan_set_priority(struct nvkm_object *object, void *data, u32 size)
+{
+ struct gk104_fifo_priv *priv = (void *)object->engine;
+ struct gk104_fifo_chan *chan = (void *)object;
+ union {
+ struct kepler_set_channel_priority_v0 v0;
+ } *args = data;
+ int ret;
+
+ if (nvif_unpack(args->v0, 0, 0, false)) {
+ switch (args->v0.priority) {
+ case KEPLER_SET_CHANNEL_PRIORITY_LOW:
+ /* 64 << 3 == 512 us */
+ return gk104_fifo_set_runlist_timeslice(priv, chan, 64);
+ case KEPLER_SET_CHANNEL_PRIORITY_MEDIUM:
+ /* 128 << 3 == 1024 us */
+ return gk104_fifo_set_runlist_timeslice(priv, chan, 128);
+ case KEPLER_SET_CHANNEL_PRIORITY_HIGH:
+ /* 256 << 3 == 2048 us */
+ return gk104_fifo_set_runlist_timeslice(priv, chan, 255);
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return ret;
+}
+
+int
+gk104_fifo_chan_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
+{
+ switch (mthd) {
+ case KEPLER_SET_CHANNEL_PRIORITY:
+ return gk104_fifo_chan_set_priority(object, data, size);
+ default:
+ break;
+ }
+ return -EINVAL;
+}
+
struct nvkm_ofuncs
gk104_fifo_chan_ofuncs = {
.ctor = gk104_fifo_chan_ctor,
.dtor = _nvkm_fifo_channel_dtor,
.init = gk104_fifo_chan_init,
.fini = gk104_fifo_chan_fini,
+ .mthd = gk104_fifo_chan_mthd,
.map = _nvkm_fifo_channel_map,
.rd32 = _nvkm_fifo_channel_rd32,
.wr32 = _nvkm_fifo_channel_wr32,
.ntfy = _nvkm_fifo_channel_ntfy
};
static struct nvkm_oclass
gk104_fifo_sclass[] = {
--
2.1.4
More information about the Nouveau
mailing list