| .. | .. |
|---|
| 25 | 25 | #include <core/client.h> |
|---|
| 26 | 26 | #include <core/gpuobj.h> |
|---|
| 27 | 27 | |
|---|
| 28 | | -#include <nvif/cla06f.h> |
|---|
| 28 | +#include <nvif/clc36f.h> |
|---|
| 29 | 29 | #include <nvif/unpack.h> |
|---|
| 30 | + |
|---|
| 31 | +static u32 |
|---|
| 32 | +gv100_fifo_gpfifo_submit_token(struct nvkm_fifo_chan *chan) |
|---|
| 33 | +{ |
|---|
| 34 | + return chan->chid; |
|---|
| 35 | +} |
|---|
| 30 | 36 | |
|---|
| 31 | 37 | static int |
|---|
| 32 | 38 | gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid) |
|---|
| .. | .. |
|---|
| 56 | 62 | return ret; |
|---|
| 57 | 63 | } |
|---|
| 58 | 64 | |
|---|
| 59 | | -static int |
|---|
| 65 | +int |
|---|
| 60 | 66 | gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, |
|---|
| 61 | 67 | struct nvkm_engine *engine, bool suspend) |
|---|
| 62 | 68 | { |
|---|
| .. | .. |
|---|
| 79 | 85 | return ret; |
|---|
| 80 | 86 | } |
|---|
| 81 | 87 | |
|---|
| 82 | | -static int |
|---|
| 88 | +int |
|---|
| 83 | 89 | gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base, |
|---|
| 84 | 90 | struct nvkm_engine *engine) |
|---|
| 85 | 91 | { |
|---|
| .. | .. |
|---|
| 100 | 106 | return gv100_fifo_gpfifo_engine_valid(chan, false, true); |
|---|
| 101 | 107 | } |
|---|
| 102 | 108 | |
|---|
| 103 | | -const struct nvkm_fifo_chan_func |
|---|
| 104 | | -gv100_fifo_gpfifo_func = { |
|---|
| 109 | +static const struct nvkm_fifo_chan_func |
|---|
| 110 | +gv100_fifo_gpfifo = { |
|---|
| 105 | 111 | .dtor = gk104_fifo_gpfifo_dtor, |
|---|
| 106 | 112 | .init = gk104_fifo_gpfifo_init, |
|---|
| 107 | 113 | .fini = gk104_fifo_gpfifo_fini, |
|---|
| .. | .. |
|---|
| 110 | 116 | .engine_dtor = gk104_fifo_gpfifo_engine_dtor, |
|---|
| 111 | 117 | .engine_init = gv100_fifo_gpfifo_engine_init, |
|---|
| 112 | 118 | .engine_fini = gv100_fifo_gpfifo_engine_fini, |
|---|
| 119 | + .submit_token = gv100_fifo_gpfifo_submit_token, |
|---|
| 113 | 120 | }; |
|---|
| 114 | 121 | |
|---|
| 115 | | -static int |
|---|
| 116 | | -gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, |
|---|
| 117 | | - u64 vmm, u64 ioffset, u64 ilength, |
|---|
| 118 | | - const struct nvkm_oclass *oclass, |
|---|
| 122 | +int |
|---|
| 123 | +gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func, |
|---|
| 124 | + struct gk104_fifo *fifo, u64 *runlists, u16 *chid, |
|---|
| 125 | + u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv, |
|---|
| 126 | + u32 *token, const struct nvkm_oclass *oclass, |
|---|
| 119 | 127 | struct nvkm_object **pobject) |
|---|
| 120 | 128 | { |
|---|
| 129 | + struct nvkm_device *device = fifo->base.engine.subdev.device; |
|---|
| 121 | 130 | struct gk104_fifo_chan *chan; |
|---|
| 122 | 131 | int runlist = ffs(*runlists) -1, ret, i; |
|---|
| 123 | 132 | unsigned long engm; |
|---|
| 124 | 133 | u64 subdevs = 0; |
|---|
| 125 | | - u64 usermem; |
|---|
| 134 | + u64 usermem, mthd; |
|---|
| 135 | + u32 size; |
|---|
| 126 | 136 | |
|---|
| 127 | 137 | if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr) |
|---|
| 128 | 138 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 142 | 152 | chan->runl = runlist; |
|---|
| 143 | 153 | INIT_LIST_HEAD(&chan->head); |
|---|
| 144 | 154 | |
|---|
| 145 | | - ret = nvkm_fifo_chan_ctor(&gv100_fifo_gpfifo_func, &fifo->base, |
|---|
| 146 | | - 0x1000, 0x1000, true, vmm, 0, subdevs, |
|---|
| 147 | | - 1, fifo->user.bar->addr, 0x200, |
|---|
| 155 | + ret = nvkm_fifo_chan_ctor(func, &fifo->base, 0x1000, 0x1000, true, vmm, |
|---|
| 156 | + 0, subdevs, 1, fifo->user.bar->addr, 0x200, |
|---|
| 148 | 157 | oclass, &chan->base); |
|---|
| 149 | 158 | if (ret) |
|---|
| 150 | 159 | return ret; |
|---|
| 151 | 160 | |
|---|
| 152 | 161 | *chid = chan->base.chid; |
|---|
| 162 | + *inst = chan->base.inst->addr; |
|---|
| 163 | + *token = chan->base.func->submit_token(&chan->base); |
|---|
| 153 | 164 | |
|---|
| 154 | 165 | /* Hack to support GPUs where even individual channels should be |
|---|
| 155 | 166 | * part of a channel group. |
|---|
| .. | .. |
|---|
| 173 | 184 | nvkm_done(fifo->user.mem); |
|---|
| 174 | 185 | usermem = nvkm_memory_addr(fifo->user.mem) + usermem; |
|---|
| 175 | 186 | |
|---|
| 187 | + /* Allocate fault method buffer (magics come from nvgpu). */ |
|---|
| 188 | + size = nvkm_rd32(device, 0x104028); /* NV_PCE_PCE_MAP */ |
|---|
| 189 | + size = 27 * 5 * (((9 + 1 + 3) * hweight32(size)) + 2); |
|---|
| 190 | + size = roundup(size, PAGE_SIZE); |
|---|
| 191 | + |
|---|
| 192 | + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, 0x1000, true, |
|---|
| 193 | + &chan->mthd); |
|---|
| 194 | + if (ret) |
|---|
| 195 | + return ret; |
|---|
| 196 | + |
|---|
| 197 | + mthd = nvkm_memory_bar2(chan->mthd); |
|---|
| 198 | + if (mthd == ~0ULL) |
|---|
| 199 | + return -EFAULT; |
|---|
| 200 | + |
|---|
| 176 | 201 | /* RAMFC */ |
|---|
| 177 | 202 | nvkm_kmap(chan->base.inst); |
|---|
| 178 | 203 | nvkm_wo32(chan->base.inst, 0x008, lower_32_bits(usermem)); |
|---|
| .. | .. |
|---|
| 184 | 209 | (ilength << 16)); |
|---|
| 185 | 210 | nvkm_wo32(chan->base.inst, 0x084, 0x20400000); |
|---|
| 186 | 211 | nvkm_wo32(chan->base.inst, 0x094, 0x30000001); |
|---|
| 187 | | - nvkm_wo32(chan->base.inst, 0x0e4, 0x00000020); |
|---|
| 212 | + nvkm_wo32(chan->base.inst, 0x0e4, priv ? 0x00000020 : 0x00000000); |
|---|
| 188 | 213 | nvkm_wo32(chan->base.inst, 0x0e8, chan->base.chid); |
|---|
| 189 | | - nvkm_wo32(chan->base.inst, 0x0f4, 0x00001100); |
|---|
| 214 | + nvkm_wo32(chan->base.inst, 0x0f4, 0x00001000); |
|---|
| 190 | 215 | nvkm_wo32(chan->base.inst, 0x0f8, 0x10003080); |
|---|
| 191 | 216 | nvkm_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000); |
|---|
| 192 | | - nvkm_wo32(chan->base.inst, 0x220, 0x020a1000); |
|---|
| 193 | | - nvkm_wo32(chan->base.inst, 0x224, 0x00000000); |
|---|
| 217 | + nvkm_wo32(chan->base.inst, 0x220, lower_32_bits(mthd)); |
|---|
| 218 | + nvkm_wo32(chan->base.inst, 0x224, upper_32_bits(mthd)); |
|---|
| 194 | 219 | nvkm_done(chan->base.inst); |
|---|
| 195 | 220 | return gv100_fifo_gpfifo_engine_valid(chan, true, true); |
|---|
| 196 | 221 | } |
|---|
| .. | .. |
|---|
| 201 | 226 | { |
|---|
| 202 | 227 | struct nvkm_object *parent = oclass->parent; |
|---|
| 203 | 228 | union { |
|---|
| 204 | | - struct kepler_channel_gpfifo_a_v0 v0; |
|---|
| 229 | + struct volta_channel_gpfifo_a_v0 v0; |
|---|
| 205 | 230 | } *args = data; |
|---|
| 206 | 231 | int ret = -ENOSYS; |
|---|
| 207 | 232 | |
|---|
| .. | .. |
|---|
| 209 | 234 | if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { |
|---|
| 210 | 235 | nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " |
|---|
| 211 | 236 | "ioffset %016llx ilength %08x " |
|---|
| 212 | | - "runlist %016llx\n", |
|---|
| 237 | + "runlist %016llx priv %d\n", |
|---|
| 213 | 238 | args->v0.version, args->v0.vmm, args->v0.ioffset, |
|---|
| 214 | | - args->v0.ilength, args->v0.runlist); |
|---|
| 215 | | - return gv100_fifo_gpfifo_new_(fifo, |
|---|
| 239 | + args->v0.ilength, args->v0.runlist, args->v0.priv); |
|---|
| 240 | + if (args->v0.priv && !oclass->client->super) |
|---|
| 241 | + return -EINVAL; |
|---|
| 242 | + return gv100_fifo_gpfifo_new_(&gv100_fifo_gpfifo, fifo, |
|---|
| 216 | 243 | &args->v0.runlist, |
|---|
| 217 | 244 | &args->v0.chid, |
|---|
| 218 | 245 | args->v0.vmm, |
|---|
| 219 | 246 | args->v0.ioffset, |
|---|
| 220 | 247 | args->v0.ilength, |
|---|
| 248 | + &args->v0.inst, |
|---|
| 249 | + args->v0.priv, |
|---|
| 250 | + &args->v0.token, |
|---|
| 221 | 251 | oclass, pobject); |
|---|
| 222 | 252 | } |
|---|
| 223 | 253 | |
|---|