Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

Various fixes/cleanups, along with initial support for SVM features
utilising HMM address-space mirroring and device memory migration.
There's a lot more work to do in these areas, both in terms of
features and efficiency, but these can slowly trickle in later down
the track.

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Ben Skeggs <skeggsb@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CACAvsv5bsB4rRY1Gqa_Bp_KAd-v_q1rGZ4nYmOAQhceL0Nr-Xg@mail.gmail.com

+4336 -1070
+2
drivers/gpu/drm/nouveau/Kbuild
··· 30 30 # DRM - memory management 31 31 nouveau-y += nouveau_bo.o 32 32 nouveau-y += nouveau_gem.o 33 + nouveau-$(CONFIG_DRM_NOUVEAU_SVM) += nouveau_svm.o 34 + nouveau-$(CONFIG_DRM_NOUVEAU_SVM) += nouveau_dmem.o 33 35 nouveau-y += nouveau_mem.o 34 36 nouveau-y += nouveau_prime.o 35 37 nouveau-y += nouveau_sgdma.o
+12
drivers/gpu/drm/nouveau/Kconfig
··· 71 71 help 72 72 Say Y here if you want to control the backlight of your display 73 73 (e.g. a laptop panel). 74 + 75 + config DRM_NOUVEAU_SVM 76 + bool "(EXPERIMENTAL) Enable SVM (Shared Virtual Memory) support" 77 + depends on ARCH_HAS_HMM 78 + depends on DRM_NOUVEAU 79 + depends on STAGING 80 + select HMM_MIRROR 81 + select DEVICE_PRIVATE 82 + default n 83 + help 84 + Say Y here if you want to enable experimental support for 85 + Shared Virtual Memory (SVM).
+213 -1
drivers/gpu/drm/nouveau/dispnv04/crtc.c
··· 40 40 #include "nvreg.h" 41 41 #include "nouveau_fbcon.h" 42 42 #include "disp.h" 43 + #include "nouveau_dma.h" 43 44 44 45 #include <subdev/bios/pll.h> 45 46 #include <subdev/clk.h> ··· 1078 1077 return ret; 1079 1078 } 1080 1079 1080 + struct nv04_page_flip_state { 1081 + struct list_head head; 1082 + struct drm_pending_vblank_event *event; 1083 + struct drm_crtc *crtc; 1084 + int bpp, pitch; 1085 + u64 offset; 1086 + }; 1087 + 1088 + static int 1089 + nv04_finish_page_flip(struct nouveau_channel *chan, 1090 + struct nv04_page_flip_state *ps) 1091 + { 1092 + struct nouveau_fence_chan *fctx = chan->fence; 1093 + struct nouveau_drm *drm = chan->drm; 1094 + struct drm_device *dev = drm->dev; 1095 + struct nv04_page_flip_state *s; 1096 + unsigned long flags; 1097 + 1098 + spin_lock_irqsave(&dev->event_lock, flags); 1099 + 1100 + if (list_empty(&fctx->flip)) { 1101 + NV_ERROR(drm, "unexpected pageflip\n"); 1102 + spin_unlock_irqrestore(&dev->event_lock, flags); 1103 + return -EINVAL; 1104 + } 1105 + 1106 + s = list_first_entry(&fctx->flip, struct nv04_page_flip_state, head); 1107 + if (s->event) { 1108 + drm_crtc_arm_vblank_event(s->crtc, s->event); 1109 + } else { 1110 + /* Give up ownership of vblank for page-flipped crtc */ 1111 + drm_crtc_vblank_put(s->crtc); 1112 + } 1113 + 1114 + list_del(&s->head); 1115 + if (ps) 1116 + *ps = *s; 1117 + kfree(s); 1118 + 1119 + spin_unlock_irqrestore(&dev->event_lock, flags); 1120 + return 0; 1121 + } 1122 + 1123 + int 1124 + nv04_flip_complete(struct nvif_notify *notify) 1125 + { 1126 + struct nouveau_cli *cli = (void *)notify->object->client; 1127 + struct nouveau_drm *drm = cli->drm; 1128 + struct nouveau_channel *chan = drm->channel; 1129 + struct nv04_page_flip_state state; 1130 + 1131 + if (!nv04_finish_page_flip(chan, &state)) { 1132 + nv_set_crtc_base(drm->dev, drm_crtc_index(state.crtc), 1133 + state.offset + state.crtc->y * 1134 + state.pitch + state.crtc->x * 1135 + state.bpp / 8); 1136 + } 1137 + 1138 + return NVIF_NOTIFY_KEEP; 1139 + } 1140 + 1141 + static int 1142 + nv04_page_flip_emit(struct nouveau_channel *chan, 1143 + struct nouveau_bo *old_bo, 1144 + struct nouveau_bo *new_bo, 1145 + struct nv04_page_flip_state *s, 1146 + struct nouveau_fence **pfence) 1147 + { 1148 + struct nouveau_fence_chan *fctx = chan->fence; 1149 + struct nouveau_drm *drm = chan->drm; 1150 + struct drm_device *dev = drm->dev; 1151 + unsigned long flags; 1152 + int ret; 1153 + 1154 + /* Queue it to the pending list */ 1155 + spin_lock_irqsave(&dev->event_lock, flags); 1156 + list_add_tail(&s->head, &fctx->flip); 1157 + spin_unlock_irqrestore(&dev->event_lock, flags); 1158 + 1159 + /* Synchronize with the old framebuffer */ 1160 + ret = nouveau_fence_sync(old_bo, chan, false, false); 1161 + if (ret) 1162 + goto fail; 1163 + 1164 + /* Emit the pageflip */ 1165 + ret = RING_SPACE(chan, 2); 1166 + if (ret) 1167 + goto fail; 1168 + 1169 + BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); 1170 + OUT_RING (chan, 0x00000000); 1171 + FIRE_RING (chan); 1172 + 1173 + ret = nouveau_fence_new(chan, false, pfence); 1174 + if (ret) 1175 + goto fail; 1176 + 1177 + return 0; 1178 + fail: 1179 + spin_lock_irqsave(&dev->event_lock, flags); 1180 + list_del(&s->head); 1181 + spin_unlock_irqrestore(&dev->event_lock, flags); 1182 + return ret; 1183 + } 1184 + 1185 + static int 1186 + nv04_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, 1187 + struct drm_pending_vblank_event *event, u32 flags, 1188 + struct drm_modeset_acquire_ctx *ctx) 1189 + { 1190 + const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1; 1191 + struct drm_device *dev = crtc->dev; 1192 + struct nouveau_drm *drm = nouveau_drm(dev); 1193 + struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo; 1194 + struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; 1195 + struct nv04_page_flip_state *s; 1196 + struct nouveau_channel *chan; 1197 + struct nouveau_cli *cli; 1198 + struct nouveau_fence *fence; 1199 + struct nv04_display *dispnv04 = nv04_display(dev); 1200 + int head = nouveau_crtc(crtc)->index; 1201 + int ret; 1202 + 1203 + chan = drm->channel; 1204 + if (!chan) 1205 + return -ENODEV; 1206 + cli = (void *)chan->user.client; 1207 + 1208 + s = kzalloc(sizeof(*s), GFP_KERNEL); 1209 + if (!s) 1210 + return -ENOMEM; 1211 + 1212 + if (new_bo != old_bo) { 1213 + ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM, true); 1214 + if (ret) 1215 + goto fail_free; 1216 + } 1217 + 1218 + mutex_lock(&cli->mutex); 1219 + ret = ttm_bo_reserve(&new_bo->bo, true, false, NULL); 1220 + if (ret) 1221 + goto fail_unpin; 1222 + 1223 + /* synchronise rendering channel with the kernel's channel */ 1224 + ret = nouveau_fence_sync(new_bo, chan, false, true); 1225 + if (ret) { 1226 + ttm_bo_unreserve(&new_bo->bo); 1227 + goto fail_unpin; 1228 + } 1229 + 1230 + if (new_bo != old_bo) { 1231 + ttm_bo_unreserve(&new_bo->bo); 1232 + 1233 + ret = ttm_bo_reserve(&old_bo->bo, true, false, NULL); 1234 + if (ret) 1235 + goto fail_unpin; 1236 + } 1237 + 1238 + /* Initialize a page flip struct */ 1239 + *s = (struct nv04_page_flip_state) 1240 + { { }, event, crtc, fb->format->cpp[0] * 8, fb->pitches[0], 1241 + new_bo->bo.offset }; 1242 + 1243 + /* Keep vblanks on during flip, for the target crtc of this flip */ 1244 + drm_crtc_vblank_get(crtc); 1245 + 1246 + /* Emit a page flip */ 1247 + if (swap_interval) { 1248 + ret = RING_SPACE(chan, 8); 1249 + if (ret) 1250 + goto fail_unreserve; 1251 + 1252 + BEGIN_NV04(chan, NvSubImageBlit, 0x012c, 1); 1253 + OUT_RING (chan, 0); 1254 + BEGIN_NV04(chan, NvSubImageBlit, 0x0134, 1); 1255 + OUT_RING (chan, head); 1256 + BEGIN_NV04(chan, NvSubImageBlit, 0x0100, 1); 1257 + OUT_RING (chan, 0); 1258 + BEGIN_NV04(chan, NvSubImageBlit, 0x0130, 1); 1259 + OUT_RING (chan, 0); 1260 + } 1261 + 1262 + nouveau_bo_ref(new_bo, &dispnv04->image[head]); 1263 + 1264 + ret = nv04_page_flip_emit(chan, old_bo, new_bo, s, &fence); 1265 + if (ret) 1266 + goto fail_unreserve; 1267 + mutex_unlock(&cli->mutex); 1268 + 1269 + /* Update the crtc struct and cleanup */ 1270 + crtc->primary->fb = fb; 1271 + 1272 + nouveau_bo_fence(old_bo, fence, false); 1273 + ttm_bo_unreserve(&old_bo->bo); 1274 + if (old_bo != new_bo) 1275 + nouveau_bo_unpin(old_bo); 1276 + nouveau_fence_unref(&fence); 1277 + return 0; 1278 + 1279 + fail_unreserve: 1280 + drm_crtc_vblank_put(crtc); 1281 + ttm_bo_unreserve(&old_bo->bo); 1282 + fail_unpin: 1283 + mutex_unlock(&cli->mutex); 1284 + if (old_bo != new_bo) 1285 + nouveau_bo_unpin(new_bo); 1286 + fail_free: 1287 + kfree(s); 1288 + return ret; 1289 + } 1290 + 1081 1291 static const struct drm_crtc_funcs nv04_crtc_funcs = { 1082 1292 .cursor_set = nv04_crtc_cursor_set, 1083 1293 .cursor_move = nv04_crtc_cursor_move, 1084 1294 .gamma_set = nv_crtc_gamma_set, 1085 1295 .set_config = nouveau_crtc_set_config, 1086 - .page_flip = nouveau_crtc_page_flip, 1296 + .page_flip = nv04_crtc_page_flip, 1087 1297 .destroy = nv_crtc_destroy, 1088 1298 }; 1089 1299
+161 -55
drivers/gpu/drm/nouveau/dispnv04/disp.c
··· 30 30 #include "hw.h" 31 31 #include "nouveau_encoder.h" 32 32 #include "nouveau_connector.h" 33 + #include "nouveau_bo.h" 34 + 35 + #include <nvif/if0004.h> 36 + 37 + static void 38 + nv04_display_fini(struct drm_device *dev, bool suspend) 39 + { 40 + struct nv04_display *disp = nv04_display(dev); 41 + struct drm_crtc *crtc; 42 + 43 + /* Disable flip completion events. */ 44 + nvif_notify_put(&disp->flip); 45 + 46 + /* Disable vblank interrupts. */ 47 + NVWriteCRTC(dev, 0, NV_PCRTC_INTR_EN_0, 0); 48 + if (nv_two_heads(dev)) 49 + NVWriteCRTC(dev, 1, NV_PCRTC_INTR_EN_0, 0); 50 + 51 + if (!suspend) 52 + return; 53 + 54 + /* Un-pin FB and cursors so they'll be evicted to system memory. */ 55 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 56 + struct nouveau_framebuffer *nouveau_fb; 57 + 58 + nouveau_fb = nouveau_framebuffer(crtc->primary->fb); 59 + if (!nouveau_fb || !nouveau_fb->nvbo) 60 + continue; 61 + 62 + nouveau_bo_unpin(nouveau_fb->nvbo); 63 + } 64 + 65 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 66 + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 67 + if (nv_crtc->cursor.nvbo) { 68 + if (nv_crtc->cursor.set_offset) 69 + nouveau_bo_unmap(nv_crtc->cursor.nvbo); 70 + nouveau_bo_unpin(nv_crtc->cursor.nvbo); 71 + } 72 + } 73 + } 74 + 75 + static int 76 + nv04_display_init(struct drm_device *dev, bool resume, bool runtime) 77 + { 78 + struct nv04_display *disp = nv04_display(dev); 79 + struct nouveau_drm *drm = nouveau_drm(dev); 80 + struct nouveau_encoder *encoder; 81 + struct drm_crtc *crtc; 82 + int ret; 83 + 84 + /* meh.. modeset apparently doesn't setup all the regs and depends 85 + * on pre-existing state, for now load the state of the card *before* 86 + * nouveau was loaded, and then do a modeset. 87 + * 88 + * best thing to do probably is to make save/restore routines not 89 + * save/restore "pre-load" state, but more general so we can save 90 + * on suspend too. 91 + */ 92 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 93 + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 94 + nv_crtc->save(&nv_crtc->base); 95 + } 96 + 97 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.base.head) 98 + encoder->enc_save(&encoder->base.base); 99 + 100 + /* Enable flip completion events. */ 101 + nvif_notify_get(&disp->flip); 102 + 103 + if (!resume) 104 + return 0; 105 + 106 + /* Re-pin FB/cursors. */ 107 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 108 + struct nouveau_framebuffer *nouveau_fb; 109 + 110 + nouveau_fb = nouveau_framebuffer(crtc->primary->fb); 111 + if (!nouveau_fb || !nouveau_fb->nvbo) 112 + continue; 113 + 114 + ret = nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM, true); 115 + if (ret) 116 + NV_ERROR(drm, "Could not pin framebuffer\n"); 117 + } 118 + 119 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 120 + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 121 + if (!nv_crtc->cursor.nvbo) 122 + continue; 123 + 124 + ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM, true); 125 + if (!ret && nv_crtc->cursor.set_offset) 126 + ret = nouveau_bo_map(nv_crtc->cursor.nvbo); 127 + if (ret) 128 + NV_ERROR(drm, "Could not pin/map cursor.\n"); 129 + } 130 + 131 + /* Force CLUT to get re-loaded during modeset. */ 132 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 133 + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 134 + 135 + nv_crtc->lut.depth = 0; 136 + } 137 + 138 + /* This should ensure we don't hit a locking problem when someone 139 + * wakes us up via a connector. We should never go into suspend 140 + * while the display is on anyways. 141 + */ 142 + if (runtime) 143 + return 0; 144 + 145 + /* Restore mode. */ 146 + drm_helper_resume_force_mode(dev); 147 + 148 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 149 + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 150 + 151 + if (!nv_crtc->cursor.nvbo) 152 + continue; 153 + 154 + if (nv_crtc->cursor.set_offset) 155 + nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset); 156 + nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, 157 + nv_crtc->cursor_saved_y); 158 + } 159 + 160 + return 0; 161 + } 162 + 163 + static void 164 + nv04_display_destroy(struct drm_device *dev) 165 + { 166 + struct nv04_display *disp = nv04_display(dev); 167 + struct nouveau_drm *drm = nouveau_drm(dev); 168 + struct nouveau_encoder *encoder; 169 + struct nouveau_crtc *nv_crtc; 170 + 171 + /* Restore state */ 172 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.base.head) 173 + encoder->enc_restore(&encoder->base.base); 174 + 175 + list_for_each_entry(nv_crtc, &dev->mode_config.crtc_list, base.head) 176 + nv_crtc->restore(&nv_crtc->base); 177 + 178 + nouveau_hw_save_vga_fonts(dev, 0); 179 + 180 + nvif_notify_fini(&disp->flip); 181 + 182 + nouveau_display(dev)->priv = NULL; 183 + kfree(disp); 184 + 185 + nvif_object_unmap(&drm->client.device.object); 186 + } 33 187 34 188 int 35 189 nv04_display_create(struct drm_device *dev) ··· 211 57 212 58 /* Pre-nv50 doesn't support atomic, so don't expose the ioctls */ 213 59 dev->driver->driver_features &= ~DRIVER_ATOMIC; 60 + 61 + /* Request page flip completion event. */ 62 + if (drm->nvsw.client) { 63 + nvif_notify_init(&drm->nvsw, nv04_flip_complete, 64 + false, NV04_NVSW_NTFY_UEVENT, 65 + NULL, 0, 0, &disp->flip); 66 + } 214 67 215 68 nouveau_hw_save_vga_fonts(dev, 1); 216 69 ··· 281 120 nouveau_overlay_init(dev); 282 121 283 122 return 0; 284 - } 285 - 286 - void 287 - nv04_display_destroy(struct drm_device *dev) 288 - { 289 - struct nv04_display *disp = nv04_display(dev); 290 - struct nouveau_drm *drm = nouveau_drm(dev); 291 - struct nouveau_encoder *encoder; 292 - struct nouveau_crtc *nv_crtc; 293 - 294 - /* Restore state */ 295 - list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.base.head) 296 - encoder->enc_restore(&encoder->base.base); 297 - 298 - list_for_each_entry(nv_crtc, &dev->mode_config.crtc_list, base.head) 299 - nv_crtc->restore(&nv_crtc->base); 300 - 301 - nouveau_hw_save_vga_fonts(dev, 0); 302 - 303 - nouveau_display(dev)->priv = NULL; 304 - kfree(disp); 305 - 306 - nvif_object_unmap(&drm->client.device.object); 307 - } 308 - 309 - int 310 - nv04_display_init(struct drm_device *dev) 311 - { 312 - struct nouveau_encoder *encoder; 313 - struct nouveau_crtc *crtc; 314 - 315 - /* meh.. modeset apparently doesn't setup all the regs and depends 316 - * on pre-existing state, for now load the state of the card *before* 317 - * nouveau was loaded, and then do a modeset. 318 - * 319 - * best thing to do probably is to make save/restore routines not 320 - * save/restore "pre-load" state, but more general so we can save 321 - * on suspend too. 322 - */ 323 - list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) 324 - crtc->save(&crtc->base); 325 - 326 - list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.base.head) 327 - encoder->enc_save(&encoder->base.base); 328 - 329 - return 0; 330 - } 331 - 332 - void 333 - nv04_display_fini(struct drm_device *dev) 334 - { 335 - /* disable vblank interrupts */ 336 - NVWriteCRTC(dev, 0, NV_PCRTC_INTR_EN_0, 0); 337 - if (nv_two_heads(dev)) 338 - NVWriteCRTC(dev, 1, NV_PCRTC_INTR_EN_0, 0); 339 123 }
+2 -3
drivers/gpu/drm/nouveau/dispnv04/disp.h
··· 82 82 uint32_t saved_vga_font[4][16384]; 83 83 uint32_t dac_users[4]; 84 84 struct nouveau_bo *image[2]; 85 + struct nvif_notify flip; 85 86 }; 86 87 87 88 static inline struct nv04_display * ··· 93 92 94 93 /* nv04_display.c */ 95 94 int nv04_display_create(struct drm_device *); 96 - void nv04_display_destroy(struct drm_device *); 97 - int nv04_display_init(struct drm_device *); 98 - void nv04_display_fini(struct drm_device *); 99 95 100 96 /* nv04_crtc.c */ 101 97 int nv04_crtc_create(struct drm_device *, int index); ··· 174 176 ); 175 177 } 176 178 179 + int nv04_flip_complete(struct nvif_notify *); 177 180 #endif
+1 -1
drivers/gpu/drm/nouveau/dispnv50/core.c
··· 42 42 int version; 43 43 int (*new)(struct nouveau_drm *, s32, struct nv50_core **); 44 44 } cores[] = { 45 - { TU104_DISP_CORE_CHANNEL_DMA, 0, corec57d_new }, 45 + { TU102_DISP_CORE_CHANNEL_DMA, 0, corec57d_new }, 46 46 { GV100_DISP_CORE_CHANNEL_DMA, 0, corec37d_new }, 47 47 { GP102_DISP_CORE_CHANNEL_DMA, 0, core917d_new }, 48 48 { GP100_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
+1 -1
drivers/gpu/drm/nouveau/dispnv50/curs.c
··· 31 31 int version; 32 32 int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **); 33 33 } curses[] = { 34 - { TU104_DISP_CURSOR, 0, cursc37a_new }, 34 + { TU102_DISP_CURSOR, 0, cursc37a_new }, 35 35 { GV100_DISP_CURSOR, 0, cursc37a_new }, 36 36 { GK104_DISP_CURSOR, 0, curs907a_new }, 37 37 { GF110_DISP_CURSOR, 0, curs907a_new },
+7 -6
drivers/gpu/drm/nouveau/dispnv50/disp.c
··· 817 817 818 818 r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, armh->dp.pbn, 819 819 armh->dp.tu); 820 - WARN_ON(!r); 820 + if (!r) 821 + DRM_DEBUG_KMS("Failed to allocate VCPI\n"); 821 822 822 823 if (!mstm->links++) 823 824 nv50_outp_acquire(mstm->outp); ··· 2221 2220 * Init 2222 2221 *****************************************************************************/ 2223 2222 2224 - void 2225 - nv50_display_fini(struct drm_device *dev) 2223 + static void 2224 + nv50_display_fini(struct drm_device *dev, bool suspend) 2226 2225 { 2227 2226 struct nouveau_encoder *nv_encoder; 2228 2227 struct drm_encoder *encoder; ··· 2243 2242 } 2244 2243 } 2245 2244 2246 - int 2247 - nv50_display_init(struct drm_device *dev) 2245 + static int 2246 + nv50_display_init(struct drm_device *dev, bool resume, bool runtime) 2248 2247 { 2249 2248 struct nv50_core *core = nv50_disp(dev)->core; 2250 2249 struct drm_encoder *encoder; ··· 2270 2269 return 0; 2271 2270 } 2272 2271 2273 - void 2272 + static void 2274 2273 nv50_display_destroy(struct drm_device *dev) 2275 2274 { 2276 2275 struct nv50_disp *disp = nv50_disp(dev);
+1 -1
drivers/gpu/drm/nouveau/dispnv50/wimm.c
··· 31 31 int version; 32 32 int (*init)(struct nouveau_drm *, s32, struct nv50_wndw *); 33 33 } wimms[] = { 34 - { TU104_DISP_WINDOW_IMM_CHANNEL_DMA, 0, wimmc37b_init }, 34 + { TU102_DISP_WINDOW_IMM_CHANNEL_DMA, 0, wimmc37b_init }, 35 35 { GV100_DISP_WINDOW_IMM_CHANNEL_DMA, 0, wimmc37b_init }, 36 36 {} 37 37 };
+1 -1
drivers/gpu/drm/nouveau/dispnv50/wndw.c
··· 626 626 int (*new)(struct nouveau_drm *, enum drm_plane_type, 627 627 int, s32, struct nv50_wndw **); 628 628 } wndws[] = { 629 - { TU104_DISP_WINDOW_CHANNEL_DMA, 0, wndwc57e_new }, 629 + { TU102_DISP_WINDOW_CHANNEL_DMA, 0, wndwc57e_new }, 630 630 { GV100_DISP_WINDOW_CHANNEL_DMA, 0, wndwc37e_new }, 631 631 {} 632 632 };
+8 -5
drivers/gpu/drm/nouveau/include/nvif/class.h
··· 54 54 55 55 #define VOLTA_USERMODE_A 0x0000c361 56 56 57 + #define MAXWELL_FAULT_BUFFER_A /* clb069.h */ 0x0000b069 58 + #define VOLTA_FAULT_BUFFER_A /* clb069.h */ 0x0000c369 59 + 57 60 #define NV03_CHANNEL_DMA /* cl506b.h */ 0x0000006b 58 61 #define NV10_CHANNEL_DMA /* cl506b.h */ 0x0000006e 59 62 #define NV17_CHANNEL_DMA /* cl506b.h */ 0x0000176e ··· 87 84 #define GP100_DISP /* cl5070.h */ 0x00009770 88 85 #define GP102_DISP /* cl5070.h */ 0x00009870 89 86 #define GV100_DISP /* cl5070.h */ 0x0000c370 90 - #define TU104_DISP /* cl5070.h */ 0x0000c570 87 + #define TU102_DISP /* cl5070.h */ 0x0000c570 91 88 92 89 #define NV31_MPEG 0x00003174 93 90 #define G82_MPEG 0x00008274 ··· 100 97 #define GF110_DISP_CURSOR /* cl507a.h */ 0x0000907a 101 98 #define GK104_DISP_CURSOR /* cl507a.h */ 0x0000917a 102 99 #define GV100_DISP_CURSOR /* cl507a.h */ 0x0000c37a 103 - #define TU104_DISP_CURSOR /* cl507a.h */ 0x0000c57a 100 + #define TU102_DISP_CURSOR /* cl507a.h */ 0x0000c57a 104 101 105 102 #define NV50_DISP_OVERLAY /* cl507b.h */ 0x0000507b 106 103 #define G82_DISP_OVERLAY /* cl507b.h */ 0x0000827b ··· 109 106 #define GK104_DISP_OVERLAY /* cl507b.h */ 0x0000917b 110 107 111 108 #define GV100_DISP_WINDOW_IMM_CHANNEL_DMA /* clc37b.h */ 0x0000c37b 112 - #define TU104_DISP_WINDOW_IMM_CHANNEL_DMA /* clc37b.h */ 0x0000c57b 109 + #define TU102_DISP_WINDOW_IMM_CHANNEL_DMA /* clc37b.h */ 0x0000c57b 113 110 114 111 #define NV50_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000507c 115 112 #define G82_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000827c ··· 132 129 #define GP100_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000977d 133 130 #define GP102_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000987d 134 131 #define GV100_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000c37d 135 - #define TU104_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000c57d 132 + #define TU102_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000c57d 136 133 137 134 #define NV50_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000507e 138 135 #define G82_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000827e ··· 142 139 #define GK104_DISP_OVERLAY_CONTROL_DMA /* cl507e.h */ 0x0000917e 143 140 144 141 #define GV100_DISP_WINDOW_CHANNEL_DMA /* clc37e.h */ 0x0000c37e 145 - #define TU104_DISP_WINDOW_CHANNEL_DMA /* clc37e.h */ 0x0000c57e 142 + #define TU102_DISP_WINDOW_CHANNEL_DMA /* clc37e.h */ 0x0000c57e 146 143 147 144 #define NV50_TESLA 0x00005097 148 145 #define G82_TESLA 0x00008297
+12
drivers/gpu/drm/nouveau/include/nvif/clb069.h
··· 1 + #ifndef __NVIF_CLB069_H__ 2 + #define __NVIF_CLB069_H__ 3 + struct nvif_clb069_v0 { 4 + __u8 version; 5 + __u8 pad01[3]; 6 + __u32 entries; 7 + __u32 get; 8 + __u32 put; 9 + }; 10 + 11 + #define NVB069_V0_NTFY_FAULT 0x00 12 + #endif
+29 -1
drivers/gpu/drm/nouveau/include/nvif/if000c.h
··· 3 3 struct nvif_vmm_v0 { 4 4 __u8 version; 5 5 __u8 page_nr; 6 - __u8 pad02[6]; 6 + __u8 managed; 7 + __u8 pad03[5]; 7 8 __u64 addr; 8 9 __u64 size; 9 10 __u8 data[]; ··· 15 14 #define NVIF_VMM_V0_PUT 0x02 16 15 #define NVIF_VMM_V0_MAP 0x03 17 16 #define NVIF_VMM_V0_UNMAP 0x04 17 + #define NVIF_VMM_V0_PFNMAP 0x05 18 + #define NVIF_VMM_V0_PFNCLR 0x06 19 + #define NVIF_VMM_V0_MTHD(i) ((i) + 0x80) 18 20 19 21 struct nvif_vmm_page_v0 { 20 22 __u8 version; ··· 64 60 __u8 version; 65 61 __u8 pad01[7]; 66 62 __u64 addr; 63 + }; 64 + 65 + struct nvif_vmm_pfnmap_v0 { 66 + __u8 version; 67 + __u8 page; 68 + __u8 pad02[6]; 69 + __u64 addr; 70 + __u64 size; 71 + #define NVIF_VMM_PFNMAP_V0_ADDR 0xfffffffffffff000ULL 72 + #define NVIF_VMM_PFNMAP_V0_ADDR_SHIFT 12 73 + #define NVIF_VMM_PFNMAP_V0_APER 0x00000000000000f0ULL 74 + #define NVIF_VMM_PFNMAP_V0_HOST 0x0000000000000000ULL 75 + #define NVIF_VMM_PFNMAP_V0_VRAM 0x0000000000000010ULL 76 + #define NVIF_VMM_PFNMAP_V0_W 0x0000000000000002ULL 77 + #define NVIF_VMM_PFNMAP_V0_V 0x0000000000000001ULL 78 + #define NVIF_VMM_PFNMAP_V0_NONE 0x0000000000000000ULL 79 + __u64 phys[]; 80 + }; 81 + 82 + struct nvif_vmm_pfnclr_v0 { 83 + __u8 version; 84 + __u8 pad01[7]; 85 + __u64 addr; 86 + __u64 size; 67 87 }; 68 88 #endif
+21
drivers/gpu/drm/nouveau/include/nvif/ifc00d.h
··· 6 6 /* nvif_vmm_vX ... */ 7 7 }; 8 8 9 + struct gp100_vmm_v0 { 10 + /* nvif_vmm_vX ... */ 11 + __u8 version; 12 + __u8 fault_replay; 13 + }; 14 + 9 15 struct gp100_vmm_map_vn { 10 16 /* nvif_vmm_map_vX ... */ 11 17 }; ··· 23 17 __u8 ro; 24 18 __u8 priv; 25 19 __u8 kind; 20 + }; 21 + 22 + #define GP100_VMM_VN_FAULT_REPLAY NVIF_VMM_V0_MTHD(0x00) 23 + #define GP100_VMM_VN_FAULT_CANCEL NVIF_VMM_V0_MTHD(0x01) 24 + 25 + struct gp100_vmm_fault_replay_vn { 26 + }; 27 + 28 + struct gp100_vmm_fault_cancel_v0 { 29 + __u8 version; 30 + __u8 hub; 31 + __u8 gpc; 32 + __u8 client; 33 + __u8 pad04[4]; 34 + __u64 inst; 26 35 }; 27 36 #endif
+2 -2
drivers/gpu/drm/nouveau/include/nvif/vmm.h
··· 30 30 int page_nr; 31 31 }; 32 32 33 - int nvif_vmm_init(struct nvif_mmu *, s32 oclass, u64 addr, u64 size, 34 - void *argv, u32 argc, struct nvif_vmm *); 33 + int nvif_vmm_init(struct nvif_mmu *, s32 oclass, bool managed, u64 addr, 34 + u64 size, void *argv, u32 argc, struct nvif_vmm *); 35 35 void nvif_vmm_fini(struct nvif_vmm *); 36 36 int nvif_vmm_get(struct nvif_vmm *, enum nvif_vmm_get, bool sparse, 37 37 u8 page, u8 align, u64 size, struct nvif_vma *);
+3
drivers/gpu/drm/nouveau/include/nvkm/core/device.h
··· 28 28 NVKM_SUBDEV_ICCSENSE, 29 29 NVKM_SUBDEV_THERM, 30 30 NVKM_SUBDEV_CLK, 31 + NVKM_SUBDEV_GSP, 31 32 NVKM_SUBDEV_SECBOOT, 32 33 33 34 NVKM_ENGINE_BSP, ··· 138 137 struct nvkm_fb *fb; 139 138 struct nvkm_fuse *fuse; 140 139 struct nvkm_gpio *gpio; 140 + struct nvkm_gsp *gsp; 141 141 struct nvkm_i2c *i2c; 142 142 struct nvkm_subdev *ibus; 143 143 struct nvkm_iccsense *iccsense; ··· 211 209 int (*fb )(struct nvkm_device *, int idx, struct nvkm_fb **); 212 210 int (*fuse )(struct nvkm_device *, int idx, struct nvkm_fuse **); 213 211 int (*gpio )(struct nvkm_device *, int idx, struct nvkm_gpio **); 212 + int (*gsp )(struct nvkm_device *, int idx, struct nvkm_gsp **); 214 213 int (*i2c )(struct nvkm_device *, int idx, struct nvkm_i2c **); 215 214 int (*ibus )(struct nvkm_device *, int idx, struct nvkm_subdev **); 216 215 int (*iccsense)(struct nvkm_device *, int idx, struct nvkm_iccsense **);
+1 -1
drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
··· 11 11 int gp100_ce_new(struct nvkm_device *, int, struct nvkm_engine **); 12 12 int gp102_ce_new(struct nvkm_device *, int, struct nvkm_engine **); 13 13 int gv100_ce_new(struct nvkm_device *, int, struct nvkm_engine **); 14 - int tu104_ce_new(struct nvkm_device *, int, struct nvkm_engine **); 14 + int tu102_ce_new(struct nvkm_device *, int, struct nvkm_engine **); 15 15 #endif
+1 -1
drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
··· 36 36 int gp100_disp_new(struct nvkm_device *, int, struct nvkm_disp **); 37 37 int gp102_disp_new(struct nvkm_device *, int, struct nvkm_disp **); 38 38 int gv100_disp_new(struct nvkm_device *, int, struct nvkm_disp **); 39 - int tu104_disp_new(struct nvkm_device *, int, struct nvkm_disp **); 39 + int tu102_disp_new(struct nvkm_device *, int, struct nvkm_disp **); 40 40 #endif
+1 -1
drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
··· 74 74 int gp100_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); 75 75 int gp10b_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); 76 76 int gv100_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); 77 - int tu104_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); 77 + int tu102_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); 78 78 #endif
+3
drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h
··· 10 10 11 11 u64 nvkm_gr_units(struct nvkm_gr *); 12 12 int nvkm_gr_tlb_flush(struct nvkm_gr *); 13 + int nvkm_gr_ctxsw_pause(struct nvkm_device *); 14 + int nvkm_gr_ctxsw_resume(struct nvkm_device *); 15 + u32 nvkm_gr_ctxsw_inst(struct nvkm_device *); 13 16 14 17 int nv04_gr_new(struct nvkm_device *, int, struct nvkm_gr **); 15 18 int nv10_gr_new(struct nvkm_device *, int, struct nvkm_gr **);
+2
drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h
··· 6 6 7 7 struct nvkm_nvdec { 8 8 struct nvkm_engine engine; 9 + u32 addr; 10 + 9 11 struct nvkm_falcon *falcon; 10 12 }; 11 13
+3
drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h
··· 5 5 6 6 struct nvkm_sec2 { 7 7 struct nvkm_engine engine; 8 + u32 addr; 9 + 8 10 struct nvkm_falcon *falcon; 9 11 struct nvkm_msgqueue *queue; 10 12 struct work_struct work; 11 13 }; 12 14 13 15 int gp102_sec2_new(struct nvkm_device *, int, struct nvkm_sec2 **); 16 + int tu102_sec2_new(struct nvkm_device *, int, struct nvkm_sec2 **); 14 17 #endif
+1 -1
drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h
··· 29 29 int gk20a_bar_new(struct nvkm_device *, int, struct nvkm_bar **); 30 30 int gm107_bar_new(struct nvkm_device *, int, struct nvkm_bar **); 31 31 int gm20b_bar_new(struct nvkm_device *, int, struct nvkm_bar **); 32 - int tu104_bar_new(struct nvkm_device *, int, struct nvkm_bar **); 32 + int tu102_bar_new(struct nvkm_device *, int, struct nvkm_bar **); 33 33 #endif
+1 -1
drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h
··· 31 31 int gm107_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); 32 32 int gm200_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); 33 33 int gv100_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); 34 - int tu104_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); 34 + int tu102_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); 35 35 #endif
+3 -1
drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h
··· 13 13 struct nvkm_event event; 14 14 15 15 struct nvkm_notify nrpfb; 16 + 17 + struct nvkm_device_oclass user; 16 18 }; 17 19 18 20 struct nvkm_fault_data { ··· 32 30 33 31 int gp100_fault_new(struct nvkm_device *, int, struct nvkm_fault **); 34 32 int gv100_fault_new(struct nvkm_device *, int, struct nvkm_fault **); 35 - int tu104_fault_new(struct nvkm_device *, int, struct nvkm_fault **); 33 + int tu102_fault_new(struct nvkm_device *, int, struct nvkm_fault **); 36 34 #endif
+14
drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
··· 1 + #ifndef __NVKM_GSP_H__ 2 + #define __NVKM_GSP_H__ 3 + #define nvkm_gsp(p) container_of((p), struct nvkm_gsp, subdev) 4 + #include <core/subdev.h> 5 + 6 + struct nvkm_gsp { 7 + struct nvkm_subdev subdev; 8 + u32 addr; 9 + 10 + struct nvkm_falcon *falcon; 11 + }; 12 + 13 + int gv100_gsp_new(struct nvkm_device *, int, struct nvkm_gsp **); 14 + #endif
+1 -1
drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h
··· 31 31 int gk20a_mc_new(struct nvkm_device *, int, struct nvkm_mc **); 32 32 int gp100_mc_new(struct nvkm_device *, int, struct nvkm_mc **); 33 33 int gp10b_mc_new(struct nvkm_device *, int, struct nvkm_mc **); 34 - int tu104_mc_new(struct nvkm_device *, int, struct nvkm_mc **); 34 + int tu102_mc_new(struct nvkm_device *, int, struct nvkm_mc **); 35 35 #endif
+5 -1
drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
··· 17 17 bool part:1; /* Region was split from an allocated region by map(). */ 18 18 bool user:1; /* Region user-allocated. */ 19 19 bool busy:1; /* Region busy (for temporarily preventing user access). */ 20 + bool mapped:1; /* Region contains valid pages. */ 20 21 struct nvkm_memory *memory; /* Memory currently mapped into VMA. */ 21 22 struct nvkm_tags *tags; /* Compression tag reference. */ 22 23 }; ··· 45 44 46 45 dma_addr_t null; 47 46 void *nullp; 47 + 48 + bool replay; 48 49 }; 49 50 50 51 int nvkm_vmm_new(struct nvkm_device *, u64 addr, u64 size, void *argv, u32 argc, ··· 66 63 struct nvkm_mm_node *mem; 67 64 struct scatterlist *sgl; 68 65 dma_addr_t *dma; 66 + u64 *pfn; 69 67 u64 off; 70 68 71 69 const struct nvkm_vmm_page *page; ··· 134 130 int gp100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); 135 131 int gp10b_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); 136 132 int gv100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); 137 - int tu104_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); 133 + int tu102_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); 138 134 #endif
+1
drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h
··· 9 9 struct list_head device; 10 10 }; 11 11 12 + u32 nvkm_top_addr(struct nvkm_device *, enum nvkm_devidx); 12 13 u32 nvkm_top_reset(struct nvkm_device *, enum nvkm_devidx); 13 14 u32 nvkm_top_intr(struct nvkm_device *, u32 intr, u64 *subdevs); 14 15 u32 nvkm_top_intr_mask(struct nvkm_device *, enum nvkm_devidx);
+1
drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
··· 38 38 39 39 int nv40_volt_new(struct nvkm_device *, int, struct nvkm_volt **); 40 40 int gf100_volt_new(struct nvkm_device *, int, struct nvkm_volt **); 41 + int gf117_volt_new(struct nvkm_device *, int, struct nvkm_volt **); 41 42 int gk104_volt_new(struct nvkm_device *, int, struct nvkm_volt **); 42 43 int gk20a_volt_new(struct nvkm_device *, int, struct nvkm_volt **); 43 44 int gm20b_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
+3 -1
drivers/gpu/drm/nouveau/nouveau_abi16.c
··· 214 214 WARN_ON(1); 215 215 break; 216 216 } 217 + break; 217 218 case NOUVEAU_GETPARAM_FB_SIZE: 218 219 getparam->value = drm->gem.vram_available; 219 220 break; ··· 339 338 goto done; 340 339 341 340 if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) { 342 - ret = nouveau_vma_new(chan->ntfy, &cli->vmm, &chan->ntfy_vma); 341 + ret = nouveau_vma_new(chan->ntfy, chan->chan->vmm, 342 + &chan->ntfy_vma); 343 343 if (ret) 344 344 goto done; 345 345 }
+2 -2
drivers/gpu/drm/nouveau/nouveau_bo.c
··· 194 194 struct nouveau_drm *drm = cli->drm; 195 195 struct nouveau_bo *nvbo; 196 196 struct nvif_mmu *mmu = &cli->mmu; 197 - struct nvif_vmm *vmm = &cli->vmm.vmm; 197 + struct nvif_vmm *vmm = cli->svm.cli ? &cli->svm.vmm : &cli->vmm.vmm; 198 198 size_t acc_size; 199 199 int type = ttm_bo_type_device; 200 200 int ret, i, pi = -1; ··· 1434 1434 if (drm->client.mem->oclass < NVIF_CLASS_MEM_NV50 || !mem->kind) 1435 1435 /* untiled */ 1436 1436 break; 1437 - /* fallthrough, tiled memory */ 1437 + /* fall through - tiled memory */ 1438 1438 case TTM_PL_VRAM: 1439 1439 reg->bus.offset = reg->start << PAGE_SHIFT; 1440 1440 reg->bus.base = device->func->resource_addr(device, 1);
+20 -12
drivers/gpu/drm/nouveau/nouveau_chan.c
··· 42 42 #include "nouveau_fence.h" 43 43 #include "nouveau_abi16.h" 44 44 #include "nouveau_vmm.h" 45 + #include "nouveau_svm.h" 45 46 46 47 MODULE_PARM_DESC(vram_pushbuf, "Create DMA push buffers in VRAM"); 47 48 int nouveau_vram_pushbuf; ··· 96 95 97 96 if (chan->fence) 98 97 nouveau_fence(chan->drm)->context_del(chan); 98 + 99 + if (cli) 100 + nouveau_svmm_part(chan->vmm->svmm, chan->inst); 101 + 99 102 nvif_object_fini(&chan->nvsw); 100 103 nvif_object_fini(&chan->gart); 101 104 nvif_object_fini(&chan->vram); ··· 135 130 136 131 chan->device = device; 137 132 chan->drm = drm; 133 + chan->vmm = cli->svm.cli ? &cli->svm : &cli->vmm; 138 134 atomic_set(&chan->killed, 0); 139 135 140 136 /* allocate memory for dma push buffer */ ··· 163 157 chan->push.addr = chan->push.buffer->bo.offset; 164 158 165 159 if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) { 166 - ret = nouveau_vma_new(chan->push.buffer, &cli->vmm, 160 + ret = nouveau_vma_new(chan->push.buffer, chan->vmm, 167 161 &chan->push.vma); 168 162 if (ret) { 169 163 nouveau_channel_del(pchan); ··· 178 172 args.target = NV_DMA_V0_TARGET_VM; 179 173 args.access = NV_DMA_V0_ACCESS_VM; 180 174 args.start = 0; 181 - args.limit = cli->vmm.vmm.limit - 1; 175 + args.limit = chan->vmm->vmm.limit - 1; 182 176 } else 183 177 if (chan->push.buffer->bo.mem.mem_type == TTM_PL_VRAM) { 184 178 if (device->info.family == NV_DEVICE_INFO_V0_TNT) { ··· 208 202 args.target = NV_DMA_V0_TARGET_VM; 209 203 args.access = NV_DMA_V0_ACCESS_RDWR; 210 204 args.start = 0; 211 - args.limit = cli->vmm.vmm.limit - 1; 205 + args.limit = chan->vmm->vmm.limit - 1; 212 206 } 213 207 } 214 208 ··· 226 220 nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, 227 221 u64 runlist, bool priv, struct nouveau_channel **pchan) 228 222 { 229 - struct nouveau_cli *cli = (void *)device->object.client; 230 223 static const u16 oclasses[] = { TURING_CHANNEL_GPFIFO_A, 231 224 VOLTA_CHANNEL_GPFIFO_A, 232 225 PASCAL_CHANNEL_GPFIFO_A, ··· 260 255 args.volta.ilength = 0x02000; 261 256 args.volta.ioffset = 0x10000 + chan->push.addr; 262 257 args.volta.runlist = runlist; 263 - args.volta.vmm = nvif_handle(&cli->vmm.vmm.object); 258 + args.volta.vmm = nvif_handle(&chan->vmm->vmm.object); 264 259 args.volta.priv = priv; 265 260 size = sizeof(args.volta); 266 261 } else ··· 269 264 args.kepler.ilength = 0x02000; 270 265 args.kepler.ioffset = 0x10000 + chan->push.addr; 271 266 args.kepler.runlist = runlist; 272 - args.kepler.vmm = nvif_handle(&cli->vmm.vmm.object); 267 + args.kepler.vmm = nvif_handle(&chan->vmm->vmm.object); 273 268 args.kepler.priv = priv; 274 269 size = sizeof(args.kepler); 275 270 } else ··· 277 272 args.fermi.version = 0; 278 273 args.fermi.ilength = 0x02000; 279 274 args.fermi.ioffset = 0x10000 + chan->push.addr; 280 - args.fermi.vmm = nvif_handle(&cli->vmm.vmm.object); 275 + args.fermi.vmm = nvif_handle(&chan->vmm->vmm.object); 281 276 size = sizeof(args.fermi); 282 277 } else { 283 278 args.nv50.version = 0; 284 279 args.nv50.ilength = 0x02000; 285 280 args.nv50.ioffset = 0x10000 + chan->push.addr; 286 281 args.nv50.pushbuf = nvif_handle(&chan->push.ctxdma); 287 - args.nv50.vmm = nvif_handle(&cli->vmm.vmm.object); 282 + args.nv50.vmm = nvif_handle(&chan->vmm->vmm.object); 288 283 size = sizeof(args.nv50); 289 284 } 290 285 ··· 355 350 nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) 356 351 { 357 352 struct nvif_device *device = chan->device; 358 - struct nouveau_cli *cli = (void *)chan->user.client; 359 353 struct nouveau_drm *drm = chan->drm; 360 354 struct nv_dma_v0 args = {}; 361 355 int ret, i; ··· 380 376 args.target = NV_DMA_V0_TARGET_VM; 381 377 args.access = NV_DMA_V0_ACCESS_VM; 382 378 args.start = 0; 383 - args.limit = cli->vmm.vmm.limit - 1; 379 + args.limit = chan->vmm->vmm.limit - 1; 384 380 } else { 385 381 args.target = NV_DMA_V0_TARGET_VRAM; 386 382 args.access = NV_DMA_V0_ACCESS_RDWR; ··· 397 393 args.target = NV_DMA_V0_TARGET_VM; 398 394 args.access = NV_DMA_V0_ACCESS_VM; 399 395 args.start = 0; 400 - args.limit = cli->vmm.vmm.limit - 1; 396 + args.limit = chan->vmm->vmm.limit - 1; 401 397 } else 402 398 if (chan->drm->agp.bridge) { 403 399 args.target = NV_DMA_V0_TARGET_AGP; ··· 409 405 args.target = NV_DMA_V0_TARGET_VM; 410 406 args.access = NV_DMA_V0_ACCESS_RDWR; 411 407 args.start = 0; 412 - args.limit = cli->vmm.vmm.limit - 1; 408 + args.limit = chan->vmm->vmm.limit - 1; 413 409 } 414 410 415 411 ret = nvif_object_init(&chan->user, gart, NV_DMA_IN_MEMORY, ··· 498 494 NV_PRINTK(err, cli, "channel failed to initialise, %d\n", ret); 499 495 nouveau_channel_del(pchan); 500 496 } 497 + 498 + ret = nouveau_svmm_join((*pchan)->vmm->svmm, (*pchan)->inst); 499 + if (ret) 500 + nouveau_channel_del(pchan); 501 501 502 502 done: 503 503 cli->base.super = super;
+1
drivers/gpu/drm/nouveau/nouveau_chan.h
··· 8 8 struct nouveau_channel { 9 9 struct nvif_device *device; 10 10 struct nouveau_drm *drm; 11 + struct nouveau_vmm *vmm; 11 12 12 13 int chid; 13 14 u64 inst;
+6 -300
drivers/gpu/drm/nouveau/nouveau_display.c
··· 32 32 #include <drm/drm_fb_helper.h> 33 33 #include <drm/drm_probe_helper.h> 34 34 35 - #include <nvif/class.h> 36 - 37 35 #include "nouveau_fbcon.h" 38 - #include "dispnv04/hw.h" 39 36 #include "nouveau_crtc.h" 40 - #include "nouveau_dma.h" 41 37 #include "nouveau_gem.h" 42 38 #include "nouveau_connector.h" 43 39 #include "nv50_display.h" 44 40 45 - #include "nouveau_fence.h" 46 - 41 + #include <nvif/class.h> 47 42 #include <nvif/cl0046.h> 48 43 #include <nvif/event.h> 49 44 ··· 407 412 #endif 408 413 409 414 int 410 - nouveau_display_init(struct drm_device *dev) 415 + nouveau_display_init(struct drm_device *dev, bool resume, bool runtime) 411 416 { 412 417 struct nouveau_display *disp = nouveau_display(dev); 413 - struct nouveau_drm *drm = nouveau_drm(dev); 414 418 struct drm_connector *connector; 415 419 struct drm_connector_list_iter conn_iter; 416 420 int ret; 417 421 418 - ret = disp->init(dev); 422 + ret = disp->init(dev, resume, runtime); 419 423 if (ret) 420 424 return ret; 421 425 ··· 431 437 } 432 438 drm_connector_list_iter_end(&conn_iter); 433 439 434 - /* enable flip completion events */ 435 - nvif_notify_get(&drm->flip); 436 440 return ret; 437 441 } 438 442 ··· 449 457 drm_helper_force_disable_all(dev); 450 458 } 451 459 452 - /* disable flip completion events */ 453 - nvif_notify_put(&drm->flip); 454 - 455 460 /* disable hotplug interrupts */ 456 461 drm_connector_list_iter_begin(dev, &conn_iter); 457 462 nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { ··· 461 472 cancel_work_sync(&drm->hpd_work); 462 473 463 474 drm_kms_helper_poll_disable(dev); 464 - disp->fini(dev); 475 + disp->fini(dev, suspend); 465 476 } 466 477 467 478 static void ··· 614 625 nouveau_display_suspend(struct drm_device *dev, bool runtime) 615 626 { 616 627 struct nouveau_display *disp = nouveau_display(dev); 617 - struct drm_crtc *crtc; 618 628 619 629 if (drm_drv_uses_atomic_modeset(dev)) { 620 630 if (!runtime) { ··· 624 636 return ret; 625 637 } 626 638 } 627 - 628 - nouveau_display_fini(dev, true, runtime); 629 - return 0; 630 639 } 631 640 632 641 nouveau_display_fini(dev, true, runtime); 633 - 634 - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 635 - struct nouveau_framebuffer *nouveau_fb; 636 - 637 - nouveau_fb = nouveau_framebuffer(crtc->primary->fb); 638 - if (!nouveau_fb || !nouveau_fb->nvbo) 639 - continue; 640 - 641 - nouveau_bo_unpin(nouveau_fb->nvbo); 642 - } 643 - 644 - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 645 - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 646 - if (nv_crtc->cursor.nvbo) { 647 - if (nv_crtc->cursor.set_offset) 648 - nouveau_bo_unmap(nv_crtc->cursor.nvbo); 649 - nouveau_bo_unpin(nv_crtc->cursor.nvbo); 650 - } 651 - } 652 - 653 642 return 0; 654 643 } 655 644 ··· 634 669 nouveau_display_resume(struct drm_device *dev, bool runtime) 635 670 { 636 671 struct nouveau_display *disp = nouveau_display(dev); 637 - struct nouveau_drm *drm = nouveau_drm(dev); 638 - struct drm_crtc *crtc; 639 - int ret; 672 + 673 + nouveau_display_init(dev, true, runtime); 640 674 641 675 if (drm_drv_uses_atomic_modeset(dev)) { 642 - nouveau_display_init(dev); 643 676 if (disp->suspend) { 644 677 drm_atomic_helper_resume(dev, disp->suspend); 645 678 disp->suspend = NULL; 646 679 } 647 680 return; 648 681 } 649 - 650 - /* re-pin fb/cursors */ 651 - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 652 - struct nouveau_framebuffer *nouveau_fb; 653 - 654 - nouveau_fb = nouveau_framebuffer(crtc->primary->fb); 655 - if (!nouveau_fb || !nouveau_fb->nvbo) 656 - continue; 657 - 658 - ret = nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM, true); 659 - if (ret) 660 - NV_ERROR(drm, "Could not pin framebuffer\n"); 661 - } 662 - 663 - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 664 - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 665 - if (!nv_crtc->cursor.nvbo) 666 - continue; 667 - 668 - ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM, true); 669 - if (!ret && nv_crtc->cursor.set_offset) 670 - ret = nouveau_bo_map(nv_crtc->cursor.nvbo); 671 - if (ret) 672 - NV_ERROR(drm, "Could not pin/map cursor.\n"); 673 - } 674 - 675 - nouveau_display_init(dev); 676 - 677 - /* Force CLUT to get re-loaded during modeset */ 678 - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 679 - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 680 - 681 - nv_crtc->lut.depth = 0; 682 - } 683 - 684 - /* This should ensure we don't hit a locking problem when someone 685 - * wakes us up via a connector. We should never go into suspend 686 - * while the display is on anyways. 687 - */ 688 - if (runtime) 689 - return; 690 - 691 - drm_helper_resume_force_mode(dev); 692 - 693 - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 694 - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 695 - 696 - if (!nv_crtc->cursor.nvbo) 697 - continue; 698 - 699 - if (nv_crtc->cursor.set_offset) 700 - nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset); 701 - nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, 702 - nv_crtc->cursor_saved_y); 703 - } 704 - } 705 - 706 - static int 707 - nouveau_page_flip_emit(struct nouveau_channel *chan, 708 - struct nouveau_bo *old_bo, 709 - struct nouveau_bo *new_bo, 710 - struct nouveau_page_flip_state *s, 711 - struct nouveau_fence **pfence) 712 - { 713 - struct nouveau_fence_chan *fctx = chan->fence; 714 - struct nouveau_drm *drm = chan->drm; 715 - struct drm_device *dev = drm->dev; 716 - unsigned long flags; 717 - int ret; 718 - 719 - /* Queue it to the pending list */ 720 - spin_lock_irqsave(&dev->event_lock, flags); 721 - list_add_tail(&s->head, &fctx->flip); 722 - spin_unlock_irqrestore(&dev->event_lock, flags); 723 - 724 - /* Synchronize with the old framebuffer */ 725 - ret = nouveau_fence_sync(old_bo, chan, false, false); 726 - if (ret) 727 - goto fail; 728 - 729 - /* Emit the pageflip */ 730 - ret = RING_SPACE(chan, 2); 731 - if (ret) 732 - goto fail; 733 - 734 - BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); 735 - OUT_RING (chan, 0x00000000); 736 - FIRE_RING (chan); 737 - 738 - ret = nouveau_fence_new(chan, false, pfence); 739 - if (ret) 740 - goto fail; 741 - 742 - return 0; 743 - fail: 744 - spin_lock_irqsave(&dev->event_lock, flags); 745 - list_del(&s->head); 746 - spin_unlock_irqrestore(&dev->event_lock, flags); 747 - return ret; 748 - } 749 - 750 - int 751 - nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, 752 - struct drm_pending_vblank_event *event, u32 flags, 753 - struct drm_modeset_acquire_ctx *ctx) 754 - { 755 - const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1; 756 - struct drm_device *dev = crtc->dev; 757 - struct nouveau_drm *drm = nouveau_drm(dev); 758 - struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo; 759 - struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; 760 - struct nouveau_page_flip_state *s; 761 - struct nouveau_channel *chan; 762 - struct nouveau_cli *cli; 763 - struct nouveau_fence *fence; 764 - struct nv04_display *dispnv04 = nv04_display(dev); 765 - int head = nouveau_crtc(crtc)->index; 766 - int ret; 767 - 768 - chan = drm->channel; 769 - if (!chan) 770 - return -ENODEV; 771 - cli = (void *)chan->user.client; 772 - 773 - s = kzalloc(sizeof(*s), GFP_KERNEL); 774 - if (!s) 775 - return -ENOMEM; 776 - 777 - if (new_bo != old_bo) { 778 - ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM, true); 779 - if (ret) 780 - goto fail_free; 781 - } 782 - 783 - mutex_lock(&cli->mutex); 784 - ret = ttm_bo_reserve(&new_bo->bo, true, false, NULL); 785 - if (ret) 786 - goto fail_unpin; 787 - 788 - /* synchronise rendering channel with the kernel's channel */ 789 - ret = nouveau_fence_sync(new_bo, chan, false, true); 790 - if (ret) { 791 - ttm_bo_unreserve(&new_bo->bo); 792 - goto fail_unpin; 793 - } 794 - 795 - if (new_bo != old_bo) { 796 - ttm_bo_unreserve(&new_bo->bo); 797 - 798 - ret = ttm_bo_reserve(&old_bo->bo, true, false, NULL); 799 - if (ret) 800 - goto fail_unpin; 801 - } 802 - 803 - /* Initialize a page flip struct */ 804 - *s = (struct nouveau_page_flip_state) 805 - { { }, event, crtc, fb->format->cpp[0] * 8, fb->pitches[0], 806 - new_bo->bo.offset }; 807 - 808 - /* Keep vblanks on during flip, for the target crtc of this flip */ 809 - drm_crtc_vblank_get(crtc); 810 - 811 - /* Emit a page flip */ 812 - if (swap_interval) { 813 - ret = RING_SPACE(chan, 8); 814 - if (ret) 815 - goto fail_unreserve; 816 - 817 - BEGIN_NV04(chan, NvSubImageBlit, 0x012c, 1); 818 - OUT_RING (chan, 0); 819 - BEGIN_NV04(chan, NvSubImageBlit, 0x0134, 1); 820 - OUT_RING (chan, head); 821 - BEGIN_NV04(chan, NvSubImageBlit, 0x0100, 1); 822 - OUT_RING (chan, 0); 823 - BEGIN_NV04(chan, NvSubImageBlit, 0x0130, 1); 824 - OUT_RING (chan, 0); 825 - } 826 - 827 - nouveau_bo_ref(new_bo, &dispnv04->image[head]); 828 - 829 - ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); 830 - if (ret) 831 - goto fail_unreserve; 832 - mutex_unlock(&cli->mutex); 833 - 834 - /* Update the crtc struct and cleanup */ 835 - crtc->primary->fb = fb; 836 - 837 - nouveau_bo_fence(old_bo, fence, false); 838 - ttm_bo_unreserve(&old_bo->bo); 839 - if (old_bo != new_bo) 840 - nouveau_bo_unpin(old_bo); 841 - nouveau_fence_unref(&fence); 842 - return 0; 843 - 844 - fail_unreserve: 845 - drm_crtc_vblank_put(crtc); 846 - ttm_bo_unreserve(&old_bo->bo); 847 - fail_unpin: 848 - mutex_unlock(&cli->mutex); 849 - if (old_bo != new_bo) 850 - nouveau_bo_unpin(new_bo); 851 - fail_free: 852 - kfree(s); 853 - return ret; 854 - } 855 - 856 - int 857 - nouveau_finish_page_flip(struct nouveau_channel *chan, 858 - struct nouveau_page_flip_state *ps) 859 - { 860 - struct nouveau_fence_chan *fctx = chan->fence; 861 - struct nouveau_drm *drm = chan->drm; 862 - struct drm_device *dev = drm->dev; 863 - struct nouveau_page_flip_state *s; 864 - unsigned long flags; 865 - 866 - spin_lock_irqsave(&dev->event_lock, flags); 867 - 868 - if (list_empty(&fctx->flip)) { 869 - NV_ERROR(drm, "unexpected pageflip\n"); 870 - spin_unlock_irqrestore(&dev->event_lock, flags); 871 - return -EINVAL; 872 - } 873 - 874 - s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head); 875 - if (s->event) { 876 - drm_crtc_arm_vblank_event(s->crtc, s->event); 877 - } else { 878 - /* Give up ownership of vblank for page-flipped crtc */ 879 - drm_crtc_vblank_put(s->crtc); 880 - } 881 - 882 - list_del(&s->head); 883 - if (ps) 884 - *ps = *s; 885 - kfree(s); 886 - 887 - spin_unlock_irqrestore(&dev->event_lock, flags); 888 - return 0; 889 - } 890 - 891 - int 892 - nouveau_flip_complete(struct nvif_notify *notify) 893 - { 894 - struct nouveau_drm *drm = container_of(notify, typeof(*drm), flip); 895 - struct nouveau_channel *chan = drm->channel; 896 - struct nouveau_page_flip_state state; 897 - 898 - if (!nouveau_finish_page_flip(chan, &state)) { 899 - nv_set_crtc_base(drm->dev, drm_crtc_index(state.crtc), 900 - state.offset + state.crtc->y * 901 - state.pitch + state.crtc->x * 902 - state.bpp / 8); 903 - } 904 - 905 - return NVIF_NOTIFY_KEEP; 906 682 } 907 683 908 684 int
+3 -18
drivers/gpu/drm/nouveau/nouveau_display.h
··· 25 25 const struct drm_mode_fb_cmd2 *, 26 26 struct nouveau_bo *, struct nouveau_framebuffer **); 27 27 28 - struct nouveau_page_flip_state { 29 - struct list_head head; 30 - struct drm_pending_vblank_event *event; 31 - struct drm_crtc *crtc; 32 - int bpp, pitch; 33 - u64 offset; 34 - }; 35 - 36 28 struct nouveau_display { 37 29 void *priv; 38 30 void (*dtor)(struct drm_device *); 39 - int (*init)(struct drm_device *); 40 - void (*fini)(struct drm_device *); 31 + int (*init)(struct drm_device *, bool resume, bool runtime); 32 + void (*fini)(struct drm_device *, bool suspend); 41 33 42 34 struct nvif_disp disp; 43 35 ··· 53 61 54 62 int nouveau_display_create(struct drm_device *dev); 55 63 void nouveau_display_destroy(struct drm_device *dev); 56 - int nouveau_display_init(struct drm_device *dev); 64 + int nouveau_display_init(struct drm_device *dev, bool resume, bool runtime); 57 65 void nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime); 58 66 int nouveau_display_suspend(struct drm_device *dev, bool runtime); 59 67 void nouveau_display_resume(struct drm_device *dev, bool runtime); ··· 62 70 bool nouveau_display_scanoutpos(struct drm_device *, unsigned int, 63 71 bool, int *, int *, ktime_t *, 64 72 ktime_t *, const struct drm_display_mode *); 65 - 66 - int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, 67 - struct drm_pending_vblank_event *event, 68 - uint32_t page_flip_flags, 69 - struct drm_modeset_acquire_ctx *ctx); 70 - int nouveau_finish_page_flip(struct nouveau_channel *, 71 - struct nouveau_page_flip_state *); 72 73 73 74 int nouveau_display_dumb_create(struct drm_file *, struct drm_device *, 74 75 struct drm_mode_create_dumb *args);
+887
drivers/gpu/drm/nouveau/nouveau_dmem.c
··· 1 + /* 2 + * Copyright 2018 Red Hat Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + */ 22 + #include "nouveau_dmem.h" 23 + #include "nouveau_drv.h" 24 + #include "nouveau_chan.h" 25 + #include "nouveau_dma.h" 26 + #include "nouveau_mem.h" 27 + #include "nouveau_bo.h" 28 + 29 + #include <nvif/class.h> 30 + #include <nvif/object.h> 31 + #include <nvif/if500b.h> 32 + #include <nvif/if900b.h> 33 + 34 + #include <linux/sched/mm.h> 35 + #include <linux/hmm.h> 36 + 37 + /* 38 + * FIXME: this is ugly right now we are using TTM to allocate vram and we pin 39 + * it in vram while in use. We likely want to overhaul memory management for 40 + * nouveau to be more page like (not necessarily with system page size but a 41 + * bigger page size) at lowest level and have some shim layer on top that would 42 + * provide the same functionality as TTM. 43 + */ 44 + #define DMEM_CHUNK_SIZE (2UL << 20) 45 + #define DMEM_CHUNK_NPAGES (DMEM_CHUNK_SIZE >> PAGE_SHIFT) 46 + 47 + struct nouveau_migrate; 48 + 49 + enum nouveau_aper { 50 + NOUVEAU_APER_VIRT, 51 + NOUVEAU_APER_VRAM, 52 + NOUVEAU_APER_HOST, 53 + }; 54 + 55 + typedef int (*nouveau_migrate_copy_t)(struct nouveau_drm *drm, u64 npages, 56 + enum nouveau_aper, u64 dst_addr, 57 + enum nouveau_aper, u64 src_addr); 58 + 59 + struct nouveau_dmem_chunk { 60 + struct list_head list; 61 + struct nouveau_bo *bo; 62 + struct nouveau_drm *drm; 63 + unsigned long pfn_first; 64 + unsigned long callocated; 65 + unsigned long bitmap[BITS_TO_LONGS(DMEM_CHUNK_NPAGES)]; 66 + spinlock_t lock; 67 + }; 68 + 69 + struct nouveau_dmem_migrate { 70 + nouveau_migrate_copy_t copy_func; 71 + struct nouveau_channel *chan; 72 + }; 73 + 74 + struct nouveau_dmem { 75 + struct hmm_devmem *devmem; 76 + struct nouveau_dmem_migrate migrate; 77 + struct list_head chunk_free; 78 + struct list_head chunk_full; 79 + struct list_head chunk_empty; 80 + struct mutex mutex; 81 + }; 82 + 83 + struct nouveau_dmem_fault { 84 + struct nouveau_drm *drm; 85 + struct nouveau_fence *fence; 86 + dma_addr_t *dma; 87 + unsigned long npages; 88 + }; 89 + 90 + struct nouveau_migrate { 91 + struct vm_area_struct *vma; 92 + struct nouveau_drm *drm; 93 + struct nouveau_fence *fence; 94 + unsigned long npages; 95 + dma_addr_t *dma; 96 + unsigned long dma_nr; 97 + }; 98 + 99 + static void 100 + nouveau_dmem_free(struct hmm_devmem *devmem, struct page *page) 101 + { 102 + struct nouveau_dmem_chunk *chunk; 103 + struct nouveau_drm *drm; 104 + unsigned long idx; 105 + 106 + chunk = (void *)hmm_devmem_page_get_drvdata(page); 107 + idx = page_to_pfn(page) - chunk->pfn_first; 108 + drm = chunk->drm; 109 + 110 + /* 111 + * FIXME: 112 + * 113 + * This is really a bad example, we need to overhaul nouveau memory 114 + * management to be more page focus and allow lighter locking scheme 115 + * to be use in the process. 116 + */ 117 + spin_lock(&chunk->lock); 118 + clear_bit(idx, chunk->bitmap); 119 + WARN_ON(!chunk->callocated); 120 + chunk->callocated--; 121 + /* 122 + * FIXME when chunk->callocated reach 0 we should add the chunk to 123 + * a reclaim list so that it can be freed in case of memory pressure. 124 + */ 125 + spin_unlock(&chunk->lock); 126 + } 127 + 128 + static void 129 + nouveau_dmem_fault_alloc_and_copy(struct vm_area_struct *vma, 130 + const unsigned long *src_pfns, 131 + unsigned long *dst_pfns, 132 + unsigned long start, 133 + unsigned long end, 134 + void *private) 135 + { 136 + struct nouveau_dmem_fault *fault = private; 137 + struct nouveau_drm *drm = fault->drm; 138 + struct device *dev = drm->dev->dev; 139 + unsigned long addr, i, npages = 0; 140 + nouveau_migrate_copy_t copy; 141 + int ret; 142 + 143 + 144 + /* First allocate new memory */ 145 + for (addr = start, i = 0; addr < end; addr += PAGE_SIZE, i++) { 146 + struct page *dpage, *spage; 147 + 148 + dst_pfns[i] = 0; 149 + spage = migrate_pfn_to_page(src_pfns[i]); 150 + if (!spage || !(src_pfns[i] & MIGRATE_PFN_MIGRATE)) 151 + continue; 152 + 153 + dpage = hmm_vma_alloc_locked_page(vma, addr); 154 + if (!dpage) { 155 + dst_pfns[i] = MIGRATE_PFN_ERROR; 156 + continue; 157 + } 158 + 159 + dst_pfns[i] = migrate_pfn(page_to_pfn(dpage)) | 160 + MIGRATE_PFN_LOCKED; 161 + npages++; 162 + } 163 + 164 + /* Allocate storage for DMA addresses, so we can unmap later. */ 165 + fault->dma = kmalloc(sizeof(*fault->dma) * npages, GFP_KERNEL); 166 + if (!fault->dma) 167 + goto error; 168 + 169 + /* Copy things over */ 170 + copy = drm->dmem->migrate.copy_func; 171 + for (addr = start, i = 0; addr < end; addr += PAGE_SIZE, i++) { 172 + struct nouveau_dmem_chunk *chunk; 173 + struct page *spage, *dpage; 174 + u64 src_addr, dst_addr; 175 + 176 + dpage = migrate_pfn_to_page(dst_pfns[i]); 177 + if (!dpage || dst_pfns[i] == MIGRATE_PFN_ERROR) 178 + continue; 179 + 180 + spage = migrate_pfn_to_page(src_pfns[i]); 181 + if (!spage || !(src_pfns[i] & MIGRATE_PFN_MIGRATE)) { 182 + dst_pfns[i] = MIGRATE_PFN_ERROR; 183 + __free_page(dpage); 184 + continue; 185 + } 186 + 187 + fault->dma[fault->npages] = 188 + dma_map_page_attrs(dev, dpage, 0, PAGE_SIZE, 189 + PCI_DMA_BIDIRECTIONAL, 190 + DMA_ATTR_SKIP_CPU_SYNC); 191 + if (dma_mapping_error(dev, fault->dma[fault->npages])) { 192 + dst_pfns[i] = MIGRATE_PFN_ERROR; 193 + __free_page(dpage); 194 + continue; 195 + } 196 + 197 + dst_addr = fault->dma[fault->npages++]; 198 + 199 + chunk = (void *)hmm_devmem_page_get_drvdata(spage); 200 + src_addr = page_to_pfn(spage) - chunk->pfn_first; 201 + src_addr = (src_addr << PAGE_SHIFT) + chunk->bo->bo.offset; 202 + 203 + ret = copy(drm, 1, NOUVEAU_APER_HOST, dst_addr, 204 + NOUVEAU_APER_VRAM, src_addr); 205 + if (ret) { 206 + dst_pfns[i] = MIGRATE_PFN_ERROR; 207 + __free_page(dpage); 208 + continue; 209 + } 210 + } 211 + 212 + nouveau_fence_new(drm->dmem->migrate.chan, false, &fault->fence); 213 + 214 + return; 215 + 216 + error: 217 + for (addr = start, i = 0; addr < end; addr += PAGE_SIZE, ++i) { 218 + struct page *page; 219 + 220 + if (!dst_pfns[i] || dst_pfns[i] == MIGRATE_PFN_ERROR) 221 + continue; 222 + 223 + page = migrate_pfn_to_page(dst_pfns[i]); 224 + dst_pfns[i] = MIGRATE_PFN_ERROR; 225 + if (page == NULL) 226 + continue; 227 + 228 + __free_page(page); 229 + } 230 + } 231 + 232 + void nouveau_dmem_fault_finalize_and_map(struct vm_area_struct *vma, 233 + const unsigned long *src_pfns, 234 + const unsigned long *dst_pfns, 235 + unsigned long start, 236 + unsigned long end, 237 + void *private) 238 + { 239 + struct nouveau_dmem_fault *fault = private; 240 + struct nouveau_drm *drm = fault->drm; 241 + 242 + if (fault->fence) { 243 + nouveau_fence_wait(fault->fence, true, false); 244 + nouveau_fence_unref(&fault->fence); 245 + } else { 246 + /* 247 + * FIXME wait for channel to be IDLE before calling finalizing 248 + * the hmem object below (nouveau_migrate_hmem_fini()). 249 + */ 250 + } 251 + 252 + while (fault->npages--) { 253 + dma_unmap_page(drm->dev->dev, fault->dma[fault->npages], 254 + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 255 + } 256 + kfree(fault->dma); 257 + } 258 + 259 + static const struct migrate_vma_ops nouveau_dmem_fault_migrate_ops = { 260 + .alloc_and_copy = nouveau_dmem_fault_alloc_and_copy, 261 + .finalize_and_map = nouveau_dmem_fault_finalize_and_map, 262 + }; 263 + 264 + static int 265 + nouveau_dmem_fault(struct hmm_devmem *devmem, 266 + struct vm_area_struct *vma, 267 + unsigned long addr, 268 + const struct page *page, 269 + unsigned int flags, 270 + pmd_t *pmdp) 271 + { 272 + struct drm_device *drm_dev = dev_get_drvdata(devmem->device); 273 + unsigned long src[1] = {0}, dst[1] = {0}; 274 + struct nouveau_dmem_fault fault = {0}; 275 + int ret; 276 + 277 + 278 + 279 + /* 280 + * FIXME what we really want is to find some heuristic to migrate more 281 + * than just one page on CPU fault. When such fault happens it is very 282 + * likely that more surrounding page will CPU fault too. 283 + */ 284 + fault.drm = nouveau_drm(drm_dev); 285 + ret = migrate_vma(&nouveau_dmem_fault_migrate_ops, vma, addr, 286 + addr + PAGE_SIZE, src, dst, &fault); 287 + if (ret) 288 + return VM_FAULT_SIGBUS; 289 + 290 + if (dst[0] == MIGRATE_PFN_ERROR) 291 + return VM_FAULT_SIGBUS; 292 + 293 + return 0; 294 + } 295 + 296 + static const struct hmm_devmem_ops 297 + nouveau_dmem_devmem_ops = { 298 + .free = nouveau_dmem_free, 299 + .fault = nouveau_dmem_fault, 300 + }; 301 + 302 + static int 303 + nouveau_dmem_chunk_alloc(struct nouveau_drm *drm) 304 + { 305 + struct nouveau_dmem_chunk *chunk; 306 + int ret; 307 + 308 + if (drm->dmem == NULL) 309 + return -EINVAL; 310 + 311 + mutex_lock(&drm->dmem->mutex); 312 + chunk = list_first_entry_or_null(&drm->dmem->chunk_empty, 313 + struct nouveau_dmem_chunk, 314 + list); 315 + if (chunk == NULL) { 316 + mutex_unlock(&drm->dmem->mutex); 317 + return -ENOMEM; 318 + } 319 + 320 + list_del(&chunk->list); 321 + mutex_unlock(&drm->dmem->mutex); 322 + 323 + ret = nouveau_bo_new(&drm->client, DMEM_CHUNK_SIZE, 0, 324 + TTM_PL_FLAG_VRAM, 0, 0, NULL, NULL, 325 + &chunk->bo); 326 + if (ret) 327 + goto out; 328 + 329 + ret = nouveau_bo_pin(chunk->bo, TTM_PL_FLAG_VRAM, false); 330 + if (ret) { 331 + nouveau_bo_ref(NULL, &chunk->bo); 332 + goto out; 333 + } 334 + 335 + bitmap_zero(chunk->bitmap, DMEM_CHUNK_NPAGES); 336 + spin_lock_init(&chunk->lock); 337 + 338 + out: 339 + mutex_lock(&drm->dmem->mutex); 340 + if (chunk->bo) 341 + list_add(&chunk->list, &drm->dmem->chunk_empty); 342 + else 343 + list_add_tail(&chunk->list, &drm->dmem->chunk_empty); 344 + mutex_unlock(&drm->dmem->mutex); 345 + 346 + return ret; 347 + } 348 + 349 + static struct nouveau_dmem_chunk * 350 + nouveau_dmem_chunk_first_free_locked(struct nouveau_drm *drm) 351 + { 352 + struct nouveau_dmem_chunk *chunk; 353 + 354 + chunk = list_first_entry_or_null(&drm->dmem->chunk_free, 355 + struct nouveau_dmem_chunk, 356 + list); 357 + if (chunk) 358 + return chunk; 359 + 360 + chunk = list_first_entry_or_null(&drm->dmem->chunk_empty, 361 + struct nouveau_dmem_chunk, 362 + list); 363 + if (chunk->bo) 364 + return chunk; 365 + 366 + return NULL; 367 + } 368 + 369 + static int 370 + nouveau_dmem_pages_alloc(struct nouveau_drm *drm, 371 + unsigned long npages, 372 + unsigned long *pages) 373 + { 374 + struct nouveau_dmem_chunk *chunk; 375 + unsigned long c; 376 + int ret; 377 + 378 + memset(pages, 0xff, npages * sizeof(*pages)); 379 + 380 + mutex_lock(&drm->dmem->mutex); 381 + for (c = 0; c < npages;) { 382 + unsigned long i; 383 + 384 + chunk = nouveau_dmem_chunk_first_free_locked(drm); 385 + if (chunk == NULL) { 386 + mutex_unlock(&drm->dmem->mutex); 387 + ret = nouveau_dmem_chunk_alloc(drm); 388 + if (ret) { 389 + if (c) 390 + break; 391 + return ret; 392 + } 393 + continue; 394 + } 395 + 396 + spin_lock(&chunk->lock); 397 + i = find_first_zero_bit(chunk->bitmap, DMEM_CHUNK_NPAGES); 398 + while (i < DMEM_CHUNK_NPAGES && c < npages) { 399 + pages[c] = chunk->pfn_first + i; 400 + set_bit(i, chunk->bitmap); 401 + chunk->callocated++; 402 + c++; 403 + 404 + i = find_next_zero_bit(chunk->bitmap, 405 + DMEM_CHUNK_NPAGES, i); 406 + } 407 + spin_unlock(&chunk->lock); 408 + } 409 + mutex_unlock(&drm->dmem->mutex); 410 + 411 + return 0; 412 + } 413 + 414 + static struct page * 415 + nouveau_dmem_page_alloc_locked(struct nouveau_drm *drm) 416 + { 417 + unsigned long pfns[1]; 418 + struct page *page; 419 + int ret; 420 + 421 + /* FIXME stop all the miss-match API ... */ 422 + ret = nouveau_dmem_pages_alloc(drm, 1, pfns); 423 + if (ret) 424 + return NULL; 425 + 426 + page = pfn_to_page(pfns[0]); 427 + get_page(page); 428 + lock_page(page); 429 + return page; 430 + } 431 + 432 + static void 433 + nouveau_dmem_page_free_locked(struct nouveau_drm *drm, struct page *page) 434 + { 435 + unlock_page(page); 436 + put_page(page); 437 + } 438 + 439 + void 440 + nouveau_dmem_resume(struct nouveau_drm *drm) 441 + { 442 + struct nouveau_dmem_chunk *chunk; 443 + int ret; 444 + 445 + if (drm->dmem == NULL) 446 + return; 447 + 448 + mutex_lock(&drm->dmem->mutex); 449 + list_for_each_entry (chunk, &drm->dmem->chunk_free, list) { 450 + ret = nouveau_bo_pin(chunk->bo, TTM_PL_FLAG_VRAM, false); 451 + /* FIXME handle pin failure */ 452 + WARN_ON(ret); 453 + } 454 + list_for_each_entry (chunk, &drm->dmem->chunk_full, list) { 455 + ret = nouveau_bo_pin(chunk->bo, TTM_PL_FLAG_VRAM, false); 456 + /* FIXME handle pin failure */ 457 + WARN_ON(ret); 458 + } 459 + list_for_each_entry (chunk, &drm->dmem->chunk_empty, list) { 460 + ret = nouveau_bo_pin(chunk->bo, TTM_PL_FLAG_VRAM, false); 461 + /* FIXME handle pin failure */ 462 + WARN_ON(ret); 463 + } 464 + mutex_unlock(&drm->dmem->mutex); 465 + } 466 + 467 + void 468 + nouveau_dmem_suspend(struct nouveau_drm *drm) 469 + { 470 + struct nouveau_dmem_chunk *chunk; 471 + 472 + if (drm->dmem == NULL) 473 + return; 474 + 475 + mutex_lock(&drm->dmem->mutex); 476 + list_for_each_entry (chunk, &drm->dmem->chunk_free, list) { 477 + nouveau_bo_unpin(chunk->bo); 478 + } 479 + list_for_each_entry (chunk, &drm->dmem->chunk_full, list) { 480 + nouveau_bo_unpin(chunk->bo); 481 + } 482 + list_for_each_entry (chunk, &drm->dmem->chunk_empty, list) { 483 + nouveau_bo_unpin(chunk->bo); 484 + } 485 + mutex_unlock(&drm->dmem->mutex); 486 + } 487 + 488 + void 489 + nouveau_dmem_fini(struct nouveau_drm *drm) 490 + { 491 + struct nouveau_dmem_chunk *chunk, *tmp; 492 + 493 + if (drm->dmem == NULL) 494 + return; 495 + 496 + mutex_lock(&drm->dmem->mutex); 497 + 498 + WARN_ON(!list_empty(&drm->dmem->chunk_free)); 499 + WARN_ON(!list_empty(&drm->dmem->chunk_full)); 500 + 501 + list_for_each_entry_safe (chunk, tmp, &drm->dmem->chunk_empty, list) { 502 + if (chunk->bo) { 503 + nouveau_bo_unpin(chunk->bo); 504 + nouveau_bo_ref(NULL, &chunk->bo); 505 + } 506 + list_del(&chunk->list); 507 + kfree(chunk); 508 + } 509 + 510 + mutex_unlock(&drm->dmem->mutex); 511 + } 512 + 513 + static int 514 + nvc0b5_migrate_copy(struct nouveau_drm *drm, u64 npages, 515 + enum nouveau_aper dst_aper, u64 dst_addr, 516 + enum nouveau_aper src_aper, u64 src_addr) 517 + { 518 + struct nouveau_channel *chan = drm->dmem->migrate.chan; 519 + u32 launch_dma = (1 << 9) /* MULTI_LINE_ENABLE. */ | 520 + (1 << 8) /* DST_MEMORY_LAYOUT_PITCH. */ | 521 + (1 << 7) /* SRC_MEMORY_LAYOUT_PITCH. */ | 522 + (1 << 2) /* FLUSH_ENABLE_TRUE. */ | 523 + (2 << 0) /* DATA_TRANSFER_TYPE_NON_PIPELINED. */; 524 + int ret; 525 + 526 + ret = RING_SPACE(chan, 13); 527 + if (ret) 528 + return ret; 529 + 530 + if (src_aper != NOUVEAU_APER_VIRT) { 531 + switch (src_aper) { 532 + case NOUVEAU_APER_VRAM: 533 + BEGIN_IMC0(chan, NvSubCopy, 0x0260, 0); 534 + break; 535 + case NOUVEAU_APER_HOST: 536 + BEGIN_IMC0(chan, NvSubCopy, 0x0260, 1); 537 + break; 538 + default: 539 + return -EINVAL; 540 + } 541 + launch_dma |= 0x00001000; /* SRC_TYPE_PHYSICAL. */ 542 + } 543 + 544 + if (dst_aper != NOUVEAU_APER_VIRT) { 545 + switch (dst_aper) { 546 + case NOUVEAU_APER_VRAM: 547 + BEGIN_IMC0(chan, NvSubCopy, 0x0264, 0); 548 + break; 549 + case NOUVEAU_APER_HOST: 550 + BEGIN_IMC0(chan, NvSubCopy, 0x0264, 1); 551 + break; 552 + default: 553 + return -EINVAL; 554 + } 555 + launch_dma |= 0x00002000; /* DST_TYPE_PHYSICAL. */ 556 + } 557 + 558 + BEGIN_NVC0(chan, NvSubCopy, 0x0400, 8); 559 + OUT_RING (chan, upper_32_bits(src_addr)); 560 + OUT_RING (chan, lower_32_bits(src_addr)); 561 + OUT_RING (chan, upper_32_bits(dst_addr)); 562 + OUT_RING (chan, lower_32_bits(dst_addr)); 563 + OUT_RING (chan, PAGE_SIZE); 564 + OUT_RING (chan, PAGE_SIZE); 565 + OUT_RING (chan, PAGE_SIZE); 566 + OUT_RING (chan, npages); 567 + BEGIN_NVC0(chan, NvSubCopy, 0x0300, 1); 568 + OUT_RING (chan, launch_dma); 569 + return 0; 570 + } 571 + 572 + static int 573 + nouveau_dmem_migrate_init(struct nouveau_drm *drm) 574 + { 575 + switch (drm->ttm.copy.oclass) { 576 + case PASCAL_DMA_COPY_A: 577 + case PASCAL_DMA_COPY_B: 578 + case VOLTA_DMA_COPY_A: 579 + case TURING_DMA_COPY_A: 580 + drm->dmem->migrate.copy_func = nvc0b5_migrate_copy; 581 + drm->dmem->migrate.chan = drm->ttm.chan; 582 + return 0; 583 + default: 584 + break; 585 + } 586 + return -ENODEV; 587 + } 588 + 589 + void 590 + nouveau_dmem_init(struct nouveau_drm *drm) 591 + { 592 + struct device *device = drm->dev->dev; 593 + unsigned long i, size; 594 + int ret; 595 + 596 + /* This only make sense on PASCAL or newer */ 597 + if (drm->client.device.info.family < NV_DEVICE_INFO_V0_PASCAL) 598 + return; 599 + 600 + if (!(drm->dmem = kzalloc(sizeof(*drm->dmem), GFP_KERNEL))) 601 + return; 602 + 603 + mutex_init(&drm->dmem->mutex); 604 + INIT_LIST_HEAD(&drm->dmem->chunk_free); 605 + INIT_LIST_HEAD(&drm->dmem->chunk_full); 606 + INIT_LIST_HEAD(&drm->dmem->chunk_empty); 607 + 608 + size = ALIGN(drm->client.device.info.ram_user, DMEM_CHUNK_SIZE); 609 + 610 + /* Initialize migration dma helpers before registering memory */ 611 + ret = nouveau_dmem_migrate_init(drm); 612 + if (ret) { 613 + kfree(drm->dmem); 614 + drm->dmem = NULL; 615 + return; 616 + } 617 + 618 + /* 619 + * FIXME we need some kind of policy to decide how much VRAM we 620 + * want to register with HMM. For now just register everything 621 + * and latter if we want to do thing like over commit then we 622 + * could revisit this. 623 + */ 624 + drm->dmem->devmem = hmm_devmem_add(&nouveau_dmem_devmem_ops, 625 + device, size); 626 + if (drm->dmem->devmem == NULL) { 627 + kfree(drm->dmem); 628 + drm->dmem = NULL; 629 + return; 630 + } 631 + 632 + for (i = 0; i < (size / DMEM_CHUNK_SIZE); ++i) { 633 + struct nouveau_dmem_chunk *chunk; 634 + struct page *page; 635 + unsigned long j; 636 + 637 + chunk = kzalloc(sizeof(*chunk), GFP_KERNEL); 638 + if (chunk == NULL) { 639 + nouveau_dmem_fini(drm); 640 + return; 641 + } 642 + 643 + chunk->drm = drm; 644 + chunk->pfn_first = drm->dmem->devmem->pfn_first; 645 + chunk->pfn_first += (i * DMEM_CHUNK_NPAGES); 646 + list_add_tail(&chunk->list, &drm->dmem->chunk_empty); 647 + 648 + page = pfn_to_page(chunk->pfn_first); 649 + for (j = 0; j < DMEM_CHUNK_NPAGES; ++j, ++page) { 650 + hmm_devmem_page_set_drvdata(page, (long)chunk); 651 + } 652 + } 653 + 654 + NV_INFO(drm, "DMEM: registered %ldMB of device memory\n", size >> 20); 655 + } 656 + 657 + static void 658 + nouveau_dmem_migrate_alloc_and_copy(struct vm_area_struct *vma, 659 + const unsigned long *src_pfns, 660 + unsigned long *dst_pfns, 661 + unsigned long start, 662 + unsigned long end, 663 + void *private) 664 + { 665 + struct nouveau_migrate *migrate = private; 666 + struct nouveau_drm *drm = migrate->drm; 667 + struct device *dev = drm->dev->dev; 668 + unsigned long addr, i, npages = 0; 669 + nouveau_migrate_copy_t copy; 670 + int ret; 671 + 672 + /* First allocate new memory */ 673 + for (addr = start, i = 0; addr < end; addr += PAGE_SIZE, i++) { 674 + struct page *dpage, *spage; 675 + 676 + dst_pfns[i] = 0; 677 + spage = migrate_pfn_to_page(src_pfns[i]); 678 + if (!spage || !(src_pfns[i] & MIGRATE_PFN_MIGRATE)) 679 + continue; 680 + 681 + dpage = nouveau_dmem_page_alloc_locked(drm); 682 + if (!dpage) 683 + continue; 684 + 685 + dst_pfns[i] = migrate_pfn(page_to_pfn(dpage)) | 686 + MIGRATE_PFN_LOCKED | 687 + MIGRATE_PFN_DEVICE; 688 + npages++; 689 + } 690 + 691 + if (!npages) 692 + return; 693 + 694 + /* Allocate storage for DMA addresses, so we can unmap later. */ 695 + migrate->dma = kmalloc(sizeof(*migrate->dma) * npages, GFP_KERNEL); 696 + if (!migrate->dma) 697 + goto error; 698 + 699 + /* Copy things over */ 700 + copy = drm->dmem->migrate.copy_func; 701 + for (addr = start, i = 0; addr < end; addr += PAGE_SIZE, i++) { 702 + struct nouveau_dmem_chunk *chunk; 703 + struct page *spage, *dpage; 704 + u64 src_addr, dst_addr; 705 + 706 + dpage = migrate_pfn_to_page(dst_pfns[i]); 707 + if (!dpage || dst_pfns[i] == MIGRATE_PFN_ERROR) 708 + continue; 709 + 710 + chunk = (void *)hmm_devmem_page_get_drvdata(dpage); 711 + dst_addr = page_to_pfn(dpage) - chunk->pfn_first; 712 + dst_addr = (dst_addr << PAGE_SHIFT) + chunk->bo->bo.offset; 713 + 714 + spage = migrate_pfn_to_page(src_pfns[i]); 715 + if (!spage || !(src_pfns[i] & MIGRATE_PFN_MIGRATE)) { 716 + nouveau_dmem_page_free_locked(drm, dpage); 717 + dst_pfns[i] = 0; 718 + continue; 719 + } 720 + 721 + migrate->dma[migrate->dma_nr] = 722 + dma_map_page_attrs(dev, spage, 0, PAGE_SIZE, 723 + PCI_DMA_BIDIRECTIONAL, 724 + DMA_ATTR_SKIP_CPU_SYNC); 725 + if (dma_mapping_error(dev, migrate->dma[migrate->dma_nr])) { 726 + nouveau_dmem_page_free_locked(drm, dpage); 727 + dst_pfns[i] = 0; 728 + continue; 729 + } 730 + 731 + src_addr = migrate->dma[migrate->dma_nr++]; 732 + 733 + ret = copy(drm, 1, NOUVEAU_APER_VRAM, dst_addr, 734 + NOUVEAU_APER_HOST, src_addr); 735 + if (ret) { 736 + nouveau_dmem_page_free_locked(drm, dpage); 737 + dst_pfns[i] = 0; 738 + continue; 739 + } 740 + } 741 + 742 + nouveau_fence_new(drm->dmem->migrate.chan, false, &migrate->fence); 743 + 744 + return; 745 + 746 + error: 747 + for (addr = start, i = 0; addr < end; addr += PAGE_SIZE, ++i) { 748 + struct page *page; 749 + 750 + if (!dst_pfns[i] || dst_pfns[i] == MIGRATE_PFN_ERROR) 751 + continue; 752 + 753 + page = migrate_pfn_to_page(dst_pfns[i]); 754 + dst_pfns[i] = MIGRATE_PFN_ERROR; 755 + if (page == NULL) 756 + continue; 757 + 758 + __free_page(page); 759 + } 760 + } 761 + 762 + void nouveau_dmem_migrate_finalize_and_map(struct vm_area_struct *vma, 763 + const unsigned long *src_pfns, 764 + const unsigned long *dst_pfns, 765 + unsigned long start, 766 + unsigned long end, 767 + void *private) 768 + { 769 + struct nouveau_migrate *migrate = private; 770 + struct nouveau_drm *drm = migrate->drm; 771 + 772 + if (migrate->fence) { 773 + nouveau_fence_wait(migrate->fence, true, false); 774 + nouveau_fence_unref(&migrate->fence); 775 + } else { 776 + /* 777 + * FIXME wait for channel to be IDLE before finalizing 778 + * the hmem object below (nouveau_migrate_hmem_fini()) ? 779 + */ 780 + } 781 + 782 + while (migrate->dma_nr--) { 783 + dma_unmap_page(drm->dev->dev, migrate->dma[migrate->dma_nr], 784 + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 785 + } 786 + kfree(migrate->dma); 787 + 788 + /* 789 + * FIXME optimization: update GPU page table to point to newly 790 + * migrated memory. 791 + */ 792 + } 793 + 794 + static const struct migrate_vma_ops nouveau_dmem_migrate_ops = { 795 + .alloc_and_copy = nouveau_dmem_migrate_alloc_and_copy, 796 + .finalize_and_map = nouveau_dmem_migrate_finalize_and_map, 797 + }; 798 + 799 + int 800 + nouveau_dmem_migrate_vma(struct nouveau_drm *drm, 801 + struct vm_area_struct *vma, 802 + unsigned long start, 803 + unsigned long end) 804 + { 805 + unsigned long *src_pfns, *dst_pfns, npages; 806 + struct nouveau_migrate migrate = {0}; 807 + unsigned long i, c, max; 808 + int ret = 0; 809 + 810 + npages = (end - start) >> PAGE_SHIFT; 811 + max = min(SG_MAX_SINGLE_ALLOC, npages); 812 + src_pfns = kzalloc(sizeof(long) * max, GFP_KERNEL); 813 + if (src_pfns == NULL) 814 + return -ENOMEM; 815 + dst_pfns = kzalloc(sizeof(long) * max, GFP_KERNEL); 816 + if (dst_pfns == NULL) { 817 + kfree(src_pfns); 818 + return -ENOMEM; 819 + } 820 + 821 + migrate.drm = drm; 822 + migrate.vma = vma; 823 + migrate.npages = npages; 824 + for (i = 0; i < npages; i += c) { 825 + unsigned long next; 826 + 827 + c = min(SG_MAX_SINGLE_ALLOC, npages); 828 + next = start + (c << PAGE_SHIFT); 829 + ret = migrate_vma(&nouveau_dmem_migrate_ops, vma, start, 830 + next, src_pfns, dst_pfns, &migrate); 831 + if (ret) 832 + goto out; 833 + start = next; 834 + } 835 + 836 + out: 837 + kfree(dst_pfns); 838 + kfree(src_pfns); 839 + return ret; 840 + } 841 + 842 + static inline bool 843 + nouveau_dmem_page(struct nouveau_drm *drm, struct page *page) 844 + { 845 + if (!is_device_private_page(page)) 846 + return false; 847 + 848 + if (drm->dmem->devmem != page->pgmap->data) 849 + return false; 850 + 851 + return true; 852 + } 853 + 854 + void 855 + nouveau_dmem_convert_pfn(struct nouveau_drm *drm, 856 + struct hmm_range *range) 857 + { 858 + unsigned long i, npages; 859 + 860 + npages = (range->end - range->start) >> PAGE_SHIFT; 861 + for (i = 0; i < npages; ++i) { 862 + struct nouveau_dmem_chunk *chunk; 863 + struct page *page; 864 + uint64_t addr; 865 + 866 + page = hmm_pfn_to_page(range, range->pfns[i]); 867 + if (page == NULL) 868 + continue; 869 + 870 + if (!(range->pfns[i] & range->flags[HMM_PFN_DEVICE_PRIVATE])) { 871 + continue; 872 + } 873 + 874 + if (!nouveau_dmem_page(drm, page)) { 875 + WARN(1, "Some unknown device memory !\n"); 876 + range->pfns[i] = 0; 877 + continue; 878 + } 879 + 880 + chunk = (void *)hmm_devmem_page_get_drvdata(page); 881 + addr = page_to_pfn(page) - chunk->pfn_first; 882 + addr = (addr + chunk->bo->bo.mem.start) << PAGE_SHIFT; 883 + 884 + range->pfns[i] &= ((1UL << range->pfn_shift) - 1); 885 + range->pfns[i] |= (addr >> PAGE_SHIFT) << range->pfn_shift; 886 + } 887 + }
+60
drivers/gpu/drm/nouveau/nouveau_dmem.h
··· 1 + /* 2 + * Copyright 2018 Red Hat Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + */ 22 + #ifndef __NOUVEAU_DMEM_H__ 23 + #define __NOUVEAU_DMEM_H__ 24 + #include <nvif/os.h> 25 + struct drm_device; 26 + struct drm_file; 27 + struct nouveau_drm; 28 + struct hmm_range; 29 + 30 + #if IS_ENABLED(CONFIG_DRM_NOUVEAU_SVM) 31 + void nouveau_dmem_init(struct nouveau_drm *); 32 + void nouveau_dmem_fini(struct nouveau_drm *); 33 + void nouveau_dmem_suspend(struct nouveau_drm *); 34 + void nouveau_dmem_resume(struct nouveau_drm *); 35 + 36 + int nouveau_dmem_migrate_vma(struct nouveau_drm *drm, 37 + struct vm_area_struct *vma, 38 + unsigned long start, 39 + unsigned long end); 40 + 41 + void nouveau_dmem_convert_pfn(struct nouveau_drm *drm, 42 + struct hmm_range *range); 43 + #else /* IS_ENABLED(CONFIG_DRM_NOUVEAU_SVM) */ 44 + static inline void nouveau_dmem_init(struct nouveau_drm *drm) {} 45 + static inline void nouveau_dmem_fini(struct nouveau_drm *drm) {} 46 + static inline void nouveau_dmem_suspend(struct nouveau_drm *drm) {} 47 + static inline void nouveau_dmem_resume(struct nouveau_drm *drm) {} 48 + 49 + static inline int nouveau_dmem_migrate_vma(struct nouveau_drm *drm, 50 + struct vm_area_struct *vma, 51 + unsigned long start, 52 + unsigned long end) 53 + { 54 + return 0; 55 + } 56 + 57 + static inline void nouveau_dmem_convert_pfn(struct nouveau_drm *drm, 58 + struct hmm_range *range) {} 59 + #endif /* IS_ENABLED(CONFIG_DRM_NOUVEAU_SVM) */ 60 + #endif
+146 -102
drivers/gpu/drm/nouveau/nouveau_drm.c
··· 44 44 #include <nvif/class.h> 45 45 #include <nvif/cl0002.h> 46 46 #include <nvif/cla06f.h> 47 - #include <nvif/if0004.h> 48 47 49 48 #include "nouveau_drv.h" 50 49 #include "nouveau_dma.h" ··· 62 63 #include "nouveau_usif.h" 63 64 #include "nouveau_connector.h" 64 65 #include "nouveau_platform.h" 66 + #include "nouveau_svm.h" 67 + #include "nouveau_dmem.h" 65 68 66 69 MODULE_PARM_DESC(config, "option string to pass to driver core"); 67 70 static char *nouveau_config; ··· 174 173 WARN_ON(!list_empty(&cli->worker)); 175 174 176 175 usif_client_fini(cli); 176 + nouveau_vmm_fini(&cli->svm); 177 177 nouveau_vmm_fini(&cli->vmm); 178 178 nvif_mmu_fini(&cli->mmu); 179 179 nvif_device_fini(&cli->device); ··· 285 283 } 286 284 287 285 static void 288 - nouveau_accel_fini(struct nouveau_drm *drm) 286 + nouveau_accel_ce_fini(struct nouveau_drm *drm) 287 + { 288 + nouveau_channel_idle(drm->cechan); 289 + nvif_object_fini(&drm->ttm.copy); 290 + nouveau_channel_del(&drm->cechan); 291 + } 292 + 293 + static void 294 + nouveau_accel_ce_init(struct nouveau_drm *drm) 295 + { 296 + struct nvif_device *device = &drm->client.device; 297 + int ret = 0; 298 + 299 + /* Allocate channel that has access to a (preferably async) copy 300 + * engine, to use for TTM buffer moves. 301 + */ 302 + if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { 303 + ret = nouveau_channel_new(drm, device, 304 + nvif_fifo_runlist_ce(device), 0, 305 + true, &drm->cechan); 306 + } else 307 + if (device->info.chipset >= 0xa3 && 308 + device->info.chipset != 0xaa && 309 + device->info.chipset != 0xac) { 310 + /* Prior to Kepler, there's only a single runlist, so all 311 + * engines can be accessed from any channel. 312 + * 313 + * We still want to use a separate channel though. 314 + */ 315 + ret = nouveau_channel_new(drm, device, NvDmaFB, NvDmaTT, false, 316 + &drm->cechan); 317 + } 318 + 319 + if (ret) 320 + NV_ERROR(drm, "failed to create ce channel, %d\n", ret); 321 + } 322 + 323 + static void 324 + nouveau_accel_gr_fini(struct nouveau_drm *drm) 289 325 { 290 326 nouveau_channel_idle(drm->channel); 291 327 nvif_object_fini(&drm->ntfy); 292 328 nvkm_gpuobj_del(&drm->notify); 293 - nvif_notify_fini(&drm->flip); 294 329 nvif_object_fini(&drm->nvsw); 295 330 nouveau_channel_del(&drm->channel); 331 + } 296 332 297 - nouveau_channel_idle(drm->cechan); 298 - nvif_object_fini(&drm->ttm.copy); 299 - nouveau_channel_del(&drm->cechan); 333 + static void 334 + nouveau_accel_gr_init(struct nouveau_drm *drm) 335 + { 336 + struct nvif_device *device = &drm->client.device; 337 + u32 arg0, arg1; 338 + int ret; 300 339 340 + /* Allocate channel that has access to the graphics engine. */ 341 + if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { 342 + arg0 = nvif_fifo_runlist(device, NV_DEVICE_INFO_ENGINE_GR); 343 + arg1 = 1; 344 + } else { 345 + arg0 = NvDmaFB; 346 + arg1 = NvDmaTT; 347 + } 348 + 349 + ret = nouveau_channel_new(drm, device, arg0, arg1, false, 350 + &drm->channel); 351 + if (ret) { 352 + NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); 353 + nouveau_accel_gr_fini(drm); 354 + return; 355 + } 356 + 357 + /* A SW class is used on pre-NV50 HW to assist with handling the 358 + * synchronisation of page flips, as well as to implement fences 359 + * on TNT/TNT2 HW that lacks any kind of support in host. 360 + */ 361 + if (device->info.family < NV_DEVICE_INFO_V0_TESLA) { 362 + ret = nvif_object_init(&drm->channel->user, NVDRM_NVSW, 363 + nouveau_abi16_swclass(drm), NULL, 0, 364 + &drm->nvsw); 365 + if (ret == 0) { 366 + ret = RING_SPACE(drm->channel, 2); 367 + if (ret == 0) { 368 + BEGIN_NV04(drm->channel, NvSubSw, 0, 1); 369 + OUT_RING (drm->channel, drm->nvsw.handle); 370 + } 371 + } 372 + 373 + if (ret) { 374 + NV_ERROR(drm, "failed to allocate sw class, %d\n", ret); 375 + nouveau_accel_gr_fini(drm); 376 + return; 377 + } 378 + } 379 + 380 + /* NvMemoryToMemoryFormat requires a notifier ctxdma for some reason, 381 + * even if notification is never requested, so, allocate a ctxdma on 382 + * any GPU where it's possible we'll end up using M2MF for BO moves. 383 + */ 384 + if (device->info.family < NV_DEVICE_INFO_V0_FERMI) { 385 + ret = nvkm_gpuobj_new(nvxx_device(device), 32, 0, false, NULL, 386 + &drm->notify); 387 + if (ret) { 388 + NV_ERROR(drm, "failed to allocate notifier, %d\n", ret); 389 + nouveau_accel_gr_fini(drm); 390 + return; 391 + } 392 + 393 + ret = nvif_object_init(&drm->channel->user, NvNotify0, 394 + NV_DMA_IN_MEMORY, 395 + &(struct nv_dma_v0) { 396 + .target = NV_DMA_V0_TARGET_VRAM, 397 + .access = NV_DMA_V0_ACCESS_RDWR, 398 + .start = drm->notify->addr, 399 + .limit = drm->notify->addr + 31 400 + }, sizeof(struct nv_dma_v0), 401 + &drm->ntfy); 402 + if (ret) { 403 + nouveau_accel_gr_fini(drm); 404 + return; 405 + } 406 + } 407 + } 408 + 409 + static void 410 + nouveau_accel_fini(struct nouveau_drm *drm) 411 + { 412 + nouveau_accel_ce_fini(drm); 413 + nouveau_accel_gr_fini(drm); 301 414 if (drm->fence) 302 415 nouveau_fence(drm)->dtor(drm); 303 416 } ··· 422 305 { 423 306 struct nvif_device *device = &drm->client.device; 424 307 struct nvif_sclass *sclass; 425 - u32 arg0, arg1; 426 308 int ret, i, n; 427 309 428 310 if (nouveau_noaccel) 429 311 return; 430 312 313 + /* Initialise global support for channels, and synchronisation. */ 431 314 ret = nouveau_channels_init(drm); 432 315 if (ret) 433 316 return; 434 317 435 - if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_VOLTA) { 436 - ret = nvif_user_init(device); 437 - if (ret) 438 - return; 439 - } 440 - 441 - /* initialise synchronisation routines */ 442 318 /*XXX: this is crap, but the fence/channel stuff is a little 443 319 * backwards in some places. this will be fixed. 444 320 */ ··· 478 368 return; 479 369 } 480 370 481 - if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { 482 - ret = nouveau_channel_new(drm, &drm->client.device, 483 - nvif_fifo_runlist_ce(device), 0, 484 - true, &drm->cechan); 371 + /* Volta requires access to a doorbell register for kickoff. */ 372 + if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_VOLTA) { 373 + ret = nvif_user_init(device); 485 374 if (ret) 486 - NV_ERROR(drm, "failed to create ce channel, %d\n", ret); 487 - 488 - arg0 = nvif_fifo_runlist(device, NV_DEVICE_INFO_ENGINE_GR); 489 - arg1 = 1; 490 - } else 491 - if (device->info.chipset >= 0xa3 && 492 - device->info.chipset != 0xaa && 493 - device->info.chipset != 0xac) { 494 - ret = nouveau_channel_new(drm, &drm->client.device, 495 - NvDmaFB, NvDmaTT, false, 496 - &drm->cechan); 497 - if (ret) 498 - NV_ERROR(drm, "failed to create ce channel, %d\n", ret); 499 - 500 - arg0 = NvDmaFB; 501 - arg1 = NvDmaTT; 502 - } else { 503 - arg0 = NvDmaFB; 504 - arg1 = NvDmaTT; 505 - } 506 - 507 - ret = nouveau_channel_new(drm, &drm->client.device, 508 - arg0, arg1, false, &drm->channel); 509 - if (ret) { 510 - NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); 511 - nouveau_accel_fini(drm); 512 - return; 513 - } 514 - 515 - if (device->info.family < NV_DEVICE_INFO_V0_TESLA) { 516 - ret = nvif_object_init(&drm->channel->user, NVDRM_NVSW, 517 - nouveau_abi16_swclass(drm), NULL, 0, 518 - &drm->nvsw); 519 - if (ret == 0) { 520 - ret = RING_SPACE(drm->channel, 2); 521 - if (ret == 0) { 522 - BEGIN_NV04(drm->channel, NvSubSw, 0, 1); 523 - OUT_RING (drm->channel, drm->nvsw.handle); 524 - } 525 - 526 - ret = nvif_notify_init(&drm->nvsw, 527 - nouveau_flip_complete, 528 - false, NV04_NVSW_NTFY_UEVENT, 529 - NULL, 0, 0, &drm->flip); 530 - if (ret == 0) 531 - ret = nvif_notify_get(&drm->flip); 532 - if (ret) { 533 - nouveau_accel_fini(drm); 534 - return; 535 - } 536 - } 537 - 538 - if (ret) { 539 - NV_ERROR(drm, "failed to allocate sw class, %d\n", ret); 540 - nouveau_accel_fini(drm); 541 375 return; 542 - } 543 376 } 544 377 545 - if (device->info.family < NV_DEVICE_INFO_V0_FERMI) { 546 - ret = nvkm_gpuobj_new(nvxx_device(&drm->client.device), 32, 0, 547 - false, NULL, &drm->notify); 548 - if (ret) { 549 - NV_ERROR(drm, "failed to allocate notifier, %d\n", ret); 550 - nouveau_accel_fini(drm); 551 - return; 552 - } 378 + /* Allocate channels we need to support various functions. */ 379 + nouveau_accel_gr_init(drm); 380 + nouveau_accel_ce_init(drm); 553 381 554 - ret = nvif_object_init(&drm->channel->user, NvNotify0, 555 - NV_DMA_IN_MEMORY, 556 - &(struct nv_dma_v0) { 557 - .target = NV_DMA_V0_TARGET_VRAM, 558 - .access = NV_DMA_V0_ACCESS_RDWR, 559 - .start = drm->notify->addr, 560 - .limit = drm->notify->addr + 31 561 - }, sizeof(struct nv_dma_v0), 562 - &drm->ntfy); 563 - if (ret) { 564 - nouveau_accel_fini(drm); 565 - return; 566 - } 567 - } 568 - 569 - 382 + /* Initialise accelerated TTM buffer moves. */ 570 383 nouveau_bo_move_init(drm); 571 384 } 572 385 ··· 537 504 if (ret) 538 505 goto fail_bios; 539 506 507 + nouveau_accel_init(drm); 508 + 540 509 ret = nouveau_display_create(dev); 541 510 if (ret) 542 511 goto fail_dispctor; 543 512 544 513 if (dev->mode_config.num_crtc) { 545 - ret = nouveau_display_init(dev); 514 + ret = nouveau_display_init(dev, false, false); 546 515 if (ret) 547 516 goto fail_dispinit; 548 517 } 549 518 550 519 nouveau_debugfs_init(drm); 551 520 nouveau_hwmon_init(dev); 552 - nouveau_accel_init(drm); 521 + nouveau_svm_init(drm); 522 + nouveau_dmem_init(drm); 553 523 nouveau_fbcon_init(dev); 554 524 nouveau_led_init(dev); 555 525 ··· 570 534 fail_dispinit: 571 535 nouveau_display_destroy(dev); 572 536 fail_dispctor: 537 + nouveau_accel_fini(drm); 573 538 nouveau_bios_takedown(dev); 574 539 fail_bios: 575 540 nouveau_ttm_fini(drm); ··· 596 559 597 560 nouveau_led_fini(dev); 598 561 nouveau_fbcon_fini(dev); 599 - nouveau_accel_fini(drm); 562 + nouveau_dmem_fini(drm); 563 + nouveau_svm_fini(drm); 600 564 nouveau_hwmon_fini(dev); 601 565 nouveau_debugfs_fini(drm); 602 566 ··· 605 567 nouveau_display_fini(dev, false, false); 606 568 nouveau_display_destroy(dev); 607 569 570 + nouveau_accel_fini(drm); 608 571 nouveau_bios_takedown(dev); 609 572 610 573 nouveau_ttm_fini(drm); ··· 743 704 struct nouveau_drm *drm = nouveau_drm(dev); 744 705 int ret; 745 706 707 + nouveau_svm_suspend(drm); 708 + nouveau_dmem_suspend(drm); 746 709 nouveau_led_suspend(dev); 747 710 748 711 if (dev->mode_config.num_crtc) { ··· 821 780 } 822 781 823 782 nouveau_led_resume(dev); 824 - 783 + nouveau_dmem_resume(drm); 784 + nouveau_svm_resume(drm); 825 785 return 0; 826 786 } 827 787 ··· 1042 1000 DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_AUTH|DRM_RENDER_ALLOW), 1043 1001 DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_AUTH|DRM_RENDER_ALLOW), 1044 1002 DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_AUTH|DRM_RENDER_ALLOW), 1003 + DRM_IOCTL_DEF_DRV(NOUVEAU_SVM_INIT, nouveau_svmm_init, DRM_AUTH|DRM_RENDER_ALLOW), 1004 + DRM_IOCTL_DEF_DRV(NOUVEAU_SVM_BIND, nouveau_svmm_bind, DRM_AUTH|DRM_RENDER_ALLOW), 1045 1005 DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH|DRM_RENDER_ALLOW), 1046 1006 DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH|DRM_RENDER_ALLOW), 1047 1007 DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW),
+5 -1
drivers/gpu/drm/nouveau/nouveau_drv.h
··· 96 96 struct nvif_device device; 97 97 struct nvif_mmu mmu; 98 98 struct nouveau_vmm vmm; 99 + struct nouveau_vmm svm; 99 100 const struct nvif_mclass *mem; 100 101 101 102 struct list_head head; ··· 182 181 struct nouveau_fbdev *fbcon; 183 182 struct nvif_object nvsw; 184 183 struct nvif_object ntfy; 185 - struct nvif_notify flip; 186 184 187 185 /* nv10-nv40 tiling regions */ 188 186 struct { ··· 210 210 bool have_disp_power_ref; 211 211 212 212 struct dev_pm_domain vga_pm_domain; 213 + 214 + struct nouveau_svm *svm; 215 + 216 + struct nouveau_dmem *dmem; 213 217 }; 214 218 215 219 static inline struct nouveau_drm *
+1 -1
drivers/gpu/drm/nouveau/nouveau_fbcon.c
··· 353 353 354 354 chan = nouveau_nofbaccel ? NULL : drm->channel; 355 355 if (chan && device->info.family >= NV_DEVICE_INFO_V0_TESLA) { 356 - ret = nouveau_vma_new(nvbo, &drm->client.vmm, &fb->vma); 356 + ret = nouveau_vma_new(nvbo, chan->vmm, &fb->vma); 357 357 if (ret) { 358 358 NV_ERROR(drm, "failed to map fb into chan: %d\n", ret); 359 359 chan = NULL;
-2
drivers/gpu/drm/nouveau/nouveau_fence.h
··· 82 82 int nv84_fence_create(struct nouveau_drm *); 83 83 int nvc0_fence_create(struct nouveau_drm *); 84 84 85 - int nouveau_flip_complete(struct nvif_notify *); 86 - 87 85 struct nv84_fence_chan { 88 86 struct nouveau_fence_chan base; 89 87 struct nouveau_vma *vma;
+23 -20
drivers/gpu/drm/nouveau/nouveau_gem.c
··· 68 68 struct nouveau_bo *nvbo = nouveau_gem_object(gem); 69 69 struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); 70 70 struct device *dev = drm->dev->dev; 71 + struct nouveau_vmm *vmm = cli->svm.cli ? &cli->svm : &cli->vmm; 71 72 struct nouveau_vma *vma; 72 73 int ret; 73 74 74 - if (cli->vmm.vmm.object.oclass < NVIF_CLASS_VMM_NV50) 75 + if (vmm->vmm.object.oclass < NVIF_CLASS_VMM_NV50) 75 76 return 0; 76 77 77 78 ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL); ··· 83 82 if (ret < 0 && ret != -EACCES) 84 83 goto out; 85 84 86 - ret = nouveau_vma_new(nvbo, &cli->vmm, &vma); 85 + ret = nouveau_vma_new(nvbo, vmm, &vma); 87 86 pm_runtime_mark_last_busy(dev); 88 87 pm_runtime_put_autosuspend(dev); 89 88 out: ··· 143 142 struct nouveau_bo *nvbo = nouveau_gem_object(gem); 144 143 struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); 145 144 struct device *dev = drm->dev->dev; 145 + struct nouveau_vmm *vmm = cli->svm.cli ? &cli->svm : & cli->vmm; 146 146 struct nouveau_vma *vma; 147 147 int ret; 148 148 149 - if (cli->vmm.vmm.object.oclass < NVIF_CLASS_VMM_NV50) 149 + if (vmm->vmm.object.oclass < NVIF_CLASS_VMM_NV50) 150 150 return; 151 151 152 152 ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL); 153 153 if (ret) 154 154 return; 155 155 156 - vma = nouveau_vma_find(nvbo, &cli->vmm); 156 + vma = nouveau_vma_find(nvbo, vmm); 157 157 if (vma) { 158 158 if (--vma->refs == 0) { 159 159 ret = pm_runtime_get_sync(dev); ··· 221 219 { 222 220 struct nouveau_cli *cli = nouveau_cli(file_priv); 223 221 struct nouveau_bo *nvbo = nouveau_gem_object(gem); 222 + struct nouveau_vmm *vmm = cli->svm.cli ? &cli->svm : &cli->vmm; 224 223 struct nouveau_vma *vma; 225 224 226 225 if (is_power_of_2(nvbo->valid_domains)) ··· 231 228 else 232 229 rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; 233 230 rep->offset = nvbo->bo.offset; 234 - if (cli->vmm.vmm.object.oclass >= NVIF_CLASS_VMM_NV50) { 235 - vma = nouveau_vma_find(nvbo, &cli->vmm); 231 + if (vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50) { 232 + vma = nouveau_vma_find(nvbo, vmm); 236 233 if (!vma) 237 234 return -EINVAL; 238 235 ··· 324 321 }; 325 322 326 323 static void 327 - validate_fini_no_ticket(struct validate_op *op, struct nouveau_fence *fence, 324 + validate_fini_no_ticket(struct validate_op *op, struct nouveau_channel *chan, 325 + struct nouveau_fence *fence, 328 326 struct drm_nouveau_gem_pushbuf_bo *pbbo) 329 327 { 330 328 struct nouveau_bo *nvbo; ··· 336 332 b = &pbbo[nvbo->pbbo_index]; 337 333 338 334 if (likely(fence)) { 339 - struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); 340 - struct nouveau_vma *vma; 341 - 342 335 nouveau_bo_fence(nvbo, fence, !!b->write_domains); 343 336 344 - if (drm->client.vmm.vmm.object.oclass >= NVIF_CLASS_VMM_NV50) { 345 - vma = (void *)(unsigned long)b->user_priv; 337 + if (chan->vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50) { 338 + struct nouveau_vma *vma = 339 + (void *)(unsigned long)b->user_priv; 346 340 nouveau_fence_unref(&vma->fence); 347 341 dma_fence_get(&fence->base); 348 342 vma->fence = fence; ··· 360 358 } 361 359 362 360 static void 363 - validate_fini(struct validate_op *op, struct nouveau_fence *fence, 361 + validate_fini(struct validate_op *op, struct nouveau_channel *chan, 362 + struct nouveau_fence *fence, 364 363 struct drm_nouveau_gem_pushbuf_bo *pbbo) 365 364 { 366 - validate_fini_no_ticket(op, fence, pbbo); 365 + validate_fini_no_ticket(op, chan, fence, pbbo); 367 366 ww_acquire_fini(&op->ticket); 368 367 } 369 368 ··· 419 416 list_splice_tail_init(&vram_list, &op->list); 420 417 list_splice_tail_init(&gart_list, &op->list); 421 418 list_splice_tail_init(&both_list, &op->list); 422 - validate_fini_no_ticket(op, NULL, NULL); 419 + validate_fini_no_ticket(op, chan, NULL, NULL); 423 420 if (unlikely(ret == -EDEADLK)) { 424 421 ret = ttm_bo_reserve_slowpath(&nvbo->bo, true, 425 422 &op->ticket); ··· 433 430 } 434 431 } 435 432 436 - if (cli->vmm.vmm.object.oclass >= NVIF_CLASS_VMM_NV50) { 437 - struct nouveau_vmm *vmm = &cli->vmm; 433 + if (chan->vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50) { 434 + struct nouveau_vmm *vmm = chan->vmm; 438 435 struct nouveau_vma *vma = nouveau_vma_find(nvbo, vmm); 439 436 if (!vma) { 440 437 NV_PRINTK(err, cli, "vma not found!\n"); ··· 474 471 list_splice_tail(&gart_list, &op->list); 475 472 list_splice_tail(&both_list, &op->list); 476 473 if (ret) 477 - validate_fini(op, NULL, NULL); 474 + validate_fini(op, chan, NULL, NULL); 478 475 return ret; 479 476 480 477 } ··· 566 563 if (unlikely(ret < 0)) { 567 564 if (ret != -ERESTARTSYS) 568 565 NV_PRINTK(err, cli, "validating bo list\n"); 569 - validate_fini(op, NULL, NULL); 566 + validate_fini(op, chan, NULL, NULL); 570 567 return ret; 571 568 } 572 569 *apply_relocs = ret; ··· 845 842 } 846 843 847 844 out: 848 - validate_fini(&op, fence, bo); 845 + validate_fini(&op, chan, fence, bo); 849 846 nouveau_fence_unref(&fence); 850 847 851 848 out_prevalid:
+835
drivers/gpu/drm/nouveau/nouveau_svm.c
··· 1 + /* 2 + * Copyright 2018 Red Hat Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + */ 22 + #include "nouveau_svm.h" 23 + #include "nouveau_drv.h" 24 + #include "nouveau_chan.h" 25 + #include "nouveau_dmem.h" 26 + 27 + #include <nvif/notify.h> 28 + #include <nvif/object.h> 29 + #include <nvif/vmm.h> 30 + 31 + #include <nvif/class.h> 32 + #include <nvif/clb069.h> 33 + #include <nvif/ifc00d.h> 34 + 35 + #include <linux/sched/mm.h> 36 + #include <linux/sort.h> 37 + #include <linux/hmm.h> 38 + 39 + struct nouveau_svm { 40 + struct nouveau_drm *drm; 41 + struct mutex mutex; 42 + struct list_head inst; 43 + 44 + struct nouveau_svm_fault_buffer { 45 + int id; 46 + struct nvif_object object; 47 + u32 entries; 48 + u32 getaddr; 49 + u32 putaddr; 50 + u32 get; 51 + u32 put; 52 + struct nvif_notify notify; 53 + 54 + struct nouveau_svm_fault { 55 + u64 inst; 56 + u64 addr; 57 + u64 time; 58 + u32 engine; 59 + u8 gpc; 60 + u8 hub; 61 + u8 access; 62 + u8 client; 63 + u8 fault; 64 + struct nouveau_svmm *svmm; 65 + } **fault; 66 + int fault_nr; 67 + } buffer[1]; 68 + }; 69 + 70 + #define SVM_DBG(s,f,a...) NV_DEBUG((s)->drm, "svm: "f"\n", ##a) 71 + #define SVM_ERR(s,f,a...) NV_WARN((s)->drm, "svm: "f"\n", ##a) 72 + 73 + struct nouveau_ivmm { 74 + struct nouveau_svmm *svmm; 75 + u64 inst; 76 + struct list_head head; 77 + }; 78 + 79 + static struct nouveau_ivmm * 80 + nouveau_ivmm_find(struct nouveau_svm *svm, u64 inst) 81 + { 82 + struct nouveau_ivmm *ivmm; 83 + list_for_each_entry(ivmm, &svm->inst, head) { 84 + if (ivmm->inst == inst) 85 + return ivmm; 86 + } 87 + return NULL; 88 + } 89 + 90 + struct nouveau_svmm { 91 + struct nouveau_vmm *vmm; 92 + struct { 93 + unsigned long start; 94 + unsigned long limit; 95 + } unmanaged; 96 + 97 + struct mutex mutex; 98 + 99 + struct mm_struct *mm; 100 + struct hmm_mirror mirror; 101 + }; 102 + 103 + #define SVMM_DBG(s,f,a...) \ 104 + NV_DEBUG((s)->vmm->cli->drm, "svm-%p: "f"\n", (s), ##a) 105 + #define SVMM_ERR(s,f,a...) \ 106 + NV_WARN((s)->vmm->cli->drm, "svm-%p: "f"\n", (s), ##a) 107 + 108 + int 109 + nouveau_svmm_bind(struct drm_device *dev, void *data, 110 + struct drm_file *file_priv) 111 + { 112 + struct nouveau_cli *cli = nouveau_cli(file_priv); 113 + struct drm_nouveau_svm_bind *args = data; 114 + unsigned target, cmd, priority; 115 + unsigned long addr, end, size; 116 + struct mm_struct *mm; 117 + 118 + args->va_start &= PAGE_MASK; 119 + args->va_end &= PAGE_MASK; 120 + 121 + /* Sanity check arguments */ 122 + if (args->reserved0 || args->reserved1) 123 + return -EINVAL; 124 + if (args->header & (~NOUVEAU_SVM_BIND_VALID_MASK)) 125 + return -EINVAL; 126 + if (args->va_start >= args->va_end) 127 + return -EINVAL; 128 + if (!args->npages) 129 + return -EINVAL; 130 + 131 + cmd = args->header >> NOUVEAU_SVM_BIND_COMMAND_SHIFT; 132 + cmd &= NOUVEAU_SVM_BIND_COMMAND_MASK; 133 + switch (cmd) { 134 + case NOUVEAU_SVM_BIND_COMMAND__MIGRATE: 135 + break; 136 + default: 137 + return -EINVAL; 138 + } 139 + 140 + priority = args->header >> NOUVEAU_SVM_BIND_PRIORITY_SHIFT; 141 + priority &= NOUVEAU_SVM_BIND_PRIORITY_MASK; 142 + 143 + /* FIXME support CPU target ie all target value < GPU_VRAM */ 144 + target = args->header >> NOUVEAU_SVM_BIND_TARGET_SHIFT; 145 + target &= NOUVEAU_SVM_BIND_TARGET_MASK; 146 + switch (target) { 147 + case NOUVEAU_SVM_BIND_TARGET__GPU_VRAM: 148 + break; 149 + default: 150 + return -EINVAL; 151 + } 152 + 153 + /* 154 + * FIXME: For now refuse non 0 stride, we need to change the migrate 155 + * kernel function to handle stride to avoid to create a mess within 156 + * each device driver. 157 + */ 158 + if (args->stride) 159 + return -EINVAL; 160 + 161 + size = ((unsigned long)args->npages) << PAGE_SHIFT; 162 + if ((args->va_start + size) <= args->va_start) 163 + return -EINVAL; 164 + if ((args->va_start + size) > args->va_end) 165 + return -EINVAL; 166 + 167 + /* 168 + * Ok we are ask to do something sane, for now we only support migrate 169 + * commands but we will add things like memory policy (what to do on 170 + * page fault) and maybe some other commands. 171 + */ 172 + 173 + mm = get_task_mm(current); 174 + down_read(&mm->mmap_sem); 175 + 176 + for (addr = args->va_start, end = args->va_start + size; addr < end;) { 177 + struct vm_area_struct *vma; 178 + unsigned long next; 179 + 180 + vma = find_vma_intersection(mm, addr, end); 181 + if (!vma) 182 + break; 183 + 184 + next = min(vma->vm_end, end); 185 + /* This is a best effort so we ignore errors */ 186 + nouveau_dmem_migrate_vma(cli->drm, vma, addr, next); 187 + addr = next; 188 + } 189 + 190 + /* 191 + * FIXME Return the number of page we have migrated, again we need to 192 + * update the migrate API to return that information so that we can 193 + * report it to user space. 194 + */ 195 + args->result = 0; 196 + 197 + up_read(&mm->mmap_sem); 198 + mmput(mm); 199 + 200 + return 0; 201 + } 202 + 203 + /* Unlink channel instance from SVMM. */ 204 + void 205 + nouveau_svmm_part(struct nouveau_svmm *svmm, u64 inst) 206 + { 207 + struct nouveau_ivmm *ivmm; 208 + if (svmm) { 209 + mutex_lock(&svmm->vmm->cli->drm->svm->mutex); 210 + ivmm = nouveau_ivmm_find(svmm->vmm->cli->drm->svm, inst); 211 + if (ivmm) { 212 + list_del(&ivmm->head); 213 + kfree(ivmm); 214 + } 215 + mutex_unlock(&svmm->vmm->cli->drm->svm->mutex); 216 + } 217 + } 218 + 219 + /* Link channel instance to SVMM. */ 220 + int 221 + nouveau_svmm_join(struct nouveau_svmm *svmm, u64 inst) 222 + { 223 + struct nouveau_ivmm *ivmm; 224 + if (svmm) { 225 + if (!(ivmm = kmalloc(sizeof(*ivmm), GFP_KERNEL))) 226 + return -ENOMEM; 227 + ivmm->svmm = svmm; 228 + ivmm->inst = inst; 229 + 230 + mutex_lock(&svmm->vmm->cli->drm->svm->mutex); 231 + list_add(&ivmm->head, &svmm->vmm->cli->drm->svm->inst); 232 + mutex_unlock(&svmm->vmm->cli->drm->svm->mutex); 233 + } 234 + return 0; 235 + } 236 + 237 + /* Invalidate SVMM address-range on GPU. */ 238 + static void 239 + nouveau_svmm_invalidate(struct nouveau_svmm *svmm, u64 start, u64 limit) 240 + { 241 + if (limit > start) { 242 + bool super = svmm->vmm->vmm.object.client->super; 243 + svmm->vmm->vmm.object.client->super = true; 244 + nvif_object_mthd(&svmm->vmm->vmm.object, NVIF_VMM_V0_PFNCLR, 245 + &(struct nvif_vmm_pfnclr_v0) { 246 + .addr = start, 247 + .size = limit - start, 248 + }, sizeof(struct nvif_vmm_pfnclr_v0)); 249 + svmm->vmm->vmm.object.client->super = super; 250 + } 251 + } 252 + 253 + static int 254 + nouveau_svmm_sync_cpu_device_pagetables(struct hmm_mirror *mirror, 255 + const struct hmm_update *update) 256 + { 257 + struct nouveau_svmm *svmm = container_of(mirror, typeof(*svmm), mirror); 258 + unsigned long start = update->start; 259 + unsigned long limit = update->end; 260 + 261 + if (!update->blockable) 262 + return -EAGAIN; 263 + 264 + SVMM_DBG(svmm, "invalidate %016lx-%016lx", start, limit); 265 + 266 + mutex_lock(&svmm->mutex); 267 + if (limit > svmm->unmanaged.start && start < svmm->unmanaged.limit) { 268 + if (start < svmm->unmanaged.start) { 269 + nouveau_svmm_invalidate(svmm, start, 270 + svmm->unmanaged.limit); 271 + } 272 + start = svmm->unmanaged.limit; 273 + } 274 + 275 + nouveau_svmm_invalidate(svmm, start, limit); 276 + mutex_unlock(&svmm->mutex); 277 + return 0; 278 + } 279 + 280 + static void 281 + nouveau_svmm_release(struct hmm_mirror *mirror) 282 + { 283 + } 284 + 285 + static const struct hmm_mirror_ops 286 + nouveau_svmm = { 287 + .sync_cpu_device_pagetables = nouveau_svmm_sync_cpu_device_pagetables, 288 + .release = nouveau_svmm_release, 289 + }; 290 + 291 + void 292 + nouveau_svmm_fini(struct nouveau_svmm **psvmm) 293 + { 294 + struct nouveau_svmm *svmm = *psvmm; 295 + if (svmm) { 296 + hmm_mirror_unregister(&svmm->mirror); 297 + kfree(*psvmm); 298 + *psvmm = NULL; 299 + } 300 + } 301 + 302 + int 303 + nouveau_svmm_init(struct drm_device *dev, void *data, 304 + struct drm_file *file_priv) 305 + { 306 + struct nouveau_cli *cli = nouveau_cli(file_priv); 307 + struct nouveau_svmm *svmm; 308 + struct drm_nouveau_svm_init *args = data; 309 + int ret; 310 + 311 + /* Allocate tracking for SVM-enabled VMM. */ 312 + if (!(svmm = kzalloc(sizeof(*svmm), GFP_KERNEL))) 313 + return -ENOMEM; 314 + svmm->vmm = &cli->svm; 315 + svmm->unmanaged.start = args->unmanaged_addr; 316 + svmm->unmanaged.limit = args->unmanaged_addr + args->unmanaged_size; 317 + mutex_init(&svmm->mutex); 318 + 319 + /* Check that SVM isn't already enabled for the client. */ 320 + mutex_lock(&cli->mutex); 321 + if (cli->svm.cli) { 322 + ret = -EBUSY; 323 + goto done; 324 + } 325 + 326 + /* Allocate a new GPU VMM that can support SVM (managed by the 327 + * client, with replayable faults enabled). 328 + * 329 + * All future channel/memory allocations will make use of this 330 + * VMM instead of the standard one. 331 + */ 332 + ret = nvif_vmm_init(&cli->mmu, cli->vmm.vmm.object.oclass, true, 333 + args->unmanaged_addr, args->unmanaged_size, 334 + &(struct gp100_vmm_v0) { 335 + .fault_replay = true, 336 + }, sizeof(struct gp100_vmm_v0), &cli->svm.vmm); 337 + if (ret) 338 + goto done; 339 + 340 + /* Enable HMM mirroring of CPU address-space to VMM. */ 341 + svmm->mm = get_task_mm(current); 342 + down_write(&svmm->mm->mmap_sem); 343 + svmm->mirror.ops = &nouveau_svmm; 344 + ret = hmm_mirror_register(&svmm->mirror, svmm->mm); 345 + if (ret == 0) { 346 + cli->svm.svmm = svmm; 347 + cli->svm.cli = cli; 348 + } 349 + up_write(&svmm->mm->mmap_sem); 350 + mmput(svmm->mm); 351 + 352 + done: 353 + if (ret) 354 + nouveau_svmm_fini(&svmm); 355 + mutex_unlock(&cli->mutex); 356 + return ret; 357 + } 358 + 359 + static const u64 360 + nouveau_svm_pfn_flags[HMM_PFN_FLAG_MAX] = { 361 + [HMM_PFN_VALID ] = NVIF_VMM_PFNMAP_V0_V, 362 + [HMM_PFN_WRITE ] = NVIF_VMM_PFNMAP_V0_W, 363 + [HMM_PFN_DEVICE_PRIVATE] = NVIF_VMM_PFNMAP_V0_VRAM, 364 + }; 365 + 366 + static const u64 367 + nouveau_svm_pfn_values[HMM_PFN_VALUE_MAX] = { 368 + [HMM_PFN_ERROR ] = ~NVIF_VMM_PFNMAP_V0_V, 369 + [HMM_PFN_NONE ] = NVIF_VMM_PFNMAP_V0_NONE, 370 + [HMM_PFN_SPECIAL] = ~NVIF_VMM_PFNMAP_V0_V, 371 + }; 372 + 373 + /* Issue fault replay for GPU to retry accesses that faulted previously. */ 374 + static void 375 + nouveau_svm_fault_replay(struct nouveau_svm *svm) 376 + { 377 + SVM_DBG(svm, "replay"); 378 + WARN_ON(nvif_object_mthd(&svm->drm->client.vmm.vmm.object, 379 + GP100_VMM_VN_FAULT_REPLAY, 380 + &(struct gp100_vmm_fault_replay_vn) {}, 381 + sizeof(struct gp100_vmm_fault_replay_vn))); 382 + } 383 + 384 + /* Cancel a replayable fault that could not be handled. 385 + * 386 + * Cancelling the fault will trigger recovery to reset the engine 387 + * and kill the offending channel (ie. GPU SIGSEGV). 388 + */ 389 + static void 390 + nouveau_svm_fault_cancel(struct nouveau_svm *svm, 391 + u64 inst, u8 hub, u8 gpc, u8 client) 392 + { 393 + SVM_DBG(svm, "cancel %016llx %d %02x %02x", inst, hub, gpc, client); 394 + WARN_ON(nvif_object_mthd(&svm->drm->client.vmm.vmm.object, 395 + GP100_VMM_VN_FAULT_CANCEL, 396 + &(struct gp100_vmm_fault_cancel_v0) { 397 + .hub = hub, 398 + .gpc = gpc, 399 + .client = client, 400 + .inst = inst, 401 + }, sizeof(struct gp100_vmm_fault_cancel_v0))); 402 + } 403 + 404 + static void 405 + nouveau_svm_fault_cancel_fault(struct nouveau_svm *svm, 406 + struct nouveau_svm_fault *fault) 407 + { 408 + nouveau_svm_fault_cancel(svm, fault->inst, 409 + fault->hub, 410 + fault->gpc, 411 + fault->client); 412 + } 413 + 414 + static int 415 + nouveau_svm_fault_cmp(const void *a, const void *b) 416 + { 417 + const struct nouveau_svm_fault *fa = *(struct nouveau_svm_fault **)a; 418 + const struct nouveau_svm_fault *fb = *(struct nouveau_svm_fault **)b; 419 + int ret; 420 + if ((ret = (s64)fa->inst - fb->inst)) 421 + return ret; 422 + if ((ret = (s64)fa->addr - fb->addr)) 423 + return ret; 424 + /*XXX: atomic? */ 425 + return (fa->access == 0 || fa->access == 3) - 426 + (fb->access == 0 || fb->access == 3); 427 + } 428 + 429 + static void 430 + nouveau_svm_fault_cache(struct nouveau_svm *svm, 431 + struct nouveau_svm_fault_buffer *buffer, u32 offset) 432 + { 433 + struct nvif_object *memory = &buffer->object; 434 + const u32 instlo = nvif_rd32(memory, offset + 0x00); 435 + const u32 insthi = nvif_rd32(memory, offset + 0x04); 436 + const u32 addrlo = nvif_rd32(memory, offset + 0x08); 437 + const u32 addrhi = nvif_rd32(memory, offset + 0x0c); 438 + const u32 timelo = nvif_rd32(memory, offset + 0x10); 439 + const u32 timehi = nvif_rd32(memory, offset + 0x14); 440 + const u32 engine = nvif_rd32(memory, offset + 0x18); 441 + const u32 info = nvif_rd32(memory, offset + 0x1c); 442 + const u64 inst = (u64)insthi << 32 | instlo; 443 + const u8 gpc = (info & 0x1f000000) >> 24; 444 + const u8 hub = (info & 0x00100000) >> 20; 445 + const u8 client = (info & 0x00007f00) >> 8; 446 + struct nouveau_svm_fault *fault; 447 + 448 + //XXX: i think we're supposed to spin waiting */ 449 + if (WARN_ON(!(info & 0x80000000))) 450 + return; 451 + 452 + nvif_mask(memory, offset + 0x1c, 0x80000000, 0x00000000); 453 + 454 + if (!buffer->fault[buffer->fault_nr]) { 455 + fault = kmalloc(sizeof(*fault), GFP_KERNEL); 456 + if (WARN_ON(!fault)) { 457 + nouveau_svm_fault_cancel(svm, inst, hub, gpc, client); 458 + return; 459 + } 460 + buffer->fault[buffer->fault_nr] = fault; 461 + } 462 + 463 + fault = buffer->fault[buffer->fault_nr++]; 464 + fault->inst = inst; 465 + fault->addr = (u64)addrhi << 32 | addrlo; 466 + fault->time = (u64)timehi << 32 | timelo; 467 + fault->engine = engine; 468 + fault->gpc = gpc; 469 + fault->hub = hub; 470 + fault->access = (info & 0x000f0000) >> 16; 471 + fault->client = client; 472 + fault->fault = (info & 0x0000001f); 473 + 474 + SVM_DBG(svm, "fault %016llx %016llx %02x", 475 + fault->inst, fault->addr, fault->access); 476 + } 477 + 478 + static int 479 + nouveau_svm_fault(struct nvif_notify *notify) 480 + { 481 + struct nouveau_svm_fault_buffer *buffer = 482 + container_of(notify, typeof(*buffer), notify); 483 + struct nouveau_svm *svm = 484 + container_of(buffer, typeof(*svm), buffer[buffer->id]); 485 + struct nvif_object *device = &svm->drm->client.device.object; 486 + struct nouveau_svmm *svmm; 487 + struct { 488 + struct { 489 + struct nvif_ioctl_v0 i; 490 + struct nvif_ioctl_mthd_v0 m; 491 + struct nvif_vmm_pfnmap_v0 p; 492 + } i; 493 + u64 phys[16]; 494 + } args; 495 + struct hmm_range range; 496 + struct vm_area_struct *vma; 497 + u64 inst, start, limit; 498 + int fi, fn, pi, fill; 499 + int replay = 0, ret; 500 + 501 + /* Parse available fault buffer entries into a cache, and update 502 + * the GET pointer so HW can reuse the entries. 503 + */ 504 + SVM_DBG(svm, "fault handler"); 505 + if (buffer->get == buffer->put) { 506 + buffer->put = nvif_rd32(device, buffer->putaddr); 507 + buffer->get = nvif_rd32(device, buffer->getaddr); 508 + if (buffer->get == buffer->put) 509 + return NVIF_NOTIFY_KEEP; 510 + } 511 + buffer->fault_nr = 0; 512 + 513 + SVM_DBG(svm, "get %08x put %08x", buffer->get, buffer->put); 514 + while (buffer->get != buffer->put) { 515 + nouveau_svm_fault_cache(svm, buffer, buffer->get * 0x20); 516 + if (++buffer->get == buffer->entries) 517 + buffer->get = 0; 518 + } 519 + nvif_wr32(device, buffer->getaddr, buffer->get); 520 + SVM_DBG(svm, "%d fault(s) pending", buffer->fault_nr); 521 + 522 + /* Sort parsed faults by instance pointer to prevent unnecessary 523 + * instance to SVMM translations, followed by address and access 524 + * type to reduce the amount of work when handling the faults. 525 + */ 526 + sort(buffer->fault, buffer->fault_nr, sizeof(*buffer->fault), 527 + nouveau_svm_fault_cmp, NULL); 528 + 529 + /* Lookup SVMM structure for each unique instance pointer. */ 530 + mutex_lock(&svm->mutex); 531 + for (fi = 0, svmm = NULL; fi < buffer->fault_nr; fi++) { 532 + if (!svmm || buffer->fault[fi]->inst != inst) { 533 + struct nouveau_ivmm *ivmm = 534 + nouveau_ivmm_find(svm, buffer->fault[fi]->inst); 535 + svmm = ivmm ? ivmm->svmm : NULL; 536 + inst = buffer->fault[fi]->inst; 537 + SVM_DBG(svm, "inst %016llx -> svm-%p", inst, svmm); 538 + } 539 + buffer->fault[fi]->svmm = svmm; 540 + } 541 + mutex_unlock(&svm->mutex); 542 + 543 + /* Process list of faults. */ 544 + args.i.i.version = 0; 545 + args.i.i.type = NVIF_IOCTL_V0_MTHD; 546 + args.i.m.version = 0; 547 + args.i.m.method = NVIF_VMM_V0_PFNMAP; 548 + args.i.p.version = 0; 549 + 550 + for (fi = 0; fn = fi + 1, fi < buffer->fault_nr; fi = fn) { 551 + /* Cancel any faults from non-SVM channels. */ 552 + if (!(svmm = buffer->fault[fi]->svmm)) { 553 + nouveau_svm_fault_cancel_fault(svm, buffer->fault[fi]); 554 + continue; 555 + } 556 + SVMM_DBG(svmm, "addr %016llx", buffer->fault[fi]->addr); 557 + 558 + /* We try and group handling of faults within a small 559 + * window into a single update. 560 + */ 561 + start = buffer->fault[fi]->addr; 562 + limit = start + (ARRAY_SIZE(args.phys) << PAGE_SHIFT); 563 + if (start < svmm->unmanaged.limit) 564 + limit = min_t(u64, limit, svmm->unmanaged.start); 565 + else 566 + if (limit > svmm->unmanaged.start) 567 + start = max_t(u64, start, svmm->unmanaged.limit); 568 + SVMM_DBG(svmm, "wndw %016llx-%016llx", start, limit); 569 + 570 + /* Intersect fault window with the CPU VMA, cancelling 571 + * the fault if the address is invalid. 572 + */ 573 + down_read(&svmm->mm->mmap_sem); 574 + vma = find_vma_intersection(svmm->mm, start, limit); 575 + if (!vma) { 576 + SVMM_ERR(svmm, "wndw %016llx-%016llx", start, limit); 577 + up_read(&svmm->mm->mmap_sem); 578 + nouveau_svm_fault_cancel_fault(svm, buffer->fault[fi]); 579 + continue; 580 + } 581 + start = max_t(u64, start, vma->vm_start); 582 + limit = min_t(u64, limit, vma->vm_end); 583 + SVMM_DBG(svmm, "wndw %016llx-%016llx", start, limit); 584 + 585 + if (buffer->fault[fi]->addr != start) { 586 + SVMM_ERR(svmm, "addr %016llx", buffer->fault[fi]->addr); 587 + up_read(&svmm->mm->mmap_sem); 588 + nouveau_svm_fault_cancel_fault(svm, buffer->fault[fi]); 589 + continue; 590 + } 591 + 592 + /* Prepare the GPU-side update of all pages within the 593 + * fault window, determining required pages and access 594 + * permissions based on pending faults. 595 + */ 596 + args.i.p.page = PAGE_SHIFT; 597 + args.i.p.addr = start; 598 + for (fn = fi, pi = 0;;) { 599 + /* Determine required permissions based on GPU fault 600 + * access flags. 601 + *XXX: atomic? 602 + */ 603 + if (buffer->fault[fn]->access != 0 /* READ. */ && 604 + buffer->fault[fn]->access != 3 /* PREFETCH. */) { 605 + args.phys[pi++] = NVIF_VMM_PFNMAP_V0_V | 606 + NVIF_VMM_PFNMAP_V0_W; 607 + } else { 608 + args.phys[pi++] = NVIF_VMM_PFNMAP_V0_V; 609 + } 610 + args.i.p.size = pi << PAGE_SHIFT; 611 + 612 + /* It's okay to skip over duplicate addresses from the 613 + * same SVMM as faults are ordered by access type such 614 + * that only the first one needs to be handled. 615 + * 616 + * ie. WRITE faults appear first, thus any handling of 617 + * pending READ faults will already be satisfied. 618 + */ 619 + while (++fn < buffer->fault_nr && 620 + buffer->fault[fn]->svmm == svmm && 621 + buffer->fault[fn ]->addr == 622 + buffer->fault[fn - 1]->addr); 623 + 624 + /* If the next fault is outside the window, or all GPU 625 + * faults have been dealt with, we're done here. 626 + */ 627 + if (fn >= buffer->fault_nr || 628 + buffer->fault[fn]->svmm != svmm || 629 + buffer->fault[fn]->addr >= limit) 630 + break; 631 + 632 + /* Fill in the gap between this fault and the next. */ 633 + fill = (buffer->fault[fn ]->addr - 634 + buffer->fault[fn - 1]->addr) >> PAGE_SHIFT; 635 + while (--fill) 636 + args.phys[pi++] = NVIF_VMM_PFNMAP_V0_NONE; 637 + } 638 + 639 + SVMM_DBG(svmm, "wndw %016llx-%016llx covering %d fault(s)", 640 + args.i.p.addr, 641 + args.i.p.addr + args.i.p.size, fn - fi); 642 + 643 + /* Have HMM fault pages within the fault window to the GPU. */ 644 + range.vma = vma; 645 + range.start = args.i.p.addr; 646 + range.end = args.i.p.addr + args.i.p.size; 647 + range.pfns = args.phys; 648 + range.flags = nouveau_svm_pfn_flags; 649 + range.values = nouveau_svm_pfn_values; 650 + range.pfn_shift = NVIF_VMM_PFNMAP_V0_ADDR_SHIFT; 651 + again: 652 + ret = hmm_vma_fault(&range, true); 653 + if (ret == 0) { 654 + mutex_lock(&svmm->mutex); 655 + if (!hmm_vma_range_done(&range)) { 656 + mutex_unlock(&svmm->mutex); 657 + goto again; 658 + } 659 + 660 + nouveau_dmem_convert_pfn(svm->drm, &range); 661 + 662 + svmm->vmm->vmm.object.client->super = true; 663 + ret = nvif_object_ioctl(&svmm->vmm->vmm.object, 664 + &args, sizeof(args.i) + 665 + pi * sizeof(args.phys[0]), 666 + NULL); 667 + svmm->vmm->vmm.object.client->super = false; 668 + mutex_unlock(&svmm->mutex); 669 + } 670 + up_read(&svmm->mm->mmap_sem); 671 + 672 + /* Cancel any faults in the window whose pages didn't manage 673 + * to keep their valid bit, or stay writeable when required. 674 + * 675 + * If handling failed completely, cancel all faults. 676 + */ 677 + while (fi < fn) { 678 + struct nouveau_svm_fault *fault = buffer->fault[fi++]; 679 + pi = (fault->addr - range.start) >> PAGE_SHIFT; 680 + if (ret || 681 + !(range.pfns[pi] & NVIF_VMM_PFNMAP_V0_V) || 682 + (!(range.pfns[pi] & NVIF_VMM_PFNMAP_V0_W) && 683 + fault->access != 0 && fault->access != 3)) { 684 + nouveau_svm_fault_cancel_fault(svm, fault); 685 + continue; 686 + } 687 + replay++; 688 + } 689 + } 690 + 691 + /* Issue fault replay to the GPU. */ 692 + if (replay) 693 + nouveau_svm_fault_replay(svm); 694 + return NVIF_NOTIFY_KEEP; 695 + } 696 + 697 + static void 698 + nouveau_svm_fault_buffer_fini(struct nouveau_svm *svm, int id) 699 + { 700 + struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id]; 701 + nvif_notify_put(&buffer->notify); 702 + } 703 + 704 + static int 705 + nouveau_svm_fault_buffer_init(struct nouveau_svm *svm, int id) 706 + { 707 + struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id]; 708 + struct nvif_object *device = &svm->drm->client.device.object; 709 + buffer->get = nvif_rd32(device, buffer->getaddr); 710 + buffer->put = nvif_rd32(device, buffer->putaddr); 711 + SVM_DBG(svm, "get %08x put %08x (init)", buffer->get, buffer->put); 712 + return nvif_notify_get(&buffer->notify); 713 + } 714 + 715 + static void 716 + nouveau_svm_fault_buffer_dtor(struct nouveau_svm *svm, int id) 717 + { 718 + struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id]; 719 + int i; 720 + 721 + if (buffer->fault) { 722 + for (i = 0; buffer->fault[i] && i < buffer->entries; i++) 723 + kfree(buffer->fault[i]); 724 + kvfree(buffer->fault); 725 + } 726 + 727 + nouveau_svm_fault_buffer_fini(svm, id); 728 + 729 + nvif_notify_fini(&buffer->notify); 730 + nvif_object_fini(&buffer->object); 731 + } 732 + 733 + static int 734 + nouveau_svm_fault_buffer_ctor(struct nouveau_svm *svm, s32 oclass, int id) 735 + { 736 + struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id]; 737 + struct nouveau_drm *drm = svm->drm; 738 + struct nvif_object *device = &drm->client.device.object; 739 + struct nvif_clb069_v0 args = {}; 740 + int ret; 741 + 742 + buffer->id = id; 743 + 744 + ret = nvif_object_init(device, 0, oclass, &args, sizeof(args), 745 + &buffer->object); 746 + if (ret < 0) { 747 + SVM_ERR(svm, "Fault buffer allocation failed: %d", ret); 748 + return ret; 749 + } 750 + 751 + nvif_object_map(&buffer->object, NULL, 0); 752 + buffer->entries = args.entries; 753 + buffer->getaddr = args.get; 754 + buffer->putaddr = args.put; 755 + 756 + ret = nvif_notify_init(&buffer->object, nouveau_svm_fault, true, 757 + NVB069_V0_NTFY_FAULT, NULL, 0, 0, 758 + &buffer->notify); 759 + if (ret) 760 + return ret; 761 + 762 + buffer->fault = kvzalloc(sizeof(*buffer->fault) * buffer->entries, GFP_KERNEL); 763 + if (!buffer->fault) 764 + return -ENOMEM; 765 + 766 + return nouveau_svm_fault_buffer_init(svm, id); 767 + } 768 + 769 + void 770 + nouveau_svm_resume(struct nouveau_drm *drm) 771 + { 772 + struct nouveau_svm *svm = drm->svm; 773 + if (svm) 774 + nouveau_svm_fault_buffer_init(svm, 0); 775 + } 776 + 777 + void 778 + nouveau_svm_suspend(struct nouveau_drm *drm) 779 + { 780 + struct nouveau_svm *svm = drm->svm; 781 + if (svm) 782 + nouveau_svm_fault_buffer_fini(svm, 0); 783 + } 784 + 785 + void 786 + nouveau_svm_fini(struct nouveau_drm *drm) 787 + { 788 + struct nouveau_svm *svm = drm->svm; 789 + if (svm) { 790 + nouveau_svm_fault_buffer_dtor(svm, 0); 791 + kfree(drm->svm); 792 + drm->svm = NULL; 793 + } 794 + } 795 + 796 + void 797 + nouveau_svm_init(struct nouveau_drm *drm) 798 + { 799 + static const struct nvif_mclass buffers[] = { 800 + { VOLTA_FAULT_BUFFER_A, 0 }, 801 + { MAXWELL_FAULT_BUFFER_A, 0 }, 802 + {} 803 + }; 804 + struct nouveau_svm *svm; 805 + int ret; 806 + 807 + /* Disable on Volta and newer until channel recovery is fixed, 808 + * otherwise clients will have a trivial way to trash the GPU 809 + * for everyone. 810 + */ 811 + if (drm->client.device.info.family > NV_DEVICE_INFO_V0_PASCAL) 812 + return; 813 + 814 + if (!(drm->svm = svm = kzalloc(sizeof(*drm->svm), GFP_KERNEL))) 815 + return; 816 + 817 + drm->svm->drm = drm; 818 + mutex_init(&drm->svm->mutex); 819 + INIT_LIST_HEAD(&drm->svm->inst); 820 + 821 + ret = nvif_mclass(&drm->client.device.object, buffers); 822 + if (ret < 0) { 823 + SVM_DBG(svm, "No supported fault buffer class"); 824 + nouveau_svm_fini(drm); 825 + return; 826 + } 827 + 828 + ret = nouveau_svm_fault_buffer_ctor(svm, buffers[ret].oclass, 0); 829 + if (ret) { 830 + nouveau_svm_fini(drm); 831 + return; 832 + } 833 + 834 + SVM_DBG(svm, "Initialised"); 835 + }
+48
drivers/gpu/drm/nouveau/nouveau_svm.h
··· 1 + #ifndef __NOUVEAU_SVM_H__ 2 + #define __NOUVEAU_SVM_H__ 3 + #include <nvif/os.h> 4 + struct drm_device; 5 + struct drm_file; 6 + struct nouveau_drm; 7 + 8 + struct nouveau_svmm; 9 + 10 + #if IS_ENABLED(CONFIG_DRM_NOUVEAU_SVM) 11 + void nouveau_svm_init(struct nouveau_drm *); 12 + void nouveau_svm_fini(struct nouveau_drm *); 13 + void nouveau_svm_suspend(struct nouveau_drm *); 14 + void nouveau_svm_resume(struct nouveau_drm *); 15 + 16 + int nouveau_svmm_init(struct drm_device *, void *, struct drm_file *); 17 + void nouveau_svmm_fini(struct nouveau_svmm **); 18 + int nouveau_svmm_join(struct nouveau_svmm *, u64 inst); 19 + void nouveau_svmm_part(struct nouveau_svmm *, u64 inst); 20 + int nouveau_svmm_bind(struct drm_device *, void *, struct drm_file *); 21 + #else /* IS_ENABLED(CONFIG_DRM_NOUVEAU_SVM) */ 22 + static inline void nouveau_svm_init(struct nouveau_drm *drm) {} 23 + static inline void nouveau_svm_fini(struct nouveau_drm *drm) {} 24 + static inline void nouveau_svm_suspend(struct nouveau_drm *drm) {} 25 + static inline void nouveau_svm_resume(struct nouveau_drm *drm) {} 26 + 27 + static inline int nouveau_svmm_init(struct drm_device *device, void *p, 28 + struct drm_file *file) 29 + { 30 + return -ENOSYS; 31 + } 32 + 33 + static inline void nouveau_svmm_fini(struct nouveau_svmm **svmmp) {} 34 + 35 + static inline int nouveau_svmm_join(struct nouveau_svmm *svmm, u64 inst) 36 + { 37 + return 0; 38 + } 39 + 40 + static inline void nouveau_svmm_part(struct nouveau_svmm *svmm, u64 inst) {} 41 + 42 + static inline int nouveau_svmm_bind(struct drm_device *device, void *p, 43 + struct drm_file *file) 44 + { 45 + return -ENOSYS; 46 + } 47 + #endif /* IS_ENABLED(CONFIG_DRM_NOUVEAU_SVM) */ 48 + #endif
+3 -1
drivers/gpu/drm/nouveau/nouveau_vmm.c
··· 22 22 #include "nouveau_vmm.h" 23 23 #include "nouveau_drv.h" 24 24 #include "nouveau_bo.h" 25 + #include "nouveau_svm.h" 25 26 #include "nouveau_mem.h" 26 27 27 28 void ··· 120 119 void 121 120 nouveau_vmm_fini(struct nouveau_vmm *vmm) 122 121 { 122 + nouveau_svmm_fini(&vmm->svmm); 123 123 nvif_vmm_fini(&vmm->vmm); 124 124 vmm->cli = NULL; 125 125 } ··· 128 126 int 129 127 nouveau_vmm_init(struct nouveau_cli *cli, s32 oclass, struct nouveau_vmm *vmm) 130 128 { 131 - int ret = nvif_vmm_init(&cli->mmu, oclass, PAGE_SIZE, 0, NULL, 0, 129 + int ret = nvif_vmm_init(&cli->mmu, oclass, false, PAGE_SIZE, 0, NULL, 0, 132 130 &vmm->vmm); 133 131 if (ret) 134 132 return ret;
+1
drivers/gpu/drm/nouveau/nouveau_vmm.h
··· 25 25 struct nouveau_vmm { 26 26 struct nouveau_cli *cli; 27 27 struct nvif_vmm vmm; 28 + struct nouveau_svmm *svmm; 28 29 }; 29 30 30 31 int nouveau_vmm_init(struct nouveau_cli *, s32 oclass, struct nouveau_vmm *);
+1 -2
drivers/gpu/drm/nouveau/nv84_fence.c
··· 109 109 int 110 110 nv84_fence_context_new(struct nouveau_channel *chan) 111 111 { 112 - struct nouveau_cli *cli = (void *)chan->user.client; 113 112 struct nv84_fence_priv *priv = chan->drm->fence; 114 113 struct nv84_fence_chan *fctx; 115 114 int ret; ··· 126 127 fctx->base.sequence = nv84_fence_read(chan); 127 128 128 129 mutex_lock(&priv->mutex); 129 - ret = nouveau_vma_new(priv->bo, &cli->vmm, &fctx->vma); 130 + ret = nouveau_vma_new(priv->bo, chan->vmm, &fctx->vma); 130 131 mutex_unlock(&priv->mutex); 131 132 132 133 if (ret)
+1 -1
drivers/gpu/drm/nouveau/nvif/disp.c
··· 34 34 nvif_disp_ctor(struct nvif_device *device, s32 oclass, struct nvif_disp *disp) 35 35 { 36 36 static const struct nvif_mclass disps[] = { 37 - { TU104_DISP, -1 }, 37 + { TU102_DISP, -1 }, 38 38 { GV100_DISP, -1 }, 39 39 { GP102_DISP, -1 }, 40 40 { GP100_DISP, -1 },
+3 -2
drivers/gpu/drm/nouveau/nvif/vmm.c
··· 112 112 } 113 113 114 114 int 115 - nvif_vmm_init(struct nvif_mmu *mmu, s32 oclass, u64 addr, u64 size, 116 - void *argv, u32 argc, struct nvif_vmm *vmm) 115 + nvif_vmm_init(struct nvif_mmu *mmu, s32 oclass, bool managed, u64 addr, 116 + u64 size, void *argv, u32 argc, struct nvif_vmm *vmm) 117 117 { 118 118 struct nvif_vmm_v0 *args; 119 119 u32 argn = sizeof(*args) + argc; ··· 125 125 if (!(args = kmalloc(argn, GFP_KERNEL))) 126 126 return -ENOMEM; 127 127 args->version = 0; 128 + args->managed = managed; 128 129 args->addr = addr; 129 130 args->size = size; 130 131 memcpy(args->data, argv, argc);
+1
drivers/gpu/drm/nouveau/nvkm/core/subdev.c
··· 39 39 [NVKM_SUBDEV_FB ] = "fb", 40 40 [NVKM_SUBDEV_FUSE ] = "fuse", 41 41 [NVKM_SUBDEV_GPIO ] = "gpio", 42 + [NVKM_SUBDEV_GSP ] = "gsp", 42 43 [NVKM_SUBDEV_I2C ] = "i2c", 43 44 [NVKM_SUBDEV_IBUS ] = "priv", 44 45 [NVKM_SUBDEV_ICCSENSE] = "iccsense",
+1 -1
drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild
··· 6 6 nvkm-y += nvkm/engine/ce/gp100.o 7 7 nvkm-y += nvkm/engine/ce/gp102.o 8 8 nvkm-y += nvkm/engine/ce/gv100.o 9 - nvkm-y += nvkm/engine/ce/tu104.o 9 + nvkm-y += nvkm/engine/ce/tu102.o
+17 -12
drivers/gpu/drm/nouveau/nvkm/engine/ce/tu104.c drivers/gpu/drm/nouveau/nvkm/engine/fifo/usertu102.c
··· 19 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 20 * OTHER DEALINGS IN THE SOFTWARE. 21 21 */ 22 - #include "priv.h" 22 + #include "user.h" 23 23 24 - #include <nvif/class.h> 24 + static int 25 + tu102_fifo_user_map(struct nvkm_object *object, void *argv, u32 argc, 26 + enum nvkm_object_map *type, u64 *addr, u64 *size) 27 + { 28 + struct nvkm_device *device = object->engine->subdev.device; 29 + *addr = 0xbb0000 + device->func->resource_addr(device, 0); 30 + *size = 0x010000; 31 + *type = NVKM_OBJECT_MAP_IO; 32 + return 0; 33 + } 25 34 26 - static const struct nvkm_engine_func 27 - tu104_ce = { 28 - .intr = gp100_ce_intr, 29 - .sclass = { 30 - { -1, -1, TURING_DMA_COPY_A }, 31 - {} 32 - } 35 + static const struct nvkm_object_func 36 + tu102_fifo_user = { 37 + .map = tu102_fifo_user_map, 33 38 }; 34 39 35 40 int 36 - tu104_ce_new(struct nvkm_device *device, int index, 37 - struct nvkm_engine **pengine) 41 + tu102_fifo_user_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, 42 + struct nvkm_object **pobject) 38 43 { 39 - return nvkm_engine_new_(&tu104_ce, device, index, true, pengine); 44 + return nvkm_object_new_(&tu102_fifo_user, oclass, argv, argc, pobject); 40 45 }
+49 -37
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
··· 1613 1613 .pci = gf106_pci_new, 1614 1614 .therm = gf119_therm_new, 1615 1615 .timer = nv41_timer_new, 1616 - .volt = gf100_volt_new, 1616 + .volt = gf117_volt_new, 1617 1617 .ce[0] = gf100_ce_new, 1618 1618 .disp = gf119_disp_new, 1619 1619 .dma = gf119_dma_new, ··· 2405 2405 .fb = gv100_fb_new, 2406 2406 .fuse = gm107_fuse_new, 2407 2407 .gpio = gk104_gpio_new, 2408 + .gsp = gv100_gsp_new, 2408 2409 .i2c = gm200_i2c_new, 2409 2410 .ibus = gm200_ibus_new, 2410 2411 .imem = nv50_instmem_new, ··· 2438 2437 static const struct nvkm_device_chip 2439 2438 nv162_chipset = { 2440 2439 .name = "TU102", 2441 - .bar = tu104_bar_new, 2440 + .bar = tu102_bar_new, 2442 2441 .bios = nvkm_bios_new, 2443 2442 .bus = gf100_bus_new, 2444 - .devinit = tu104_devinit_new, 2445 - .fault = tu104_fault_new, 2443 + .devinit = tu102_devinit_new, 2444 + .fault = tu102_fault_new, 2446 2445 .fb = gv100_fb_new, 2447 2446 .fuse = gm107_fuse_new, 2448 2447 .gpio = gk104_gpio_new, 2448 + .gsp = gv100_gsp_new, 2449 2449 .i2c = gm200_i2c_new, 2450 2450 .ibus = gm200_ibus_new, 2451 2451 .imem = nv50_instmem_new, 2452 2452 .ltc = gp102_ltc_new, 2453 - .mc = tu104_mc_new, 2454 - .mmu = tu104_mmu_new, 2453 + .mc = tu102_mc_new, 2454 + .mmu = tu102_mmu_new, 2455 2455 .pci = gp100_pci_new, 2456 2456 .pmu = gp102_pmu_new, 2457 2457 .therm = gp100_therm_new, 2458 2458 .timer = gk20a_timer_new, 2459 2459 .top = gk104_top_new, 2460 - .ce[0] = tu104_ce_new, 2461 - .ce[1] = tu104_ce_new, 2462 - .ce[2] = tu104_ce_new, 2463 - .ce[3] = tu104_ce_new, 2464 - .ce[4] = tu104_ce_new, 2465 - .disp = tu104_disp_new, 2460 + .ce[0] = tu102_ce_new, 2461 + .ce[1] = tu102_ce_new, 2462 + .ce[2] = tu102_ce_new, 2463 + .ce[3] = tu102_ce_new, 2464 + .ce[4] = tu102_ce_new, 2465 + .disp = tu102_disp_new, 2466 2466 .dma = gv100_dma_new, 2467 - .fifo = tu104_fifo_new, 2467 + .fifo = tu102_fifo_new, 2468 + .nvdec[0] = gp102_nvdec_new, 2469 + .sec2 = tu102_sec2_new, 2468 2470 }; 2469 2471 2470 2472 static const struct nvkm_device_chip 2471 2473 nv164_chipset = { 2472 2474 .name = "TU104", 2473 - .bar = tu104_bar_new, 2475 + .bar = tu102_bar_new, 2474 2476 .bios = nvkm_bios_new, 2475 2477 .bus = gf100_bus_new, 2476 - .devinit = tu104_devinit_new, 2477 - .fault = tu104_fault_new, 2478 + .devinit = tu102_devinit_new, 2479 + .fault = tu102_fault_new, 2478 2480 .fb = gv100_fb_new, 2479 2481 .fuse = gm107_fuse_new, 2480 2482 .gpio = gk104_gpio_new, 2483 + .gsp = gv100_gsp_new, 2481 2484 .i2c = gm200_i2c_new, 2482 2485 .ibus = gm200_ibus_new, 2483 2486 .imem = nv50_instmem_new, 2484 2487 .ltc = gp102_ltc_new, 2485 - .mc = tu104_mc_new, 2486 - .mmu = tu104_mmu_new, 2488 + .mc = tu102_mc_new, 2489 + .mmu = tu102_mmu_new, 2487 2490 .pci = gp100_pci_new, 2488 2491 .pmu = gp102_pmu_new, 2489 2492 .therm = gp100_therm_new, 2490 2493 .timer = gk20a_timer_new, 2491 2494 .top = gk104_top_new, 2492 - .ce[0] = tu104_ce_new, 2493 - .ce[1] = tu104_ce_new, 2494 - .ce[2] = tu104_ce_new, 2495 - .ce[3] = tu104_ce_new, 2496 - .ce[4] = tu104_ce_new, 2497 - .disp = tu104_disp_new, 2495 + .ce[0] = tu102_ce_new, 2496 + .ce[1] = tu102_ce_new, 2497 + .ce[2] = tu102_ce_new, 2498 + .ce[3] = tu102_ce_new, 2499 + .ce[4] = tu102_ce_new, 2500 + .disp = tu102_disp_new, 2498 2501 .dma = gv100_dma_new, 2499 - .fifo = tu104_fifo_new, 2502 + .fifo = tu102_fifo_new, 2503 + .nvdec[0] = gp102_nvdec_new, 2504 + .sec2 = tu102_sec2_new, 2500 2505 }; 2501 2506 2502 2507 static const struct nvkm_device_chip 2503 2508 nv166_chipset = { 2504 2509 .name = "TU106", 2505 - .bar = tu104_bar_new, 2510 + .bar = tu102_bar_new, 2506 2511 .bios = nvkm_bios_new, 2507 2512 .bus = gf100_bus_new, 2508 - .devinit = tu104_devinit_new, 2509 - .fault = tu104_fault_new, 2513 + .devinit = tu102_devinit_new, 2514 + .fault = tu102_fault_new, 2510 2515 .fb = gv100_fb_new, 2511 2516 .fuse = gm107_fuse_new, 2512 2517 .gpio = gk104_gpio_new, 2518 + .gsp = gv100_gsp_new, 2513 2519 .i2c = gm200_i2c_new, 2514 2520 .ibus = gm200_ibus_new, 2515 2521 .imem = nv50_instmem_new, 2516 2522 .ltc = gp102_ltc_new, 2517 - .mc = tu104_mc_new, 2518 - .mmu = tu104_mmu_new, 2523 + .mc = tu102_mc_new, 2524 + .mmu = tu102_mmu_new, 2519 2525 .pci = gp100_pci_new, 2520 2526 .pmu = gp102_pmu_new, 2521 2527 .therm = gp100_therm_new, 2522 2528 .timer = gk20a_timer_new, 2523 2529 .top = gk104_top_new, 2524 - .ce[0] = tu104_ce_new, 2525 - .ce[1] = tu104_ce_new, 2526 - .ce[2] = tu104_ce_new, 2527 - .ce[3] = tu104_ce_new, 2528 - .ce[4] = tu104_ce_new, 2529 - .disp = tu104_disp_new, 2530 + .ce[0] = tu102_ce_new, 2531 + .ce[1] = tu102_ce_new, 2532 + .ce[2] = tu102_ce_new, 2533 + .ce[3] = tu102_ce_new, 2534 + .ce[4] = tu102_ce_new, 2535 + .disp = tu102_disp_new, 2530 2536 .dma = gv100_dma_new, 2531 - .fifo = tu104_fifo_new, 2537 + .fifo = tu102_fifo_new, 2538 + .nvdec[0] = gp102_nvdec_new, 2539 + .sec2 = tu102_sec2_new, 2532 2540 }; 2533 2541 2534 2542 static int ··· 2577 2567 _(FB , device->fb , &device->fb->subdev); 2578 2568 _(FUSE , device->fuse , &device->fuse->subdev); 2579 2569 _(GPIO , device->gpio , &device->gpio->subdev); 2570 + _(GSP , device->gsp , &device->gsp->subdev); 2580 2571 _(I2C , device->i2c , &device->i2c->subdev); 2581 2572 _(IBUS , device->ibus , device->ibus); 2582 2573 _(ICCSENSE, device->iccsense, &device->iccsense->subdev); ··· 3061 3050 _(NVKM_SUBDEV_FB , fb); 3062 3051 _(NVKM_SUBDEV_FUSE , fuse); 3063 3052 _(NVKM_SUBDEV_GPIO , gpio); 3053 + _(NVKM_SUBDEV_GSP , gsp); 3064 3054 _(NVKM_SUBDEV_I2C , i2c); 3065 3055 _(NVKM_SUBDEV_IBUS , ibus); 3066 3056 _(NVKM_SUBDEV_ICCSENSE, iccsense);
+1
drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h
··· 12 12 #include <subdev/fb.h> 13 13 #include <subdev/fuse.h> 14 14 #include <subdev/gpio.h> 15 + #include <subdev/gsp.h> 15 16 #include <subdev/i2c.h> 16 17 #include <subdev/ibus.h> 17 18 #include <subdev/iccsense.h>
+7 -8
drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
··· 365 365 } 366 366 367 367 if (!sclass) { 368 - switch (index) { 369 - case 0: sclass = &nvkm_control_oclass; break; 370 - case 1: 371 - if (!device->mmu) 372 - return -EINVAL; 368 + if (index-- == 0) 369 + sclass = &nvkm_control_oclass; 370 + else if (device->mmu && index-- == 0) 373 371 sclass = &device->mmu->user; 374 - break; 375 - default: 372 + else if (device->fault && index-- == 0) 373 + sclass = &device->fault->user; 374 + else 376 375 return -EINVAL; 377 - } 376 + 378 377 oclass->base = sclass->base; 379 378 } 380 379
+3 -3
drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
··· 15 15 nvkm-y += nvkm/engine/disp/gp100.o 16 16 nvkm-y += nvkm/engine/disp/gp102.o 17 17 nvkm-y += nvkm/engine/disp/gv100.o 18 - nvkm-y += nvkm/engine/disp/tu104.o 18 + nvkm-y += nvkm/engine/disp/tu102.o 19 19 nvkm-y += nvkm/engine/disp/vga.o 20 20 21 21 nvkm-y += nvkm/engine/disp/head.o ··· 39 39 nvkm-y += nvkm/engine/disp/sorgm107.o 40 40 nvkm-y += nvkm/engine/disp/sorgm200.o 41 41 nvkm-y += nvkm/engine/disp/sorgv100.o 42 - nvkm-y += nvkm/engine/disp/sortu104.o 42 + nvkm-y += nvkm/engine/disp/sortu102.o 43 43 44 44 nvkm-y += nvkm/engine/disp/outp.o 45 45 nvkm-y += nvkm/engine/disp/dp.o ··· 71 71 nvkm-y += nvkm/engine/disp/rootgp100.o 72 72 nvkm-y += nvkm/engine/disp/rootgp102.o 73 73 nvkm-y += nvkm/engine/disp/rootgv100.o 74 - nvkm-y += nvkm/engine/disp/roottu104.o 74 + nvkm-y += nvkm/engine/disp/roottu102.o 75 75 76 76 nvkm-y += nvkm/engine/disp/channv50.o 77 77 nvkm-y += nvkm/engine/disp/changf119.o
+11 -5
drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
··· 91 91 { 92 92 struct nvkm_subdev *subdev = &disp->base.engine.subdev; 93 93 struct nvkm_device *device = subdev->device; 94 - u32 mthd = nvkm_rd32(device, 0x6101f0 + (chid * 12)); 94 + u32 stat = nvkm_rd32(device, 0x6101f0 + (chid * 12)); 95 + u32 type = (stat & 0x00007000) >> 12; 96 + u32 mthd = (stat & 0x00000ffc); 95 97 u32 data = nvkm_rd32(device, 0x6101f4 + (chid * 12)); 96 - u32 unkn = nvkm_rd32(device, 0x6101f8 + (chid * 12)); 98 + u32 code = nvkm_rd32(device, 0x6101f8 + (chid * 12)); 99 + const struct nvkm_enum *reason = 100 + nvkm_enum_find(nv50_disp_intr_error_type, type); 97 101 98 - nvkm_error(subdev, "chid %d mthd %04x data %08x %08x %08x\n", 99 - chid, (mthd & 0x0000ffc), data, mthd, unkn); 102 + nvkm_error(subdev, "chid %d stat %08x reason %d [%s] mthd %04x " 103 + "data %08x code %08x\n", 104 + chid, stat, type, reason ? reason->name : "", 105 + mthd, data, code); 100 106 101 107 if (chid < ARRAY_SIZE(disp->chan)) { 102 - switch (mthd & 0xffc) { 108 + switch (mthd) { 103 109 case 0x0080: 104 110 nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR); 105 111 break;
+5 -2
drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
··· 103 103 u32 mthd = (stat & 0x00000fff) << 2; 104 104 u32 data = nvkm_rd32(device, 0x611024 + (chid * 12)); 105 105 u32 code = nvkm_rd32(device, 0x611028 + (chid * 12)); 106 + const struct nvkm_enum *reason = 107 + nvkm_enum_find(nv50_disp_intr_error_type, type); 106 108 107 - nvkm_error(subdev, "chid %d %08x [type %d mthd %04x] " 109 + nvkm_error(subdev, "chid %d stat %08x reason %d [%s] mthd %04x " 108 110 "data %08x code %08x\n", 109 - chid, stat, type, mthd, data, code); 111 + chid, stat, type, reason ? reason->name : "", 112 + mthd, data, code); 110 113 111 114 if (chid < ARRAY_SIZE(disp->chan) && disp->chan[chid]) { 112 115 switch (mthd) {
+1 -1
drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
··· 201 201 int gv100_sor_cnt(struct nvkm_disp *, unsigned long *); 202 202 int gv100_sor_new(struct nvkm_disp *, int); 203 203 204 - int tu104_sor_new(struct nvkm_disp *, int); 204 + int tu102_sor_new(struct nvkm_disp *, int); 205 205 #endif
+7 -5
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
··· 28 28 #include "rootnv50.h" 29 29 30 30 #include <core/client.h> 31 - #include <core/enum.h> 32 31 #include <core/ramht.h> 33 32 #include <subdev/bios.h> 34 33 #include <subdev/bios/disp.h> ··· 592 593 nvkm_wr32(device, 0x610030, 0x80000000); 593 594 } 594 595 595 - static const struct nvkm_enum 596 + const struct nvkm_enum 596 597 nv50_disp_intr_error_type[] = { 597 - { 3, "ILLEGAL_MTHD" }, 598 - { 4, "INVALID_VALUE" }, 598 + { 0, "NONE" }, 599 + { 1, "PUSHBUFFER_ERR" }, 600 + { 2, "TRAP" }, 601 + { 3, "RESERVED_METHOD" }, 602 + { 4, "INVALID_ARG" }, 599 603 { 5, "INVALID_STATE" }, 600 - { 7, "INVALID_HANDLE" }, 604 + { 7, "UNRESOLVABLE_HANDLE" }, 601 605 {} 602 606 }; 603 607
+3
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
··· 5 5 #include "priv.h" 6 6 struct nvkm_head; 7 7 8 + #include <core/enum.h> 9 + 8 10 struct nv50_disp { 9 11 const struct nv50_disp_func *func; 10 12 struct nvkm_disp base; ··· 73 71 void nv50_disp_fini(struct nv50_disp *); 74 72 void nv50_disp_intr(struct nv50_disp *); 75 73 void nv50_disp_super(struct work_struct *); 74 + extern const struct nvkm_enum nv50_disp_intr_error_type[]; 76 75 77 76 int gf119_disp_init(struct nv50_disp *); 78 77 void gf119_disp_fini(struct nv50_disp *);
+1 -1
drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h
··· 37 37 extern const struct nvkm_disp_oclass gp100_disp_root_oclass; 38 38 extern const struct nvkm_disp_oclass gp102_disp_root_oclass; 39 39 extern const struct nvkm_disp_oclass gv100_disp_root_oclass; 40 - extern const struct nvkm_disp_oclass tu104_disp_root_oclass; 40 + extern const struct nvkm_disp_oclass tu102_disp_root_oclass; 41 41 #endif
+11 -23
drivers/gpu/drm/nouveau/nvkm/engine/disp/roottu104.c drivers/gpu/drm/nouveau/nvkm/engine/ce/tu102.c
··· 19 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 20 * OTHER DEALINGS IN THE SOFTWARE. 21 21 */ 22 - #include "rootnv50.h" 23 - #include "channv50.h" 22 + #include "priv.h" 24 23 25 24 #include <nvif/class.h> 26 25 27 - static const struct nv50_disp_root_func 28 - tu104_disp_root = { 29 - .user = { 30 - {{0,0,TU104_DISP_CURSOR }, gv100_disp_curs_new }, 31 - {{0,0,TU104_DISP_WINDOW_IMM_CHANNEL_DMA}, gv100_disp_wimm_new }, 32 - {{0,0,TU104_DISP_CORE_CHANNEL_DMA }, gv100_disp_core_new }, 33 - {{0,0,TU104_DISP_WINDOW_CHANNEL_DMA }, gv100_disp_wndw_new }, 26 + static const struct nvkm_engine_func 27 + tu102_ce = { 28 + .intr = gp100_ce_intr, 29 + .sclass = { 30 + { -1, -1, TURING_DMA_COPY_A }, 34 31 {} 35 - }, 32 + } 36 33 }; 37 34 38 - static int 39 - tu104_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, 40 - void *data, u32 size, struct nvkm_object **pobject) 35 + int 36 + tu102_ce_new(struct nvkm_device *device, int index, 37 + struct nvkm_engine **pengine) 41 38 { 42 - return nv50_disp_root_new_(&tu104_disp_root, disp, oclass, 43 - data, size, pobject); 39 + return nvkm_engine_new_(&tu102_ce, device, index, true, pengine); 44 40 } 45 - 46 - const struct nvkm_disp_oclass 47 - tu104_disp_root_oclass = { 48 - .base.oclass = TU104_DISP, 49 - .base.minver = -1, 50 - .base.maxver = -1, 51 - .ctor = tu104_disp_root_new, 52 - };
+7 -7
drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu104.c drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu102.c
··· 24 24 #include <subdev/timer.h> 25 25 26 26 static void 27 - tu104_sor_dp_vcpi(struct nvkm_ior *sor, int head, 27 + tu102_sor_dp_vcpi(struct nvkm_ior *sor, int head, 28 28 u8 slot, u8 slot_nr, u16 pbn, u16 aligned) 29 29 { 30 30 struct nvkm_device *device = sor->disp->engine.subdev.device; ··· 35 35 } 36 36 37 37 static int 38 - tu104_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) 38 + tu102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) 39 39 { 40 40 struct nvkm_device *device = sor->disp->engine.subdev.device; 41 41 const u32 soff = nv50_ior_base(sor); ··· 62 62 } 63 63 64 64 static const struct nvkm_ior_func 65 - tu104_sor = { 65 + tu102_sor = { 66 66 .route = { 67 67 .get = gm200_sor_route_get, 68 68 .set = gm200_sor_route_set, ··· 75 75 }, 76 76 .dp = { 77 77 .lanes = { 0, 1, 2, 3 }, 78 - .links = tu104_sor_dp_links, 78 + .links = tu102_sor_dp_links, 79 79 .power = g94_sor_dp_power, 80 80 .pattern = gm107_sor_dp_pattern, 81 81 .drive = gm200_sor_dp_drive, 82 - .vcpi = tu104_sor_dp_vcpi, 82 + .vcpi = tu102_sor_dp_vcpi, 83 83 .audio = gv100_sor_dp_audio, 84 84 .audio_sym = gv100_sor_dp_audio_sym, 85 85 .watermark = gv100_sor_dp_watermark, ··· 91 91 }; 92 92 93 93 int 94 - tu104_sor_new(struct nvkm_disp *disp, int id) 94 + tu102_sor_new(struct nvkm_disp *disp, int id) 95 95 { 96 - return nvkm_ior_new_(&tu104_sor, disp, SOR, id); 96 + return nvkm_ior_new_(&tu102_sor, disp, SOR, id); 97 97 }
+7 -7
drivers/gpu/drm/nouveau/nvkm/engine/disp/tu104.c drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c
··· 29 29 #include <subdev/timer.h> 30 30 31 31 static int 32 - tu104_disp_init(struct nv50_disp *disp) 32 + tu102_disp_init(struct nv50_disp *disp) 33 33 { 34 34 struct nvkm_device *device = disp->base.engine.subdev.device; 35 35 struct nvkm_head *head; ··· 132 132 } 133 133 134 134 static const struct nv50_disp_func 135 - tu104_disp = { 136 - .init = tu104_disp_init, 135 + tu102_disp = { 136 + .init = tu102_disp_init, 137 137 .fini = gv100_disp_fini, 138 138 .intr = gv100_disp_intr, 139 139 .uevent = &gv100_disp_chan_uevent, 140 140 .super = gv100_disp_super, 141 - .root = &tu104_disp_root_oclass, 141 + .root = &tu102_disp_root_oclass, 142 142 .wndw = { .cnt = gv100_disp_wndw_cnt }, 143 143 .head = { .cnt = gv100_head_cnt, .new = gv100_head_new }, 144 - .sor = { .cnt = gv100_sor_cnt, .new = tu104_sor_new }, 144 + .sor = { .cnt = gv100_sor_cnt, .new = tu102_sor_new }, 145 145 .ramht_size = 0x2000, 146 146 }; 147 147 148 148 int 149 - tu104_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) 149 + tu102_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp) 150 150 { 151 - return nv50_disp_new_(&tu104_disp, device, index, pdisp); 151 + return nv50_disp_new_(&tu102_disp, device, index, pdisp); 152 152 }
+3 -3
drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild
··· 16 16 nvkm-y += nvkm/engine/fifo/gp100.o 17 17 nvkm-y += nvkm/engine/fifo/gp10b.o 18 18 nvkm-y += nvkm/engine/fifo/gv100.o 19 - nvkm-y += nvkm/engine/fifo/tu104.o 19 + nvkm-y += nvkm/engine/fifo/tu102.o 20 20 21 21 nvkm-y += nvkm/engine/fifo/chan.o 22 22 nvkm-y += nvkm/engine/fifo/channv50.o ··· 34 34 nvkm-y += nvkm/engine/fifo/gpfifogf100.o 35 35 nvkm-y += nvkm/engine/fifo/gpfifogk104.o 36 36 nvkm-y += nvkm/engine/fifo/gpfifogv100.o 37 - nvkm-y += nvkm/engine/fifo/gpfifotu104.o 37 + nvkm-y += nvkm/engine/fifo/gpfifotu102.o 38 38 39 39 nvkm-y += nvkm/engine/fifo/usergv100.o 40 - nvkm-y += nvkm/engine/fifo/usertu104.o 40 + nvkm-y += nvkm/engine/fifo/usertu102.o
+1 -1
drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
··· 47 47 int gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *, 48 48 struct nvkm_engine *, bool); 49 49 50 - int tu104_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *, 50 + int tu102_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *, 51 51 void *data, u32 size, struct nvkm_object **); 52 52 #endif
+5 -5
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu104.c drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c
··· 29 29 #include <nvif/unpack.h> 30 30 31 31 static u32 32 - tu104_fifo_gpfifo_submit_token(struct nvkm_fifo_chan *base) 32 + tu102_fifo_gpfifo_submit_token(struct nvkm_fifo_chan *base) 33 33 { 34 34 struct gk104_fifo_chan *chan = gk104_fifo_chan(base); 35 35 return (chan->runl << 16) | chan->base.chid; 36 36 } 37 37 38 38 static const struct nvkm_fifo_chan_func 39 - tu104_fifo_gpfifo = { 39 + tu102_fifo_gpfifo = { 40 40 .dtor = gk104_fifo_gpfifo_dtor, 41 41 .init = gk104_fifo_gpfifo_init, 42 42 .fini = gk104_fifo_gpfifo_fini, ··· 45 45 .engine_dtor = gk104_fifo_gpfifo_engine_dtor, 46 46 .engine_init = gv100_fifo_gpfifo_engine_init, 47 47 .engine_fini = gv100_fifo_gpfifo_engine_fini, 48 - .submit_token = tu104_fifo_gpfifo_submit_token, 48 + .submit_token = tu102_fifo_gpfifo_submit_token, 49 49 }; 50 50 51 51 int 52 - tu104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass, 52 + tu102_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass, 53 53 void *data, u32 size, struct nvkm_object **pobject) 54 54 { 55 55 struct nvkm_object *parent = oclass->parent; ··· 67 67 args->v0.ilength, args->v0.runlist, args->v0.priv); 68 68 if (args->v0.priv && !oclass->client->super) 69 69 return -EINVAL; 70 - return gv100_fifo_gpfifo_new_(&tu104_fifo_gpfifo, fifo, 70 + return gv100_fifo_gpfifo_new_(&tu102_fifo_gpfifo, fifo, 71 71 &args->v0.runlist, 72 72 &args->v0.chid, 73 73 args->v0.vmm,
+15 -15
drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu104.c drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c
··· 29 29 #include <nvif/class.h> 30 30 31 31 static void 32 - tu104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl, 32 + tu102_fifo_runlist_commit(struct gk104_fifo *fifo, int runl, 33 33 struct nvkm_memory *mem, int nr) 34 34 { 35 35 struct nvkm_device *device = fifo->base.engine.subdev.device; ··· 44 44 } 45 45 46 46 const struct gk104_fifo_runlist_func 47 - tu104_fifo_runlist = { 47 + tu102_fifo_runlist = { 48 48 .size = 16, 49 49 .cgrp = gv100_fifo_runlist_cgrp, 50 50 .chan = gv100_fifo_runlist_chan, 51 - .commit = tu104_fifo_runlist_commit, 51 + .commit = tu102_fifo_runlist_commit, 52 52 }; 53 53 54 54 static const struct nvkm_enum 55 - tu104_fifo_fault_engine[] = { 55 + tu102_fifo_fault_engine[] = { 56 56 { 0x01, "DISPLAY" }, 57 57 { 0x03, "PTP" }, 58 58 { 0x06, "PWR_PMU" }, ··· 80 80 }; 81 81 82 82 static void 83 - tu104_fifo_pbdma_init(struct gk104_fifo *fifo) 83 + tu102_fifo_pbdma_init(struct gk104_fifo *fifo) 84 84 { 85 85 struct nvkm_device *device = fifo->base.engine.subdev.device; 86 86 const u32 mask = (1 << fifo->pbdma_nr) - 1; ··· 89 89 } 90 90 91 91 static const struct gk104_fifo_pbdma_func 92 - tu104_fifo_pbdma = { 92 + tu102_fifo_pbdma = { 93 93 .nr = gm200_fifo_pbdma_nr, 94 - .init = tu104_fifo_pbdma_init, 94 + .init = tu102_fifo_pbdma_init, 95 95 .init_timeout = gk208_fifo_pbdma_init_timeout, 96 96 }; 97 97 98 98 static const struct gk104_fifo_func 99 - tu104_fifo = { 100 - .pbdma = &tu104_fifo_pbdma, 99 + tu102_fifo = { 100 + .pbdma = &tu102_fifo_pbdma, 101 101 .fault.access = gv100_fifo_fault_access, 102 - .fault.engine = tu104_fifo_fault_engine, 102 + .fault.engine = tu102_fifo_fault_engine, 103 103 .fault.reason = gv100_fifo_fault_reason, 104 104 .fault.hubclient = gv100_fifo_fault_hubclient, 105 105 .fault.gpcclient = gv100_fifo_fault_gpcclient, 106 - .runlist = &tu104_fifo_runlist, 107 - .user = {{-1,-1,VOLTA_USERMODE_A }, tu104_fifo_user_new }, 108 - .chan = {{ 0, 0,TURING_CHANNEL_GPFIFO_A}, tu104_fifo_gpfifo_new }, 106 + .runlist = &tu102_fifo_runlist, 107 + .user = {{-1,-1,VOLTA_USERMODE_A }, tu102_fifo_user_new }, 108 + .chan = {{ 0, 0,TURING_CHANNEL_GPFIFO_A}, tu102_fifo_gpfifo_new }, 109 109 .cgrp_force = true, 110 110 }; 111 111 112 112 int 113 - tu104_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) 113 + tu102_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo) 114 114 { 115 - return gk104_fifo_new_(&tu104_fifo, device, index, 4096, pfifo); 115 + return gk104_fifo_new_(&tu102_fifo, device, index, 4096, pfifo); 116 116 }
+1 -1
drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h
··· 3 3 #include "priv.h" 4 4 int gv100_fifo_user_new(const struct nvkm_oclass *, void *, u32, 5 5 struct nvkm_object **); 6 - int tu104_fifo_user_new(const struct nvkm_oclass *, void *, u32, 6 + int tu102_fifo_user_new(const struct nvkm_oclass *, void *, u32, 7 7 struct nvkm_object **); 8 8 #endif
+25 -18
drivers/gpu/drm/nouveau/nvkm/engine/fifo/usertu104.c drivers/gpu/drm/nouveau/nvkm/engine/disp/roottu102.c
··· 19 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 20 * OTHER DEALINGS IN THE SOFTWARE. 21 21 */ 22 - #include "user.h" 22 + #include "rootnv50.h" 23 + #include "channv50.h" 23 24 24 - static int 25 - tu104_fifo_user_map(struct nvkm_object *object, void *argv, u32 argc, 26 - enum nvkm_object_map *type, u64 *addr, u64 *size) 27 - { 28 - struct nvkm_device *device = object->engine->subdev.device; 29 - *addr = 0xbb0000 + device->func->resource_addr(device, 0); 30 - *size = 0x010000; 31 - *type = NVKM_OBJECT_MAP_IO; 32 - return 0; 33 - } 25 + #include <nvif/class.h> 34 26 35 - static const struct nvkm_object_func 36 - tu104_fifo_user = { 37 - .map = tu104_fifo_user_map, 27 + static const struct nv50_disp_root_func 28 + tu102_disp_root = { 29 + .user = { 30 + {{0,0,TU102_DISP_CURSOR }, gv100_disp_curs_new }, 31 + {{0,0,TU102_DISP_WINDOW_IMM_CHANNEL_DMA}, gv100_disp_wimm_new }, 32 + {{0,0,TU102_DISP_CORE_CHANNEL_DMA }, gv100_disp_core_new }, 33 + {{0,0,TU102_DISP_WINDOW_CHANNEL_DMA }, gv100_disp_wndw_new }, 34 + {} 35 + }, 38 36 }; 39 37 40 - int 41 - tu104_fifo_user_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, 42 - struct nvkm_object **pobject) 38 + static int 39 + tu102_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, 40 + void *data, u32 size, struct nvkm_object **pobject) 43 41 { 44 - return nvkm_object_new_(&tu104_fifo_user, oclass, argv, argc, pobject); 42 + return nv50_disp_root_new_(&tu102_disp_root, disp, oclass, 43 + data, size, pobject); 45 44 } 45 + 46 + const struct nvkm_disp_oclass 47 + tu102_disp_root_oclass = { 48 + .base.oclass = TU102_DISP, 49 + .base.minver = -1, 50 + .base.maxver = -1, 51 + .ctor = tu102_disp_root_new, 52 + };
+27
drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c
··· 25 25 26 26 #include <engine/fifo.h> 27 27 28 + u32 29 + nvkm_gr_ctxsw_inst(struct nvkm_device *device) 30 + { 31 + struct nvkm_gr *gr = device->gr; 32 + if (gr && gr->func->ctxsw.inst) 33 + return gr->func->ctxsw.inst(gr); 34 + return 0; 35 + } 36 + 37 + int 38 + nvkm_gr_ctxsw_resume(struct nvkm_device *device) 39 + { 40 + struct nvkm_gr *gr = device->gr; 41 + if (gr && gr->func->ctxsw.resume) 42 + return gr->func->ctxsw.resume(gr); 43 + return 0; 44 + } 45 + 46 + int 47 + nvkm_gr_ctxsw_pause(struct nvkm_device *device) 48 + { 49 + struct nvkm_gr *gr = device->gr; 50 + if (gr && gr->func->ctxsw.pause) 51 + return gr->func->ctxsw.pause(gr); 52 + return 0; 53 + } 54 + 28 55 static bool 29 56 nvkm_gr_chsw_load(struct nvkm_engine *engine) 30 57 {
+3 -7
drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c
··· 1523 1523 /* Make channel current. */ 1524 1524 addr = nvkm_memory_addr(inst) >> 12; 1525 1525 if (gr->firmware) { 1526 - nvkm_wr32(device, 0x409840, 0x00000030); 1527 - nvkm_wr32(device, 0x409500, 0x80000000 | addr); 1528 - nvkm_wr32(device, 0x409504, 0x00000003); 1529 - nvkm_msec(device, 2000, 1530 - if (nvkm_rd32(device, 0x409800) & 0x00000010) 1531 - break; 1532 - ); 1526 + ret = gf100_gr_fecs_bind_pointer(gr, 0x80000000 | addr); 1527 + if (ret) 1528 + goto done; 1533 1529 1534 1530 nvkm_kmap(data); 1535 1531 nvkm_wo32(data, 0x1c, 1);
+255 -76
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
··· 715 715 * PGRAPH engine/subdev functions 716 716 ******************************************************************************/ 717 717 718 + static u32 719 + gf100_gr_ctxsw_inst(struct nvkm_gr *gr) 720 + { 721 + return nvkm_rd32(gr->engine.subdev.device, 0x409b00); 722 + } 723 + 724 + static int 725 + gf100_gr_fecs_ctrl_ctxsw(struct gf100_gr *gr, u32 mthd) 726 + { 727 + struct nvkm_device *device = gr->base.engine.subdev.device; 728 + 729 + nvkm_wr32(device, 0x409804, 0xffffffff); 730 + nvkm_wr32(device, 0x409840, 0xffffffff); 731 + nvkm_wr32(device, 0x409500, 0xffffffff); 732 + nvkm_wr32(device, 0x409504, mthd); 733 + nvkm_msec(device, 2000, 734 + u32 stat = nvkm_rd32(device, 0x409804); 735 + if (stat == 0x00000002) 736 + return -EIO; 737 + if (stat == 0x00000001) 738 + return 0; 739 + ); 740 + 741 + return -ETIMEDOUT; 742 + } 743 + 744 + int 745 + gf100_gr_fecs_start_ctxsw(struct nvkm_gr *base) 746 + { 747 + struct gf100_gr *gr = gf100_gr(base); 748 + int ret = 0; 749 + 750 + mutex_lock(&gr->fecs.mutex); 751 + if (!--gr->fecs.disable) { 752 + if (WARN_ON(ret = gf100_gr_fecs_ctrl_ctxsw(gr, 0x39))) 753 + gr->fecs.disable++; 754 + } 755 + mutex_unlock(&gr->fecs.mutex); 756 + return ret; 757 + } 758 + 759 + int 760 + gf100_gr_fecs_stop_ctxsw(struct nvkm_gr *base) 761 + { 762 + struct gf100_gr *gr = gf100_gr(base); 763 + int ret = 0; 764 + 765 + mutex_lock(&gr->fecs.mutex); 766 + if (!gr->fecs.disable++) { 767 + if (WARN_ON(ret = gf100_gr_fecs_ctrl_ctxsw(gr, 0x38))) 768 + gr->fecs.disable--; 769 + } 770 + mutex_unlock(&gr->fecs.mutex); 771 + return ret; 772 + } 773 + 774 + int 775 + gf100_gr_fecs_bind_pointer(struct gf100_gr *gr, u32 inst) 776 + { 777 + struct nvkm_device *device = gr->base.engine.subdev.device; 778 + 779 + nvkm_wr32(device, 0x409840, 0x00000030); 780 + nvkm_wr32(device, 0x409500, inst); 781 + nvkm_wr32(device, 0x409504, 0x00000003); 782 + nvkm_msec(device, 2000, 783 + u32 stat = nvkm_rd32(device, 0x409800); 784 + if (stat & 0x00000020) 785 + return -EIO; 786 + if (stat & 0x00000010) 787 + return 0; 788 + ); 789 + 790 + return -ETIMEDOUT; 791 + } 792 + 793 + static int 794 + gf100_gr_fecs_set_reglist_virtual_address(struct gf100_gr *gr, u64 addr) 795 + { 796 + struct nvkm_device *device = gr->base.engine.subdev.device; 797 + 798 + nvkm_wr32(device, 0x409810, addr >> 8); 799 + nvkm_wr32(device, 0x409800, 0x00000000); 800 + nvkm_wr32(device, 0x409500, 0x00000001); 801 + nvkm_wr32(device, 0x409504, 0x00000032); 802 + nvkm_msec(device, 2000, 803 + if (nvkm_rd32(device, 0x409800) == 0x00000001) 804 + return 0; 805 + ); 806 + 807 + return -ETIMEDOUT; 808 + } 809 + 810 + static int 811 + gf100_gr_fecs_set_reglist_bind_instance(struct gf100_gr *gr, u32 inst) 812 + { 813 + struct nvkm_device *device = gr->base.engine.subdev.device; 814 + 815 + nvkm_wr32(device, 0x409810, inst); 816 + nvkm_wr32(device, 0x409800, 0x00000000); 817 + nvkm_wr32(device, 0x409500, 0x00000001); 818 + nvkm_wr32(device, 0x409504, 0x00000031); 819 + nvkm_msec(device, 2000, 820 + if (nvkm_rd32(device, 0x409800) == 0x00000001) 821 + return 0; 822 + ); 823 + 824 + return -ETIMEDOUT; 825 + } 826 + 827 + static int 828 + gf100_gr_fecs_discover_reglist_image_size(struct gf100_gr *gr, u32 *psize) 829 + { 830 + struct nvkm_device *device = gr->base.engine.subdev.device; 831 + 832 + nvkm_wr32(device, 0x409800, 0x00000000); 833 + nvkm_wr32(device, 0x409500, 0x00000001); 834 + nvkm_wr32(device, 0x409504, 0x00000030); 835 + nvkm_msec(device, 2000, 836 + if ((*psize = nvkm_rd32(device, 0x409800))) 837 + return 0; 838 + ); 839 + 840 + return -ETIMEDOUT; 841 + } 842 + 843 + static int 844 + gf100_gr_fecs_elpg_bind(struct gf100_gr *gr) 845 + { 846 + u32 size; 847 + int ret; 848 + 849 + ret = gf100_gr_fecs_discover_reglist_image_size(gr, &size); 850 + if (ret) 851 + return ret; 852 + 853 + /*XXX: We need to allocate + map the above into PMU's inst block, 854 + * which which means we probably need a proper PMU before we 855 + * even bother. 856 + */ 857 + 858 + ret = gf100_gr_fecs_set_reglist_bind_instance(gr, 0); 859 + if (ret) 860 + return ret; 861 + 862 + return gf100_gr_fecs_set_reglist_virtual_address(gr, 0); 863 + } 864 + 865 + static int 866 + gf100_gr_fecs_discover_pm_image_size(struct gf100_gr *gr, u32 *psize) 867 + { 868 + struct nvkm_device *device = gr->base.engine.subdev.device; 869 + 870 + nvkm_wr32(device, 0x409840, 0xffffffff); 871 + nvkm_wr32(device, 0x409500, 0x00000000); 872 + nvkm_wr32(device, 0x409504, 0x00000025); 873 + nvkm_msec(device, 2000, 874 + if ((*psize = nvkm_rd32(device, 0x409800))) 875 + return 0; 876 + ); 877 + 878 + return -ETIMEDOUT; 879 + } 880 + 881 + static int 882 + gf100_gr_fecs_discover_zcull_image_size(struct gf100_gr *gr, u32 *psize) 883 + { 884 + struct nvkm_device *device = gr->base.engine.subdev.device; 885 + 886 + nvkm_wr32(device, 0x409840, 0xffffffff); 887 + nvkm_wr32(device, 0x409500, 0x00000000); 888 + nvkm_wr32(device, 0x409504, 0x00000016); 889 + nvkm_msec(device, 2000, 890 + if ((*psize = nvkm_rd32(device, 0x409800))) 891 + return 0; 892 + ); 893 + 894 + return -ETIMEDOUT; 895 + } 896 + 897 + static int 898 + gf100_gr_fecs_discover_image_size(struct gf100_gr *gr, u32 *psize) 899 + { 900 + struct nvkm_device *device = gr->base.engine.subdev.device; 901 + 902 + nvkm_wr32(device, 0x409840, 0xffffffff); 903 + nvkm_wr32(device, 0x409500, 0x00000000); 904 + nvkm_wr32(device, 0x409504, 0x00000010); 905 + nvkm_msec(device, 2000, 906 + if ((*psize = nvkm_rd32(device, 0x409800))) 907 + return 0; 908 + ); 909 + 910 + return -ETIMEDOUT; 911 + } 912 + 913 + static void 914 + gf100_gr_fecs_set_watchdog_timeout(struct gf100_gr *gr, u32 timeout) 915 + { 916 + struct nvkm_device *device = gr->base.engine.subdev.device; 917 + 918 + nvkm_wr32(device, 0x409840, 0xffffffff); 919 + nvkm_wr32(device, 0x409500, timeout); 920 + nvkm_wr32(device, 0x409504, 0x00000021); 921 + } 922 + 718 923 static bool 719 924 gf100_gr_chsw_load(struct nvkm_gr *base) 720 925 { ··· 1692 1487 struct nvkm_device *device = subdev->device; 1693 1488 struct nvkm_secboot *sb = device->secboot; 1694 1489 u32 secboot_mask = 0; 1490 + int ret; 1695 1491 1696 1492 /* load fuc microcode */ 1697 1493 nvkm_mc_unk260(device, 0); ··· 1701 1495 if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) 1702 1496 secboot_mask |= BIT(NVKM_SECBOOT_FALCON_FECS); 1703 1497 else 1704 - gf100_gr_init_fw(gr->fecs, &gr->fuc409c, &gr->fuc409d); 1498 + gf100_gr_init_fw(gr->fecs.falcon, &gr->fuc409c, &gr->fuc409d); 1705 1499 1706 1500 if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) 1707 1501 secboot_mask |= BIT(NVKM_SECBOOT_FALCON_GPCCS); 1708 1502 else 1709 - gf100_gr_init_fw(gr->gpccs, &gr->fuc41ac, &gr->fuc41ad); 1503 + gf100_gr_init_fw(gr->gpccs.falcon, &gr->fuc41ac, &gr->fuc41ad); 1710 1504 1711 1505 if (secboot_mask != 0) { 1712 1506 int ret = nvkm_secboot_reset(sb, secboot_mask); ··· 1721 1515 nvkm_wr32(device, 0x41a10c, 0x00000000); 1722 1516 nvkm_wr32(device, 0x40910c, 0x00000000); 1723 1517 1724 - nvkm_falcon_start(gr->gpccs); 1725 - nvkm_falcon_start(gr->fecs); 1518 + nvkm_falcon_start(gr->gpccs.falcon); 1519 + nvkm_falcon_start(gr->fecs.falcon); 1726 1520 1727 1521 if (nvkm_msec(device, 2000, 1728 1522 if (nvkm_rd32(device, 0x409800) & 0x00000001) ··· 1730 1524 ) < 0) 1731 1525 return -EBUSY; 1732 1526 1733 - nvkm_wr32(device, 0x409840, 0xffffffff); 1734 - nvkm_wr32(device, 0x409500, 0x7fffffff); 1735 - nvkm_wr32(device, 0x409504, 0x00000021); 1527 + gf100_gr_fecs_set_watchdog_timeout(gr, 0x7fffffff); 1736 1528 1737 - nvkm_wr32(device, 0x409840, 0xffffffff); 1738 - nvkm_wr32(device, 0x409500, 0x00000000); 1739 - nvkm_wr32(device, 0x409504, 0x00000010); 1740 - if (nvkm_msec(device, 2000, 1741 - if ((gr->size = nvkm_rd32(device, 0x409800))) 1742 - break; 1743 - ) < 0) 1744 - return -EBUSY; 1529 + /* Determine how much memory is required to store main context image. */ 1530 + ret = gf100_gr_fecs_discover_image_size(gr, &gr->size); 1531 + if (ret) 1532 + return ret; 1745 1533 1746 - nvkm_wr32(device, 0x409840, 0xffffffff); 1747 - nvkm_wr32(device, 0x409500, 0x00000000); 1748 - nvkm_wr32(device, 0x409504, 0x00000016); 1749 - if (nvkm_msec(device, 2000, 1750 - if (nvkm_rd32(device, 0x409800)) 1751 - break; 1752 - ) < 0) 1753 - return -EBUSY; 1534 + /* Determine how much memory is required to store ZCULL image. */ 1535 + ret = gf100_gr_fecs_discover_zcull_image_size(gr, &gr->size_zcull); 1536 + if (ret) 1537 + return ret; 1754 1538 1755 - nvkm_wr32(device, 0x409840, 0xffffffff); 1756 - nvkm_wr32(device, 0x409500, 0x00000000); 1757 - nvkm_wr32(device, 0x409504, 0x00000025); 1758 - if (nvkm_msec(device, 2000, 1759 - if (nvkm_rd32(device, 0x409800)) 1760 - break; 1761 - ) < 0) 1762 - return -EBUSY; 1539 + /* Determine how much memory is required to store PerfMon image. */ 1540 + ret = gf100_gr_fecs_discover_pm_image_size(gr, &gr->size_pm); 1541 + if (ret) 1542 + return ret; 1763 1543 1764 - if (device->chipset >= 0xe0) { 1765 - nvkm_wr32(device, 0x409800, 0x00000000); 1766 - nvkm_wr32(device, 0x409500, 0x00000001); 1767 - nvkm_wr32(device, 0x409504, 0x00000030); 1768 - if (nvkm_msec(device, 2000, 1769 - if (nvkm_rd32(device, 0x409800)) 1770 - break; 1771 - ) < 0) 1772 - return -EBUSY; 1773 - 1774 - nvkm_wr32(device, 0x409810, 0xb00095c8); 1775 - nvkm_wr32(device, 0x409800, 0x00000000); 1776 - nvkm_wr32(device, 0x409500, 0x00000001); 1777 - nvkm_wr32(device, 0x409504, 0x00000031); 1778 - if (nvkm_msec(device, 2000, 1779 - if (nvkm_rd32(device, 0x409800)) 1780 - break; 1781 - ) < 0) 1782 - return -EBUSY; 1783 - 1784 - nvkm_wr32(device, 0x409810, 0x00080420); 1785 - nvkm_wr32(device, 0x409800, 0x00000000); 1786 - nvkm_wr32(device, 0x409500, 0x00000001); 1787 - nvkm_wr32(device, 0x409504, 0x00000032); 1788 - if (nvkm_msec(device, 2000, 1789 - if (nvkm_rd32(device, 0x409800)) 1790 - break; 1791 - ) < 0) 1792 - return -EBUSY; 1793 - 1794 - nvkm_wr32(device, 0x409614, 0x00000070); 1795 - nvkm_wr32(device, 0x409614, 0x00000770); 1796 - nvkm_wr32(device, 0x40802c, 0x00000001); 1544 + /*XXX: We (likely) require PMU support to even bother with this. 1545 + * 1546 + * Also, it seems like not all GPUs support ELPG. Traces I 1547 + * have here show RM enabling it on Kepler/Turing, but none 1548 + * of the GPUs between those. NVGPU decides this by PCIID. 1549 + */ 1550 + if (0) { 1551 + ret = gf100_gr_fecs_elpg_bind(gr); 1552 + if (ret) 1553 + return ret; 1797 1554 } 1798 1555 1556 + /* Generate golden context image. */ 1799 1557 if (gr->data == NULL) { 1800 1558 int ret = gf100_grctx_generate(gr); 1801 1559 if (ret) { ··· 1784 1614 1785 1615 /* load HUB microcode */ 1786 1616 nvkm_mc_unk260(device, 0); 1787 - nvkm_falcon_load_dmem(gr->fecs, gr->func->fecs.ucode->data.data, 0x0, 1617 + nvkm_falcon_load_dmem(gr->fecs.falcon, 1618 + gr->func->fecs.ucode->data.data, 0x0, 1788 1619 gr->func->fecs.ucode->data.size, 0); 1789 - nvkm_falcon_load_imem(gr->fecs, gr->func->fecs.ucode->code.data, 0x0, 1620 + nvkm_falcon_load_imem(gr->fecs.falcon, 1621 + gr->func->fecs.ucode->code.data, 0x0, 1790 1622 gr->func->fecs.ucode->code.size, 0, 0, false); 1791 1623 1792 1624 /* load GPC microcode */ 1793 - nvkm_falcon_load_dmem(gr->gpccs, gr->func->gpccs.ucode->data.data, 0x0, 1625 + nvkm_falcon_load_dmem(gr->gpccs.falcon, 1626 + gr->func->gpccs.ucode->data.data, 0x0, 1794 1627 gr->func->gpccs.ucode->data.size, 0); 1795 - nvkm_falcon_load_imem(gr->gpccs, gr->func->gpccs.ucode->code.data, 0x0, 1628 + nvkm_falcon_load_imem(gr->gpccs.falcon, 1629 + gr->func->gpccs.ucode->code.data, 0x0, 1796 1630 gr->func->gpccs.ucode->code.size, 0, 0, false); 1797 1631 nvkm_mc_unk260(device, 1); 1798 1632 ··· 1943 1769 int i, j; 1944 1770 int ret; 1945 1771 1946 - ret = nvkm_falcon_v1_new(subdev, "FECS", 0x409000, &gr->fecs); 1772 + ret = nvkm_falcon_v1_new(subdev, "FECS", 0x409000, &gr->fecs.falcon); 1947 1773 if (ret) 1948 1774 return ret; 1949 1775 1950 - ret = nvkm_falcon_v1_new(subdev, "GPCCS", 0x41a000, &gr->gpccs); 1776 + mutex_init(&gr->fecs.mutex); 1777 + 1778 + ret = nvkm_falcon_v1_new(subdev, "GPCCS", 0x41a000, &gr->gpccs.falcon); 1951 1779 if (ret) 1952 1780 return ret; 1953 1781 ··· 1992 1816 1993 1817 nvkm_pmu_pgob(gr->base.engine.subdev.device->pmu, false); 1994 1818 1995 - ret = nvkm_falcon_get(gr->fecs, subdev); 1819 + ret = nvkm_falcon_get(gr->fecs.falcon, subdev); 1996 1820 if (ret) 1997 1821 return ret; 1998 1822 1999 - ret = nvkm_falcon_get(gr->gpccs, subdev); 1823 + ret = nvkm_falcon_get(gr->gpccs.falcon, subdev); 2000 1824 if (ret) 2001 1825 return ret; 2002 1826 ··· 2008 1832 { 2009 1833 struct gf100_gr *gr = gf100_gr(base); 2010 1834 struct nvkm_subdev *subdev = &gr->base.engine.subdev; 2011 - nvkm_falcon_put(gr->gpccs, subdev); 2012 - nvkm_falcon_put(gr->fecs, subdev); 1835 + nvkm_falcon_put(gr->gpccs.falcon, subdev); 1836 + nvkm_falcon_put(gr->fecs.falcon, subdev); 2013 1837 return 0; 2014 1838 } 2015 1839 ··· 2035 1859 gr->func->dtor(gr); 2036 1860 kfree(gr->data); 2037 1861 2038 - nvkm_falcon_del(&gr->gpccs); 2039 - nvkm_falcon_del(&gr->fecs); 1862 + nvkm_falcon_del(&gr->gpccs.falcon); 1863 + nvkm_falcon_del(&gr->fecs.falcon); 2040 1864 2041 1865 gf100_gr_dtor_fw(&gr->fuc409c); 2042 1866 gf100_gr_dtor_fw(&gr->fuc409d); ··· 2062 1886 .chan_new = gf100_gr_chan_new, 2063 1887 .object_get = gf100_gr_object_get, 2064 1888 .chsw_load = gf100_gr_chsw_load, 1889 + .ctxsw.pause = gf100_gr_fecs_stop_ctxsw, 1890 + .ctxsw.resume = gf100_gr_fecs_start_ctxsw, 1891 + .ctxsw.inst = gf100_gr_ctxsw_inst, 2065 1892 }; 2066 1893 2067 1894 int
+14 -2
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
··· 82 82 const struct gf100_gr_func *func; 83 83 struct nvkm_gr base; 84 84 85 - struct nvkm_falcon *fecs; 86 - struct nvkm_falcon *gpccs; 85 + struct { 86 + struct nvkm_falcon *falcon; 87 + struct mutex mutex; 88 + u32 disable; 89 + } fecs; 90 + 91 + struct { 92 + struct nvkm_falcon *falcon; 93 + } gpccs; 94 + 87 95 struct gf100_gr_fuc fuc409c; 88 96 struct gf100_gr_fuc fuc409d; 89 97 struct gf100_gr_fuc fuc41ac; ··· 136 128 struct gf100_gr_mmio mmio_list[4096/8]; 137 129 u32 size; 138 130 u32 *data; 131 + u32 size_zcull; 132 + u32 size_pm; 139 133 }; 140 134 141 135 int gf100_gr_ctor(const struct gf100_gr_func *, struct nvkm_device *, ··· 145 135 int gf100_gr_new_(const struct gf100_gr_func *, struct nvkm_device *, 146 136 int, struct nvkm_gr **); 147 137 void *gf100_gr_dtor(struct nvkm_gr *); 138 + 139 + int gf100_gr_fecs_bind_pointer(struct gf100_gr *, u32 inst); 148 140 149 141 struct gf100_gr_func_zbc { 150 142 void (*clear_color)(struct gf100_gr *, int zbc);
+5
drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h
··· 27 27 */ 28 28 u64 (*units)(struct nvkm_gr *); 29 29 bool (*chsw_load)(struct nvkm_gr *); 30 + struct { 31 + int (*pause)(struct nvkm_gr *); 32 + int (*resume)(struct nvkm_gr *); 33 + u32 (*inst)(struct nvkm_gr *); 34 + } ctxsw; 30 35 struct nvkm_sclass sclass[]; 31 36 }; 32 37
+9 -1
drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c
··· 21 21 */ 22 22 #include "priv.h" 23 23 24 + #include <subdev/top.h> 24 25 #include <engine/falcon.h> 25 26 26 27 static int 27 28 nvkm_nvdec_oneinit(struct nvkm_engine *engine) 28 29 { 29 30 struct nvkm_nvdec *nvdec = nvkm_nvdec(engine); 30 - return nvkm_falcon_v1_new(&nvdec->engine.subdev, "NVDEC", 0x84000, 31 + struct nvkm_subdev *subdev = &nvdec->engine.subdev; 32 + 33 + nvdec->addr = nvkm_top_addr(subdev->device, subdev->index); 34 + if (!nvdec->addr) 35 + return -EINVAL; 36 + 37 + /*XXX: fix naming of this when adding support for multiple-NVDEC */ 38 + return nvkm_falcon_v1_new(subdev, "NVDEC", nvdec->addr, 31 39 &nvdec->falcon); 32 40 } 33 41
+1
drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild
··· 1 1 nvkm-y += nvkm/engine/sec2/base.o 2 2 nvkm-y += nvkm/engine/sec2/gp102.o 3 + nvkm-y += nvkm/engine/sec2/tu102.o
+16 -7
drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c
··· 22 22 #include "priv.h" 23 23 24 24 #include <core/msgqueue.h> 25 + #include <subdev/top.h> 25 26 #include <engine/falcon.h> 26 27 27 28 static void * ··· 40 39 struct nvkm_sec2 *sec2 = nvkm_sec2(engine); 41 40 struct nvkm_subdev *subdev = &engine->subdev; 42 41 struct nvkm_device *device = subdev->device; 43 - u32 disp = nvkm_rd32(device, 0x8701c); 44 - u32 intr = nvkm_rd32(device, 0x87008) & disp & ~(disp >> 16); 42 + u32 disp = nvkm_rd32(device, sec2->addr + 0x01c); 43 + u32 intr = nvkm_rd32(device, sec2->addr + 0x008) & disp & ~(disp >> 16); 45 44 46 45 if (intr & 0x00000040) { 47 46 schedule_work(&sec2->work); 48 - nvkm_wr32(device, 0x87004, 0x00000040); 47 + nvkm_wr32(device, sec2->addr + 0x004, 0x00000040); 49 48 intr &= ~0x00000040; 50 49 } 51 50 52 51 if (intr) { 53 52 nvkm_error(subdev, "unhandled intr %08x\n", intr); 54 - nvkm_wr32(device, 0x87004, intr); 53 + nvkm_wr32(device, sec2->addr + 0x004, intr); 55 54 56 55 } 57 56 } ··· 75 74 nvkm_sec2_oneinit(struct nvkm_engine *engine) 76 75 { 77 76 struct nvkm_sec2 *sec2 = nvkm_sec2(engine); 78 - return nvkm_falcon_v1_new(&sec2->engine.subdev, "SEC2", 0x87000, 79 - &sec2->falcon); 77 + struct nvkm_subdev *subdev = &sec2->engine.subdev; 78 + 79 + if (!sec2->addr) { 80 + sec2->addr = nvkm_top_addr(subdev->device, subdev->index); 81 + if (WARN_ON(!sec2->addr)) 82 + return -EINVAL; 83 + } 84 + 85 + return nvkm_falcon_v1_new(subdev, "SEC2", sec2->addr, &sec2->falcon); 80 86 } 81 87 82 88 static int ··· 103 95 }; 104 96 105 97 int 106 - nvkm_sec2_new_(struct nvkm_device *device, int index, 98 + nvkm_sec2_new_(struct nvkm_device *device, int index, u32 addr, 107 99 struct nvkm_sec2 **psec2) 108 100 { 109 101 struct nvkm_sec2 *sec2; 110 102 111 103 if (!(sec2 = *psec2 = kzalloc(sizeof(*sec2), GFP_KERNEL))) 112 104 return -ENOMEM; 105 + sec2->addr = addr; 113 106 INIT_WORK(&sec2->work, nvkm_sec2_recv); 114 107 115 108 return nvkm_engine_ctor(&nvkm_sec2, device, index, true, &sec2->engine);
+1 -1
drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
··· 26 26 gp102_sec2_new(struct nvkm_device *device, int index, 27 27 struct nvkm_sec2 **psec2) 28 28 { 29 - return nvkm_sec2_new_(device, index, psec2); 29 + return nvkm_sec2_new_(device, index, 0, psec2); 30 30 }
+1 -2
drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
··· 5 5 6 6 #define nvkm_sec2(p) container_of((p), struct nvkm_sec2, engine) 7 7 8 - int nvkm_sec2_new_(struct nvkm_device *, int, struct nvkm_sec2 **); 9 - 8 + int nvkm_sec2_new_(struct nvkm_device *, int, u32 addr, struct nvkm_sec2 **); 10 9 #endif
+33
drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c
··· 1 + /* 2 + * Copyright 2019 Red Hat Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + */ 22 + 23 + #include "priv.h" 24 + 25 + int 26 + tu102_sec2_new(struct nvkm_device *device, int index, 27 + struct nvkm_sec2 **psec2) 28 + { 29 + /* TOP info wasn't updated on Turing to reflect the PRI 30 + * address change for some reason. We override it here. 31 + */ 32 + return nvkm_sec2_new_(device, index, 0x840000, psec2); 33 + }
+3
drivers/gpu/drm/nouveau/nvkm/falcon/base.c
··· 204 204 debug_reg = 0x408; 205 205 falcon->has_emem = true; 206 206 break; 207 + case NVKM_SUBDEV_GSP: 208 + debug_reg = 0x0; /*XXX*/ 209 + break; 207 210 default: 208 211 nvkm_warn(subdev, "unsupported falcon %s!\n", 209 212 nvkm_subdev_name[subdev->index]);
+3 -3
drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c
··· 269 269 commit = false; 270 270 } 271 271 272 - cmd_queue_close(priv, queue, commit); 272 + cmd_queue_close(priv, queue, commit); 273 273 274 274 return ret; 275 275 } ··· 347 347 ret = cmd_write(priv, cmd, queue); 348 348 if (ret) { 349 349 seq->state = SEQ_STATE_PENDING; 350 - msgqueue_seq_release(priv, seq); 350 + msgqueue_seq_release(priv, seq); 351 351 } 352 352 353 353 return ret; ··· 373 373 if (seq->completion) 374 374 complete(seq->completion); 375 375 376 - msgqueue_seq_release(priv, seq); 376 + msgqueue_seq_release(priv, seq); 377 377 378 378 return 0; 379 379 }
+1
drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild
··· 7 7 include $(src)/nvkm/subdev/fb/Kbuild 8 8 include $(src)/nvkm/subdev/fuse/Kbuild 9 9 include $(src)/nvkm/subdev/gpio/Kbuild 10 + include $(src)/nvkm/subdev/gsp/Kbuild 10 11 include $(src)/nvkm/subdev/i2c/Kbuild 11 12 include $(src)/nvkm/subdev/ibus/Kbuild 12 13 include $(src)/nvkm/subdev/iccsense/Kbuild
+1 -1
drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild
··· 5 5 nvkm-y += nvkm/subdev/bar/gk20a.o 6 6 nvkm-y += nvkm/subdev/bar/gm107.o 7 7 nvkm-y += nvkm/subdev/bar/gm20b.o 8 - nvkm-y += nvkm/subdev/bar/tu104.o 8 + nvkm-y += nvkm/subdev/bar/tu102.o
+15 -15
drivers/gpu/drm/nouveau/nvkm/subdev/bar/tu104.c drivers/gpu/drm/nouveau/nvkm/subdev/bar/tu102.c
··· 25 25 #include <subdev/timer.h> 26 26 27 27 static void 28 - tu104_bar_bar2_wait(struct nvkm_bar *bar) 28 + tu102_bar_bar2_wait(struct nvkm_bar *bar) 29 29 { 30 30 struct nvkm_device *device = bar->subdev.device; 31 31 nvkm_msec(device, 2000, ··· 35 35 } 36 36 37 37 static void 38 - tu104_bar_bar2_fini(struct nvkm_bar *bar) 38 + tu102_bar_bar2_fini(struct nvkm_bar *bar) 39 39 { 40 40 nvkm_mask(bar->subdev.device, 0xb80f48, 0x80000000, 0x00000000); 41 41 } 42 42 43 43 static void 44 - tu104_bar_bar2_init(struct nvkm_bar *base) 44 + tu102_bar_bar2_init(struct nvkm_bar *base) 45 45 { 46 46 struct nvkm_device *device = base->subdev.device; 47 47 struct gf100_bar *bar = gf100_bar(base); ··· 52 52 } 53 53 54 54 static void 55 - tu104_bar_bar1_wait(struct nvkm_bar *bar) 55 + tu102_bar_bar1_wait(struct nvkm_bar *bar) 56 56 { 57 57 struct nvkm_device *device = bar->subdev.device; 58 58 nvkm_msec(device, 2000, ··· 62 62 } 63 63 64 64 static void 65 - tu104_bar_bar1_fini(struct nvkm_bar *bar) 65 + tu102_bar_bar1_fini(struct nvkm_bar *bar) 66 66 { 67 67 nvkm_mask(bar->subdev.device, 0xb80f40, 0x80000000, 0x00000000); 68 68 } 69 69 70 70 static void 71 - tu104_bar_bar1_init(struct nvkm_bar *base) 71 + tu102_bar_bar1_init(struct nvkm_bar *base) 72 72 { 73 73 struct nvkm_device *device = base->subdev.device; 74 74 struct gf100_bar *bar = gf100_bar(base); ··· 77 77 } 78 78 79 79 static const struct nvkm_bar_func 80 - tu104_bar = { 80 + tu102_bar = { 81 81 .dtor = gf100_bar_dtor, 82 82 .oneinit = gf100_bar_oneinit, 83 - .bar1.init = tu104_bar_bar1_init, 84 - .bar1.fini = tu104_bar_bar1_fini, 85 - .bar1.wait = tu104_bar_bar1_wait, 83 + .bar1.init = tu102_bar_bar1_init, 84 + .bar1.fini = tu102_bar_bar1_fini, 85 + .bar1.wait = tu102_bar_bar1_wait, 86 86 .bar1.vmm = gf100_bar_bar1_vmm, 87 - .bar2.init = tu104_bar_bar2_init, 88 - .bar2.fini = tu104_bar_bar2_fini, 89 - .bar2.wait = tu104_bar_bar2_wait, 87 + .bar2.init = tu102_bar_bar2_init, 88 + .bar2.fini = tu102_bar_bar2_fini, 89 + .bar2.wait = tu102_bar_bar2_wait, 90 90 .bar2.vmm = gf100_bar_bar2_vmm, 91 91 .flush = g84_bar_flush, 92 92 }; 93 93 94 94 int 95 - tu104_bar_new(struct nvkm_device *device, int index, struct nvkm_bar **pbar) 95 + tu102_bar_new(struct nvkm_device *device, int index, struct nvkm_bar **pbar) 96 96 { 97 - return gf100_bar_new_(&tu104_bar, device, index, pbar); 97 + return gf100_bar_new_(&tu102_bar, device, index, pbar); 98 98 }
+1 -1
drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c
··· 212 212 u16 data; 213 213 214 214 if (*ver >= 0x30) { 215 - const u8 vsoff[] = { 0, 4, 7, 9 }; 215 + static const u8 vsoff[] = { 0, 4, 7, 9 }; 216 216 idx = (pc * 10) + vsoff[vs] + pe; 217 217 if (*ver >= 0x40 && *ver <= 0x41 && *hdr >= 0x12) 218 218 idx += nvbios_rd08(bios, outp + 0x11) * 40;
+7 -4
drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
··· 806 806 init->offset += 3; 807 807 808 808 switch (cond) { 809 - case 0: 809 + case 0: /* CONDITION_ID_INT_DP. */ 810 810 if (init_conn(init) != DCB_CONNECTOR_eDP) 811 811 init_exec_set(init, false); 812 812 break; 813 - case 1: 814 - case 2: 813 + case 1: /* CONDITION_ID_USE_SPPLL0. */ 814 + case 2: /* CONDITION_ID_USE_SPPLL1. */ 815 815 if ( init->outp && 816 816 (data = nvbios_dpout_match(bios, DCB_OUTPUT_DP, 817 817 (init->outp->or << 0) | ··· 826 826 if (init_exec(init)) 827 827 warn("script needs dp output table data\n"); 828 828 break; 829 - case 5: 829 + case 5: /* CONDITION_ID_ASSR_SUPPORT. */ 830 830 if (!(init_rdauxr(init, 0x0d) & 1)) 831 831 init_exec_set(init, false); 832 + break; 833 + case 7: /* CONDITION_ID_NO_PANEL_SEQ_DELAYS. */ 834 + init_exec_set(init, false); 832 835 break; 833 836 default: 834 837 warn("INIT_GENERIC_CONDITON: unknown 0x%02x\n", cond);
+1 -1
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/Kbuild
··· 13 13 nvkm-y += nvkm/subdev/devinit/gm107.o 14 14 nvkm-y += nvkm/subdev/devinit/gm200.o 15 15 nvkm-y += nvkm/subdev/devinit/gv100.o 16 - nvkm-y += nvkm/subdev/devinit/tu104.o 16 + nvkm-y += nvkm/subdev/devinit/tu102.o
+7 -7
drivers/gpu/drm/nouveau/nvkm/subdev/devinit/tu104.c drivers/gpu/drm/nouveau/nvkm/subdev/devinit/tu102.c
··· 26 26 #include <subdev/clk/pll.h> 27 27 28 28 static int 29 - tu104_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq) 29 + tu102_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq) 30 30 { 31 31 struct nvkm_subdev *subdev = &init->subdev; 32 32 struct nvkm_device *device = subdev->device; ··· 66 66 } 67 67 68 68 static int 69 - tu104_devinit_post(struct nvkm_devinit *base, bool post) 69 + tu102_devinit_post(struct nvkm_devinit *base, bool post) 70 70 { 71 71 struct nv50_devinit *init = nv50_devinit(base); 72 72 gm200_devinit_preos(init, post); ··· 74 74 } 75 75 76 76 static const struct nvkm_devinit_func 77 - tu104_devinit = { 77 + tu102_devinit = { 78 78 .init = nv50_devinit_init, 79 - .post = tu104_devinit_post, 80 - .pll_set = tu104_devinit_pll_set, 79 + .post = tu102_devinit_post, 80 + .pll_set = tu102_devinit_pll_set, 81 81 .disable = gm107_devinit_disable, 82 82 }; 83 83 84 84 int 85 - tu104_devinit_new(struct nvkm_device *device, int index, 85 + tu102_devinit_new(struct nvkm_device *device, int index, 86 86 struct nvkm_devinit **pinit) 87 87 { 88 - return nv50_devinit_new_(&tu104_devinit, device, index, pinit); 88 + return nv50_devinit_new_(&tu102_devinit, device, index, pinit); 89 89 }
+2 -1
drivers/gpu/drm/nouveau/nvkm/subdev/fault/Kbuild
··· 1 1 nvkm-y += nvkm/subdev/fault/base.o 2 + nvkm-y += nvkm/subdev/fault/user.o 2 3 nvkm-y += nvkm/subdev/fault/gp100.o 3 4 nvkm-y += nvkm/subdev/fault/gv100.o 4 - nvkm-y += nvkm/subdev/fault/tu104.o 5 + nvkm-y += nvkm/subdev/fault/tu102.o
+2
drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c
··· 176 176 return -ENOMEM; 177 177 nvkm_subdev_ctor(&nvkm_fault, device, index, &fault->subdev); 178 178 fault->func = func; 179 + fault->user.ctor = nvkm_ufault_new; 180 + fault->user.base = func->user.base; 179 181 return 0; 180 182 }
+3
drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c
··· 23 23 24 24 #include <subdev/mc.h> 25 25 26 + #include <nvif/class.h> 27 + 26 28 static void 27 29 gp100_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable) 28 30 { ··· 71 69 .buffer.init = gp100_fault_buffer_init, 72 70 .buffer.fini = gp100_fault_buffer_fini, 73 71 .buffer.intr = gp100_fault_buffer_intr, 72 + .user = { { 0, 0, MAXWELL_FAULT_BUFFER_A }, 0 }, 74 73 }; 75 74 76 75 int
+16
drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c
··· 25 25 #include <subdev/mmu.h> 26 26 #include <engine/fifo.h> 27 27 28 + #include <nvif/class.h> 29 + 28 30 static void 29 31 gv100_fault_buffer_process(struct nvkm_fault_buffer *buffer) 30 32 { ··· 168 166 } 169 167 } 170 168 169 + if (stat & 0x08000000) { 170 + if (fault->buffer[1]) { 171 + nvkm_event_send(&fault->event, 1, 1, NULL, 0); 172 + stat &= ~0x08000000; 173 + } 174 + } 175 + 171 176 if (stat) { 172 177 nvkm_debug(subdev, "intr %08x\n", stat); 173 178 } ··· 217 208 .buffer.init = gv100_fault_buffer_init, 218 209 .buffer.fini = gv100_fault_buffer_fini, 219 210 .buffer.intr = gv100_fault_buffer_intr, 211 + /*TODO: Figure out how to expose non-replayable fault buffer, which, 212 + * for some reason, is where recoverable CE faults appear... 213 + * 214 + * It's a bit tricky, as both NVKM and SVM will need access to 215 + * the non-replayable fault buffer. 216 + */ 217 + .user = { { 0, 0, VOLTA_FAULT_BUFFER_A }, 1 }, 220 218 }; 221 219 222 220 int
+7
drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h
··· 34 34 void (*fini)(struct nvkm_fault_buffer *); 35 35 void (*intr)(struct nvkm_fault_buffer *, bool enable); 36 36 } buffer; 37 + struct { 38 + struct nvkm_sclass base; 39 + int rp; 40 + } user; 37 41 }; 38 42 39 43 int gv100_fault_oneinit(struct nvkm_fault *); 44 + 45 + int nvkm_ufault_new(struct nvkm_device *, const struct nvkm_oclass *, 46 + void *, u32, struct nvkm_object **); 40 47 #endif
+20 -19
drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu104.c drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c
··· 28 28 #include <nvif/class.h> 29 29 30 30 static void 31 - tu104_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable) 31 + tu102_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable) 32 32 { 33 33 /*XXX: Earlier versions of RM touched the old regs on Turing, 34 34 * which don't appear to actually work anymore, but newer ··· 37 37 } 38 38 39 39 static void 40 - tu104_fault_buffer_fini(struct nvkm_fault_buffer *buffer) 40 + tu102_fault_buffer_fini(struct nvkm_fault_buffer *buffer) 41 41 { 42 42 struct nvkm_device *device = buffer->fault->subdev.device; 43 43 const u32 foff = buffer->id * 0x20; ··· 45 45 } 46 46 47 47 static void 48 - tu104_fault_buffer_init(struct nvkm_fault_buffer *buffer) 48 + tu102_fault_buffer_init(struct nvkm_fault_buffer *buffer) 49 49 { 50 50 struct nvkm_device *device = buffer->fault->subdev.device; 51 51 const u32 foff = buffer->id * 0x20; ··· 57 57 } 58 58 59 59 static void 60 - tu104_fault_buffer_info(struct nvkm_fault_buffer *buffer) 60 + tu102_fault_buffer_info(struct nvkm_fault_buffer *buffer) 61 61 { 62 62 struct nvkm_device *device = buffer->fault->subdev.device; 63 63 const u32 foff = buffer->id * 0x20; ··· 70 70 } 71 71 72 72 static void 73 - tu104_fault_intr_fault(struct nvkm_fault *fault) 73 + tu102_fault_intr_fault(struct nvkm_fault *fault) 74 74 { 75 75 struct nvkm_subdev *subdev = &fault->subdev; 76 76 struct nvkm_device *device = subdev->device; ··· 96 96 } 97 97 98 98 static void 99 - tu104_fault_intr(struct nvkm_fault *fault) 99 + tu102_fault_intr(struct nvkm_fault *fault) 100 100 { 101 101 struct nvkm_subdev *subdev = &fault->subdev; 102 102 struct nvkm_device *device = subdev->device; 103 103 u32 stat = nvkm_rd32(device, 0xb83094); 104 104 105 105 if (stat & 0x80000000) { 106 - tu104_fault_intr_fault(fault); 106 + tu102_fault_intr_fault(fault); 107 107 nvkm_wr32(device, 0xb83094, 0x80000000); 108 108 stat &= ~0x80000000; 109 109 } ··· 129 129 } 130 130 131 131 static void 132 - tu104_fault_fini(struct nvkm_fault *fault) 132 + tu102_fault_fini(struct nvkm_fault *fault) 133 133 { 134 134 nvkm_notify_put(&fault->nrpfb); 135 135 if (fault->buffer[0]) ··· 138 138 } 139 139 140 140 static void 141 - tu104_fault_init(struct nvkm_fault *fault) 141 + tu102_fault_init(struct nvkm_fault *fault) 142 142 { 143 143 /*XXX: enable priv faults */ 144 144 fault->func->buffer.init(fault->buffer[0]); ··· 146 146 } 147 147 148 148 static const struct nvkm_fault_func 149 - tu104_fault = { 149 + tu102_fault = { 150 150 .oneinit = gv100_fault_oneinit, 151 - .init = tu104_fault_init, 152 - .fini = tu104_fault_fini, 153 - .intr = tu104_fault_intr, 151 + .init = tu102_fault_init, 152 + .fini = tu102_fault_fini, 153 + .intr = tu102_fault_intr, 154 154 .buffer.nr = 2, 155 155 .buffer.entry_size = 32, 156 - .buffer.info = tu104_fault_buffer_info, 157 - .buffer.init = tu104_fault_buffer_init, 158 - .buffer.fini = tu104_fault_buffer_fini, 159 - .buffer.intr = tu104_fault_buffer_intr, 156 + .buffer.info = tu102_fault_buffer_info, 157 + .buffer.init = tu102_fault_buffer_init, 158 + .buffer.fini = tu102_fault_buffer_fini, 159 + .buffer.intr = tu102_fault_buffer_intr, 160 + .user = { { 0, 0, VOLTA_FAULT_BUFFER_A }, 1 }, 160 161 }; 161 162 162 163 int 163 - tu104_fault_new(struct nvkm_device *device, int index, 164 + tu102_fault_new(struct nvkm_device *device, int index, 164 165 struct nvkm_fault **pfault) 165 166 { 166 - return nvkm_fault_new_(&tu104_fault, device, index, pfault); 167 + return nvkm_fault_new_(&tu102_fault, device, index, pfault); 167 168 }
+106
drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c
··· 1 + /* 2 + * Copyright 2018 Red Hat Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + */ 22 + #include "priv.h" 23 + 24 + #include <core/memory.h> 25 + #include <subdev/mmu.h> 26 + 27 + #include <nvif/clb069.h> 28 + #include <nvif/unpack.h> 29 + 30 + static int 31 + nvkm_ufault_map(struct nvkm_object *object, void *argv, u32 argc, 32 + enum nvkm_object_map *type, u64 *addr, u64 *size) 33 + { 34 + struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object); 35 + struct nvkm_device *device = buffer->fault->subdev.device; 36 + *type = NVKM_OBJECT_MAP_IO; 37 + *addr = device->func->resource_addr(device, 3) + buffer->addr; 38 + *size = nvkm_memory_size(buffer->mem); 39 + return 0; 40 + } 41 + 42 + static int 43 + nvkm_ufault_ntfy(struct nvkm_object *object, u32 type, 44 + struct nvkm_event **pevent) 45 + { 46 + struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object); 47 + if (type == NVB069_V0_NTFY_FAULT) { 48 + *pevent = &buffer->fault->event; 49 + return 0; 50 + } 51 + return -EINVAL; 52 + } 53 + 54 + static int 55 + nvkm_ufault_fini(struct nvkm_object *object, bool suspend) 56 + { 57 + struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object); 58 + buffer->fault->func->buffer.fini(buffer); 59 + return 0; 60 + } 61 + 62 + static int 63 + nvkm_ufault_init(struct nvkm_object *object) 64 + { 65 + struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object); 66 + buffer->fault->func->buffer.init(buffer); 67 + return 0; 68 + } 69 + 70 + static void * 71 + nvkm_ufault_dtor(struct nvkm_object *object) 72 + { 73 + return NULL; 74 + } 75 + 76 + static const struct nvkm_object_func 77 + nvkm_ufault = { 78 + .dtor = nvkm_ufault_dtor, 79 + .init = nvkm_ufault_init, 80 + .fini = nvkm_ufault_fini, 81 + .ntfy = nvkm_ufault_ntfy, 82 + .map = nvkm_ufault_map, 83 + }; 84 + 85 + int 86 + nvkm_ufault_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, 87 + void *argv, u32 argc, struct nvkm_object **pobject) 88 + { 89 + union { 90 + struct nvif_clb069_v0 v0; 91 + } *args = argv; 92 + struct nvkm_fault *fault = device->fault; 93 + struct nvkm_fault_buffer *buffer = fault->buffer[fault->func->user.rp]; 94 + int ret = -ENOSYS; 95 + 96 + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { 97 + args->v0.entries = buffer->entries; 98 + args->v0.get = buffer->get; 99 + args->v0.put = buffer->put; 100 + } else 101 + return ret; 102 + 103 + nvkm_object_ctor(&nvkm_ufault, oclass, &buffer->object); 104 + *pobject = &buffer->object; 105 + return 0; 106 + }
+1 -1
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c
··· 87 87 WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16; 88 88 /* XXX: Get these values from the VBIOS instead */ 89 89 DLL = !(ram->mr[1] & 0x1); 90 - RON = !(ram->mr[1] & 0x300) >> 8; 90 + RON = !((ram->mr[1] & 0x300) >> 8); 91 91 break; 92 92 default: 93 93 return -ENOSYS;
+1
drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild
··· 1 + nvkm-y += nvkm/subdev/gsp/gv100.o
+62
drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c
··· 1 + /* 2 + * Copyright 2019 Red Hat Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + */ 22 + #include <subdev/gsp.h> 23 + #include <subdev/top.h> 24 + #include <engine/falcon.h> 25 + 26 + static int 27 + gv100_gsp_oneinit(struct nvkm_subdev *subdev) 28 + { 29 + struct nvkm_gsp *gsp = nvkm_gsp(subdev); 30 + 31 + gsp->addr = nvkm_top_addr(subdev->device, subdev->index); 32 + if (!gsp->addr) 33 + return -EINVAL; 34 + 35 + return nvkm_falcon_v1_new(subdev, "GSP", gsp->addr, &gsp->falcon); 36 + } 37 + 38 + static void * 39 + gv100_gsp_dtor(struct nvkm_subdev *subdev) 40 + { 41 + struct nvkm_gsp *gsp = nvkm_gsp(subdev); 42 + nvkm_falcon_del(&gsp->falcon); 43 + return gsp; 44 + } 45 + 46 + static const struct nvkm_subdev_func 47 + gv100_gsp = { 48 + .dtor = gv100_gsp_dtor, 49 + .oneinit = gv100_gsp_oneinit, 50 + }; 51 + 52 + int 53 + gv100_gsp_new(struct nvkm_device *device, int index, struct nvkm_gsp **pgsp) 54 + { 55 + struct nvkm_gsp *gsp; 56 + 57 + if (!(gsp = *pgsp = kzalloc(sizeof(*gsp), GFP_KERNEL))) 58 + return -ENOMEM; 59 + 60 + nvkm_subdev_ctor(&gv100_gsp, device, index, &gsp->subdev); 61 + return 0; 62 + }
+1 -1
drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild
··· 12 12 nvkm-y += nvkm/subdev/mc/gk20a.o 13 13 nvkm-y += nvkm/subdev/mc/gp100.o 14 14 nvkm-y += nvkm/subdev/mc/gp10b.o 15 - nvkm-y += nvkm/subdev/mc/tu104.o 15 + nvkm-y += nvkm/subdev/mc/tu102.o
+55
drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c
··· 1 + /* 2 + * Copyright 2018 Red Hat Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + */ 22 + #include "priv.h" 23 + 24 + static void 25 + tu102_mc_intr_hack(struct nvkm_mc *mc, bool *handled) 26 + { 27 + struct nvkm_device *device = mc->subdev.device; 28 + u32 stat = nvkm_rd32(device, 0xb81010); 29 + if (stat & 0x00000050) { 30 + struct nvkm_subdev *subdev = 31 + nvkm_device_subdev(device, NVKM_SUBDEV_FAULT); 32 + nvkm_wr32(device, 0xb81010, stat & 0x00000050); 33 + if (subdev) 34 + nvkm_subdev_intr(subdev); 35 + *handled = true; 36 + } 37 + } 38 + 39 + static const struct nvkm_mc_func 40 + tu102_mc = { 41 + .init = nv50_mc_init, 42 + .intr = gp100_mc_intr, 43 + .intr_unarm = gp100_mc_intr_unarm, 44 + .intr_rearm = gp100_mc_intr_rearm, 45 + .intr_mask = gp100_mc_intr_mask, 46 + .intr_stat = gf100_mc_intr_stat, 47 + .intr_hack = tu102_mc_intr_hack, 48 + .reset = gk104_mc_reset, 49 + }; 50 + 51 + int 52 + tu102_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc) 53 + { 54 + return gp100_mc_new_(&tu102_mc, device, index, pmc); 55 + }
+15 -27
drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu104.c drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu102.c
··· 19 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 20 * OTHER DEALINGS IN THE SOFTWARE. 21 21 */ 22 - #include "priv.h" 22 + #include "mem.h" 23 + #include "vmm.h" 23 24 24 - static void 25 - tu104_mc_intr_hack(struct nvkm_mc *mc, bool *handled) 26 - { 27 - struct nvkm_device *device = mc->subdev.device; 28 - u32 stat = nvkm_rd32(device, 0xb81010); 29 - if (stat & 0x00000050) { 30 - struct nvkm_subdev *subdev = 31 - nvkm_device_subdev(device, NVKM_SUBDEV_FAULT); 32 - nvkm_wr32(device, 0xb81010, stat & 0x00000050); 33 - if (subdev) 34 - nvkm_subdev_intr(subdev); 35 - *handled = true; 36 - } 37 - } 25 + #include <core/option.h> 38 26 39 - static const struct nvkm_mc_func 40 - tu104_mc = { 41 - .init = nv50_mc_init, 42 - .intr = gp100_mc_intr, 43 - .intr_unarm = gp100_mc_intr_unarm, 44 - .intr_rearm = gp100_mc_intr_rearm, 45 - .intr_mask = gp100_mc_intr_mask, 46 - .intr_stat = gf100_mc_intr_stat, 47 - .intr_hack = tu104_mc_intr_hack, 48 - .reset = gk104_mc_reset, 27 + #include <nvif/class.h> 28 + 29 + static const struct nvkm_mmu_func 30 + tu102_mmu = { 31 + .dma_bits = 47, 32 + .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, 33 + .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map }, 34 + .vmm = {{ -1, 0, NVIF_CLASS_VMM_GP100}, tu102_vmm_new }, 35 + .kind = gm200_mmu_kind, 36 + .kind_sys = true, 49 37 }; 50 38 51 39 int 52 - tu104_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc) 40 + tu102_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) 53 41 { 54 - return gp100_mc_new_(&tu104_mc, device, index, pmc); 42 + return nvkm_mmu_new_(&tu102_mmu, device, index, pmmu); 55 43 }
+2 -2
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild
··· 13 13 nvkm-y += nvkm/subdev/mmu/gp100.o 14 14 nvkm-y += nvkm/subdev/mmu/gp10b.o 15 15 nvkm-y += nvkm/subdev/mmu/gv100.o 16 - nvkm-y += nvkm/subdev/mmu/tu104.o 16 + nvkm-y += nvkm/subdev/mmu/tu102.o 17 17 18 18 nvkm-y += nvkm/subdev/mmu/mem.o 19 19 nvkm-y += nvkm/subdev/mmu/memnv04.o ··· 34 34 nvkm-y += nvkm/subdev/mmu/vmmgp100.o 35 35 nvkm-y += nvkm/subdev/mmu/vmmgp10b.o 36 36 nvkm-y += nvkm/subdev/mmu/vmmgv100.o 37 - nvkm-y += nvkm/subdev/mmu/vmmtu104.o 37 + nvkm-y += nvkm/subdev/mmu/vmmtu102.o 38 38 39 39 nvkm-y += nvkm/subdev/mmu/umem.o 40 40 nvkm-y += nvkm/subdev/mmu/ummu.o
+1 -1
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp100.c
··· 31 31 .dma_bits = 47, 32 32 .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, 33 33 .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map }, 34 - .vmm = {{ -1, -1, NVIF_CLASS_VMM_GP100}, gp100_vmm_new }, 34 + .vmm = {{ -1, 0, NVIF_CLASS_VMM_GP100}, gp100_vmm_new }, 35 35 .kind = gm200_mmu_kind, 36 36 .kind_sys = true, 37 37 };
+1 -1
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b.c
··· 31 31 .dma_bits = 47, 32 32 .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, 33 33 .mem = {{ -1, -1, NVIF_CLASS_MEM_GF100}, .umap = gf100_mem_map }, 34 - .vmm = {{ -1, -1, NVIF_CLASS_VMM_GP100}, gp10b_vmm_new }, 34 + .vmm = {{ -1, 0, NVIF_CLASS_VMM_GP100}, gp10b_vmm_new }, 35 35 .kind = gm200_mmu_kind, 36 36 .kind_sys = true, 37 37 };
+1 -1
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gv100.c
··· 31 31 .dma_bits = 47, 32 32 .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, 33 33 .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map }, 34 - .vmm = {{ -1, -1, NVIF_CLASS_VMM_GP100}, gv100_vmm_new }, 34 + .vmm = {{ -1, 0, NVIF_CLASS_VMM_GP100}, gv100_vmm_new }, 35 35 .kind = gm200_mmu_kind, 36 36 .kind_sys = true, 37 37 };
+1 -1
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h
··· 28 28 29 29 struct { 30 30 struct nvkm_sclass user; 31 - int (*ctor)(struct nvkm_mmu *, u64 addr, u64 size, 31 + int (*ctor)(struct nvkm_mmu *, bool managed, u64 addr, u64 size, 32 32 void *argv, u32 argc, struct lock_class_key *, 33 33 const char *name, struct nvkm_vmm **); 34 34 bool global;
+32 -15
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu104.c drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf117.c
··· 1 1 /* 2 - * Copyright 2018 Red Hat Inc. 2 + * Copyright 2019 Ilia Mirkin 3 3 * 4 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 5 * copy of this software and associated documentation files (the "Software"), ··· 18 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 20 * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: Ilia Mirkin 21 23 */ 22 - #include "mem.h" 23 - #include "vmm.h" 24 + #include "priv.h" 24 25 25 - #include <core/option.h> 26 + #include <subdev/fuse.h> 26 27 27 - #include <nvif/class.h> 28 + static int 29 + gf117_volt_speedo_read(struct nvkm_volt *volt) 30 + { 31 + struct nvkm_device *device = volt->subdev.device; 32 + struct nvkm_fuse *fuse = device->fuse; 28 33 29 - static const struct nvkm_mmu_func 30 - tu104_mmu = { 31 - .dma_bits = 47, 32 - .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, 33 - .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map }, 34 - .vmm = {{ -1, 0, NVIF_CLASS_VMM_GP100}, tu104_vmm_new }, 35 - .kind = gm200_mmu_kind, 36 - .kind_sys = true, 34 + if (!fuse) 35 + return -EINVAL; 36 + 37 + return nvkm_fuse_read(fuse, 0x3a8); 38 + } 39 + 40 + static const struct nvkm_volt_func 41 + gf117_volt = { 42 + .oneinit = gf100_volt_oneinit, 43 + .vid_get = nvkm_voltgpio_get, 44 + .vid_set = nvkm_voltgpio_set, 45 + .speedo_read = gf117_volt_speedo_read, 37 46 }; 38 47 39 48 int 40 - tu104_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) 49 + gf117_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt) 41 50 { 42 - return nvkm_mmu_new_(&tu104_mmu, device, index, pmmu); 51 + struct nvkm_volt *volt; 52 + int ret; 53 + 54 + ret = nvkm_volt_new_(&gf117_volt, device, index, &volt); 55 + *pvolt = volt; 56 + if (ret) 57 + return ret; 58 + 59 + return nvkm_voltgpio_init(volt); 43 60 }
+81 -2
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c
··· 43 43 } 44 44 45 45 static int 46 + nvkm_uvmm_mthd_pfnclr(struct nvkm_uvmm *uvmm, void *argv, u32 argc) 47 + { 48 + struct nvkm_client *client = uvmm->object.client; 49 + union { 50 + struct nvif_vmm_pfnclr_v0 v0; 51 + } *args = argv; 52 + struct nvkm_vmm *vmm = uvmm->vmm; 53 + int ret = -ENOSYS; 54 + u64 addr, size; 55 + 56 + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { 57 + addr = args->v0.addr; 58 + size = args->v0.size; 59 + } else 60 + return ret; 61 + 62 + if (!client->super) 63 + return -ENOENT; 64 + 65 + if (size) { 66 + mutex_lock(&vmm->mutex); 67 + ret = nvkm_vmm_pfn_unmap(vmm, addr, size); 68 + mutex_unlock(&vmm->mutex); 69 + } 70 + 71 + return ret; 72 + } 73 + 74 + static int 75 + nvkm_uvmm_mthd_pfnmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc) 76 + { 77 + struct nvkm_client *client = uvmm->object.client; 78 + union { 79 + struct nvif_vmm_pfnmap_v0 v0; 80 + } *args = argv; 81 + struct nvkm_vmm *vmm = uvmm->vmm; 82 + int ret = -ENOSYS; 83 + u64 addr, size, *phys; 84 + u8 page; 85 + 86 + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, true))) { 87 + page = args->v0.page; 88 + addr = args->v0.addr; 89 + size = args->v0.size; 90 + phys = args->v0.phys; 91 + if (argc != (size >> page) * sizeof(args->v0.phys[0])) 92 + return -EINVAL; 93 + } else 94 + return ret; 95 + 96 + if (!client->super) 97 + return -ENOENT; 98 + 99 + if (size) { 100 + mutex_lock(&vmm->mutex); 101 + ret = nvkm_vmm_pfn_map(vmm, page, addr, size, phys); 102 + mutex_unlock(&vmm->mutex); 103 + } 104 + 105 + return ret; 106 + } 107 + 108 + static int 46 109 nvkm_uvmm_mthd_unmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc) 47 110 { 48 111 struct nvkm_client *client = uvmm->object.client; ··· 141 78 goto done; 142 79 } 143 80 144 - nvkm_vmm_unmap_locked(vmm, vma); 81 + nvkm_vmm_unmap_locked(vmm, vma, false); 145 82 ret = 0; 146 83 done: 147 84 mutex_unlock(&vmm->mutex); ··· 184 121 if (ret = -ENOENT, (!vma->user && !client->super) || vma->busy) { 185 122 VMM_DEBUG(vmm, "denied %016llx: %d %d %d", addr, 186 123 vma->user, !client->super, vma->busy); 124 + goto fail; 125 + } 126 + 127 + if (ret = -EINVAL, vma->mapped && !vma->memory) { 128 + VMM_DEBUG(vmm, "pfnmap %016llx", addr); 187 129 goto fail; 188 130 } 189 131 ··· 339 271 case NVIF_VMM_V0_PUT : return nvkm_uvmm_mthd_put (uvmm, argv, argc); 340 272 case NVIF_VMM_V0_MAP : return nvkm_uvmm_mthd_map (uvmm, argv, argc); 341 273 case NVIF_VMM_V0_UNMAP : return nvkm_uvmm_mthd_unmap (uvmm, argv, argc); 274 + case NVIF_VMM_V0_PFNMAP: return nvkm_uvmm_mthd_pfnmap(uvmm, argv, argc); 275 + case NVIF_VMM_V0_PFNCLR: return nvkm_uvmm_mthd_pfnclr(uvmm, argv, argc); 276 + case NVIF_VMM_V0_MTHD(0x00) ... NVIF_VMM_V0_MTHD(0x7f): 277 + if (uvmm->vmm->func->mthd) { 278 + return uvmm->vmm->func->mthd(uvmm->vmm, 279 + uvmm->object.client, 280 + mthd, argv, argc); 281 + } 282 + break; 342 283 default: 343 284 break; 344 285 } ··· 381 304 struct nvkm_uvmm *uvmm; 382 305 int ret = -ENOSYS; 383 306 u64 addr, size; 307 + bool managed; 384 308 385 309 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, more))) { 310 + managed = args->v0.managed != 0; 386 311 addr = args->v0.addr; 387 312 size = args->v0.size; 388 313 } else ··· 396 317 *pobject = &uvmm->object; 397 318 398 319 if (!mmu->vmm) { 399 - ret = mmu->func->vmm.ctor(mmu, addr, size, argv, argc, 320 + ret = mmu->func->vmm.ctor(mmu, managed, addr, size, argv, argc, 400 321 NULL, "user", &uvmm->vmm); 401 322 if (ret) 402 323 return ret;
+332 -50
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
··· 255 255 } 256 256 257 257 static bool 258 - nvkm_vmm_unref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes) 258 + nvkm_vmm_unref_ptes(struct nvkm_vmm_iter *it, bool pfn, u32 ptei, u32 ptes) 259 259 { 260 260 const struct nvkm_vmm_desc *desc = it->desc; 261 261 const int type = desc->type == SPT; 262 262 struct nvkm_vmm_pt *pgt = it->pt[0]; 263 + bool dma; 264 + 265 + if (pfn) { 266 + /* Need to clear PTE valid bits before we dma_unmap_page(). */ 267 + dma = desc->func->pfn_clear(it->vmm, pgt->pt[type], ptei, ptes); 268 + if (dma) { 269 + /* GPU may have cached the PT, flush before unmap. */ 270 + nvkm_vmm_flush_mark(it); 271 + nvkm_vmm_flush(it); 272 + desc->func->pfn_unmap(it->vmm, pgt->pt[type], ptei, ptes); 273 + } 274 + } 263 275 264 276 /* Drop PTE references. */ 265 277 pgt->refs[type] -= ptes; ··· 361 349 } 362 350 363 351 static bool 364 - nvkm_vmm_ref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes) 352 + nvkm_vmm_ref_ptes(struct nvkm_vmm_iter *it, bool pfn, u32 ptei, u32 ptes) 365 353 { 366 354 const struct nvkm_vmm_desc *desc = it->desc; 367 355 const int type = desc->type == SPT; ··· 391 379 } 392 380 393 381 static bool 394 - nvkm_vmm_sparse_unref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes) 382 + nvkm_vmm_sparse_unref_ptes(struct nvkm_vmm_iter *it, bool pfn, u32 ptei, u32 ptes) 395 383 { 396 384 struct nvkm_vmm_pt *pt = it->pt[0]; 397 385 if (it->desc->type == PGD) ··· 399 387 else 400 388 if (it->desc->type == LPT) 401 389 memset(&pt->pte[ptei], 0x00, sizeof(pt->pte[0]) * ptes); 402 - return nvkm_vmm_unref_ptes(it, ptei, ptes); 390 + return nvkm_vmm_unref_ptes(it, pfn, ptei, ptes); 403 391 } 404 392 405 393 static bool 406 - nvkm_vmm_sparse_ref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes) 394 + nvkm_vmm_sparse_ref_ptes(struct nvkm_vmm_iter *it, bool pfn, u32 ptei, u32 ptes) 407 395 { 408 396 nvkm_vmm_sparse_ptes(it->desc, it->pt[0], ptei, ptes); 409 - return nvkm_vmm_ref_ptes(it, ptei, ptes); 397 + return nvkm_vmm_ref_ptes(it, pfn, ptei, ptes); 410 398 } 411 399 412 400 static bool ··· 499 487 500 488 static inline u64 501 489 nvkm_vmm_iter(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, 502 - u64 addr, u64 size, const char *name, bool ref, 503 - bool (*REF_PTES)(struct nvkm_vmm_iter *, u32, u32), 490 + u64 addr, u64 size, const char *name, bool ref, bool pfn, 491 + bool (*REF_PTES)(struct nvkm_vmm_iter *, bool pfn, u32, u32), 504 492 nvkm_vmm_pte_func MAP_PTES, struct nvkm_vmm_map *map, 505 493 nvkm_vmm_pxe_func CLR_PTES) 506 494 { ··· 560 548 } 561 549 562 550 /* Handle PTE updates. */ 563 - if (!REF_PTES || REF_PTES(&it, ptei, ptes)) { 551 + if (!REF_PTES || REF_PTES(&it, pfn, ptei, ptes)) { 564 552 struct nvkm_mmu_pt *pt = pgt->pt[type]; 565 553 if (MAP_PTES || CLR_PTES) { 566 554 if (MAP_PTES) ··· 602 590 nvkm_vmm_ptes_sparse_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, 603 591 u64 addr, u64 size) 604 592 { 605 - nvkm_vmm_iter(vmm, page, addr, size, "sparse unref", false, 593 + nvkm_vmm_iter(vmm, page, addr, size, "sparse unref", false, false, 606 594 nvkm_vmm_sparse_unref_ptes, NULL, NULL, 607 595 page->desc->func->invalid ? 608 596 page->desc->func->invalid : page->desc->func->unmap); ··· 614 602 { 615 603 if ((page->type & NVKM_VMM_PAGE_SPARSE)) { 616 604 u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "sparse ref", 617 - true, nvkm_vmm_sparse_ref_ptes, NULL, 618 - NULL, page->desc->func->sparse); 605 + true, false, nvkm_vmm_sparse_ref_ptes, 606 + NULL, NULL, page->desc->func->sparse); 619 607 if (fail != ~0ULL) { 620 608 if ((size = fail - addr)) 621 609 nvkm_vmm_ptes_sparse_put(vmm, page, addr, size); ··· 678 666 679 667 static void 680 668 nvkm_vmm_ptes_unmap_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, 681 - u64 addr, u64 size, bool sparse) 669 + u64 addr, u64 size, bool sparse, bool pfn) 682 670 { 683 671 const struct nvkm_vmm_desc_func *func = page->desc->func; 684 672 nvkm_vmm_iter(vmm, page, addr, size, "unmap + unref", 685 - false, nvkm_vmm_unref_ptes, NULL, NULL, 673 + false, pfn, nvkm_vmm_unref_ptes, NULL, NULL, 686 674 sparse ? func->sparse : func->invalid ? func->invalid : 687 675 func->unmap); 688 676 } ··· 693 681 nvkm_vmm_pte_func func) 694 682 { 695 683 u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref + map", true, 696 - nvkm_vmm_ref_ptes, func, map, NULL); 684 + false, nvkm_vmm_ref_ptes, func, map, NULL); 697 685 if (fail != ~0ULL) { 698 686 if ((size = fail - addr)) 699 - nvkm_vmm_ptes_unmap_put(vmm, page, addr, size, false); 687 + nvkm_vmm_ptes_unmap_put(vmm, page, addr, size, false, false); 700 688 return -ENOMEM; 701 689 } 702 690 return 0; ··· 704 692 705 693 static void 706 694 nvkm_vmm_ptes_unmap(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, 707 - u64 addr, u64 size, bool sparse) 695 + u64 addr, u64 size, bool sparse, bool pfn) 708 696 { 709 697 const struct nvkm_vmm_desc_func *func = page->desc->func; 710 - nvkm_vmm_iter(vmm, page, addr, size, "unmap", false, NULL, NULL, NULL, 698 + nvkm_vmm_iter(vmm, page, addr, size, "unmap", false, pfn, 699 + NULL, NULL, NULL, 711 700 sparse ? func->sparse : func->invalid ? func->invalid : 712 701 func->unmap); 713 702 } ··· 718 705 u64 addr, u64 size, struct nvkm_vmm_map *map, 719 706 nvkm_vmm_pte_func func) 720 707 { 721 - nvkm_vmm_iter(vmm, page, addr, size, "map", false, 708 + nvkm_vmm_iter(vmm, page, addr, size, "map", false, false, 722 709 NULL, func, map, NULL); 723 710 } 724 711 ··· 726 713 nvkm_vmm_ptes_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, 727 714 u64 addr, u64 size) 728 715 { 729 - nvkm_vmm_iter(vmm, page, addr, size, "unref", false, 716 + nvkm_vmm_iter(vmm, page, addr, size, "unref", false, false, 730 717 nvkm_vmm_unref_ptes, NULL, NULL, NULL); 731 718 } 732 719 ··· 734 721 nvkm_vmm_ptes_get(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, 735 722 u64 addr, u64 size) 736 723 { 737 - u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref", true, 724 + u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref", true, false, 738 725 nvkm_vmm_ref_ptes, NULL, NULL, NULL); 739 726 if (fail != ~0ULL) { 740 727 if (fail != addr) ··· 776 763 new->part = vma->part; 777 764 new->user = vma->user; 778 765 new->busy = vma->busy; 766 + new->mapped = vma->mapped; 779 767 list_add(&new->head, &vma->head); 780 768 return new; 781 769 } ··· 949 935 } 950 936 951 937 static void 938 + nvkm_vma_dump(struct nvkm_vma *vma) 939 + { 940 + printk(KERN_ERR "%016llx %016llx %c%c%c%c%c%c%c%c%c %p\n", 941 + vma->addr, (u64)vma->size, 942 + vma->used ? '-' : 'F', 943 + vma->mapref ? 'R' : '-', 944 + vma->sparse ? 'S' : '-', 945 + vma->page != NVKM_VMA_PAGE_NONE ? '0' + vma->page : '-', 946 + vma->refd != NVKM_VMA_PAGE_NONE ? '0' + vma->refd : '-', 947 + vma->part ? 'P' : '-', 948 + vma->user ? 'U' : '-', 949 + vma->busy ? 'B' : '-', 950 + vma->mapped ? 'M' : '-', 951 + vma->memory); 952 + } 953 + 954 + static void 955 + nvkm_vmm_dump(struct nvkm_vmm *vmm) 956 + { 957 + struct nvkm_vma *vma; 958 + list_for_each_entry(vma, &vmm->list, head) { 959 + nvkm_vma_dump(vma); 960 + } 961 + } 962 + 963 + static void 952 964 nvkm_vmm_dtor(struct nvkm_vmm *vmm) 953 965 { 954 966 struct nvkm_vma *vma; 955 967 struct rb_node *node; 968 + 969 + if (0) 970 + nvkm_vmm_dump(vmm); 956 971 957 972 while ((node = rb_first(&vmm->root))) { 958 973 struct nvkm_vma *vma = rb_entry(node, typeof(*vma), tree); ··· 1015 972 } 1016 973 } 1017 974 975 + static int 976 + nvkm_vmm_ctor_managed(struct nvkm_vmm *vmm, u64 addr, u64 size) 977 + { 978 + struct nvkm_vma *vma; 979 + if (!(vma = nvkm_vma_new(addr, size))) 980 + return -ENOMEM; 981 + vma->mapref = true; 982 + vma->sparse = false; 983 + vma->used = true; 984 + vma->user = true; 985 + nvkm_vmm_node_insert(vmm, vma); 986 + list_add_tail(&vma->head, &vmm->list); 987 + return 0; 988 + } 989 + 1018 990 int 1019 991 nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, 1020 - u32 pd_header, u64 addr, u64 size, struct lock_class_key *key, 1021 - const char *name, struct nvkm_vmm *vmm) 992 + u32 pd_header, bool managed, u64 addr, u64 size, 993 + struct lock_class_key *key, const char *name, 994 + struct nvkm_vmm *vmm) 1022 995 { 1023 996 static struct lock_class_key _key; 1024 997 const struct nvkm_vmm_page *page = func->page; 1025 998 const struct nvkm_vmm_desc *desc; 1026 999 struct nvkm_vma *vma; 1027 - int levels, bits = 0; 1000 + int levels, bits = 0, ret; 1028 1001 1029 1002 vmm->func = func; 1030 1003 vmm->mmu = mmu; ··· 1068 1009 if (WARN_ON(levels > NVKM_VMM_LEVELS_MAX)) 1069 1010 return -EINVAL; 1070 1011 1071 - vmm->start = addr; 1072 - vmm->limit = size ? (addr + size) : (1ULL << bits); 1073 - if (vmm->start > vmm->limit || vmm->limit > (1ULL << bits)) 1074 - return -EINVAL; 1075 - 1076 1012 /* Allocate top-level page table. */ 1077 1013 vmm->pd = nvkm_vmm_pt_new(desc, false, NULL); 1078 1014 if (!vmm->pd) ··· 1090 1036 vmm->free = RB_ROOT; 1091 1037 vmm->root = RB_ROOT; 1092 1038 1093 - if (!(vma = nvkm_vma_new(vmm->start, vmm->limit - vmm->start))) 1094 - return -ENOMEM; 1039 + if (managed) { 1040 + /* Address-space will be managed by the client for the most 1041 + * part, except for a specified area where NVKM allocations 1042 + * are allowed to be placed. 1043 + */ 1044 + vmm->start = 0; 1045 + vmm->limit = 1ULL << bits; 1046 + if (addr + size < addr || addr + size > vmm->limit) 1047 + return -EINVAL; 1095 1048 1096 - nvkm_vmm_free_insert(vmm, vma); 1097 - list_add(&vma->head, &vmm->list); 1049 + /* Client-managed area before the NVKM-managed area. */ 1050 + if (addr && (ret = nvkm_vmm_ctor_managed(vmm, 0, addr))) 1051 + return ret; 1052 + 1053 + /* NVKM-managed area. */ 1054 + if (size) { 1055 + if (!(vma = nvkm_vma_new(addr, size))) 1056 + return -ENOMEM; 1057 + nvkm_vmm_free_insert(vmm, vma); 1058 + list_add_tail(&vma->head, &vmm->list); 1059 + } 1060 + 1061 + /* Client-managed area after the NVKM-managed area. */ 1062 + addr = addr + size; 1063 + size = vmm->limit - addr; 1064 + if (size && (ret = nvkm_vmm_ctor_managed(vmm, addr, size))) 1065 + return ret; 1066 + } else { 1067 + /* Address-space fully managed by NVKM, requiring calls to 1068 + * nvkm_vmm_get()/nvkm_vmm_put() to allocate address-space. 1069 + */ 1070 + vmm->start = addr; 1071 + vmm->limit = size ? (addr + size) : (1ULL << bits); 1072 + if (vmm->start > vmm->limit || vmm->limit > (1ULL << bits)) 1073 + return -EINVAL; 1074 + 1075 + if (!(vma = nvkm_vma_new(vmm->start, vmm->limit - vmm->start))) 1076 + return -ENOMEM; 1077 + 1078 + nvkm_vmm_free_insert(vmm, vma); 1079 + list_add(&vma->head, &vmm->list); 1080 + } 1081 + 1098 1082 return 0; 1099 1083 } 1100 1084 1101 1085 int 1102 1086 nvkm_vmm_new_(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, 1103 - u32 hdr, u64 addr, u64 size, struct lock_class_key *key, 1104 - const char *name, struct nvkm_vmm **pvmm) 1087 + u32 hdr, bool managed, u64 addr, u64 size, 1088 + struct lock_class_key *key, const char *name, 1089 + struct nvkm_vmm **pvmm) 1105 1090 { 1106 1091 if (!(*pvmm = kzalloc(sizeof(**pvmm), GFP_KERNEL))) 1107 1092 return -ENOMEM; 1108 - return nvkm_vmm_ctor(func, mmu, hdr, addr, size, key, name, *pvmm); 1093 + return nvkm_vmm_ctor(func, mmu, hdr, managed, addr, size, key, name, *pvmm); 1094 + } 1095 + 1096 + static struct nvkm_vma * 1097 + nvkm_vmm_pfn_split_merge(struct nvkm_vmm *vmm, struct nvkm_vma *vma, 1098 + u64 addr, u64 size, u8 page, bool map) 1099 + { 1100 + struct nvkm_vma *prev = NULL; 1101 + struct nvkm_vma *next = NULL; 1102 + 1103 + if (vma->addr == addr && vma->part && (prev = node(vma, prev))) { 1104 + if (prev->memory || prev->mapped != map) 1105 + prev = NULL; 1106 + } 1107 + 1108 + if (vma->addr + vma->size == addr + size && (next = node(vma, next))) { 1109 + if (!next->part || 1110 + next->memory || next->mapped != map) 1111 + next = NULL; 1112 + } 1113 + 1114 + if (prev || next) 1115 + return nvkm_vmm_node_merge(vmm, prev, vma, next, size); 1116 + return nvkm_vmm_node_split(vmm, vma, addr, size); 1117 + } 1118 + 1119 + int 1120 + nvkm_vmm_pfn_unmap(struct nvkm_vmm *vmm, u64 addr, u64 size) 1121 + { 1122 + struct nvkm_vma *vma = nvkm_vmm_node_search(vmm, addr); 1123 + struct nvkm_vma *next; 1124 + u64 limit = addr + size; 1125 + u64 start = addr; 1126 + 1127 + if (!vma) 1128 + return -EINVAL; 1129 + 1130 + do { 1131 + if (!vma->mapped || vma->memory) 1132 + continue; 1133 + 1134 + size = min(limit - start, vma->size - (start - vma->addr)); 1135 + 1136 + nvkm_vmm_ptes_unmap_put(vmm, &vmm->func->page[vma->refd], 1137 + start, size, false, true); 1138 + 1139 + next = nvkm_vmm_pfn_split_merge(vmm, vma, start, size, 0, false); 1140 + if (!WARN_ON(!next)) { 1141 + vma = next; 1142 + vma->refd = NVKM_VMA_PAGE_NONE; 1143 + vma->mapped = false; 1144 + } 1145 + } while ((vma = node(vma, next)) && (start = vma->addr) < limit); 1146 + 1147 + return 0; 1148 + } 1149 + 1150 + /*TODO: 1151 + * - Avoid PT readback (for dma_unmap etc), this might end up being dealt 1152 + * with inside HMM, which would be a lot nicer for us to deal with. 1153 + * - Multiple page sizes (particularly for huge page support). 1154 + * - Support for systems without a 4KiB page size. 1155 + */ 1156 + int 1157 + nvkm_vmm_pfn_map(struct nvkm_vmm *vmm, u8 shift, u64 addr, u64 size, u64 *pfn) 1158 + { 1159 + const struct nvkm_vmm_page *page = vmm->func->page; 1160 + struct nvkm_vma *vma, *tmp; 1161 + u64 limit = addr + size; 1162 + u64 start = addr; 1163 + int pm = size >> shift; 1164 + int pi = 0; 1165 + 1166 + /* Only support mapping where the page size of the incoming page 1167 + * array matches a page size available for direct mapping. 1168 + */ 1169 + while (page->shift && page->shift != shift && 1170 + page->desc->func->pfn == NULL) 1171 + page++; 1172 + 1173 + if (!page->shift || !IS_ALIGNED(addr, 1ULL << shift) || 1174 + !IS_ALIGNED(size, 1ULL << shift) || 1175 + addr + size < addr || addr + size > vmm->limit) { 1176 + VMM_DEBUG(vmm, "paged map %d %d %016llx %016llx\n", 1177 + shift, page->shift, addr, size); 1178 + return -EINVAL; 1179 + } 1180 + 1181 + if (!(vma = nvkm_vmm_node_search(vmm, addr))) 1182 + return -ENOENT; 1183 + 1184 + do { 1185 + bool map = !!(pfn[pi] & NVKM_VMM_PFN_V); 1186 + bool mapped = vma->mapped; 1187 + u64 size = limit - start; 1188 + u64 addr = start; 1189 + int pn, ret = 0; 1190 + 1191 + /* Narrow the operation window to cover a single action (page 1192 + * should be mapped or not) within a single VMA. 1193 + */ 1194 + for (pn = 0; pi + pn < pm; pn++) { 1195 + if (map != !!(pfn[pi + pn] & NVKM_VMM_PFN_V)) 1196 + break; 1197 + } 1198 + size = min_t(u64, size, pn << page->shift); 1199 + size = min_t(u64, size, vma->size + vma->addr - addr); 1200 + 1201 + /* Reject any operation to unmanaged regions, and areas that 1202 + * have nvkm_memory objects mapped in them already. 1203 + */ 1204 + if (!vma->mapref || vma->memory) { 1205 + ret = -EINVAL; 1206 + goto next; 1207 + } 1208 + 1209 + /* In order to both properly refcount GPU page tables, and 1210 + * prevent "normal" mappings and these direct mappings from 1211 + * interfering with each other, we need to track contiguous 1212 + * ranges that have been mapped with this interface. 1213 + * 1214 + * Here we attempt to either split an existing VMA so we're 1215 + * able to flag the region as either unmapped/mapped, or to 1216 + * merge with adjacent VMAs that are already compatible. 1217 + * 1218 + * If the region is already compatible, nothing is required. 1219 + */ 1220 + if (map != mapped) { 1221 + tmp = nvkm_vmm_pfn_split_merge(vmm, vma, addr, size, 1222 + page - 1223 + vmm->func->page, map); 1224 + if (WARN_ON(!tmp)) { 1225 + ret = -ENOMEM; 1226 + goto next; 1227 + } 1228 + 1229 + if ((tmp->mapped = map)) 1230 + tmp->refd = page - vmm->func->page; 1231 + else 1232 + tmp->refd = NVKM_VMA_PAGE_NONE; 1233 + vma = tmp; 1234 + } 1235 + 1236 + /* Update HW page tables. */ 1237 + if (map) { 1238 + struct nvkm_vmm_map args; 1239 + args.page = page; 1240 + args.pfn = &pfn[pi]; 1241 + 1242 + if (!mapped) { 1243 + ret = nvkm_vmm_ptes_get_map(vmm, page, addr, 1244 + size, &args, page-> 1245 + desc->func->pfn); 1246 + } else { 1247 + nvkm_vmm_ptes_map(vmm, page, addr, size, &args, 1248 + page->desc->func->pfn); 1249 + } 1250 + } else { 1251 + if (mapped) { 1252 + nvkm_vmm_ptes_unmap_put(vmm, page, addr, size, 1253 + false, true); 1254 + } 1255 + } 1256 + 1257 + next: 1258 + /* Iterate to next operation. */ 1259 + if (vma->addr + vma->size == addr + size) 1260 + vma = node(vma, next); 1261 + start += size; 1262 + 1263 + if (ret) { 1264 + /* Failure is signalled by clearing the valid bit on 1265 + * any PFN that couldn't be modified as requested. 1266 + */ 1267 + while (size) { 1268 + pfn[pi++] = NVKM_VMM_PFN_NONE; 1269 + size -= 1 << page->shift; 1270 + } 1271 + } else { 1272 + pi += size >> page->shift; 1273 + } 1274 + } while (vma && start < limit); 1275 + 1276 + return 0; 1109 1277 } 1110 1278 1111 1279 void 1112 1280 nvkm_vmm_unmap_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma) 1113 1281 { 1114 - struct nvkm_vma *next = node(vma, next); 1115 1282 struct nvkm_vma *prev = NULL; 1283 + struct nvkm_vma *next; 1116 1284 1117 1285 nvkm_memory_tags_put(vma->memory, vmm->mmu->subdev.device, &vma->tags); 1118 1286 nvkm_memory_unref(&vma->memory); 1287 + vma->mapped = false; 1119 1288 1120 - if (!vma->part || ((prev = node(vma, prev)), prev->memory)) 1289 + if (vma->part && (prev = node(vma, prev)) && prev->mapped) 1121 1290 prev = NULL; 1122 - if (!next->part || next->memory) 1291 + if ((next = node(vma, next)) && (!next->part || next->mapped)) 1123 1292 next = NULL; 1124 1293 nvkm_vmm_node_merge(vmm, prev, vma, next, vma->size); 1125 1294 } 1126 1295 1127 1296 void 1128 - nvkm_vmm_unmap_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma) 1297 + nvkm_vmm_unmap_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma, bool pfn) 1129 1298 { 1130 1299 const struct nvkm_vmm_page *page = &vmm->func->page[vma->refd]; 1131 1300 1132 1301 if (vma->mapref) { 1133 - nvkm_vmm_ptes_unmap_put(vmm, page, vma->addr, vma->size, vma->sparse); 1302 + nvkm_vmm_ptes_unmap_put(vmm, page, vma->addr, vma->size, vma->sparse, pfn); 1134 1303 vma->refd = NVKM_VMA_PAGE_NONE; 1135 1304 } else { 1136 - nvkm_vmm_ptes_unmap(vmm, page, vma->addr, vma->size, vma->sparse); 1305 + nvkm_vmm_ptes_unmap(vmm, page, vma->addr, vma->size, vma->sparse, pfn); 1137 1306 } 1138 1307 1139 1308 nvkm_vmm_unmap_region(vmm, vma); ··· 1367 1090 { 1368 1091 if (vma->memory) { 1369 1092 mutex_lock(&vmm->mutex); 1370 - nvkm_vmm_unmap_locked(vmm, vma); 1093 + nvkm_vmm_unmap_locked(vmm, vma, false); 1371 1094 mutex_unlock(&vmm->mutex); 1372 1095 } 1373 1096 } ··· 1501 1224 nvkm_memory_tags_put(vma->memory, vmm->mmu->subdev.device, &vma->tags); 1502 1225 nvkm_memory_unref(&vma->memory); 1503 1226 vma->memory = nvkm_memory_ref(map->memory); 1227 + vma->mapped = true; 1504 1228 vma->tags = map->tags; 1505 1229 return 0; 1506 1230 } ··· 1547 1269 1548 1270 if (vma->mapref || !vma->sparse) { 1549 1271 do { 1550 - const bool map = next->memory != NULL; 1272 + const bool mem = next->memory != NULL; 1273 + const bool map = next->mapped; 1551 1274 const u8 refd = next->refd; 1552 1275 const u64 addr = next->addr; 1553 1276 u64 size = next->size; 1554 1277 1555 1278 /* Merge regions that are in the same state. */ 1556 1279 while ((next = node(next, next)) && next->part && 1557 - (next->memory != NULL) == map && 1280 + (next->mapped == map) && 1281 + (next->memory != NULL) == mem && 1558 1282 (next->refd == refd)) 1559 1283 size += next->size; 1560 1284 ··· 1566 1286 * the page tree. 1567 1287 */ 1568 1288 nvkm_vmm_ptes_unmap_put(vmm, &page[refd], addr, 1569 - size, vma->sparse); 1289 + size, vma->sparse, 1290 + !mem); 1570 1291 } else 1571 1292 if (refd != NVKM_VMA_PAGE_NONE) { 1572 1293 /* Drop allocation-time PTE references. */ ··· 1582 1301 */ 1583 1302 next = vma; 1584 1303 do { 1585 - if (next->memory) 1304 + if (next->mapped) 1586 1305 nvkm_vmm_unmap_region(vmm, next); 1587 1306 } while ((next = node(vma, next)) && next->part); 1588 1307 ··· 1803 1522 } 1804 1523 1805 1524 static bool 1806 - nvkm_vmm_boot_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes) 1525 + nvkm_vmm_boot_ptes(struct nvkm_vmm_iter *it, bool pfn, u32 ptei, u32 ptes) 1807 1526 { 1808 1527 const struct nvkm_vmm_desc *desc = it->desc; 1809 1528 const int type = desc->type == SPT; ··· 1825 1544 if (ret) 1826 1545 return ret; 1827 1546 1828 - nvkm_vmm_iter(vmm, page, vmm->start, limit, "bootstrap", false, 1547 + nvkm_vmm_iter(vmm, page, vmm->start, limit, "bootstrap", false, false, 1829 1548 nvkm_vmm_boot_ptes, NULL, NULL, NULL); 1830 1549 vmm->bootstrapped = true; 1831 1550 return 0; ··· 1865 1584 struct nvkm_mmu *mmu = device->mmu; 1866 1585 struct nvkm_vmm *vmm = NULL; 1867 1586 int ret; 1868 - ret = mmu->func->vmm.ctor(mmu, addr, size, argv, argc, key, name, &vmm); 1587 + ret = mmu->func->vmm.ctor(mmu, false, addr, size, argv, argc, 1588 + key, name, &vmm); 1869 1589 if (ret) 1870 1590 nvkm_vmm_unref(&vmm); 1871 1591 *pvmm = vmm;
+55 -27
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h
··· 67 67 nvkm_vmm_pte_func mem; 68 68 nvkm_vmm_pte_func dma; 69 69 nvkm_vmm_pte_func sgl; 70 + 71 + nvkm_vmm_pte_func pfn; 72 + bool (*pfn_clear)(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32 ptei, u32 ptes); 73 + nvkm_vmm_pxe_func pfn_unmap; 70 74 }; 71 75 72 76 extern const struct nvkm_vmm_desc_func gf100_vmm_pgd; ··· 145 141 struct nvkm_vmm_map *); 146 142 void (*flush)(struct nvkm_vmm *, int depth); 147 143 144 + int (*mthd)(struct nvkm_vmm *, struct nvkm_client *, 145 + u32 mthd, void *argv, u32 argc); 146 + 147 + void (*invalidate_pdb)(struct nvkm_vmm *, u64 addr); 148 + 148 149 u64 page_block; 149 150 const struct nvkm_vmm_page page[]; 150 151 }; ··· 160 151 }; 161 152 162 153 int nvkm_vmm_new_(const struct nvkm_vmm_func *, struct nvkm_mmu *, 163 - u32 pd_header, u64 addr, u64 size, struct lock_class_key *, 164 - const char *name, struct nvkm_vmm **); 154 + u32 pd_header, bool managed, u64 addr, u64 size, 155 + struct lock_class_key *, const char *name, 156 + struct nvkm_vmm **); 165 157 int nvkm_vmm_ctor(const struct nvkm_vmm_func *, struct nvkm_mmu *, 166 - u32 pd_header, u64 addr, u64 size, struct lock_class_key *, 167 - const char *name, struct nvkm_vmm *); 158 + u32 pd_header, bool managed, u64 addr, u64 size, 159 + struct lock_class_key *, const char *name, struct nvkm_vmm *); 168 160 struct nvkm_vma *nvkm_vmm_node_search(struct nvkm_vmm *, u64 addr); 169 161 struct nvkm_vma *nvkm_vmm_node_split(struct nvkm_vmm *, struct nvkm_vma *, 170 162 u64 addr, u64 size); ··· 173 163 bool sparse, u8 page, u8 align, u64 size, 174 164 struct nvkm_vma **pvma); 175 165 void nvkm_vmm_put_locked(struct nvkm_vmm *, struct nvkm_vma *); 176 - void nvkm_vmm_unmap_locked(struct nvkm_vmm *, struct nvkm_vma *); 177 - void nvkm_vmm_unmap_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma); 166 + void nvkm_vmm_unmap_locked(struct nvkm_vmm *, struct nvkm_vma *, bool pfn); 167 + void nvkm_vmm_unmap_region(struct nvkm_vmm *, struct nvkm_vma *); 168 + 169 + #define NVKM_VMM_PFN_ADDR 0xfffffffffffff000ULL 170 + #define NVKM_VMM_PFN_ADDR_SHIFT 12 171 + #define NVKM_VMM_PFN_APER 0x00000000000000f0ULL 172 + #define NVKM_VMM_PFN_HOST 0x0000000000000000ULL 173 + #define NVKM_VMM_PFN_VRAM 0x0000000000000010ULL 174 + #define NVKM_VMM_PFN_W 0x0000000000000002ULL 175 + #define NVKM_VMM_PFN_V 0x0000000000000001ULL 176 + #define NVKM_VMM_PFN_NONE 0x0000000000000000ULL 177 + 178 + int nvkm_vmm_pfn_map(struct nvkm_vmm *, u8 page, u64 addr, u64 size, u64 *pfn); 179 + int nvkm_vmm_pfn_unmap(struct nvkm_vmm *, u64 addr, u64 size); 178 180 179 181 struct nvkm_vma *nvkm_vma_tail(struct nvkm_vma *, u64 tail); 180 182 181 183 int nv04_vmm_new_(const struct nvkm_vmm_func *, struct nvkm_mmu *, u32, 182 - u64, u64, void *, u32, struct lock_class_key *, 184 + bool, u64, u64, void *, u32, struct lock_class_key *, 183 185 const char *, struct nvkm_vmm **); 184 186 int nv04_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *); 185 187 ··· 201 179 void nv50_vmm_flush(struct nvkm_vmm *, int); 202 180 203 181 int gf100_vmm_new_(const struct nvkm_vmm_func *, const struct nvkm_vmm_func *, 204 - struct nvkm_mmu *, u64, u64, void *, u32, 182 + struct nvkm_mmu *, bool, u64, u64, void *, u32, 205 183 struct lock_class_key *, const char *, struct nvkm_vmm **); 206 184 int gf100_vmm_join_(struct nvkm_vmm *, struct nvkm_memory *, u64 base); 207 185 int gf100_vmm_join(struct nvkm_vmm *, struct nvkm_memory *); 208 186 void gf100_vmm_part(struct nvkm_vmm *, struct nvkm_memory *); 209 187 int gf100_vmm_aper(enum nvkm_memory_target); 210 188 int gf100_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *); 211 - void gf100_vmm_flush_(struct nvkm_vmm *, int); 212 189 void gf100_vmm_flush(struct nvkm_vmm *, int); 190 + void gf100_vmm_invalidate(struct nvkm_vmm *, u32 type); 191 + void gf100_vmm_invalidate_pdb(struct nvkm_vmm *, u64 addr); 213 192 214 193 int gk20a_vmm_aper(enum nvkm_memory_target); 215 194 216 195 int gm200_vmm_new_(const struct nvkm_vmm_func *, const struct nvkm_vmm_func *, 217 - struct nvkm_mmu *, u64, u64, void *, u32, 196 + struct nvkm_mmu *, bool, u64, u64, void *, u32, 218 197 struct lock_class_key *, const char *, struct nvkm_vmm **); 219 198 int gm200_vmm_join_(struct nvkm_vmm *, struct nvkm_memory *, u64 base); 220 199 int gm200_vmm_join(struct nvkm_vmm *, struct nvkm_memory *); 221 200 201 + int gp100_vmm_new_(const struct nvkm_vmm_func *, 202 + struct nvkm_mmu *, bool, u64, u64, void *, u32, 203 + struct lock_class_key *, const char *, struct nvkm_vmm **); 222 204 int gp100_vmm_join(struct nvkm_vmm *, struct nvkm_memory *); 223 205 int gp100_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *); 224 206 void gp100_vmm_flush(struct nvkm_vmm *, int); 207 + int gp100_vmm_mthd(struct nvkm_vmm *, struct nvkm_client *, u32, void *, u32); 208 + void gp100_vmm_invalidate_pdb(struct nvkm_vmm *, u64 addr); 225 209 226 210 int gv100_vmm_join(struct nvkm_vmm *, struct nvkm_memory *); 227 211 228 - int nv04_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 212 + int nv04_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 229 213 struct lock_class_key *, const char *, struct nvkm_vmm **); 230 - int nv41_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 214 + int nv41_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 231 215 struct lock_class_key *, const char *, struct nvkm_vmm **); 232 - int nv44_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 216 + int nv44_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 233 217 struct lock_class_key *, const char *, struct nvkm_vmm **); 234 - int nv50_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 218 + int nv50_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 235 219 struct lock_class_key *, const char *, struct nvkm_vmm **); 236 - int mcp77_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 220 + int mcp77_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 237 221 struct lock_class_key *, const char *, struct nvkm_vmm **); 238 - int g84_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 222 + int g84_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 239 223 struct lock_class_key *, const char *, struct nvkm_vmm **); 240 - int gf100_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 224 + int gf100_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 241 225 struct lock_class_key *, const char *, struct nvkm_vmm **); 242 - int gk104_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 226 + int gk104_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 243 227 struct lock_class_key *, const char *, struct nvkm_vmm **); 244 - int gk20a_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 228 + int gk20a_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 245 229 struct lock_class_key *, const char *, struct nvkm_vmm **); 246 - int gm200_vmm_new_fixed(struct nvkm_mmu *, u64, u64, void *, u32, 230 + int gm200_vmm_new_fixed(struct nvkm_mmu *, bool, u64, u64, void *, u32, 247 231 struct lock_class_key *, const char *, 248 232 struct nvkm_vmm **); 249 - int gm200_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 233 + int gm200_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 250 234 struct lock_class_key *, const char *, 251 235 struct nvkm_vmm **); 252 - int gm20b_vmm_new_fixed(struct nvkm_mmu *, u64, u64, void *, u32, 236 + int gm20b_vmm_new_fixed(struct nvkm_mmu *, bool, u64, u64, void *, u32, 253 237 struct lock_class_key *, const char *, 254 238 struct nvkm_vmm **); 255 - int gm20b_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 239 + int gm20b_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 256 240 struct lock_class_key *, const char *, 257 241 struct nvkm_vmm **); 258 - int gp100_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 242 + int gp100_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 259 243 struct lock_class_key *, const char *, 260 244 struct nvkm_vmm **); 261 - int gp10b_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 245 + int gp10b_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 262 246 struct lock_class_key *, const char *, 263 247 struct nvkm_vmm **); 264 - int gv100_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 248 + int gv100_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 265 249 struct lock_class_key *, const char *, 266 250 struct nvkm_vmm **); 267 - int tu104_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, 251 + int tu102_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32, 268 252 struct lock_class_key *, const char *, 269 253 struct nvkm_vmm **); 270 254
+39 -17
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c
··· 178 178 }; 179 179 180 180 void 181 - gf100_vmm_flush_(struct nvkm_vmm *vmm, int depth) 181 + gf100_vmm_invalidate_pdb(struct nvkm_vmm *vmm, u64 addr) 182 + { 183 + struct nvkm_device *device = vmm->mmu->subdev.device; 184 + nvkm_wr32(device, 0x100cb8, addr); 185 + } 186 + 187 + void 188 + gf100_vmm_invalidate(struct nvkm_vmm *vmm, u32 type) 182 189 { 183 190 struct nvkm_subdev *subdev = &vmm->mmu->subdev; 184 191 struct nvkm_device *device = subdev->device; 185 - u32 type = depth << 24; 186 - 187 - type = 0x00000001; /* PAGE_ALL */ 188 - if (atomic_read(&vmm->engref[NVKM_SUBDEV_BAR])) 189 - type |= 0x00000004; /* HUB_ONLY */ 192 + struct nvkm_mmu_pt *pd = vmm->pd->pt[0]; 193 + u64 addr = 0; 190 194 191 195 mutex_lock(&subdev->mutex); 192 196 /* Looks like maybe a "free flush slots" counter, the ··· 201 197 break; 202 198 ); 203 199 204 - nvkm_wr32(device, 0x100cb8, vmm->pd->pt[0]->addr >> 8); 200 + if (!(type & 0x00000002) /* ALL_PDB. */) { 201 + switch (nvkm_memory_target(pd->memory)) { 202 + case NVKM_MEM_TARGET_VRAM: addr |= 0x00000000; break; 203 + case NVKM_MEM_TARGET_HOST: addr |= 0x00000002; break; 204 + case NVKM_MEM_TARGET_NCOH: addr |= 0x00000003; break; 205 + default: 206 + WARN_ON(1); 207 + break; 208 + } 209 + addr |= (vmm->pd->pt[0]->addr >> 12) << 4; 210 + 211 + vmm->func->invalidate_pdb(vmm, addr); 212 + } 213 + 205 214 nvkm_wr32(device, 0x100cbc, 0x80000000 | type); 206 215 207 216 /* Wait for flush to be queued? */ ··· 228 211 void 229 212 gf100_vmm_flush(struct nvkm_vmm *vmm, int depth) 230 213 { 231 - gf100_vmm_flush_(vmm, 0); 214 + u32 type = 0x00000001; /* PAGE_ALL */ 215 + if (atomic_read(&vmm->engref[NVKM_SUBDEV_BAR])) 216 + type |= 0x00000004; /* HUB_ONLY */ 217 + gf100_vmm_invalidate(vmm, type); 232 218 } 233 219 234 220 int ··· 374 354 .aper = gf100_vmm_aper, 375 355 .valid = gf100_vmm_valid, 376 356 .flush = gf100_vmm_flush, 357 + .invalidate_pdb = gf100_vmm_invalidate_pdb, 377 358 .page = { 378 359 { 17, &gf100_vmm_desc_17_17[0], NVKM_VMM_PAGE_xVxC }, 379 360 { 12, &gf100_vmm_desc_17_12[0], NVKM_VMM_PAGE_xVHx }, ··· 389 368 .aper = gf100_vmm_aper, 390 369 .valid = gf100_vmm_valid, 391 370 .flush = gf100_vmm_flush, 371 + .invalidate_pdb = gf100_vmm_invalidate_pdb, 392 372 .page = { 393 373 { 16, &gf100_vmm_desc_16_16[0], NVKM_VMM_PAGE_xVxC }, 394 374 { 12, &gf100_vmm_desc_16_12[0], NVKM_VMM_PAGE_xVHx }, ··· 400 378 int 401 379 gf100_vmm_new_(const struct nvkm_vmm_func *func_16, 402 380 const struct nvkm_vmm_func *func_17, 403 - struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 404 - struct lock_class_key *key, const char *name, 405 - struct nvkm_vmm **pvmm) 381 + struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 382 + void *argv, u32 argc, struct lock_class_key *key, 383 + const char *name, struct nvkm_vmm **pvmm) 406 384 { 407 385 switch (mmu->subdev.device->fb->page) { 408 - case 16: return nv04_vmm_new_(func_16, mmu, 0, addr, size, 386 + case 16: return nv04_vmm_new_(func_16, mmu, 0, managed, addr, size, 409 387 argv, argc, key, name, pvmm); 410 - case 17: return nv04_vmm_new_(func_17, mmu, 0, addr, size, 388 + case 17: return nv04_vmm_new_(func_17, mmu, 0, managed, addr, size, 411 389 argv, argc, key, name, pvmm); 412 390 default: 413 391 WARN_ON(1); ··· 416 394 } 417 395 418 396 int 419 - gf100_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 420 - struct lock_class_key *key, const char *name, 421 - struct nvkm_vmm **pvmm) 397 + gf100_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 398 + void *argv, u32 argc, struct lock_class_key *key, 399 + const char *name, struct nvkm_vmm **pvmm) 422 400 { 423 - return gf100_vmm_new_(&gf100_vmm_16, &gf100_vmm_17, mmu, addr, 401 + return gf100_vmm_new_(&gf100_vmm_16, &gf100_vmm_17, mmu, managed, addr, 424 402 size, argv, argc, key, name, pvmm); 425 403 }
+6 -4
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk104.c
··· 71 71 .aper = gf100_vmm_aper, 72 72 .valid = gf100_vmm_valid, 73 73 .flush = gf100_vmm_flush, 74 + .invalidate_pdb = gf100_vmm_invalidate_pdb, 74 75 .page = { 75 76 { 17, &gk104_vmm_desc_17_17[0], NVKM_VMM_PAGE_xVxC }, 76 77 { 12, &gk104_vmm_desc_17_12[0], NVKM_VMM_PAGE_xVHx }, ··· 86 85 .aper = gf100_vmm_aper, 87 86 .valid = gf100_vmm_valid, 88 87 .flush = gf100_vmm_flush, 88 + .invalidate_pdb = gf100_vmm_invalidate_pdb, 89 89 .page = { 90 90 { 16, &gk104_vmm_desc_16_16[0], NVKM_VMM_PAGE_xVxC }, 91 91 { 12, &gk104_vmm_desc_16_12[0], NVKM_VMM_PAGE_xVHx }, ··· 95 93 }; 96 94 97 95 int 98 - gk104_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 99 - struct lock_class_key *key, const char *name, 100 - struct nvkm_vmm **pvmm) 96 + gk104_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 97 + void *argv, u32 argc, struct lock_class_key *key, 98 + const char *name, struct nvkm_vmm **pvmm) 101 99 { 102 - return gf100_vmm_new_(&gk104_vmm_16, &gk104_vmm_17, mmu, addr, 100 + return gf100_vmm_new_(&gk104_vmm_16, &gk104_vmm_17, mmu, managed, addr, 103 101 size, argv, argc, key, name, pvmm); 104 102 }
+6 -4
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk20a.c
··· 40 40 .aper = gf100_vmm_aper, 41 41 .valid = gf100_vmm_valid, 42 42 .flush = gf100_vmm_flush, 43 + .invalidate_pdb = gf100_vmm_invalidate_pdb, 43 44 .page = { 44 45 { 17, &gk104_vmm_desc_17_17[0], NVKM_VMM_PAGE_xxHC }, 45 46 { 12, &gk104_vmm_desc_17_12[0], NVKM_VMM_PAGE_xxHx }, ··· 55 54 .aper = gf100_vmm_aper, 56 55 .valid = gf100_vmm_valid, 57 56 .flush = gf100_vmm_flush, 57 + .invalidate_pdb = gf100_vmm_invalidate_pdb, 58 58 .page = { 59 59 { 16, &gk104_vmm_desc_16_16[0], NVKM_VMM_PAGE_xxHC }, 60 60 { 12, &gk104_vmm_desc_16_12[0], NVKM_VMM_PAGE_xxHx }, ··· 64 62 }; 65 63 66 64 int 67 - gk20a_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 68 - struct lock_class_key *key, const char *name, 69 - struct nvkm_vmm **pvmm) 65 + gk20a_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 66 + void *argv, u32 argc, struct lock_class_key *key, 67 + const char *name, struct nvkm_vmm **pvmm) 70 68 { 71 - return gf100_vmm_new_(&gk20a_vmm_16, &gk20a_vmm_17, mmu, addr, 69 + return gf100_vmm_new_(&gk20a_vmm_16, &gk20a_vmm_17, mmu, managed, addr, 72 70 size, argv, argc, key, name, pvmm); 73 71 }
+12 -10
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm200.c
··· 113 113 .aper = gf100_vmm_aper, 114 114 .valid = gf100_vmm_valid, 115 115 .flush = gf100_vmm_flush, 116 + .invalidate_pdb = gf100_vmm_invalidate_pdb, 116 117 .page = { 117 118 { 27, &gm200_vmm_desc_17_17[1], NVKM_VMM_PAGE_Sxxx }, 118 119 { 17, &gm200_vmm_desc_17_17[0], NVKM_VMM_PAGE_SVxC }, ··· 129 128 .aper = gf100_vmm_aper, 130 129 .valid = gf100_vmm_valid, 131 130 .flush = gf100_vmm_flush, 131 + .invalidate_pdb = gf100_vmm_invalidate_pdb, 132 132 .page = { 133 133 { 27, &gm200_vmm_desc_16_16[1], NVKM_VMM_PAGE_Sxxx }, 134 134 { 16, &gm200_vmm_desc_16_16[0], NVKM_VMM_PAGE_SVxC }, ··· 141 139 int 142 140 gm200_vmm_new_(const struct nvkm_vmm_func *func_16, 143 141 const struct nvkm_vmm_func *func_17, 144 - struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 145 - struct lock_class_key *key, const char *name, 146 - struct nvkm_vmm **pvmm) 142 + struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 143 + void *argv, u32 argc, struct lock_class_key *key, 144 + const char *name, struct nvkm_vmm **pvmm) 147 145 { 148 146 const struct nvkm_vmm_func *func; 149 147 union { ··· 165 163 } else 166 164 return ret; 167 165 168 - return nvkm_vmm_new_(func, mmu, 0, addr, size, key, name, pvmm); 166 + return nvkm_vmm_new_(func, mmu, 0, managed, addr, size, key, name, pvmm); 169 167 } 170 168 171 169 int 172 - gm200_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 173 - struct lock_class_key *key, const char *name, 174 - struct nvkm_vmm **pvmm) 170 + gm200_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 171 + void *argv, u32 argc, struct lock_class_key *key, 172 + const char *name, struct nvkm_vmm **pvmm) 175 173 { 176 - return gm200_vmm_new_(&gm200_vmm_16, &gm200_vmm_17, mmu, addr, 174 + return gm200_vmm_new_(&gm200_vmm_16, &gm200_vmm_17, mmu, managed, addr, 177 175 size, argv, argc, key, name, pvmm); 178 176 } 179 177 180 178 int 181 - gm200_vmm_new_fixed(struct nvkm_mmu *mmu, u64 addr, u64 size, 179 + gm200_vmm_new_fixed(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 182 180 void *argv, u32 argc, struct lock_class_key *key, 183 181 const char *name, struct nvkm_vmm **pvmm) 184 182 { 185 - return gf100_vmm_new_(&gm200_vmm_16, &gm200_vmm_17, mmu, addr, 183 + return gf100_vmm_new_(&gm200_vmm_16, &gm200_vmm_17, mmu, managed, addr, 186 184 size, argv, argc, key, name, pvmm); 187 185 }
+8 -6
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm20b.c
··· 28 28 .aper = gk20a_vmm_aper, 29 29 .valid = gf100_vmm_valid, 30 30 .flush = gf100_vmm_flush, 31 + .invalidate_pdb = gf100_vmm_invalidate_pdb, 31 32 .page = { 32 33 { 27, &gm200_vmm_desc_17_17[1], NVKM_VMM_PAGE_Sxxx }, 33 34 { 17, &gm200_vmm_desc_17_17[0], NVKM_VMM_PAGE_SxHC }, ··· 44 43 .aper = gk20a_vmm_aper, 45 44 .valid = gf100_vmm_valid, 46 45 .flush = gf100_vmm_flush, 46 + .invalidate_pdb = gf100_vmm_invalidate_pdb, 47 47 .page = { 48 48 { 27, &gm200_vmm_desc_16_16[1], NVKM_VMM_PAGE_Sxxx }, 49 49 { 16, &gm200_vmm_desc_16_16[0], NVKM_VMM_PAGE_SxHC }, ··· 54 52 }; 55 53 56 54 int 57 - gm20b_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 58 - struct lock_class_key *key, const char *name, 59 - struct nvkm_vmm **pvmm) 55 + gm20b_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 56 + void *argv, u32 argc, struct lock_class_key *key, 57 + const char *name, struct nvkm_vmm **pvmm) 60 58 { 61 - return gm200_vmm_new_(&gm20b_vmm_16, &gm20b_vmm_17, mmu, addr, 59 + return gm200_vmm_new_(&gm20b_vmm_16, &gm20b_vmm_17, mmu, managed, addr, 62 60 size, argv, argc, key, name, pvmm); 63 61 } 64 62 65 63 int 66 - gm20b_vmm_new_fixed(struct nvkm_mmu *mmu, u64 addr, u64 size, 64 + gm20b_vmm_new_fixed(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 67 65 void *argv, u32 argc, struct lock_class_key *key, 68 66 const char *name, struct nvkm_vmm **pvmm) 69 67 { 70 - return gf100_vmm_new_(&gm20b_vmm_16, &gm20b_vmm_17, mmu, addr, 68 + return gf100_vmm_new_(&gm20b_vmm_16, &gm20b_vmm_17, mmu, managed, addr, 71 69 size, argv, argc, key, name, pvmm); 72 70 }
+203 -7
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c
··· 21 21 */ 22 22 #include "vmm.h" 23 23 24 + #include <core/client.h> 24 25 #include <subdev/fb.h> 25 26 #include <subdev/ltc.h> 27 + #include <subdev/timer.h> 28 + #include <engine/gr.h> 26 29 27 30 #include <nvif/ifc00d.h> 28 31 #include <nvif/unpack.h> 32 + 33 + static void 34 + gp100_vmm_pfn_unmap(struct nvkm_vmm *vmm, 35 + struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) 36 + { 37 + struct device *dev = vmm->mmu->subdev.device->dev; 38 + dma_addr_t addr; 39 + 40 + nvkm_kmap(pt->memory); 41 + while (ptes--) { 42 + u32 datalo = nvkm_ro32(pt->memory, pt->base + ptei * 8 + 0); 43 + u32 datahi = nvkm_ro32(pt->memory, pt->base + ptei * 8 + 4); 44 + u64 data = (u64)datahi << 32 | datalo; 45 + if ((data & (3ULL << 1)) != 0) { 46 + addr = (data >> 8) << 12; 47 + dma_unmap_page(dev, addr, PAGE_SIZE, DMA_BIDIRECTIONAL); 48 + } 49 + ptei++; 50 + } 51 + nvkm_done(pt->memory); 52 + } 53 + 54 + static bool 55 + gp100_vmm_pfn_clear(struct nvkm_vmm *vmm, 56 + struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) 57 + { 58 + bool dma = false; 59 + nvkm_kmap(pt->memory); 60 + while (ptes--) { 61 + u32 datalo = nvkm_ro32(pt->memory, pt->base + ptei * 8 + 0); 62 + u32 datahi = nvkm_ro32(pt->memory, pt->base + ptei * 8 + 4); 63 + u64 data = (u64)datahi << 32 | datalo; 64 + if ((data & BIT_ULL(0)) && (data & (3ULL << 1)) != 0) { 65 + VMM_WO064(pt, vmm, ptei * 8, data & ~BIT_ULL(0)); 66 + dma = true; 67 + } 68 + ptei++; 69 + } 70 + nvkm_done(pt->memory); 71 + return dma; 72 + } 73 + 74 + static void 75 + gp100_vmm_pgt_pfn(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, 76 + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) 77 + { 78 + struct device *dev = vmm->mmu->subdev.device->dev; 79 + dma_addr_t addr; 80 + 81 + nvkm_kmap(pt->memory); 82 + while (ptes--) { 83 + u64 data = 0; 84 + if (!(*map->pfn & NVKM_VMM_PFN_W)) 85 + data |= BIT_ULL(6); /* RO. */ 86 + 87 + if (!(*map->pfn & NVKM_VMM_PFN_VRAM)) { 88 + addr = *map->pfn >> NVKM_VMM_PFN_ADDR_SHIFT; 89 + addr = dma_map_page(dev, pfn_to_page(addr), 0, 90 + PAGE_SIZE, DMA_BIDIRECTIONAL); 91 + if (!WARN_ON(dma_mapping_error(dev, addr))) { 92 + data |= addr >> 4; 93 + data |= 2ULL << 1; /* SYSTEM_COHERENT_MEMORY. */ 94 + data |= BIT_ULL(3); /* VOL. */ 95 + data |= BIT_ULL(0); /* VALID. */ 96 + } 97 + } else { 98 + data |= (*map->pfn & NVKM_VMM_PFN_ADDR) >> 4; 99 + data |= BIT_ULL(0); /* VALID. */ 100 + } 101 + 102 + VMM_WO064(pt, vmm, ptei++ * 8, data); 103 + map->pfn++; 104 + } 105 + nvkm_done(pt->memory); 106 + } 29 107 30 108 static inline void 31 109 gp100_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, ··· 167 89 .mem = gp100_vmm_pgt_mem, 168 90 .dma = gp100_vmm_pgt_dma, 169 91 .sgl = gp100_vmm_pgt_sgl, 92 + .pfn = gp100_vmm_pgt_pfn, 93 + .pfn_clear = gp100_vmm_pfn_clear, 94 + .pfn_unmap = gp100_vmm_pfn_unmap, 170 95 }; 171 96 172 97 static void ··· 387 306 return 0; 388 307 } 389 308 309 + static int 310 + gp100_vmm_fault_cancel(struct nvkm_vmm *vmm, void *argv, u32 argc) 311 + { 312 + struct nvkm_device *device = vmm->mmu->subdev.device; 313 + union { 314 + struct gp100_vmm_fault_cancel_v0 v0; 315 + } *args = argv; 316 + int ret = -ENOSYS; 317 + u32 inst, aper; 318 + 319 + if ((ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) 320 + return ret; 321 + 322 + /* Translate MaxwellFaultBufferA instance pointer to the same 323 + * format as the NV_GR_FECS_CURRENT_CTX register. 324 + */ 325 + aper = (args->v0.inst >> 8) & 3; 326 + args->v0.inst >>= 12; 327 + args->v0.inst |= aper << 28; 328 + args->v0.inst |= 0x80000000; 329 + 330 + if (!WARN_ON(nvkm_gr_ctxsw_pause(device))) { 331 + if ((inst = nvkm_gr_ctxsw_inst(device)) == args->v0.inst) { 332 + gf100_vmm_invalidate(vmm, 0x0000001b 333 + /* CANCEL_TARGETED. */ | 334 + (args->v0.hub << 20) | 335 + (args->v0.gpc << 15) | 336 + (args->v0.client << 9)); 337 + } 338 + WARN_ON(nvkm_gr_ctxsw_resume(device)); 339 + } 340 + 341 + return 0; 342 + } 343 + 344 + static int 345 + gp100_vmm_fault_replay(struct nvkm_vmm *vmm, void *argv, u32 argc) 346 + { 347 + union { 348 + struct gp100_vmm_fault_replay_vn vn; 349 + } *args = argv; 350 + int ret = -ENOSYS; 351 + 352 + if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) { 353 + gf100_vmm_invalidate(vmm, 0x0000000b); /* REPLAY_GLOBAL. */ 354 + } 355 + 356 + return ret; 357 + } 358 + 359 + int 360 + gp100_vmm_mthd(struct nvkm_vmm *vmm, 361 + struct nvkm_client *client, u32 mthd, void *argv, u32 argc) 362 + { 363 + if (client->super) { 364 + switch (mthd) { 365 + case GP100_VMM_VN_FAULT_REPLAY: 366 + return gp100_vmm_fault_replay(vmm, argv, argc); 367 + case GP100_VMM_VN_FAULT_CANCEL: 368 + return gp100_vmm_fault_cancel(vmm, argv, argc); 369 + default: 370 + break; 371 + } 372 + } 373 + return -EINVAL; 374 + } 375 + 376 + void 377 + gp100_vmm_invalidate_pdb(struct nvkm_vmm *vmm, u64 addr) 378 + { 379 + struct nvkm_device *device = vmm->mmu->subdev.device; 380 + nvkm_wr32(device, 0x100cb8, lower_32_bits(addr)); 381 + nvkm_wr32(device, 0x100cec, upper_32_bits(addr)); 382 + } 383 + 390 384 void 391 385 gp100_vmm_flush(struct nvkm_vmm *vmm, int depth) 392 386 { 393 - gf100_vmm_flush_(vmm, 5 /* CACHE_LEVEL_UP_TO_PDE3 */ - depth); 387 + u32 type = (5 /* CACHE_LEVEL_UP_TO_PDE3 */ - depth) << 24; 388 + type = 0; /*XXX: need to confirm stuff works with depth enabled... */ 389 + if (atomic_read(&vmm->engref[NVKM_SUBDEV_BAR])) 390 + type |= 0x00000004; /* HUB_ONLY */ 391 + type |= 0x00000001; /* PAGE_ALL */ 392 + gf100_vmm_invalidate(vmm, type); 394 393 } 395 394 396 395 int 397 396 gp100_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst) 398 397 { 399 - const u64 base = BIT_ULL(10) /* VER2 */ | BIT_ULL(11); /* 64KiB */ 398 + u64 base = BIT_ULL(10) /* VER2 */ | BIT_ULL(11) /* 64KiB */; 399 + if (vmm->replay) { 400 + base |= BIT_ULL(4); /* FAULT_REPLAY_TEX */ 401 + base |= BIT_ULL(5); /* FAULT_REPLAY_GCC */ 402 + } 400 403 return gf100_vmm_join_(vmm, inst, base); 401 404 } 402 405 ··· 491 326 .aper = gf100_vmm_aper, 492 327 .valid = gp100_vmm_valid, 493 328 .flush = gp100_vmm_flush, 329 + .mthd = gp100_vmm_mthd, 330 + .invalidate_pdb = gp100_vmm_invalidate_pdb, 494 331 .page = { 495 332 { 47, &gp100_vmm_desc_16[4], NVKM_VMM_PAGE_Sxxx }, 496 333 { 38, &gp100_vmm_desc_16[3], NVKM_VMM_PAGE_Sxxx }, ··· 505 338 }; 506 339 507 340 int 508 - gp100_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 509 - struct lock_class_key *key, const char *name, 510 - struct nvkm_vmm **pvmm) 341 + gp100_vmm_new_(const struct nvkm_vmm_func *func, 342 + struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 343 + void *argv, u32 argc, struct lock_class_key *key, 344 + const char *name, struct nvkm_vmm **pvmm) 511 345 { 512 - return nv04_vmm_new_(&gp100_vmm, mmu, 0, addr, size, 513 - argv, argc, key, name, pvmm); 346 + union { 347 + struct gp100_vmm_vn vn; 348 + struct gp100_vmm_v0 v0; 349 + } *args = argv; 350 + int ret = -ENOSYS; 351 + bool replay; 352 + 353 + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { 354 + replay = args->v0.fault_replay != 0; 355 + } else 356 + if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) { 357 + replay = false; 358 + } else 359 + return ret; 360 + 361 + ret = nvkm_vmm_new_(func, mmu, 0, managed, addr, size, key, name, pvmm); 362 + if (ret) 363 + return ret; 364 + 365 + (*pvmm)->replay = replay; 366 + return 0; 367 + } 368 + 369 + int 370 + gp100_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 371 + void *argv, u32 argc, struct lock_class_key *key, 372 + const char *name, struct nvkm_vmm **pvmm) 373 + { 374 + return gp100_vmm_new_(&gp100_vmm, mmu, managed, addr, size, 375 + argv, argc, key, name, pvmm); 514 376 }
+7 -5
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp10b.c
··· 28 28 .aper = gk20a_vmm_aper, 29 29 .valid = gp100_vmm_valid, 30 30 .flush = gp100_vmm_flush, 31 + .mthd = gp100_vmm_mthd, 32 + .invalidate_pdb = gp100_vmm_invalidate_pdb, 31 33 .page = { 32 34 { 47, &gp100_vmm_desc_16[4], NVKM_VMM_PAGE_Sxxx }, 33 35 { 38, &gp100_vmm_desc_16[3], NVKM_VMM_PAGE_Sxxx }, ··· 42 40 }; 43 41 44 42 int 45 - gp10b_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 46 - struct lock_class_key *key, const char *name, 47 - struct nvkm_vmm **pvmm) 43 + gp10b_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 44 + void *argv, u32 argc, struct lock_class_key *key, 45 + const char *name, struct nvkm_vmm **pvmm) 48 46 { 49 - return nv04_vmm_new_(&gp10b_vmm, mmu, 0, addr, size, 50 - argv, argc, key, name, pvmm); 47 + return gp100_vmm_new_(&gp10b_vmm, mmu, managed, addr, size, 48 + argv, argc, key, name, pvmm); 51 49 }
+7 -5
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgv100.c
··· 66 66 .aper = gf100_vmm_aper, 67 67 .valid = gp100_vmm_valid, 68 68 .flush = gp100_vmm_flush, 69 + .mthd = gp100_vmm_mthd, 70 + .invalidate_pdb = gp100_vmm_invalidate_pdb, 69 71 .page = { 70 72 { 47, &gp100_vmm_desc_16[4], NVKM_VMM_PAGE_Sxxx }, 71 73 { 38, &gp100_vmm_desc_16[3], NVKM_VMM_PAGE_Sxxx }, ··· 80 78 }; 81 79 82 80 int 83 - gv100_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 84 - struct lock_class_key *key, const char *name, 85 - struct nvkm_vmm **pvmm) 81 + gv100_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 82 + void *argv, u32 argc, struct lock_class_key *key, 83 + const char *name, struct nvkm_vmm **pvmm) 86 84 { 87 - return nv04_vmm_new_(&gv100_vmm, mmu, 0, addr, size, 88 - argv, argc, key, name, pvmm); 85 + return gp100_vmm_new_(&gv100_vmm, mmu, managed, addr, size, 86 + argv, argc, key, name, pvmm); 89 87 }
+4 -4
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmmcp77.c
··· 36 36 }; 37 37 38 38 int 39 - mcp77_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 40 - struct lock_class_key *key, const char *name, 41 - struct nvkm_vmm **pvmm) 39 + mcp77_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 40 + void *argv, u32 argc, struct lock_class_key *key, 41 + const char *name, struct nvkm_vmm **pvmm) 42 42 { 43 - return nv04_vmm_new_(&mcp77_vmm, mmu, 0, addr, size, 43 + return nv04_vmm_new_(&mcp77_vmm, mmu, 0, managed, addr, size, 44 44 argv, argc, key, name, pvmm); 45 45 }
+8 -7
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv04.c
··· 100 100 101 101 int 102 102 nv04_vmm_new_(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, 103 - u32 pd_header, u64 addr, u64 size, void *argv, u32 argc, 104 - struct lock_class_key *key, const char *name, 105 - struct nvkm_vmm **pvmm) 103 + u32 pd_header, bool managed, u64 addr, u64 size, 104 + void *argv, u32 argc, struct lock_class_key *key, 105 + const char *name, struct nvkm_vmm **pvmm) 106 106 { 107 107 union { 108 108 struct nv04_vmm_vn vn; 109 109 } *args = argv; 110 110 int ret; 111 111 112 - ret = nvkm_vmm_new_(func, mmu, pd_header, addr, size, key, name, pvmm); 112 + ret = nvkm_vmm_new_(func, mmu, pd_header, managed, addr, size, 113 + key, name, pvmm); 113 114 if (ret) 114 115 return ret; 115 116 ··· 118 117 } 119 118 120 119 int 121 - nv04_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 122 - struct lock_class_key *key, const char *name, 120 + nv04_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 121 + void *argv, u32 argc, struct lock_class_key *key, const char *name, 123 122 struct nvkm_vmm **pvmm) 124 123 { 125 124 struct nvkm_memory *mem; 126 125 struct nvkm_vmm *vmm; 127 126 int ret; 128 127 129 - ret = nv04_vmm_new_(&nv04_vmm, mmu, 8, addr, size, 128 + ret = nv04_vmm_new_(&nv04_vmm, mmu, 8, managed, addr, size, 130 129 argv, argc, key, name, &vmm); 131 130 *pvmm = vmm; 132 131 if (ret)
+3 -3
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv41.c
··· 104 104 }; 105 105 106 106 int 107 - nv41_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 108 - struct lock_class_key *key, const char *name, 107 + nv41_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 108 + void *argv, u32 argc, struct lock_class_key *key, const char *name, 109 109 struct nvkm_vmm **pvmm) 110 110 { 111 - return nv04_vmm_new_(&nv41_vmm, mmu, 0, addr, size, 111 + return nv04_vmm_new_(&nv41_vmm, mmu, 0, managed, addr, size, 112 112 argv, argc, key, name, pvmm); 113 113 }
+3 -3
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv44.c
··· 205 205 }; 206 206 207 207 int 208 - nv44_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 209 - struct lock_class_key *key, const char *name, 208 + nv44_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 209 + void *argv, u32 argc, struct lock_class_key *key, const char *name, 210 210 struct nvkm_vmm **pvmm) 211 211 { 212 212 struct nvkm_subdev *subdev = &mmu->subdev; 213 213 struct nvkm_vmm *vmm; 214 214 int ret; 215 215 216 - ret = nv04_vmm_new_(&nv44_vmm, mmu, 0, addr, size, 216 + ret = nv04_vmm_new_(&nv44_vmm, mmu, 0, managed, addr, size, 217 217 argv, argc, key, name, &vmm); 218 218 *pvmm = vmm; 219 219 if (ret)
+3 -3
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c
··· 376 376 }; 377 377 378 378 int 379 - nv50_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, 380 - struct lock_class_key *key, const char *name, 379 + nv50_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 380 + void *argv, u32 argc, struct lock_class_key *key, const char *name, 381 381 struct nvkm_vmm **pvmm) 382 382 { 383 - return nv04_vmm_new_(&nv50_vmm, mmu, 0, addr, size, 383 + return nv04_vmm_new_(&nv50_vmm, mmu, 0, managed, addr, size, 384 384 argv, argc, key, name, pvmm); 385 385 }
+7 -6
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu104.c drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c
··· 24 24 #include <subdev/timer.h> 25 25 26 26 static void 27 - tu104_vmm_flush(struct nvkm_vmm *vmm, int depth) 27 + tu102_vmm_flush(struct nvkm_vmm *vmm, int depth) 28 28 { 29 29 struct nvkm_subdev *subdev = &vmm->mmu->subdev; 30 30 struct nvkm_device *device = subdev->device; ··· 50 50 } 51 51 52 52 static const struct nvkm_vmm_func 53 - tu104_vmm = { 53 + tu102_vmm = { 54 54 .join = gv100_vmm_join, 55 55 .part = gf100_vmm_part, 56 56 .aper = gf100_vmm_aper, 57 57 .valid = gp100_vmm_valid, 58 - .flush = tu104_vmm_flush, 58 + .flush = tu102_vmm_flush, 59 + .mthd = gp100_vmm_mthd, 59 60 .page = { 60 61 { 47, &gp100_vmm_desc_16[4], NVKM_VMM_PAGE_Sxxx }, 61 62 { 38, &gp100_vmm_desc_16[3], NVKM_VMM_PAGE_Sxxx }, ··· 69 68 }; 70 69 71 70 int 72 - tu104_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, 71 + tu102_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size, 73 72 void *argv, u32 argc, struct lock_class_key *key, 74 73 const char *name, struct nvkm_vmm **pvmm) 75 74 { 76 - return nv04_vmm_new_(&tu104_vmm, mmu, 0, addr, size, 77 - argv, argc, key, name, pvmm); 75 + return gp100_vmm_new_(&tu102_vmm, mmu, managed, addr, size, 76 + argv, argc, key, name, pvmm); 78 77 }
+2 -2
drivers/gpu/drm/nouveau/nvkm/subdev/pmu/memx.c
··· 88 88 if (exec) { 89 89 nvkm_pmu_send(pmu, reply, PROC_MEMX, MEMX_MSG_EXEC, 90 90 memx->base, finish); 91 + nvkm_debug(subdev, "Exec took %uns, PMU_IN %08x\n", 92 + reply[0], reply[1]); 91 93 } 92 94 93 - nvkm_debug(subdev, "Exec took %uns, PMU_IN %08x\n", 94 - reply[0], reply[1]); 95 95 kfree(memx); 96 96 return 0; 97 97 }
+2 -2
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
··· 853 853 * and the expected behavior on RM as well 854 854 */ 855 855 if (ret && ret != 0x1d) { 856 - nvkm_error(subdev, "HS unload failed, ret 0x%08x", ret); 856 + nvkm_error(subdev, "HS unload failed, ret 0x%08x\n", ret); 857 857 return -EINVAL; 858 858 } 859 859 nvkm_debug(subdev, "HS unload blob completed\n"); ··· 922 922 if (ret < 0) { 923 923 return ret; 924 924 } else if (ret > 0) { 925 - nvkm_error(subdev, "HS load failed, ret 0x%08x", ret); 925 + nvkm_error(subdev, "HS load failed, ret 0x%08x\n", ret); 926 926 return -EINVAL; 927 927 } 928 928 nvkm_debug(subdev, "HS load blob completed\n");
+16
drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c
··· 41 41 } 42 42 43 43 u32 44 + nvkm_top_addr(struct nvkm_device *device, enum nvkm_devidx index) 45 + { 46 + struct nvkm_top *top = device->top; 47 + struct nvkm_top_device *info; 48 + 49 + if (top) { 50 + list_for_each_entry(info, &top->device, head) { 51 + if (info->index == index) 52 + return info->addr; 53 + } 54 + } 55 + 56 + return 0; 57 + } 58 + 59 + u32 44 60 nvkm_top_reset(struct nvkm_device *device, enum nvkm_devidx index) 45 61 { 46 62 struct nvkm_top *top = device->top;
+2
drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c
··· 73 73 #define A_(A) if (inst == 0) info->index = NVKM_ENGINE_##A 74 74 #define B_(A) if (inst + NVKM_ENGINE_##A##0 < NVKM_ENGINE_##A##_LAST + 1) \ 75 75 info->index = NVKM_ENGINE_##A##0 + inst 76 + #define C_(A) if (inst == 0) info->index = NVKM_SUBDEV_##A 76 77 switch (type) { 77 78 case 0x00000000: A_(GR ); break; 78 79 case 0x00000001: A_(CE0 ); break; ··· 89 88 case 0x0000000f: A_(NVENC1); break; 90 89 case 0x00000010: B_(NVDEC ); break; 91 90 case 0x00000013: B_(CE ); break; 91 + case 0x00000014: C_(GSP ); break; 92 92 break; 93 93 default: 94 94 break;
+1
drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild
··· 2 2 nvkm-y += nvkm/subdev/volt/gpio.o 3 3 nvkm-y += nvkm/subdev/volt/nv40.o 4 4 nvkm-y += nvkm/subdev/volt/gf100.o 5 + nvkm-y += nvkm/subdev/volt/gf117.o 5 6 nvkm-y += nvkm/subdev/volt/gk104.o 6 7 nvkm-y += nvkm/subdev/volt/gk20a.o 7 8 nvkm-y += nvkm/subdev/volt/gm20b.o
+51
include/uapi/drm/nouveau_drm.h
··· 133 133 #define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x05 /* deprecated */ 134 134 #define DRM_NOUVEAU_GPUOBJ_FREE 0x06 /* deprecated */ 135 135 #define DRM_NOUVEAU_NVIF 0x07 136 + #define DRM_NOUVEAU_SVM_INIT 0x08 137 + #define DRM_NOUVEAU_SVM_BIND 0x09 136 138 #define DRM_NOUVEAU_GEM_NEW 0x40 137 139 #define DRM_NOUVEAU_GEM_PUSHBUF 0x41 138 140 #define DRM_NOUVEAU_GEM_CPU_PREP 0x42 139 141 #define DRM_NOUVEAU_GEM_CPU_FINI 0x43 140 142 #define DRM_NOUVEAU_GEM_INFO 0x44 143 + 144 + struct drm_nouveau_svm_init { 145 + __u64 unmanaged_addr; 146 + __u64 unmanaged_size; 147 + }; 148 + 149 + struct drm_nouveau_svm_bind { 150 + __u64 header; 151 + __u64 va_start; 152 + __u64 va_end; 153 + __u64 npages; 154 + __u64 stride; 155 + __u64 result; 156 + __u64 reserved0; 157 + __u64 reserved1; 158 + }; 159 + 160 + #define NOUVEAU_SVM_BIND_COMMAND_SHIFT 0 161 + #define NOUVEAU_SVM_BIND_COMMAND_BITS 8 162 + #define NOUVEAU_SVM_BIND_COMMAND_MASK ((1 << 8) - 1) 163 + #define NOUVEAU_SVM_BIND_PRIORITY_SHIFT 8 164 + #define NOUVEAU_SVM_BIND_PRIORITY_BITS 8 165 + #define NOUVEAU_SVM_BIND_PRIORITY_MASK ((1 << 8) - 1) 166 + #define NOUVEAU_SVM_BIND_TARGET_SHIFT 16 167 + #define NOUVEAU_SVM_BIND_TARGET_BITS 32 168 + #define NOUVEAU_SVM_BIND_TARGET_MASK 0xffffffff 169 + 170 + /* 171 + * Below is use to validate ioctl argument, userspace can also use it to make 172 + * sure that no bit are set beyond known fields for a given kernel version. 173 + */ 174 + #define NOUVEAU_SVM_BIND_VALID_BITS 48 175 + #define NOUVEAU_SVM_BIND_VALID_MASK ((1ULL << NOUVEAU_SVM_BIND_VALID_BITS) - 1) 176 + 177 + 178 + /* 179 + * NOUVEAU_BIND_COMMAND__MIGRATE: synchronous migrate to target memory. 180 + * result: number of page successfuly migrate to the target memory. 181 + */ 182 + #define NOUVEAU_SVM_BIND_COMMAND__MIGRATE 0 183 + 184 + /* 185 + * NOUVEAU_SVM_BIND_HEADER_TARGET__GPU_VRAM: target the GPU VRAM memory. 186 + */ 187 + #define NOUVEAU_SVM_BIND_TARGET__GPU_VRAM (1UL << 31) 188 + 189 + 190 + #define DRM_IOCTL_NOUVEAU_SVM_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_SVM_INIT, struct drm_nouveau_svm_init) 191 + #define DRM_IOCTL_NOUVEAU_SVM_BIND DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_SVM_BIND, struct drm_nouveau_svm_bind) 141 192 142 193 #define DRM_IOCTL_NOUVEAU_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_NEW, struct drm_nouveau_gem_new) 143 194 #define DRM_IOCTL_NOUVEAU_GEM_PUSHBUF DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_PUSHBUF, struct drm_nouveau_gem_pushbuf)