diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau')
180 files changed, 2794 insertions, 4737 deletions
diff --git a/drivers/gpu/drm/nouveau/Kbuild b/drivers/gpu/drm/nouveau/Kbuild index cf6b3a80c0c8..7b863355c5c6 100644 --- a/drivers/gpu/drm/nouveau/Kbuild +++ b/drivers/gpu/drm/nouveau/Kbuild @@ -1,10 +1,8 @@ -NOUVEAU_PATH ?= $(srctree) - # SPDX-License-Identifier: MIT -ccflags-y += -I $(NOUVEAU_PATH)/$(src)/include -ccflags-y += -I $(NOUVEAU_PATH)/$(src)/include/nvkm -ccflags-y += -I $(NOUVEAU_PATH)/$(src)/nvkm -ccflags-y += -I $(NOUVEAU_PATH)/$(src) +ccflags-y += -I $(src)/include +ccflags-y += -I $(src)/include/nvkm +ccflags-y += -I $(src)/nvkm +ccflags-y += -I $(src) # NVKM - HW resource manager #- code also used by various userspace tools/tests @@ -27,7 +25,6 @@ nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o nouveau-$(CONFIG_LEDS_CLASS) += nouveau_led.o nouveau-y += nouveau_nvif.o nouveau-$(CONFIG_NOUVEAU_PLATFORM_DRIVER) += nouveau_platform.o -nouveau-y += nouveau_usif.o # userspace <-> nvif nouveau-y += nouveau_vga.o # DRM - memory management diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index ceef470c9fbf..1050a4617fc1 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -4,6 +4,8 @@ config DRM_NOUVEAU depends on DRM && PCI && MMU select IOMMU_API select FW_LOADER + select FW_CACHE if PM_SLEEP + select DRM_CLIENT_SELECTION select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_HDMI_HELPER select DRM_DISPLAY_HELPER diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index a34917b048f9..67146f1e8482 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -118,8 +118,8 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod { struct drm_device *dev = crtc->dev; struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_bios *bios = nvxx_bios(&drm->client.device); - struct nvkm_clk *clk = nvxx_clk(&drm->client.device); + struct nvkm_bios *bios = nvxx_bios(drm); + struct nvkm_clk *clk = nvxx_clk(drm); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nv04_mode_state *state = &nv04_display(dev)->mode_reg; struct nv04_crtc_reg *regp = &state->crtc_reg[nv_crtc->index]; @@ -449,7 +449,7 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) regp->Attribute[NV_CIO_AR_CSEL_INDEX] = 0x00; } -/** +/* * Sets up registers for the given mode/adjusted_mode pair. * * The clocks, CRTCs and outputs attached to this CRTC must be off. @@ -617,15 +617,21 @@ nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, false); if (ret == 0) { - if (disp->image[nv_crtc->index]) - nouveau_bo_unpin(disp->image[nv_crtc->index]); - nouveau_bo_ref(nvbo, &disp->image[nv_crtc->index]); + if (disp->image[nv_crtc->index]) { + struct nouveau_bo *bo = disp->image[nv_crtc->index]; + + nouveau_bo_unpin(bo); + drm_gem_object_put(&bo->bo.base); + } + + drm_gem_object_get(&nvbo->bo.base); + disp->image[nv_crtc->index] = nvbo; } return ret; } -/** +/* * Sets up registers for the given mode/adjusted_mode pair. * * The clocks, CRTCs and outputs attached to this CRTC must be off. @@ -754,13 +760,17 @@ static void nv_crtc_destroy(struct drm_crtc *crtc) drm_crtc_cleanup(crtc); - if (disp->image[nv_crtc->index]) - nouveau_bo_unpin(disp->image[nv_crtc->index]); - nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]); + if (disp->image[nv_crtc->index]) { + struct nouveau_bo *bo = disp->image[nv_crtc->index]; + + nouveau_bo_unpin(bo); + drm_gem_object_put(&bo->bo.base); + disp->image[nv_crtc->index] = NULL; + } nouveau_bo_unmap(nv_crtc->cursor.nvbo); nouveau_bo_unpin(nv_crtc->cursor.nvbo); - nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); + nouveau_bo_fini(nv_crtc->cursor.nvbo); nvif_event_dtor(&nv_crtc->vblank); nvif_head_dtor(&nv_crtc->head); kfree(nv_crtc); @@ -794,9 +804,14 @@ nv_crtc_disable(struct drm_crtc *crtc) { struct nv04_display *disp = nv04_display(crtc->dev); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - if (disp->image[nv_crtc->index]) - nouveau_bo_unpin(disp->image[nv_crtc->index]); - nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]); + + if (disp->image[nv_crtc->index]) { + struct nouveau_bo *bo = disp->image[nv_crtc->index]; + + nouveau_bo_unpin(bo); + drm_gem_object_put(&bo->bo.base); + disp->image[nv_crtc->index] = NULL; + } } static int @@ -1042,7 +1057,7 @@ nv04_finish_page_flip(struct nouveau_channel *chan, struct nv04_page_flip_state *ps) { struct nouveau_fence_chan *fctx = chan->fence; - struct nouveau_drm *drm = chan->drm; + struct nouveau_drm *drm = chan->cli->drm; struct drm_device *dev = drm->dev; struct nv04_page_flip_state *s; unsigned long flags; @@ -1098,9 +1113,9 @@ nv04_page_flip_emit(struct nouveau_channel *chan, struct nouveau_fence **pfence) { struct nouveau_fence_chan *fctx = chan->fence; - struct nouveau_drm *drm = chan->drm; + struct nouveau_drm *drm = chan->cli->drm; struct drm_device *dev = drm->dev; - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; unsigned long flags; int ret; @@ -1157,8 +1172,8 @@ nv04_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, chan = drm->channel; if (!chan) return -ENODEV; - cli = (void *)chan->user.client; - push = chan->chan.push; + cli = chan->cli; + push = &chan->chan.push; s = kzalloc(sizeof(*s), GFP_KERNEL); if (!s) @@ -1210,7 +1225,11 @@ nv04_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, PUSH_NVSQ(push, NV05F, 0x0130, 0); } - nouveau_bo_ref(new_bo, &dispnv04->image[head]); + if (dispnv04->image[head]) + drm_gem_object_put(&dispnv04->image[head]->bo.base); + + drm_gem_object_get(&new_bo->bo.base); + dispnv04->image[head] = new_bo; ret = nv04_page_flip_emit(chan, old_bo, new_bo, s, &fence); if (ret) @@ -1329,7 +1348,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) nouveau_bo_unpin(nv_crtc->cursor.nvbo); } if (ret) - nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); + nouveau_bo_fini(nv_crtc->cursor.nvbo); } nv04_cursor_init(nv_crtc); diff --git a/drivers/gpu/drm/nouveau/dispnv04/dac.c b/drivers/gpu/drm/nouveau/dispnv04/dac.c index d6b8e0cce2ac..2e12bf136607 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dac.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dac.c @@ -237,7 +237,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) struct drm_device *dev = encoder->dev; struct nouveau_drm *drm = nouveau_drm(dev); struct nvif_object *device = &nouveau_drm(dev)->client.device.object; - struct nvkm_gpio *gpio = nvxx_gpio(&drm->client.device); + struct nvkm_gpio *gpio = nvxx_gpio(drm); struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder); uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c index d5b129dc623b..504c421aa176 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c @@ -626,7 +626,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) struct drm_device *dev = encoder->dev; struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_i2c *i2c = nvxx_i2c(&drm->client.device); + struct nvkm_i2c *i2c = nvxx_i2c(drm); struct nvkm_i2c_bus *bus = nvkm_i2c_bus_find(i2c, NVKM_I2C_BUS_PRI); struct nvkm_i2c_bus_probe info[] = { { diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c index 13705c5f1497..f71199a39bc4 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c @@ -68,7 +68,7 @@ nv04_display_fini(struct drm_device *dev, bool runtime, bool suspend) if (nv_two_heads(dev)) NVWriteCRTC(dev, 1, NV_PCRTC_INTR_EN_0, 0); - if (!runtime) + if (!runtime && !drm->headless) cancel_work_sync(&drm->hpd_work); if (!suspend) @@ -189,7 +189,6 @@ static void nv04_display_destroy(struct drm_device *dev) { struct nv04_display *disp = nv04_display(dev); - struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_encoder *encoder; struct nouveau_crtc *nv_crtc; @@ -206,15 +205,13 @@ nv04_display_destroy(struct drm_device *dev) nouveau_display(dev)->priv = NULL; vfree(disp); - - nvif_object_unmap(&drm->client.device.object); } int nv04_display_create(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_i2c *i2c = nvxx_i2c(&drm->client.device); + struct nvkm_i2c *i2c = nvxx_i2c(drm); struct dcb_table *dcb = &drm->vbios.dcb; struct drm_connector *connector, *ct; struct drm_encoder *encoder; @@ -229,8 +226,6 @@ nv04_display_create(struct drm_device *dev) disp->drm = drm; - nvif_object_map(&drm->client.device.object, NULL, 0); - nouveau_display(dev)->priv = disp; nouveau_display(dev)->dtor = nv04_display_destroy; nouveau_display(dev)->init = nv04_display_init; diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h index 11a6663758ec..85ec0f534392 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.h +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h @@ -176,7 +176,7 @@ static inline void nouveau_bios_run_init_table(struct drm_device *dev, u16 table, struct dcb_output *outp, int crtc) { - nvbios_init(&nvxx_bios(&nouveau_drm(dev)->client.device)->subdev, table, + nvbios_init(&nvxx_bios(nouveau_drm(dev))->subdev, table, init.outp = outp; init.head = crtc; ); diff --git a/drivers/gpu/drm/nouveau/dispnv04/hw.c b/drivers/gpu/drm/nouveau/dispnv04/hw.c index f7d35657aa64..8b376f9c8746 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/hw.c +++ b/drivers/gpu/drm/nouveau/dispnv04/hw.c @@ -166,7 +166,7 @@ nouveau_hw_get_pllvals(struct drm_device *dev, enum nvbios_pll_type plltype, { struct nouveau_drm *drm = nouveau_drm(dev); struct nvif_object *device = &drm->client.device.object; - struct nvkm_bios *bios = nvxx_bios(&drm->client.device); + struct nvkm_bios *bios = nvxx_bios(drm); uint32_t reg1, pll1, pll2 = 0; struct nvbios_pll pll_lim; int ret; @@ -258,9 +258,8 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) */ struct nouveau_drm *drm = nouveau_drm(dev); - struct nvif_device *device = &drm->client.device; - struct nvkm_clk *clk = nvxx_clk(device); - struct nvkm_bios *bios = nvxx_bios(device); + struct nvkm_clk *clk = nvxx_clk(drm); + struct nvkm_bios *bios = nvxx_bios(drm); struct nvbios_pll pll_lim; struct nvkm_pll_vals pv; enum nvbios_pll_type pll = head ? PLL_VPLL1 : PLL_VPLL0; @@ -470,7 +469,7 @@ nv_load_state_ramdac(struct drm_device *dev, int head, struct nv04_mode_state *state) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_clk *clk = nvxx_clk(&drm->client.device); + struct nvkm_clk *clk = nvxx_clk(drm); struct nv04_crtc_reg *regp = &state->crtc_reg[head]; uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF; int i; diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c index de3ea731d6e6..d3014027a812 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c @@ -53,7 +53,7 @@ static struct nvkm_i2c_bus_probe nv04_tv_encoder_info[] = { int nv04_tv_identify(struct drm_device *dev, int i2c_index) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_i2c *i2c = nvxx_i2c(&drm->client.device); + struct nvkm_i2c *i2c = nvxx_i2c(drm); struct nvkm_i2c_bus *bus = nvkm_i2c_bus_find(i2c, i2c_index); if (bus) { return nvkm_i2c_bus_probe(bus, "TV encoder", @@ -205,7 +205,7 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry) struct drm_encoder *encoder; struct drm_device *dev = connector->dev; struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_i2c *i2c = nvxx_i2c(&drm->client.device); + struct nvkm_i2c *i2c = nvxx_i2c(drm); struct nvkm_i2c_bus *bus = nvkm_i2c_bus_find(i2c, entry->i2c_index); int type, ret; diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c index 670c9739e5e1..3ecb101d23e9 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c @@ -47,7 +47,7 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_gpio *gpio = nvxx_gpio(&drm->client.device); + struct nvkm_gpio *gpio = nvxx_gpio(drm); uint32_t testval, regoffset = nv04_dac_output_offset(encoder); uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end, fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c; @@ -131,7 +131,7 @@ static bool get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_device *device = nvxx_device(&drm->client.device); + struct nvkm_device *device = nvxx_device(drm); if (device->quirk && device->quirk->tv_pin_mask) { *pin_mask = device->quirk->tv_pin_mask; @@ -209,6 +209,8 @@ static int nv17_tv_get_ld_modes(struct drm_encoder *encoder, struct drm_display_mode *mode; mode = drm_mode_duplicate(encoder->dev, tv_mode); + if (!mode) + continue; mode->clock = tv_norm->tv_enc_mode.vrefresh * mode->htotal / 1000 * @@ -258,6 +260,8 @@ static int nv17_tv_get_hd_modes(struct drm_encoder *encoder, if (modes[i].hdisplay == output_mode->hdisplay && modes[i].vdisplay == output_mode->vdisplay) { mode = drm_mode_duplicate(encoder->dev, output_mode); + if (!mode) + continue; mode->type |= DRM_MODE_TYPE_PREFERRED; } else { @@ -265,6 +269,8 @@ static int nv17_tv_get_hd_modes(struct drm_encoder *encoder, modes[i].vdisplay, 60, false, (output_mode->flags & DRM_MODE_FLAG_INTERLACE), false); + if (!mode) + continue; } /* CVT modes are sometimes unsuitable... */ @@ -363,7 +369,7 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_gpio *gpio = nvxx_gpio(&drm->client.device); + struct nvkm_gpio *gpio = nvxx_gpio(drm); struct nv17_tv_state *regs = &to_tv_enc(encoder)->state; struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); diff --git a/drivers/gpu/drm/nouveau/dispnv50/base507c.c b/drivers/gpu/drm/nouveau/dispnv50/base507c.c index 70c62b861276..a431f6c5f6fa 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base507c.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base507c.c @@ -35,7 +35,7 @@ int base507c_update(struct nv50_wndw *wndw, u32 *interlock) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 2))) @@ -48,7 +48,7 @@ base507c_update(struct nv50_wndw *wndw, u32 *interlock) int base507c_image_clr(struct nv50_wndw *wndw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 4))) @@ -65,7 +65,7 @@ base507c_image_clr(struct nv50_wndw *wndw) static int base507c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 13))) @@ -118,7 +118,7 @@ base507c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) int base507c_xlut_clr(struct nv50_wndw *wndw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 2))) @@ -132,7 +132,7 @@ base507c_xlut_clr(struct nv50_wndw *wndw) int base507c_xlut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 2))) @@ -158,7 +158,7 @@ base507c_ntfy_wait_begun(struct nouveau_bo *bo, u32 offset, int base507c_ntfy_clr(struct nv50_wndw *wndw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 2))) @@ -171,7 +171,7 @@ base507c_ntfy_clr(struct nv50_wndw *wndw) int base507c_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 3))) @@ -195,7 +195,7 @@ base507c_ntfy_reset(struct nouveau_bo *bo, u32 offset) int base507c_sema_clr(struct nv50_wndw *wndw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 2))) @@ -208,7 +208,7 @@ base507c_sema_clr(struct nv50_wndw *wndw) int base507c_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 5))) @@ -307,7 +307,6 @@ base507c_new_(const struct nv50_wndw_func *func, const u32 *format, struct nvif_disp_chan_v0 args = { .id = head, }; - struct nouveau_display *disp = nouveau_display(drm->dev); struct nv50_disp *disp50 = nv50_disp(drm->dev); struct nv50_wndw *wndw; int ret; @@ -318,7 +317,7 @@ base507c_new_(const struct nv50_wndw_func *func, const u32 *format, if (*pwndw = wndw, ret) return ret; - ret = nv50_dmac_create(&drm->client.device, &disp->disp.object, + ret = nv50_dmac_create(drm, &oclass, head, &args, sizeof(args), disp50->sync->offset, &wndw->wndw); if (ret) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/base827c.c b/drivers/gpu/drm/nouveau/dispnv50/base827c.c index 093d4ba6910e..4545cc5f3a14 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base827c.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base827c.c @@ -28,7 +28,7 @@ static int base827c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 13))) diff --git a/drivers/gpu/drm/nouveau/dispnv50/base907c.c b/drivers/gpu/drm/nouveau/dispnv50/base907c.c index e6b0417c325b..4a2d5a259e15 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base907c.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base907c.c @@ -28,7 +28,7 @@ static int base907c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 10))) @@ -65,7 +65,7 @@ base907c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) static int base907c_xlut_clr(struct nv50_wndw *wndw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 6))) @@ -84,7 +84,7 @@ base907c_xlut_clr(struct nv50_wndw *wndw) static int base907c_xlut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 6))) @@ -156,7 +156,7 @@ base907c_csc(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, static int base907c_csc_clr(struct nv50_wndw *wndw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 2))) @@ -170,7 +170,7 @@ base907c_csc_clr(struct nv50_wndw *wndw) static int base907c_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 13))) diff --git a/drivers/gpu/drm/nouveau/dispnv50/core507d.c b/drivers/gpu/drm/nouveau/dispnv50/core507d.c index e5bb5ca950c8..ce2cb78bbdd3 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/core507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/core507d.c @@ -33,7 +33,7 @@ int core507d_update(struct nv50_core *core, u32 *interlock, bool ntfy) { - struct nvif_push *push = core->chan.push; + struct nvif_push *push = &core->chan.push; int ret; if ((ret = PUSH_WAIT(push, (ntfy ? 2 : 0) + 3))) @@ -80,7 +80,7 @@ core507d_ntfy_init(struct nouveau_bo *bo, u32 offset) int core507d_read_caps(struct nv50_disp *disp) { - struct nvif_push *push = disp->core->chan.push; + struct nvif_push *push = &disp->core->chan.push; int ret; ret = PUSH_WAIT(push, 6); @@ -130,7 +130,7 @@ core507d_caps_init(struct nouveau_drm *drm, struct nv50_disp *disp) int core507d_init(struct nv50_core *core) { - struct nvif_push *push = core->chan.push; + struct nvif_push *push = &core->chan.push; int ret; if ((ret = PUSH_WAIT(push, 2))) @@ -166,7 +166,7 @@ core507d_new_(const struct nv50_core_func *func, struct nouveau_drm *drm, return -ENOMEM; core->func = func; - ret = nv50_dmac_create(&drm->client.device, &disp->disp->object, + ret = nv50_dmac_create(drm, &oclass, 0, &args, sizeof(args), disp->sync->offset, &core->chan); if (ret) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/corec37d.c b/drivers/gpu/drm/nouveau/dispnv50/corec37d.c index 42f877f2ced2..7f637b8830be 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/corec37d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/corec37d.c @@ -33,7 +33,7 @@ int corec37d_wndw_owner(struct nv50_core *core) { - struct nvif_push *push = core->chan.push; + struct nvif_push *push = &core->chan.push; const u32 windows = 8; /*XXX*/ int ret, i; @@ -51,7 +51,7 @@ corec37d_wndw_owner(struct nv50_core *core) int corec37d_update(struct nv50_core *core, u32 *interlock, bool ntfy) { - struct nvif_push *push = core->chan.push; + struct nvif_push *push = &core->chan.push; int ret; if ((ret = PUSH_WAIT(push, (ntfy ? 2 * 2 : 0) + 5))) @@ -127,7 +127,7 @@ int corec37d_caps_init(struct nouveau_drm *drm, struct nv50_disp *disp) static int corec37d_init(struct nv50_core *core) { - struct nvif_push *push = core->chan.push; + struct nvif_push *push = &core->chan.push; const u32 windows = 8; /*XXX*/ int ret, i; diff --git a/drivers/gpu/drm/nouveau/dispnv50/corec57d.c b/drivers/gpu/drm/nouveau/dispnv50/corec57d.c index 53b1e2a569c1..421d0d57e1d8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/corec57d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/corec57d.c @@ -29,7 +29,7 @@ static int corec57d_init(struct nv50_core *core) { - struct nvif_push *push = core->chan.push; + struct nvif_push *push = &core->chan.push; const u32 windows = 8; /*XXX*/ int ret, i; diff --git a/drivers/gpu/drm/nouveau/dispnv50/crc.c b/drivers/gpu/drm/nouveau/dispnv50/crc.c index 9c942fbd836d..5936b6b3b15d 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/crc.c +++ b/drivers/gpu/drm/nouveau/dispnv50/crc.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MIT +#include <linux/debugfs.h> #include <linux/string.h> + #include <drm/drm_crtc.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/nouveau/dispnv50/crc907d.c b/drivers/gpu/drm/nouveau/dispnv50/crc907d.c index f9ad641555b7..a674ba435b05 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/crc907d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/crc907d.c @@ -26,7 +26,7 @@ static int crc907d_set_src(struct nv50_head *head, int or, enum nv50_crc_source_type source, struct nv50_crc_notifier_ctx *ctx) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; u32 crc_args = NVDEF(NV907D, HEAD_SET_CRC_CONTROL, CONTROLLING_CHANNEL, CORE) | NVDEF(NV907D, HEAD_SET_CRC_CONTROL, EXPECT_BUFFER_COLLAPSE, FALSE) | @@ -74,7 +74,7 @@ crc907d_set_src(struct nv50_head *head, int or, enum nv50_crc_source_type source static int crc907d_set_ctx(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/crcc37d.c b/drivers/gpu/drm/nouveau/dispnv50/crcc37d.c index f10f6c484408..4821ce32f9ed 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/crcc37d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/crcc37d.c @@ -15,7 +15,7 @@ static int crcc37d_set_src(struct nv50_head *head, int or, enum nv50_crc_source_type source, struct nv50_crc_notifier_ctx *ctx) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; u32 crc_args = NVVAL(NVC37D, HEAD_SET_CRC_CONTROL, CONTROLLING_CHANNEL, i * 4) | NVDEF(NVC37D, HEAD_SET_CRC_CONTROL, EXPECT_BUFFER_COLLAPSE, FALSE) | @@ -53,7 +53,7 @@ crcc37d_set_src(struct nv50_head *head, int or, enum nv50_crc_source_type source int crcc37d_set_ctx(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/crcc57d.c b/drivers/gpu/drm/nouveau/dispnv50/crcc57d.c index cc0130e3d496..ad591dcb0bc9 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/crcc57d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/crcc57d.c @@ -13,7 +13,7 @@ static int crcc57d_set_src(struct nv50_head *head, int or, enum nv50_crc_source_type source, struct nv50_crc_notifier_ctx *ctx) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; u32 crc_args = NVDEF(NVC57D, HEAD_SET_CRC_CONTROL, CONTROLLING_CHANNEL, CORE) | NVDEF(NVC57D, HEAD_SET_CRC_CONTROL, EXPECT_BUFFER_COLLAPSE, FALSE) | diff --git a/drivers/gpu/drm/nouveau/dispnv50/dac507d.c b/drivers/gpu/drm/nouveau/dispnv50/dac507d.c index 09de78d96679..99ae692f219e 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/dac507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/dac507d.c @@ -29,7 +29,7 @@ static int dac507d_ctrl(struct nv50_core *core, int or, u32 ctrl, struct nv50_head_atom *asyh) { - struct nvif_push *push = core->chan.push; + struct nvif_push *push = &core->chan.push; u32 sync = 0; int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/dac907d.c b/drivers/gpu/drm/nouveau/dispnv50/dac907d.c index 95efa625b691..74bc9f81e3f1 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/dac907d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/dac907d.c @@ -29,7 +29,7 @@ static int dac907d_ctrl(struct nv50_core *core, int or, u32 ctrl, struct nv50_head_atom *asyh) { - struct nvif_push *push = core->chan.push; + struct nvif_push *push = &core->chan.push; int ret; if ((ret = PUSH_WAIT(push, 2))) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 8d37a694b772..62d72b7a8d04 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -28,6 +28,7 @@ #include "wndw.h" #include "handles.h" +#include <linux/backlight.h> #include <linux/dma-mapping.h> #include <linux/hdmi.h> #include <linux/component.h> @@ -92,8 +93,11 @@ nv50_chan_create(struct nvif_device *device, struct nvif_object *disp, ret = nvif_object_ctor(disp, "kmsChan", 0, oclass[0], data, size, &chan->user); - if (ret == 0) - nvif_object_map(&chan->user, NULL, 0); + if (ret == 0) { + ret = nvif_object_map(&chan->user, NULL, 0); + if (ret) + nvif_object_dtor(&chan->user); + } nvif_object_sclass_put(&sclass); return ret; } @@ -123,20 +127,20 @@ nv50_dmac_destroy(struct nv50_dmac *dmac) nv50_chan_destroy(&dmac->base); - nvif_mem_dtor(&dmac->_push.mem); + nvif_mem_dtor(&dmac->push.mem); } static void nv50_dmac_kick(struct nvif_push *push) { - struct nv50_dmac *dmac = container_of(push, typeof(*dmac), _push); + struct nv50_dmac *dmac = container_of(push, typeof(*dmac), push); - dmac->cur = push->cur - (u32 __iomem *)dmac->_push.mem.object.map.ptr; + dmac->cur = push->cur - (u32 __iomem *)dmac->push.mem.object.map.ptr; if (dmac->put != dmac->cur) { /* Push buffer fetches are not coherent with BAR1, we need to ensure * writes have been flushed right through to VRAM before writing PUT. */ - if (dmac->push->mem.type & NVIF_MEM_VRAM) { + if (dmac->push.mem.type & NVIF_MEM_VRAM) { struct nvif_device *device = dmac->base.device; nvif_wr32(&device->object, 0x070000, 0x00000001); nvif_msec(device, 2000, @@ -171,7 +175,7 @@ nv50_dmac_wind(struct nv50_dmac *dmac) if (get == 0) { /* Corner-case, HW idle, but non-committed work pending. */ if (dmac->put == 0) - nv50_dmac_kick(dmac->push); + nv50_dmac_kick(&dmac->push); if (nvif_msec(dmac->base.device, 2000, if (NVIF_TV32(&dmac->base.user, NV507C, GET, PTR, >, 0)) @@ -180,7 +184,7 @@ nv50_dmac_wind(struct nv50_dmac *dmac) return -ETIMEDOUT; } - PUSH_RSVD(dmac->push, PUSH_JUMP(dmac->push, 0)); + PUSH_RSVD(&dmac->push, PUSH_JUMP(&dmac->push, 0)); dmac->cur = 0; return 0; } @@ -188,19 +192,19 @@ nv50_dmac_wind(struct nv50_dmac *dmac) static int nv50_dmac_wait(struct nvif_push *push, u32 size) { - struct nv50_dmac *dmac = container_of(push, typeof(*dmac), _push); + struct nv50_dmac *dmac = container_of(push, typeof(*dmac), push); int free; if (WARN_ON(size > dmac->max)) return -EINVAL; - dmac->cur = push->cur - (u32 __iomem *)dmac->_push.mem.object.map.ptr; + dmac->cur = push->cur - (u32 __iomem *)dmac->push.mem.object.map.ptr; if (dmac->cur + size >= dmac->max) { int ret = nv50_dmac_wind(dmac); if (ret) return ret; - push->cur = dmac->_push.mem.object.map.ptr; + push->cur = dmac->push.mem.object.map.ptr; push->cur = push->cur + dmac->cur; nv50_dmac_kick(push); } @@ -213,7 +217,7 @@ nv50_dmac_wait(struct nvif_push *push, u32 size) return -ETIMEDOUT; } - push->bgn = dmac->_push.mem.object.map.ptr; + push->bgn = dmac->push.mem.object.map.ptr; push->bgn = push->bgn + dmac->cur; push->cur = push->bgn; push->end = push->cur + free; @@ -225,17 +229,16 @@ static int nv50_dmac_vram_pushbuf = -1; module_param_named(kms_vram_pushbuf, nv50_dmac_vram_pushbuf, int, 0400); int -nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, +nv50_dmac_create(struct nouveau_drm *drm, const s32 *oclass, u8 head, void *data, u32 size, s64 syncbuf, struct nv50_dmac *dmac) { - struct nouveau_cli *cli = (void *)device->object.client; + struct nvif_device *device = &drm->device; + struct nvif_object *disp = &drm->display->disp.object; struct nvif_disp_chan_v0 *args = data; u8 type = NVIF_MEM_COHERENT; int ret; - mutex_init(&dmac->lock); - /* Pascal added support for 47-bit physical addresses, but some * parts of EVO still only accept 40-bit PAs. * @@ -249,18 +252,15 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, (nv50_dmac_vram_pushbuf < 0 && device->info.family == NV_DEVICE_INFO_V0_PASCAL)) type |= NVIF_MEM_VRAM; - ret = nvif_mem_ctor_map(&cli->mmu, "kmsChanPush", type, 0x1000, - &dmac->_push.mem); + ret = nvif_mem_ctor_map(&drm->mmu, "kmsChanPush", type, 0x1000, &dmac->push.mem); if (ret) return ret; - dmac->ptr = dmac->_push.mem.object.map.ptr; - dmac->_push.wait = nv50_dmac_wait; - dmac->_push.kick = nv50_dmac_kick; - dmac->push = &dmac->_push; - dmac->push->bgn = dmac->_push.mem.object.map.ptr; - dmac->push->cur = dmac->push->bgn; - dmac->push->end = dmac->push->bgn; + dmac->push.wait = nv50_dmac_wait; + dmac->push.kick = nv50_dmac_kick; + dmac->push.bgn = dmac->push.mem.object.map.ptr; + dmac->push.cur = dmac->push.bgn; + dmac->push.end = dmac->push.bgn; dmac->max = 0x1000/4 - 1; /* EVO channels are affected by a HW bug where the last 12 DWORDs @@ -269,7 +269,7 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, if (disp->oclass < GV100_DISP) dmac->max -= 12; - args->pushbuf = nvif_handle(&dmac->_push.mem.object); + args->pushbuf = nvif_handle(&dmac->push.mem.object); ret = nv50_chan_create(device, disp, oclass, head, data, size, &dmac->base); @@ -557,7 +557,7 @@ nv50_dac_create(struct nouveau_encoder *nv_encoder) { struct drm_connector *connector = &nv_encoder->conn->base; struct nouveau_drm *drm = nouveau_drm(connector->dev); - struct nvkm_i2c *i2c = nvxx_i2c(&drm->client.device); + struct nvkm_i2c *i2c = nvxx_i2c(drm); struct nvkm_i2c_bus *bus; struct drm_encoder *encoder; struct dcb_output *dcbe = nv_encoder->dcb; @@ -592,8 +592,7 @@ static int nv50_audio_component_get_eld(struct device *kdev, int port, int dev_id, bool *enabled, unsigned char *buf, int max_bytes) { - struct drm_device *drm_dev = dev_get_drvdata(kdev); - struct nouveau_drm *drm = nouveau_drm(drm_dev); + struct nouveau_drm *drm = dev_get_drvdata(kdev); struct drm_encoder *encoder; struct nouveau_encoder *nv_encoder; struct nouveau_crtc *nv_crtc; @@ -638,18 +637,17 @@ static int nv50_audio_component_bind(struct device *kdev, struct device *hda_kdev, void *data) { - struct drm_device *drm_dev = dev_get_drvdata(kdev); - struct nouveau_drm *drm = nouveau_drm(drm_dev); + struct nouveau_drm *drm = dev_get_drvdata(kdev); struct drm_audio_component *acomp = data; if (WARN_ON(!device_link_add(hda_kdev, kdev, DL_FLAG_STATELESS))) return -ENOMEM; - drm_modeset_lock_all(drm_dev); + drm_modeset_lock_all(drm->dev); acomp->ops = &nv50_audio_component_ops; acomp->dev = kdev; drm->audio.component = acomp; - drm_modeset_unlock_all(drm_dev); + drm_modeset_unlock_all(drm->dev); return 0; } @@ -657,15 +655,14 @@ static void nv50_audio_component_unbind(struct device *kdev, struct device *hda_kdev, void *data) { - struct drm_device *drm_dev = dev_get_drvdata(kdev); - struct nouveau_drm *drm = nouveau_drm(drm_dev); + struct nouveau_drm *drm = dev_get_drvdata(kdev); struct drm_audio_component *acomp = data; - drm_modeset_lock_all(drm_dev); + drm_modeset_lock_all(drm->dev); drm->audio.component = NULL; acomp->ops = NULL; acomp->dev = NULL; - drm_modeset_unlock_all(drm_dev); + drm_modeset_unlock_all(drm->dev); } static const struct component_ops nv50_audio_component_bind_ops = { @@ -750,7 +747,7 @@ nv50_audio_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc, struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nvif_outp *outp = &nv_encoder->outp; - if (!nv50_audio_supported(encoder) || !drm_detect_monitor_audio(nv_connector->edid)) + if (!nv50_audio_supported(encoder) || !nv_connector->base.display_info.has_audio) return; mutex_lock(&drm->audio.lock); @@ -914,7 +911,7 @@ nv50_msto_cleanup(struct drm_atomic_state *state, msto->disabled = false; drm_dp_remove_payload_part2(mgr, new_mst_state, old_payload, new_payload); } else if (msto->enabled) { - drm_dp_add_payload_part2(mgr, state, new_payload); + drm_dp_add_payload_part2(mgr, new_payload); msto->enabled = false; } } @@ -995,8 +992,7 @@ nv50_msto_atomic_check(struct drm_encoder *encoder, if (!mst_state->pbn_div.full) { struct nouveau_encoder *outp = mstc->mstm->outp; - mst_state->pbn_div = drm_dp_get_vc_payload_bw(&mstm->mgr, - outp->dp.link_bw, outp->dp.link_nr); + mst_state->pbn_div = drm_dp_get_vc_payload_bw(outp->dp.link_bw, outp->dp.link_nr); } slots = drm_dp_atomic_find_time_slots(state, &mstm->mgr, mstc->port, asyh->dp.pbn); @@ -1268,8 +1264,8 @@ nv50_mstc_new(struct nv50_mstm *mstm, struct drm_dp_mst_port *port, mstc->mstm = mstm; mstc->port = port; - ret = drm_connector_init(dev, &mstc->connector, &nv50_mstc, - DRM_MODE_CONNECTOR_DisplayPort); + ret = drm_connector_dynamic_init(dev, &mstc->connector, &nv50_mstc, + DRM_MODE_CONNECTOR_DisplayPort, NULL); if (ret) { kfree(*pmstc); *pmstc = NULL; @@ -1764,7 +1760,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta if ((disp->disp->object.oclass == GT214_DISP || disp->disp->object.oclass >= GF110_DISP) && nv_encoder->dcb->type != DCB_OUTPUT_LVDS && - drm_detect_monitor_audio(nv_connector->edid)) + nv_connector->base.display_info.has_audio) hda = true; if (!nvif_outp_acquired(outp)) @@ -1773,7 +1769,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta switch (nv_encoder->dcb->type) { case DCB_OUTPUT_TMDS: if (disp->disp->object.oclass != NV50_DISP && - drm_detect_hdmi_monitor(nv_connector->edid)) + nv_connector->base.display_info.is_hdmi) nv50_hdmi_enable(encoder, nv_crtc, nv_connector, state, mode, hda); if (nv_encoder->outp.or.link & 1) { @@ -1786,7 +1782,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta */ if (mode->clock >= 165000 && nv_encoder->dcb->duallink_possible && - !drm_detect_hdmi_monitor(nv_connector->edid)) + !nv_connector->base.display_info.is_hdmi) proto = NV507D_SOR_SET_CONTROL_PROTOCOL_DUAL_TMDS; } else { proto = NV507D_SOR_SET_CONTROL_PROTOCOL_SINGLE_TMDS_B; @@ -1883,7 +1879,7 @@ nv50_sor_create(struct nouveau_encoder *nv_encoder) struct drm_connector *connector = &nv_encoder->conn->base; struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_drm *drm = nouveau_drm(connector->dev); - struct nvkm_i2c *i2c = nvxx_i2c(&drm->client.device); + struct nvkm_i2c *i2c = nvxx_i2c(drm); struct drm_encoder *encoder; struct dcb_output *dcbe = nv_encoder->dcb; struct nv50_disp *disp = nv50_disp(connector->dev); @@ -2050,7 +2046,7 @@ nv50_pior_create(struct nouveau_encoder *nv_encoder) struct drm_device *dev = connector->dev; struct nouveau_drm *drm = nouveau_drm(dev); struct nv50_disp *disp = nv50_disp(dev); - struct nvkm_i2c *i2c = nvxx_i2c(&drm->client.device); + struct nvkm_i2c *i2c = nvxx_i2c(drm); struct nvkm_i2c_bus *bus = NULL; struct nvkm_i2c_aux *aux = NULL; struct i2c_adapter *ddc; @@ -2651,7 +2647,6 @@ nv50_disp_atomic_state_alloc(struct drm_device *dev) static const struct drm_mode_config_funcs nv50_disp_func = { .fb_create = nouveau_user_framebuffer_create, - .output_poll_changed = drm_fb_helper_output_poll_changed, .atomic_check = nv50_disp_atomic_check, .atomic_commit = nv50_disp_atomic_commit, .atomic_state_alloc = nv50_disp_atomic_state_alloc, @@ -2679,7 +2674,7 @@ nv50_display_fini(struct drm_device *dev, bool runtime, bool suspend) nv50_mstm_fini(nouveau_encoder(encoder)); } - if (!runtime) + if (!runtime && !drm->headless) cancel_work_sync(&drm->hpd_work); } @@ -2818,7 +2813,7 @@ nv50_display_destroy(struct drm_device *dev) nouveau_bo_unmap(disp->sync); if (disp->sync) nouveau_bo_unpin(disp->sync); - nouveau_bo_ref(NULL, &disp->sync); + nouveau_bo_fini(disp->sync); nouveau_display(dev)->priv = NULL; kfree(disp); @@ -2861,7 +2856,7 @@ nv50_display_create(struct drm_device *dev) nouveau_bo_unpin(disp->sync); } if (ret) - nouveau_bo_ref(NULL, &disp->sync); + nouveau_bo_fini(disp->sync); } if (ret) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.h b/drivers/gpu/drm/nouveau/dispnv50/disp.h index 5508a7cfd492..15f9242b72ac 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.h +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.h @@ -62,18 +62,11 @@ struct nv50_chan { struct nv50_dmac { struct nv50_chan base; - struct nvif_push _push; - struct nvif_push *push; - u32 *ptr; + struct nvif_push push; struct nvif_object sync; struct nvif_object vram; - /* Protects against concurrent pushbuf access to this channel, lock is - * grabbed by evo_wait (if the pushbuf reservation is successful) and - * dropped again by evo_kick. */ - struct mutex lock; - u32 cur; u32 put; u32 max; @@ -95,7 +88,7 @@ struct nv50_outp_atom { } set, clr; }; -int nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, +int nv50_dmac_create(struct nouveau_drm *, const s32 *oclass, u8 head, void *data, u32 size, s64 syncbuf, struct nv50_dmac *dmac); void nv50_dmac_destroy(struct nv50_dmac *); @@ -108,9 +101,6 @@ void nv50_dmac_destroy(struct nv50_dmac *); */ struct nouveau_encoder *nv50_real_outp(struct drm_encoder *encoder); -u32 *evo_wait(struct nv50_dmac *, int nr); -void evo_kick(u32 *, struct nv50_dmac *); - extern const u64 disp50xx_modifiers[]; extern const u64 disp90xx_modifiers[]; extern const u64 wndwc57e_modifiers[]; diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c index 5f490fbf1877..d7c74cc43ba5 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c @@ -32,6 +32,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_edid.h> #include <drm/drm_vblank.h> #include "nouveau_connector.h" @@ -126,14 +127,8 @@ nv50_head_atomic_check_view(struct nv50_head_atom *armh, struct drm_display_mode *omode = &asyh->state.adjusted_mode; struct drm_display_mode *umode = &asyh->state.mode; int mode = asyc->scaler.mode; - struct edid *edid; int umode_vdisplay, omode_hdisplay, omode_vdisplay; - if (connector->edid_blob_ptr) - edid = (struct edid *)connector->edid_blob_ptr->data; - else - edid = NULL; - if (!asyc->scaler.full) { if (mode == DRM_MODE_SCALE_NONE) omode = umode; @@ -161,7 +156,7 @@ nv50_head_atomic_check_view(struct nv50_head_atom *armh, */ if ((asyc->scaler.underscan.mode == UNDERSCAN_ON || (asyc->scaler.underscan.mode == UNDERSCAN_AUTO && - drm_detect_hdmi_monitor(edid)))) { + connector->display_info.is_hdmi))) { u32 bX = asyc->scaler.underscan.hborder; u32 bY = asyc->scaler.underscan.vborder; u32 r = (asyh->view.oH << 19) / asyh->view.oW; diff --git a/drivers/gpu/drm/nouveau/dispnv50/head507d.c b/drivers/gpu/drm/nouveau/dispnv50/head507d.c index 0edd4e520c8e..7fa1e0279d7d 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head507d.c @@ -29,7 +29,7 @@ int head507d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -48,7 +48,7 @@ head507d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh) int head507d_dither(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -66,7 +66,7 @@ head507d_dither(struct nv50_head *head, struct nv50_head_atom *asyh) int head507d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; u32 bounds = 0; int ret; @@ -94,7 +94,7 @@ head507d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh) int head507d_base(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; u32 bounds = 0; int ret; @@ -122,7 +122,7 @@ head507d_base(struct nv50_head *head, struct nv50_head_atom *asyh) static int head507d_curs_clr(struct nv50_head *head) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -139,7 +139,7 @@ head507d_curs_clr(struct nv50_head *head) static int head507d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -188,7 +188,7 @@ head507d_curs_layout(struct nv50_head *head, struct nv50_wndw_atom *asyw, int head507d_core_clr(struct nv50_head *head) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -202,7 +202,7 @@ head507d_core_clr(struct nv50_head *head) static int head507d_core_set(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -278,7 +278,7 @@ head507d_core_calc(struct nv50_head *head, struct nv50_head_atom *asyh) static int head507d_olut_clr(struct nv50_head *head) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -293,7 +293,7 @@ head507d_olut_clr(struct nv50_head *head) static int head507d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -345,7 +345,7 @@ head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size) int head507d_mode(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; struct nv50_head_mode *m = &asyh->mode; const int i = head->base.index; int ret; @@ -400,7 +400,7 @@ head507d_mode(struct nv50_head *head, struct nv50_head_atom *asyh) int head507d_view(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/head827d.c b/drivers/gpu/drm/nouveau/dispnv50/head827d.c index 194d1771c481..1545d576fe9c 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head827d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head827d.c @@ -29,7 +29,7 @@ static int head827d_curs_clr(struct nv50_head *head) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -48,7 +48,7 @@ head827d_curs_clr(struct nv50_head *head) static int head827d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -73,7 +73,7 @@ head827d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh) static int head827d_core_set(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -110,7 +110,7 @@ head827d_core_set(struct nv50_head *head, struct nv50_head_atom *asyh) static int head827d_olut_clr(struct nv50_head *head) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -127,7 +127,7 @@ head827d_olut_clr(struct nv50_head *head) static int head827d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/head907d.c b/drivers/gpu/drm/nouveau/dispnv50/head907d.c index 18fe4c1e2d6a..6c9e0438e55c 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head907d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head907d.c @@ -36,7 +36,7 @@ int head907d_or(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -57,7 +57,7 @@ head907d_or(struct nv50_head *head, struct nv50_head_atom *asyh) int head907d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -77,7 +77,7 @@ head907d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh) static int head907d_dither(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -95,7 +95,7 @@ head907d_dither(struct nv50_head *head, struct nv50_head_atom *asyh) int head907d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; u32 bounds = 0; int ret; @@ -124,7 +124,7 @@ head907d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh) static int head907d_base(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; u32 bounds = 0; int ret; @@ -152,7 +152,7 @@ head907d_base(struct nv50_head *head, struct nv50_head_atom *asyh) int head907d_curs_clr(struct nv50_head *head) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -171,7 +171,7 @@ head907d_curs_clr(struct nv50_head *head) int head907d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -195,7 +195,7 @@ head907d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh) int head907d_core_clr(struct nv50_head *head) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -209,7 +209,7 @@ head907d_core_clr(struct nv50_head *head) int head907d_core_set(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -246,7 +246,7 @@ head907d_core_set(struct nv50_head *head, struct nv50_head_atom *asyh) int head907d_olut_clr(struct nv50_head *head) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -263,7 +263,7 @@ head907d_olut_clr(struct nv50_head *head) int head907d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -322,7 +322,7 @@ bool head907d_ilut_check(int size) int head907d_mode(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; struct nv50_head_mode *m = &asyh->mode; const int i = head->base.index; int ret; @@ -378,7 +378,7 @@ head907d_mode(struct nv50_head *head, struct nv50_head_atom *asyh) int head907d_view(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/head917d.c b/drivers/gpu/drm/nouveau/dispnv50/head917d.c index 4ce47b55f72c..2d9aee050510 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head917d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head917d.c @@ -30,7 +30,7 @@ static int head917d_dither(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -48,7 +48,7 @@ head917d_dither(struct nv50_head *head, struct nv50_head_atom *asyh) static int head917d_base(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; u32 bounds = 0; int ret; @@ -77,7 +77,7 @@ head917d_base(struct nv50_head *head, struct nv50_head_atom *asyh) static int head917d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/headc37d.c b/drivers/gpu/drm/nouveau/dispnv50/headc37d.c index a4a3b78ea42c..2bcb3790fc10 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/headc37d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/headc37d.c @@ -30,7 +30,7 @@ static int headc37d_or(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; u8 depth; int ret; @@ -64,7 +64,7 @@ headc37d_or(struct nv50_head *head, struct nv50_head_atom *asyh) static int headc37d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -85,7 +85,7 @@ headc37d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh) int headc37d_dither(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -104,7 +104,7 @@ headc37d_dither(struct nv50_head *head, struct nv50_head_atom *asyh) int headc37d_curs_clr(struct nv50_head *head) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -122,7 +122,7 @@ headc37d_curs_clr(struct nv50_head *head) int headc37d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -161,7 +161,7 @@ headc37d_curs_format(struct nv50_head *head, struct nv50_wndw_atom *asyw, static int headc37d_olut_clr(struct nv50_head *head) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -175,7 +175,7 @@ headc37d_olut_clr(struct nv50_head *head) static int headc37d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -209,7 +209,7 @@ headc37d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size) static int headc37d_mode(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; struct nv50_head_mode *m = &asyh->mode; const int i = head->base.index; int ret; @@ -254,7 +254,7 @@ headc37d_mode(struct nv50_head *head, struct nv50_head_atom *asyh) int headc37d_view(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/headc57d.c b/drivers/gpu/drm/nouveau/dispnv50/headc57d.c index 53b1248c40ec..fde4087e7691 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/headc57d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/headc57d.c @@ -30,7 +30,7 @@ static int headc57d_display_id(struct nv50_head *head, u32 display_id) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; int ret; if ((ret = PUSH_WAIT(push, 2))) @@ -43,7 +43,7 @@ headc57d_display_id(struct nv50_head *head, u32 display_id) static int headc57d_or(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; u8 depth; int ret; @@ -78,7 +78,7 @@ headc57d_or(struct nv50_head *head, struct nv50_head_atom *asyh) static int headc57d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -96,7 +96,7 @@ headc57d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh) static int headc57d_olut_clr(struct nv50_head *head) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -110,7 +110,7 @@ headc57d_olut_clr(struct nv50_head *head) static int headc57d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; const int i = head->base.index; int ret; @@ -201,7 +201,7 @@ headc57d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size) static int headc57d_mode(struct nv50_head *head, struct nv50_head_atom *asyh) { - struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; + struct nvif_push *push = &nv50_disp(head->base.base.dev)->core->chan.push; struct nv50_head_mode *m = &asyh->mode; const int i = head->base.index; int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c index 797c1e4e0eaa..654e506f8431 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c @@ -33,7 +33,7 @@ int ovly507e_scale_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 4))) @@ -55,7 +55,7 @@ ovly507e_scale_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) static int ovly507e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 12))) @@ -159,7 +159,7 @@ ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format, if (*pwndw = wndw, ret) return ret; - ret = nv50_dmac_create(&drm->client.device, &disp->disp->object, + ret = nv50_dmac_create(drm, &oclass, 0, &args, sizeof(args), disp->sync->offset, &wndw->wndw); if (ret) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c index 02dc02d9260f..a5ae22ed663d 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly827e.c @@ -32,7 +32,7 @@ static int ovly827e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 12))) diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c index 645130d18a99..8cf0e18fa596 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly907e.c @@ -29,7 +29,7 @@ static int ovly907e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 12))) diff --git a/drivers/gpu/drm/nouveau/dispnv50/pior507d.c b/drivers/gpu/drm/nouveau/dispnv50/pior507d.c index 17d230256bdd..79507d169778 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/pior507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/pior507d.c @@ -30,7 +30,7 @@ static int pior507d_ctrl(struct nv50_core *core, int or, u32 ctrl, struct nv50_head_atom *asyh) { - struct nvif_push *push = core->chan.push; + struct nvif_push *push = &core->chan.push; int ret; if (asyh) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/sor507d.c b/drivers/gpu/drm/nouveau/dispnv50/sor507d.c index ca73d7710885..08cc9845322e 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/sor507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/sor507d.c @@ -30,7 +30,7 @@ static int sor507d_ctrl(struct nv50_core *core, int or, u32 ctrl, struct nv50_head_atom *asyh) { - struct nvif_push *push = core->chan.push; + struct nvif_push *push = &core->chan.push; int ret; if (asyh) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/sor907d.c b/drivers/gpu/drm/nouveau/dispnv50/sor907d.c index c86cd8fa61d6..23957cc8f326 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/sor907d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/sor907d.c @@ -32,7 +32,7 @@ static int sor907d_ctrl(struct nv50_core *core, int or, u32 ctrl, struct nv50_head_atom *asyh) { - struct nvif_push *push = core->chan.push; + struct nvif_push *push = &core->chan.push; int ret; if ((ret = PUSH_WAIT(push, 2))) diff --git a/drivers/gpu/drm/nouveau/dispnv50/sorc37d.c b/drivers/gpu/drm/nouveau/dispnv50/sorc37d.c index 9eaef34816da..da05d4614e00 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/sorc37d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/sorc37d.c @@ -29,7 +29,7 @@ static int sorc37d_ctrl(struct nv50_core *core, int or, u32 ctrl, struct nv50_head_atom *asyh) { - struct nvif_push *push = core->chan.push; + struct nvif_push *push = &core->chan.push; int ret; if ((ret = PUSH_WAIT(push, 2))) diff --git a/drivers/gpu/drm/nouveau/dispnv50/tile.h b/drivers/gpu/drm/nouveau/dispnv50/tile.h new file mode 100644 index 000000000000..e2be82830cf7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv50/tile.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NV50_TILE_H__ +#define __NV50_TILE_H__ + +#include <linux/types.h> +#include <linux/math.h> + +/* + * Tiling parameters for NV50+. + * GOB = Group of bytes, the main unit for tiling blocks. + * Tiling blocks are a power of 2 number of GOB. + * All GOBs and blocks have the same width: 64 bytes (so 16 pixels in 32bits). + * tile_mode is the log2 of the number of GOB per block. + */ + +#define NV_TILE_GOB_HEIGHT_TESLA 4 /* 4 x 64 bytes = 256 bytes for a GOB on Tesla*/ +#define NV_TILE_GOB_HEIGHT 8 /* 8 x 64 bytes = 512 bytes for a GOB on Fermi and later */ +#define NV_TILE_GOB_WIDTH_BYTES 64 + +/* Number of blocks to cover the width of the framebuffer */ +static inline u32 nouveau_get_width_in_blocks(u32 stride) +{ + return DIV_ROUND_UP(stride, NV_TILE_GOB_WIDTH_BYTES); +} + +/* Return the height in pixel of one GOB */ +static inline u32 nouveau_get_gob_height(u16 family) +{ + if (family == NV_DEVICE_INFO_V0_TESLA) + return NV_TILE_GOB_HEIGHT_TESLA; + else + return NV_TILE_GOB_HEIGHT; +} + +/* Number of blocks to cover the heigth of the framebuffer */ +static inline u32 nouveau_get_height_in_blocks(u32 height, u32 gobs_in_block, u16 family) +{ + return DIV_ROUND_UP(height, nouveau_get_gob_height(family) * gobs_in_block); +} + +/* Return the GOB size in bytes */ +static inline u32 nouveau_get_gob_size(u16 family) +{ + return nouveau_get_gob_height(family) * NV_TILE_GOB_WIDTH_BYTES; +} + +/* Return the number of GOB in a block */ +static inline int nouveau_get_gobs_in_block(u32 tile_mode, u16 chipset) +{ + if (chipset >= 0xc0) + return 1 << (tile_mode >> 4); + return 1 << tile_mode; +} + +/* Return true if tile_mode is invalid */ +static inline bool nouveau_check_tile_mode(u32 tile_mode, u16 chipset) +{ + if (chipset >= 0xc0) + return (tile_mode & 0xfffff0f); + return (tile_mode & 0xfffffff0); +} + +#endif diff --git a/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c b/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c index ee76b091d4ef..7985da61aaac 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c @@ -31,7 +31,7 @@ static int wimmc37b_update(struct nv50_wndw *wndw, u32 *interlock) { - struct nvif_push *push = wndw->wimm.push; + struct nvif_push *push = &wndw->wimm.push; int ret; if ((ret = PUSH_WAIT(push, 2))) @@ -46,7 +46,7 @@ wimmc37b_update(struct nv50_wndw *wndw, u32 *interlock) static int wimmc37b_point(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wimm.push; + struct nvif_push *push = &wndw->wimm.push; int ret; if ((ret = PUSH_WAIT(push, 2))) @@ -71,10 +71,9 @@ wimmc37b_init_(const struct nv50_wimm_func *func, struct nouveau_drm *drm, struct nvif_disp_chan_v0 args = { .id = wndw->id, }; - struct nv50_disp *disp = nv50_disp(drm->dev); int ret; - ret = nv50_dmac_create(&drm->client.device, &disp->disp->object, + ret = nv50_dmac_create(drm, &oclass, 0, &args, sizeof(args), -1, &wndw->wimm); if (ret) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c index 7a2cceaee6e9..f6be426dd525 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c @@ -30,14 +30,20 @@ #include <nvhw/class/cl507e.h> #include <nvhw/class/clc37e.h> +#include <linux/iosys-map.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_blend.h> -#include <drm/drm_gem_atomic_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> +#include <drm/drm_gem_atomic_helper.h> +#include <drm/drm_panic.h> +#include <drm/ttm/ttm_bo.h> #include "nouveau_bo.h" #include "nouveau_gem.h" +#include "tile.h" static void nv50_wndw_ctxdma_del(struct nv50_wndw_ctxdma *ctxdma) @@ -577,6 +583,114 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) return 0; } +/* Only used by drm_panic get_scanout_buffer() and set_pixel(), so it is + * protected by the drm panic spinlock + */ +static u32 nv50_panic_blk_h; + +/* Return the framebuffer offset of the start of the block where pixel(x,y) is */ +static u32 +nv50_get_block_off(unsigned int x, unsigned int y, unsigned int pitch) +{ + u32 blk_x, blk_y, blk_columns; + + blk_columns = nouveau_get_width_in_blocks(pitch); + blk_x = (x * 4) / NV_TILE_GOB_WIDTH_BYTES; + blk_y = y / nv50_panic_blk_h; + + return ((blk_y * blk_columns) + blk_x) * NV_TILE_GOB_WIDTH_BYTES * nv50_panic_blk_h; +} + +/* Turing and later have 2 level of tiles inside the block */ +static void +nv50_set_pixel_swizzle(struct drm_scanout_buffer *sb, unsigned int x, + unsigned int y, u32 color) +{ + u32 blk_off, off, swizzle; + + blk_off = nv50_get_block_off(x, y, sb->pitch[0]); + + y = y % nv50_panic_blk_h; + + /* Inside the block, use the fast address swizzle to compute the offset + * For nvidia blocklinear, bit order is yn..y3 x3 y2 x2 y1 y0 x1 x0 + */ + swizzle = (x & 3) | (y & 3) << 2 | (x & 4) << 2 | (y & 4) << 3; + swizzle |= (x & 8) << 3 | (y >> 3) << 7; + off = blk_off + swizzle * 4; + + iosys_map_wr(&sb->map[0], off, u32, color); +} + +static void +nv50_set_pixel(struct drm_scanout_buffer *sb, unsigned int x, unsigned int y, + u32 color) +{ + u32 blk_off, off; + + blk_off = nv50_get_block_off(x, y, sb->width); + + x = x % (NV_TILE_GOB_WIDTH_BYTES / 4); + y = y % nv50_panic_blk_h; + off = blk_off + x * 4 + y * NV_TILE_GOB_WIDTH_BYTES; + + iosys_map_wr(&sb->map[0], off, u32, color); +} + +static int +nv50_wndw_get_scanout_buffer(struct drm_plane *plane, struct drm_scanout_buffer *sb) +{ + struct drm_framebuffer *fb; + struct nouveau_bo *nvbo; + struct nouveau_drm *drm = nouveau_drm(plane->dev); + u16 chipset = drm->client.device.info.chipset; + u8 family = drm->client.device.info.family; + u32 tile_mode; + u8 kind; + + if (!plane->state || !plane->state->fb) + return -EINVAL; + + fb = plane->state->fb; + nvbo = nouveau_gem_object(fb->obj[0]); + + /* Don't support compressed format, or multiplane yet. */ + if (nvbo->comp || fb->format->num_planes != 1) + return -EOPNOTSUPP; + + if (nouveau_bo_map(nvbo)) { + drm_warn(plane->dev, "nouveau bo map failed, panic won't be displayed\n"); + return -ENOMEM; + } + + if (nvbo->kmap.bo_kmap_type & TTM_BO_MAP_IOMEM_MASK) + iosys_map_set_vaddr_iomem(&sb->map[0], (void __iomem *)nvbo->kmap.virtual); + else + iosys_map_set_vaddr(&sb->map[0], nvbo->kmap.virtual); + + sb->height = fb->height; + sb->width = fb->width; + sb->pitch[0] = fb->pitches[0]; + sb->format = fb->format; + + nouveau_framebuffer_get_layout(fb, &tile_mode, &kind); + if (kind) { + /* If tiling is enabled, use set_pixel() to display correctly. + * Only handle 32bits format for now. + */ + if (fb->format->cpp[0] != 4) + return -EOPNOTSUPP; + nv50_panic_blk_h = nouveau_get_gob_height(family) * + nouveau_get_gobs_in_block(tile_mode, chipset); + + if (chipset >= 0x160) + sb->set_pixel = nv50_set_pixel_swizzle; + else + sb->set_pixel = nv50_set_pixel; + } + return 0; +} + static const struct drm_plane_helper_funcs nv50_wndw_helper = { .prepare_fb = nv50_wndw_prepare_fb, @@ -584,6 +698,14 @@ nv50_wndw_helper = { .atomic_check = nv50_wndw_atomic_check, }; +static const struct drm_plane_helper_funcs +nv50_wndw_primary_helper = { + .prepare_fb = nv50_wndw_prepare_fb, + .cleanup_fb = nv50_wndw_cleanup_fb, + .atomic_check = nv50_wndw_atomic_check, + .get_scanout_buffer = nv50_wndw_get_scanout_buffer, +}; + static void nv50_wndw_atomic_destroy_state(struct drm_plane *plane, struct drm_plane_state *state) @@ -732,7 +854,10 @@ nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev, return ret; } - drm_plane_helper_add(&wndw->plane, &nv50_wndw_helper); + if (type == DRM_PLANE_TYPE_PRIMARY) + drm_plane_helper_add(&wndw->plane, &nv50_wndw_primary_helper); + else + drm_plane_helper_add(&wndw->plane, &nv50_wndw_helper); if (wndw->func->ilut) { ret = nv50_lut_init(disp, mmu, &wndw->ilut); diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c index b3deea5aca58..50a7b97d37a2 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c @@ -39,7 +39,7 @@ wndwc37e_csc_clr(struct nv50_wndw *wndw) static int wndwc37e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 13))) @@ -52,7 +52,7 @@ wndwc37e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) static int wndwc37e_ilut_clr(struct nv50_wndw *wndw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 2))) @@ -65,7 +65,7 @@ wndwc37e_ilut_clr(struct nv50_wndw *wndw) static int wndwc37e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 4))) @@ -94,7 +94,7 @@ wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size) int wndwc37e_blend_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 8))) @@ -139,7 +139,7 @@ wndwc37e_blend_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) int wndwc37e_image_clr(struct nv50_wndw *wndw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 4))) @@ -156,7 +156,7 @@ wndwc37e_image_clr(struct nv50_wndw *wndw) static int wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 17))) @@ -209,7 +209,7 @@ wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) int wndwc37e_ntfy_clr(struct nv50_wndw *wndw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 2))) @@ -222,7 +222,7 @@ wndwc37e_ntfy_clr(struct nv50_wndw *wndw) int wndwc37e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 3))) @@ -239,7 +239,7 @@ wndwc37e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) int wndwc37e_sema_clr(struct nv50_wndw *wndw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 2))) @@ -252,7 +252,7 @@ wndwc37e_sema_clr(struct nv50_wndw *wndw) int wndwc37e_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 5))) @@ -268,7 +268,7 @@ wndwc37e_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) int wndwc37e_update(struct nv50_wndw *wndw, u32 *interlock) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 5))) @@ -363,7 +363,7 @@ wndwc37e_new_(const struct nv50_wndw_func *func, struct nouveau_drm *drm, if (*pwndw = wndw, ret) return ret; - ret = nv50_dmac_create(&drm->client.device, &disp->disp->object, + ret = nv50_dmac_create(drm, &oclass, 0, &args, sizeof(args), disp->sync->offset, &wndw->wndw); if (ret) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c index 1d214a4b960a..d1ca51aae58c 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c @@ -32,7 +32,7 @@ static int wndwc57e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 17))) @@ -81,7 +81,7 @@ wndwc57e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) int wndwc57e_csc_clr(struct nv50_wndw *wndw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; const u32 identity[12] = { 0x00010000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000, 0x00000000, @@ -99,7 +99,7 @@ wndwc57e_csc_clr(struct nv50_wndw *wndw) int wndwc57e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 13))) @@ -112,7 +112,7 @@ wndwc57e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) int wndwc57e_ilut_clr(struct nv50_wndw *wndw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 2))) @@ -125,7 +125,7 @@ wndwc57e_ilut_clr(struct nv50_wndw *wndw) int wndwc57e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 4))) diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc67e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc67e.c index 7a370fa1df20..52af293c98f4 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc67e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc67e.c @@ -29,7 +29,7 @@ static int wndwc67e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) { - struct nvif_push *push = wndw->wndw.push; + struct nvif_push *push = &wndw->wndw.push; int ret; if ((ret = PUSH_WAIT(push, 17))) diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl0080.h b/drivers/gpu/drm/nouveau/include/nvif/cl0080.h index fa161b74d967..ea937fa7bc55 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl0080.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl0080.h @@ -2,13 +2,6 @@ #ifndef __NVIF_CL0080_H__ #define __NVIF_CL0080_H__ -struct nv_device_v0 { - __u8 version; - __u8 priv; - __u8 pad02[6]; - __u64 device; /* device identifier, ~0 for client default */ -}; - #define NV_DEVICE_V0_INFO 0x00 #define NV_DEVICE_V0_TIME 0x01 diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index e668ab1664f0..824e052dcc25 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -7,9 +7,6 @@ #define NVIF_CLASS_CONTROL /* if0001.h */ -0x00000001 -#define NVIF_CLASS_PERFMON /* if0002.h */ -0x00000002 -#define NVIF_CLASS_PERFDOM /* if0003.h */ -0x00000003 - #define NVIF_CLASS_SW_NV04 /* if0004.h */ -0x00000004 #define NVIF_CLASS_SW_NV10 /* if0005.h */ -0x00000005 #define NVIF_CLASS_SW_NV50 /* if0005.h */ -0x00000006 diff --git a/drivers/gpu/drm/nouveau/include/nvif/client.h b/drivers/gpu/drm/nouveau/include/nvif/client.h index 5d9395e651b6..03f1d564eb12 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/client.h +++ b/drivers/gpu/drm/nouveau/include/nvif/client.h @@ -7,21 +7,12 @@ struct nvif_client { struct nvif_object object; const struct nvif_driver *driver; - u64 version; - u8 route; }; -int nvif_client_ctor(struct nvif_client *parent, const char *name, u64 device, - struct nvif_client *); +int nvif_client_ctor(struct nvif_client *parent, const char *name, struct nvif_client *); void nvif_client_dtor(struct nvif_client *); -int nvif_client_ioctl(struct nvif_client *, void *, u32); int nvif_client_suspend(struct nvif_client *); int nvif_client_resume(struct nvif_client *); /*XXX*/ -#include <core/client.h> -#define nvxx_client(a) ({ \ - struct nvif_client *_client = (a); \ - (struct nvkm_client *)_client->object.priv; \ -}) #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/device.h b/drivers/gpu/drm/nouveau/include/nvif/device.h index b0e59800a320..7877a2a79da9 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/device.h +++ b/drivers/gpu/drm/nouveau/include/nvif/device.h @@ -18,41 +18,8 @@ struct nvif_device { struct nvif_user user; }; -int nvif_device_ctor(struct nvif_object *, const char *name, u32 handle, - s32 oclass, void *, u32, struct nvif_device *); +int nvif_device_ctor(struct nvif_client *, const char *name, struct nvif_device *); void nvif_device_dtor(struct nvif_device *); +int nvif_device_map(struct nvif_device *); u64 nvif_device_time(struct nvif_device *); - -/*XXX*/ -#include <subdev/bios.h> -#include <subdev/fb.h> -#include <subdev/bar.h> -#include <subdev/gpio.h> -#include <subdev/clk.h> -#include <subdev/i2c.h> -#include <subdev/timer.h> -#include <subdev/therm.h> -#include <subdev/pci.h> - -#define nvxx_device(a) ({ \ - struct nvif_device *_device = (a); \ - struct { \ - struct nvkm_object object; \ - struct nvkm_device *device; \ - } *_udevice = _device->object.priv; \ - _udevice->device; \ -}) -#define nvxx_bios(a) nvxx_device(a)->bios -#define nvxx_fb(a) nvxx_device(a)->fb -#define nvxx_gpio(a) nvxx_device(a)->gpio -#define nvxx_clk(a) nvxx_device(a)->clk -#define nvxx_i2c(a) nvxx_device(a)->i2c -#define nvxx_iccsense(a) nvxx_device(a)->iccsense -#define nvxx_therm(a) nvxx_device(a)->therm -#define nvxx_volt(a) nvxx_device(a)->volt - -#include <engine/fifo.h> -#include <engine/gr.h> - -#define nvxx_gr(a) nvxx_device(a)->gr #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/driver.h b/drivers/gpu/drm/nouveau/include/nvif/driver.h index 7a3af05f7f98..7b08ff769039 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/driver.h +++ b/drivers/gpu/drm/nouveau/include/nvif/driver.h @@ -8,20 +8,15 @@ struct nvif_driver { const char *name; int (*init)(const char *name, u64 device, const char *cfg, const char *dbg, void **priv); - void (*fini)(void *priv); int (*suspend)(void *priv); int (*resume)(void *priv); int (*ioctl)(void *priv, void *data, u32 size, void **hack); void __iomem *(*map)(void *priv, u64 handle, u32 size); void (*unmap)(void *priv, void __iomem *ptr, u32 size); - bool keep; }; int nvif_driver_init(const char *drv, const char *cfg, const char *dbg, const char *name, u64 device, struct nvif_client *); extern const struct nvif_driver nvif_driver_nvkm; -extern const struct nvif_driver nvif_driver_drm; -extern const struct nvif_driver nvif_driver_lib; -extern const struct nvif_driver nvif_driver_null; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0000.h b/drivers/gpu/drm/nouveau/include/nvif/if0000.h index f7b8f8f48760..c06383835337 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0000.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0000.h @@ -5,16 +5,6 @@ struct nvif_client_v0 { __u8 version; __u8 pad01[7]; - __u64 device; char name[32]; }; - -#define NVIF_CLIENT_V0_DEVLIST 0x00 - -struct nvif_client_devlist_v0 { - __u8 version; - __u8 count; - __u8 pad02[6]; - __u64 device[]; -}; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0002.h b/drivers/gpu/drm/nouveau/include/nvif/if0002.h deleted file mode 100644 index df2915d6a61e..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/if0002.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_IF0002_H__ -#define __NVIF_IF0002_H__ - -#define NVIF_PERFMON_V0_QUERY_DOMAIN 0x00 -#define NVIF_PERFMON_V0_QUERY_SIGNAL 0x01 -#define NVIF_PERFMON_V0_QUERY_SOURCE 0x02 - -struct nvif_perfmon_query_domain_v0 { - __u8 version; - __u8 id; - __u8 counter_nr; - __u8 iter; - __u16 signal_nr; - __u8 pad05[2]; - char name[64]; -}; - -struct nvif_perfmon_query_signal_v0 { - __u8 version; - __u8 domain; - __u16 iter; - __u8 signal; - __u8 source_nr; - __u8 pad05[2]; - char name[64]; -}; - -struct nvif_perfmon_query_source_v0 { - __u8 version; - __u8 domain; - __u8 signal; - __u8 iter; - __u8 pad04[4]; - __u32 source; - __u32 mask; - char name[64]; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0003.h b/drivers/gpu/drm/nouveau/include/nvif/if0003.h deleted file mode 100644 index 78467da07c37..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/if0003.h +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_IF0003_H__ -#define __NVIF_IF0003_H__ - -struct nvif_perfdom_v0 { - __u8 version; - __u8 domain; - __u8 mode; - __u8 pad03[1]; - struct { - __u8 signal[4]; - __u64 source[4][8]; - __u16 logic_op; - } ctr[4]; -}; - -#define NVIF_PERFDOM_V0_INIT 0x00 -#define NVIF_PERFDOM_V0_SAMPLE 0x01 -#define NVIF_PERFDOM_V0_READ 0x02 - -struct nvif_perfdom_init { -}; - -struct nvif_perfdom_sample { -}; - -struct nvif_perfdom_read_v0 { - __u8 version; - __u8 pad01[7]; - __u32 ctr[4]; - __u32 clk; - __u8 pad04[4]; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h index 4e047bb1fc07..e825c8a1d9ca 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h +++ b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h @@ -2,17 +2,12 @@ #ifndef __NVIF_IOCTL_H__ #define __NVIF_IOCTL_H__ -#define NVIF_VERSION_LATEST 0x0000000000000100ULL - struct nvif_ioctl_v0 { __u8 version; -#define NVIF_IOCTL_V0_NOP 0x00 #define NVIF_IOCTL_V0_SCLASS 0x01 #define NVIF_IOCTL_V0_NEW 0x02 #define NVIF_IOCTL_V0_DEL 0x03 #define NVIF_IOCTL_V0_MTHD 0x04 -#define NVIF_IOCTL_V0_RD 0x05 -#define NVIF_IOCTL_V0_WR 0x06 #define NVIF_IOCTL_V0_MAP 0x07 #define NVIF_IOCTL_V0_UNMAP 0x08 __u8 type; @@ -28,10 +23,6 @@ struct nvif_ioctl_v0 { __u8 data[]; /* ioctl data (below) */ }; -struct nvif_ioctl_nop_v0 { - __u64 version; -}; - struct nvif_ioctl_sclass_v0 { /* nvif_ioctl ... */ __u8 version; @@ -67,24 +58,6 @@ struct nvif_ioctl_mthd_v0 { __u8 data[]; /* method data (class.h) */ }; -struct nvif_ioctl_rd_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 size; - __u8 pad02[2]; - __u32 data; - __u64 addr; -}; - -struct nvif_ioctl_wr_v0 { - /* nvif_ioctl ... */ - __u8 version; - __u8 size; - __u8 pad02[2]; - __u32 data; - __u64 addr; -}; - struct nvif_ioctl_map_v0 { /* nvif_ioctl ... */ __u8 version; diff --git a/drivers/gpu/drm/nouveau/include/nvif/log.h b/drivers/gpu/drm/nouveau/include/nvif/log.h new file mode 100644 index 000000000000..64f6f8fc6141 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/log.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: MIT */ +/* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. */ + +#ifndef __NVIF_LOG_H__ +#define __NVIF_LOG_H__ + +#ifdef CONFIG_DEBUG_FS + +/** + * nvif_log - structure for tracking logging buffers + * @entry: an entry in a list of struct nvif_logs + * @shutdown: pointer to function to call to clean up + * + * Structure used to track logging buffers so that they can be cleaned up + * when the module exits. + * + * The @shutdown function is called when the module exits. It should free all + * backing resources, such as logging buffers. + */ +struct nvif_log { + struct list_head entry; + void (*shutdown)(struct nvif_log *log); +}; + +/** + * nvif_logs - linked list of nvif_log objects + */ +struct nvif_logs { + struct list_head head; +}; + +#define NVIF_LOGS_DECLARE(logs) \ + struct nvif_logs logs = { LIST_HEAD_INIT(logs.head) } + +static inline void nvif_log_shutdown(struct nvif_logs *logs) +{ + if (!list_empty(&logs->head)) { + struct nvif_log *log, *n; + + list_for_each_entry_safe(log, n, &logs->head, entry) { + /* shutdown() should also delete the log entry */ + log->shutdown(log); + } + } +} + +extern struct nvif_logs gsp_logs; + +#endif + +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/object.h b/drivers/gpu/drm/nouveau/include/nvif/object.h index f52399caee82..8d205b6af46a 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/object.h +++ b/drivers/gpu/drm/nouveau/include/nvif/object.h @@ -34,8 +34,6 @@ void nvif_object_dtor(struct nvif_object *); int nvif_object_ioctl(struct nvif_object *, void *, u32, void **); int nvif_object_sclass_get(struct nvif_object *, struct nvif_sclass **); void nvif_object_sclass_put(struct nvif_sclass **); -u32 nvif_object_rd(struct nvif_object *, int, u64); -void nvif_object_wr(struct nvif_object *, int, u64, u32); int nvif_object_mthd(struct nvif_object *, u32, void *, u32); int nvif_object_map_handle(struct nvif_object *, void *, u32, u64 *handle, u64 *length); @@ -47,20 +45,11 @@ void nvif_object_unmap(struct nvif_object *); #define nvif_object(a) (a)->object #define nvif_rd(a,f,b,c) ({ \ - struct nvif_object *_object = (a); \ - u32 _data; \ - if (likely(_object->map.ptr)) \ - _data = f((u8 __iomem *)_object->map.ptr + (c)); \ - else \ - _data = nvif_object_rd(_object, (b), (c)); \ + u32 _data = f((u8 __iomem *)(a)->map.ptr + (c)); \ _data; \ }) #define nvif_wr(a,f,b,c,d) ({ \ - struct nvif_object *_object = (a); \ - if (likely(_object->map.ptr)) \ - f((d), (u8 __iomem *)_object->map.ptr + (c)); \ - else \ - nvif_object_wr(_object, (b), (c), (d)); \ + f((d), (u8 __iomem *)(a)->map.ptr + (c)); \ }) #define nvif_rd08(a,b) ({ ((u8)nvif_rd((a), ioread8, 1, (b))); }) #define nvif_rd16(a,b) ({ ((u16)nvif_rd((a), ioread16_native, 2, (b))); }) @@ -69,7 +58,7 @@ void nvif_object_unmap(struct nvif_object *); #define nvif_wr16(a,b,c) nvif_wr((a), iowrite16_native, 2, (b), (u16)(c)) #define nvif_wr32(a,b,c) nvif_wr((a), iowrite32_native, 4, (b), (u32)(c)) #define nvif_mask(a,b,c,d) ({ \ - struct nvif_object *__object = (a); \ + typeof(a) __object = (a); \ u32 _addr = (b), _data = nvif_rd32(__object, _addr); \ nvif_wr32(__object, _addr, (_data & ~(c)) | (d)); \ _data; \ @@ -134,11 +123,4 @@ struct nvif_mclass { #define NVIF_MR32(p,A...) DRF_MR(NVIF_RD32_, NVIF_WR32_, u32, (p), 0, ##A) #define NVIF_MV32(p,A...) DRF_MV(NVIF_RD32_, NVIF_WR32_, u32, (p), 0, ##A) #define NVIF_MD32(p,A...) DRF_MD(NVIF_RD32_, NVIF_WR32_, u32, (p), 0, ##A) - -/*XXX*/ -#include <core/object.h> -#define nvxx_object(a) ({ \ - struct nvif_object *_object = (a); \ - (struct nvkm_object *)_object->priv; \ -}) #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/os.h b/drivers/gpu/drm/nouveau/include/nvif/os.h index 429d0106c123..4a1123b81fee 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/os.h +++ b/drivers/gpu/drm/nouveau/include/nvif/os.h @@ -30,8 +30,27 @@ #include <linux/iommu.h> #include <linux/of_device.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <soc/tegra/fuse.h> #include <soc/tegra/pmc.h> + +#ifdef __BIG_ENDIAN +#define ioread16_native ioread16be +#define iowrite16_native iowrite16be +#define ioread32_native ioread32be +#define iowrite32_native iowrite32be +#else +#define ioread16_native ioread16 +#define iowrite16_native iowrite16 +#define ioread32_native ioread32 +#define iowrite32_native iowrite32 +#endif + +#define iowrite64_native(v,p) do { \ + u32 __iomem *_p = (u32 __iomem *)(p); \ + u64 _v = (v); \ + iowrite32_native(lower_32_bits(_v), &_p[0]); \ + iowrite32_native(upper_32_bits(_v), &_p[1]); \ +} while(0) #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h index 932c9fd0b2d8..15f27fdd877a 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h @@ -22,7 +22,6 @@ struct nvkm_client { int nvkm_client_new(const char *name, u64 device, const char *cfg, const char *dbg, int (*)(u64, void *, u32), struct nvkm_client **); -struct nvkm_client *nvkm_client_search(struct nvkm_client *, u64 handle); /* logging for client-facing objects */ #define nvif_printk(o,l,p,f,a...) do { \ diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index f057d348221e..46afb877a296 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -109,7 +109,6 @@ struct nvkm_device_chip { }; struct nvkm_device *nvkm_device_find(u64 name); -int nvkm_device_list(u64 *name, int size); /* privileged register interface accessor macros */ #define nvkm_rd08(d,a) ioread8((d)->pri + (a)) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h b/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h index 30c17db483cb..9d2a1abf64f9 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h @@ -46,7 +46,6 @@ NVKM_LAYOUT_INST(NVKM_ENGINE_NVDEC , struct nvkm_nvdec , nvdec, 8) NVKM_LAYOUT_INST(NVKM_ENGINE_NVENC , struct nvkm_nvenc , nvenc, 3) NVKM_LAYOUT_INST(NVKM_ENGINE_NVJPG , struct nvkm_engine , nvjpg, 8) NVKM_LAYOUT_ONCE(NVKM_ENGINE_OFA , struct nvkm_engine , ofa) -NVKM_LAYOUT_ONCE(NVKM_ENGINE_PM , struct nvkm_pm , pm) NVKM_LAYOUT_ONCE(NVKM_ENGINE_SEC , struct nvkm_engine , sec) NVKM_LAYOUT_ONCE(NVKM_ENGINE_SEC2 , struct nvkm_sec2 , sec2) NVKM_LAYOUT_ONCE(NVKM_ENGINE_SW , struct nvkm_sw , sw) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h index ed1f66360782..10107ef3ca49 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h @@ -15,8 +15,6 @@ struct nvkm_object { struct list_head head; struct list_head tree; - u8 route; - u64 token; u64 object; struct rb_node node; }; @@ -35,12 +33,6 @@ struct nvkm_object_func { int (*map)(struct nvkm_object *, void *argv, u32 argc, enum nvkm_object_map *, u64 *addr, u64 *size); int (*unmap)(struct nvkm_object *); - int (*rd08)(struct nvkm_object *, u64 addr, u8 *data); - int (*rd16)(struct nvkm_object *, u64 addr, u16 *data); - int (*rd32)(struct nvkm_object *, u64 addr, u32 *data); - int (*wr08)(struct nvkm_object *, u64 addr, u8 data); - int (*wr16)(struct nvkm_object *, u64 addr, u16 data); - int (*wr32)(struct nvkm_object *, u64 addr, u32 data); int (*bind)(struct nvkm_object *, struct nvkm_gpuobj *, int align, struct nvkm_gpuobj **); int (*sclass)(struct nvkm_object *, int index, struct nvkm_oclass *); @@ -63,12 +55,6 @@ int nvkm_object_ntfy(struct nvkm_object *, u32 mthd, struct nvkm_event **); int nvkm_object_map(struct nvkm_object *, void *argv, u32 argc, enum nvkm_object_map *, u64 *addr, u64 *size); int nvkm_object_unmap(struct nvkm_object *); -int nvkm_object_rd08(struct nvkm_object *, u64 addr, u8 *data); -int nvkm_object_rd16(struct nvkm_object *, u64 addr, u16 *data); -int nvkm_object_rd32(struct nvkm_object *, u64 addr, u32 *data); -int nvkm_object_wr08(struct nvkm_object *, u64 addr, u8 data); -int nvkm_object_wr16(struct nvkm_object *, u64 addr, u16 data); -int nvkm_object_wr32(struct nvkm_object *, u64 addr, u32 data); int nvkm_object_bind(struct nvkm_object *, struct nvkm_gpuobj *, int align, struct nvkm_gpuobj **); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/oclass.h b/drivers/gpu/drm/nouveau/include/nvkm/core/oclass.h index 8e1b945d38f3..cad05f0e7948 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/oclass.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/oclass.h @@ -21,8 +21,6 @@ struct nvkm_oclass { const void *priv; const void *engn; u32 handle; - u8 route; - u64 token; u64 object; struct nvkm_client *client; struct nvkm_object *parent; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h index 3fd5c007a663..9b05612e6490 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h @@ -3,25 +3,6 @@ #define __NVKM_OS_H__ #include <nvif/os.h> -#ifdef __BIG_ENDIAN -#define ioread16_native ioread16be -#define iowrite16_native iowrite16be -#define ioread32_native ioread32be -#define iowrite32_native iowrite32be -#else -#define ioread16_native ioread16 -#define iowrite16_native iowrite16 -#define ioread32_native ioread32 -#define iowrite32_native iowrite32 -#endif - -#define iowrite64_native(v,p) do { \ - u32 __iomem *_p = (u32 __iomem *)(p); \ - u64 _v = (v); \ - iowrite32_native(lower_32_bits(_v), &_p[0]); \ - iowrite32_native(upper_32_bits(_v), &_p[1]); \ -} while(0) - struct nvkm_blob { void *data; u32 size; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h b/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h index b4b5df3e1610..7444c4d59e09 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h @@ -10,6 +10,5 @@ struct nvkm_device_pci { }; int nvkm_device_pci_new(struct pci_dev *, const char *cfg, const char *dbg, - bool detect, bool mmio, u64 subdev_mask, struct nvkm_device **); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h index ccee53d4e4ec..22f74fc88cd7 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h @@ -51,6 +51,5 @@ struct nvkm_device_tegra_func { int nvkm_device_tegra_new(const struct nvkm_device_tegra_func *, struct platform_device *, const char *cfg, const char *dbg, - bool detect, bool mmio, u64 subdev_mask, struct nvkm_device **); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h deleted file mode 100644 index af89d46ea360..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVKM_PM_H__ -#define __NVKM_PM_H__ -#include <core/engine.h> - -struct nvkm_pm { - const struct nvkm_pm_func *func; - struct nvkm_engine engine; - - struct { - spinlock_t lock; - struct nvkm_object *object; - } client; - - struct list_head domains; - struct list_head sources; - u32 sequence; -}; - -int nv40_pm_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pm **); -int nv50_pm_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pm **); -int g84_pm_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pm **); -int gt200_pm_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pm **); -int gt215_pm_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pm **); -int gf100_pm_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pm **); -int gf108_pm_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pm **); -int gf117_pm_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pm **); -int gk104_pm_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pm **); -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h index 6f5d376d8fcc..5c5f4607fcc9 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h @@ -5,17 +5,22 @@ #include <core/falcon.h> #include <core/firmware.h> +#include <linux/debugfs.h> + #define GSP_PAGE_SHIFT 12 #define GSP_PAGE_SIZE BIT(GSP_PAGE_SHIFT) struct nvkm_gsp_mem { + struct device *dev; size_t size; void *data; dma_addr_t addr; }; struct nvkm_gsp_radix3 { - struct nvkm_gsp_mem mem[3]; + struct nvkm_gsp_mem lvl0; + struct nvkm_gsp_mem lvl1; + struct sg_table lvl2; }; int nvkm_gsp_sg(struct nvkm_device *, u64 size, struct sg_table *); @@ -208,9 +213,33 @@ struct nvkm_gsp { } *rm; struct { - struct mutex mutex;; + struct mutex mutex; struct idr idr; } client_id; + + /* A linked list of registry items. The registry RPC will be built from it. */ + struct list_head registry_list; + + /* The size of the registry RPC */ + size_t registry_rpc_size; + +#ifdef CONFIG_DEBUG_FS + /* + * Logging buffers in debugfs. The wrapper objects need to remain + * in memory until the dentry is deleted. + */ + struct { + struct dentry *parent; + struct dentry *init; + struct dentry *rm; + struct dentry *intr; + struct dentry *pmu; + } debugfs; + struct debugfs_blob_wrapper blob_init; + struct debugfs_blob_wrapper blob_intr; + struct debugfs_blob_wrapper blob_rm; + struct debugfs_blob_wrapper blob_pmu; +#endif }; static inline bool diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 80f74ee0fc78..2a0617e5fe2a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -46,23 +46,9 @@ nouveau_abi16(struct drm_file *file_priv) struct nouveau_abi16 *abi16; cli->abi16 = abi16 = kzalloc(sizeof(*abi16), GFP_KERNEL); if (cli->abi16) { - struct nv_device_v0 args = { - .device = ~0ULL, - }; - + abi16->cli = cli; INIT_LIST_HEAD(&abi16->channels); - - /* allocate device object targeting client's default - * device (ie. the one that belongs to the fd it - * opened) - */ - if (nvif_device_ctor(&cli->base.object, "abi16Device", - 0, NV_DEVICE, &args, sizeof(args), - &abi16->device) == 0) - return cli->abi16; - - kfree(cli->abi16); - cli->abi16 = NULL; + INIT_LIST_HEAD(&abi16->objects); } } return cli->abi16; @@ -82,11 +68,72 @@ nouveau_abi16_get(struct drm_file *file_priv) int nouveau_abi16_put(struct nouveau_abi16 *abi16, int ret) { - struct nouveau_cli *cli = (void *)abi16->device.object.client; + struct nouveau_cli *cli = abi16->cli; mutex_unlock(&cli->mutex); return ret; } +/* Tracks objects created via the DRM_NOUVEAU_NVIF ioctl. + * + * The only two types of object that userspace ever allocated via this + * interface are 'device', in order to retrieve basic device info, and + * 'engine objects', which instantiate HW classes on a channel. + * + * The remainder of what used to be available via DRM_NOUVEAU_NVIF has + * been removed, but these object types need to be tracked to maintain + * compatibility with userspace. + */ +struct nouveau_abi16_obj { + enum nouveau_abi16_obj_type { + DEVICE, + ENGOBJ, + } type; + u64 object; + + struct nvif_object engobj; + + struct list_head head; /* protected by nouveau_abi16.cli.mutex */ +}; + +static struct nouveau_abi16_obj * +nouveau_abi16_obj_find(struct nouveau_abi16 *abi16, u64 object) +{ + struct nouveau_abi16_obj *obj; + + list_for_each_entry(obj, &abi16->objects, head) { + if (obj->object == object) + return obj; + } + + return NULL; +} + +static void +nouveau_abi16_obj_del(struct nouveau_abi16_obj *obj) +{ + list_del(&obj->head); + kfree(obj); +} + +static struct nouveau_abi16_obj * +nouveau_abi16_obj_new(struct nouveau_abi16 *abi16, enum nouveau_abi16_obj_type type, u64 object) +{ + struct nouveau_abi16_obj *obj; + + obj = nouveau_abi16_obj_find(abi16, object); + if (obj) + return ERR_PTR(-EEXIST); + + obj = kzalloc(sizeof(*obj), GFP_KERNEL); + if (!obj) + return ERR_PTR(-ENOMEM); + + obj->type = type; + obj->object = object; + list_add_tail(&obj->head, &abi16->objects); + return obj; +} + s32 nouveau_abi16_swclass(struct nouveau_drm *drm) { @@ -164,17 +211,20 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, void nouveau_abi16_fini(struct nouveau_abi16 *abi16) { - struct nouveau_cli *cli = (void *)abi16->device.object.client; + struct nouveau_cli *cli = abi16->cli; struct nouveau_abi16_chan *chan, *temp; + struct nouveau_abi16_obj *obj, *tmp; + + /* cleanup objects */ + list_for_each_entry_safe(obj, tmp, &abi16->objects, head) { + nouveau_abi16_obj_del(obj); + } /* cleanup channels */ list_for_each_entry_safe(chan, temp, &abi16->channels, head) { nouveau_abi16_chan_fini(abi16, chan); } - /* destroy the device object */ - nvif_device_dtor(&abi16->device); - kfree(cli->abi16); cli->abi16 = NULL; } @@ -199,8 +249,8 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_drm *drm = nouveau_drm(dev); struct nvif_device *device = &drm->client.device; - struct nvkm_device *nvkm_device = nvxx_device(&drm->client.device); - struct nvkm_gr *gr = nvxx_gr(device); + struct nvkm_device *nvkm_device = nvxx_device(drm); + struct nvkm_gr *gr = nvxx_gr(drm); struct drm_nouveau_getparam *getparam = data; struct pci_dev *pdev = to_pci_dev(dev->dev); @@ -272,6 +322,9 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) getparam->value = (u64)ttm_resource_manager_usage(vram_mgr); break; } + case NOUVEAU_GETPARAM_HAS_VMA_TILEMODE: + getparam->value = 1; + break; default: NV_PRINTK(dbg, cli, "unknown parameter %lld\n", getparam->param); return -EINVAL; @@ -288,7 +341,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); struct nouveau_abi16_chan *chan; - struct nvif_device *device; + struct nvif_device *device = &cli->device; u64 engine, runm; int ret; @@ -305,18 +358,27 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) */ __nouveau_cli_disable_uvmm_noinit(cli); - device = &abi16->device; engine = NV_DEVICE_HOST_RUNLIST_ENGINES_GR; /* hack to allow channel engine type specification on kepler */ if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { if (init->fb_ctxdma_handle == ~0) { switch (init->tt_ctxdma_handle) { - case 0x01: engine = NV_DEVICE_HOST_RUNLIST_ENGINES_GR ; break; - case 0x02: engine = NV_DEVICE_HOST_RUNLIST_ENGINES_MSPDEC; break; - case 0x04: engine = NV_DEVICE_HOST_RUNLIST_ENGINES_MSPPP ; break; - case 0x08: engine = NV_DEVICE_HOST_RUNLIST_ENGINES_MSVLD ; break; - case 0x30: engine = NV_DEVICE_HOST_RUNLIST_ENGINES_CE ; break; + case NOUVEAU_FIFO_ENGINE_GR: + engine = NV_DEVICE_HOST_RUNLIST_ENGINES_GR; + break; + case NOUVEAU_FIFO_ENGINE_VP: + engine = NV_DEVICE_HOST_RUNLIST_ENGINES_MSPDEC; + break; + case NOUVEAU_FIFO_ENGINE_PPP: + engine = NV_DEVICE_HOST_RUNLIST_ENGINES_MSPPP; + break; + case NOUVEAU_FIFO_ENGINE_BSP: + engine = NV_DEVICE_HOST_RUNLIST_ENGINES_MSVLD; + break; + case NOUVEAU_FIFO_ENGINE_CE: + engine = NV_DEVICE_HOST_RUNLIST_ENGINES_CE; + break; default: return nouveau_abi16_put(abi16, -ENOSYS); } @@ -343,7 +405,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) list_add(&chan->head, &abi16->channels); /* create channel object and initialise dma and fence management */ - ret = nouveau_channel_new(drm, device, false, runm, init->fb_ctxdma_handle, + ret = nouveau_channel_new(cli, false, runm, init->fb_ctxdma_handle, init->tt_ctxdma_handle, &chan->chan); if (ret) goto done; @@ -445,44 +507,6 @@ nouveau_abi16_chan(struct nouveau_abi16 *abi16, int channel) } int -nouveau_abi16_usif(struct drm_file *file_priv, void *data, u32 size) -{ - union { - struct nvif_ioctl_v0 v0; - } *args = data; - struct nouveau_abi16_chan *chan; - struct nouveau_abi16 *abi16; - int ret = -ENOSYS; - - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { - switch (args->v0.type) { - case NVIF_IOCTL_V0_NEW: - case NVIF_IOCTL_V0_MTHD: - case NVIF_IOCTL_V0_SCLASS: - break; - default: - return -EACCES; - } - } else - return ret; - - if (!(abi16 = nouveau_abi16(file_priv))) - return -ENOMEM; - - if (args->v0.token != ~0ULL) { - if (!(chan = nouveau_abi16_chan(abi16, args->v0.token))) - return -EINVAL; - args->v0.object = nvif_handle(&chan->chan->user); - args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY; - return 0; - } - - args->v0.object = nvif_handle(&abi16->device.object); - args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY; - return 0; -} - -int nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS) { struct drm_nouveau_channel_free *req = data; @@ -506,7 +530,6 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS) struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); struct nouveau_abi16_chan *chan; struct nouveau_abi16_ntfy *ntfy; - struct nvif_client *client; struct nvif_sclass *sclass; s32 oclass = 0; int ret, i; @@ -516,7 +539,6 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS) if (init->handle == ~0) return nouveau_abi16_put(abi16, -EINVAL); - client = abi16->device.object.client; chan = nouveau_abi16_chan(abi16, init->channel); if (!chan) @@ -581,10 +603,8 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS) list_add(&ntfy->head, &chan->notifiers); - client->route = NVDRM_OBJECT_ABI16; ret = nvif_object_ctor(&chan->chan->user, "abi16EngObj", init->handle, oclass, NULL, 0, &ntfy->object); - client->route = NVDRM_OBJECT_NVIF; if (ret) nouveau_abi16_ntfy_fini(chan, ntfy); @@ -599,18 +619,17 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS) struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); struct nouveau_abi16_chan *chan; struct nouveau_abi16_ntfy *ntfy; - struct nvif_device *device = &abi16->device; - struct nvif_client *client; + struct nvif_device *device; struct nv_dma_v0 args = {}; int ret; if (unlikely(!abi16)) return -ENOMEM; + device = &abi16->cli->device; /* completely unnecessary for these chipsets... */ if (unlikely(device->info.family >= NV_DEVICE_INFO_V0_FERMI)) return nouveau_abi16_put(abi16, -EINVAL); - client = abi16->device.object.client; chan = nouveau_abi16_chan(abi16, info->channel); if (!chan) @@ -647,11 +666,9 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS) args.limit += chan->ntfy->offset; } - client->route = NVDRM_OBJECT_ABI16; ret = nvif_object_ctor(&chan->chan->user, "abi16Ntfy", info->handle, NV_DMA_IN_MEMORY, &args, sizeof(args), &ntfy->object); - client->route = NVDRM_OBJECT_NVIF; if (ret) goto done; @@ -691,3 +708,183 @@ nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS) return nouveau_abi16_put(abi16, ret); } + +static int +nouveau_abi16_ioctl_mthd(struct nouveau_abi16 *abi16, struct nvif_ioctl_v0 *ioctl, u32 argc) +{ + struct nouveau_cli *cli = abi16->cli; + struct nvif_ioctl_mthd_v0 *args; + struct nouveau_abi16_obj *obj; + struct nv_device_info_v0 *info; + + if (ioctl->route || argc < sizeof(*args)) + return -EINVAL; + args = (void *)ioctl->data; + argc -= sizeof(*args); + + obj = nouveau_abi16_obj_find(abi16, ioctl->object); + if (!obj || obj->type != DEVICE) + return -EINVAL; + + if (args->method != NV_DEVICE_V0_INFO || + argc != sizeof(*info)) + return -EINVAL; + + info = (void *)args->data; + if (info->version != 0x00) + return -EINVAL; + + info = &cli->device.info; + memcpy(args->data, info, sizeof(*info)); + return 0; +} + +static int +nouveau_abi16_ioctl_del(struct nouveau_abi16 *abi16, struct nvif_ioctl_v0 *ioctl, u32 argc) +{ + struct nouveau_abi16_obj *obj; + + if (ioctl->route || argc) + return -EINVAL; + + obj = nouveau_abi16_obj_find(abi16, ioctl->object); + if (obj) { + if (obj->type == ENGOBJ) + nvif_object_dtor(&obj->engobj); + nouveau_abi16_obj_del(obj); + } + + return 0; +} + +static int +nouveau_abi16_ioctl_new(struct nouveau_abi16 *abi16, struct nvif_ioctl_v0 *ioctl, u32 argc) +{ + struct nvif_ioctl_new_v0 *args; + struct nouveau_abi16_chan *chan; + struct nouveau_abi16_obj *obj; + int ret; + + if (argc < sizeof(*args)) + return -EINVAL; + args = (void *)ioctl->data; + argc -= sizeof(*args); + + if (args->version != 0) + return -EINVAL; + + if (!ioctl->route) { + if (ioctl->object || args->oclass != NV_DEVICE) + return -EINVAL; + + obj = nouveau_abi16_obj_new(abi16, DEVICE, args->object); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + return 0; + } + + chan = nouveau_abi16_chan(abi16, ioctl->token); + if (!chan) + return -EINVAL; + + obj = nouveau_abi16_obj_new(abi16, ENGOBJ, args->object); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + ret = nvif_object_ctor(&chan->chan->user, "abi16EngObj", args->handle, args->oclass, + NULL, 0, &obj->engobj); + if (ret) + nouveau_abi16_obj_del(obj); + + return ret; +} + +static int +nouveau_abi16_ioctl_sclass(struct nouveau_abi16 *abi16, struct nvif_ioctl_v0 *ioctl, u32 argc) +{ + struct nvif_ioctl_sclass_v0 *args; + struct nouveau_abi16_chan *chan; + struct nvif_sclass *sclass; + int ret; + + if (!ioctl->route || argc < sizeof(*args)) + return -EINVAL; + args = (void *)ioctl->data; + argc -= sizeof(*args); + + if (argc != args->count * sizeof(args->oclass[0])) + return -EINVAL; + + chan = nouveau_abi16_chan(abi16, ioctl->token); + if (!chan) + return -EINVAL; + + ret = nvif_object_sclass_get(&chan->chan->user, &sclass); + if (ret < 0) + return ret; + + for (int i = 0; i < min_t(u8, args->count, ret); i++) { + args->oclass[i].oclass = sclass[i].oclass; + args->oclass[i].minver = sclass[i].minver; + args->oclass[i].maxver = sclass[i].maxver; + } + args->count = ret; + + nvif_object_sclass_put(&sclass); + return 0; +} + +int +nouveau_abi16_ioctl(struct drm_file *filp, void __user *user, u32 size) +{ + struct nvif_ioctl_v0 *ioctl; + struct nouveau_abi16 *abi16; + u32 argc = size; + int ret; + + if (argc < sizeof(*ioctl)) + return -EINVAL; + argc -= sizeof(*ioctl); + + ioctl = kmalloc(size, GFP_KERNEL); + if (!ioctl) + return -ENOMEM; + + ret = -EFAULT; + if (copy_from_user(ioctl, user, size)) + goto done_free; + + if (ioctl->version != 0x00 || + (ioctl->route && ioctl->route != 0xff)) { + ret = -EINVAL; + goto done_free; + } + + abi16 = nouveau_abi16_get(filp); + if (unlikely(!abi16)) { + ret = -ENOMEM; + goto done_free; + } + + switch (ioctl->type) { + case NVIF_IOCTL_V0_SCLASS: ret = nouveau_abi16_ioctl_sclass(abi16, ioctl, argc); break; + case NVIF_IOCTL_V0_NEW : ret = nouveau_abi16_ioctl_new (abi16, ioctl, argc); break; + case NVIF_IOCTL_V0_DEL : ret = nouveau_abi16_ioctl_del (abi16, ioctl, argc); break; + case NVIF_IOCTL_V0_MTHD : ret = nouveau_abi16_ioctl_mthd (abi16, ioctl, argc); break; + default: + ret = -EINVAL; + break; + } + + nouveau_abi16_put(abi16, 0); + + if (ret == 0) { + if (copy_to_user(user, ioctl, size)) + ret = -EFAULT; + } + +done_free: + kfree(ioctl); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h index 11c8c4a80079..af6b4e1cefd2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.h +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h @@ -30,16 +30,16 @@ struct nouveau_abi16_chan { }; struct nouveau_abi16 { - struct nvif_device device; + struct nouveau_cli *cli; struct list_head channels; - u64 handles; + struct list_head objects; }; struct nouveau_abi16 *nouveau_abi16_get(struct drm_file *); int nouveau_abi16_put(struct nouveau_abi16 *, int); void nouveau_abi16_fini(struct nouveau_abi16 *); s32 nouveau_abi16_swclass(struct nouveau_drm *); -int nouveau_abi16_usif(struct drm_file *, void *data, u32 size); +int nouveau_abi16_ioctl(struct drm_file *, void __user *user, u32 size); #define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) @@ -50,18 +50,6 @@ struct drm_nouveau_grobj_alloc { int class; }; -struct drm_nouveau_notifierobj_alloc { - uint32_t channel; - uint32_t handle; - uint32_t size; - uint32_t offset; -}; - -struct drm_nouveau_gpuobj_free { - int channel; - uint32_t handle; -}; - struct drm_nouveau_setparam { uint64_t param; uint64_t value; diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 8f0c69aad248..21b56cc7605c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -384,7 +384,7 @@ nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) if (ret < 0) return NULL; - return kmemdup(edid, EDID_LENGTH, GFP_KERNEL); + return edid; } bool nouveau_acpi_video_backlight_use_native(void) diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 479effcf607e..c8335f5b49db 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -23,6 +23,7 @@ */ #include "nouveau_drv.h" +#include "nouveau_bios.h" #include "nouveau_reg.h" #include "dispnv04/hw.h" #include "nouveau_encoder.h" @@ -42,11 +43,6 @@ #define BIOSLOG(sip, fmt, arg...) NV_DEBUG(sip->dev, fmt, ##arg) #define LOG_OLD_VALUE(x) -struct init_exec { - bool execute; - bool repeat; -}; - static bool nv_cksum(const uint8_t *data, unsigned int length) { /* @@ -1677,7 +1673,7 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) */ if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) { if (*conn == 0xf2005014 && *conf == 0xffffffff) { - fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, 1); + fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, DCB_OUTPUT_B); return false; } } @@ -1763,26 +1759,26 @@ fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios) #ifdef __powerpc__ /* Apple iMac G4 NV17 */ if (of_machine_is_compatible("PowerMac4,5")) { - fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, 1); - fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, 2); + fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, DCB_OUTPUT_B); + fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, DCB_OUTPUT_C); return; } #endif /* Make up some sane defaults */ fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, - bios->legacy.i2c_indices.crt, 1, 1); + bios->legacy.i2c_indices.crt, 1, DCB_OUTPUT_B); if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0) fabricate_dcb_output(dcb, DCB_OUTPUT_TV, bios->legacy.i2c_indices.tv, - all_heads, 0); + all_heads, DCB_OUTPUT_A); else if (bios->tmds.output0_script_ptr || bios->tmds.output1_script_ptr) fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, bios->legacy.i2c_indices.panel, - all_heads, 1); + all_heads, DCB_OUTPUT_B); } static int @@ -2019,7 +2015,7 @@ uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev) static bool NVInitVBIOS(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_bios *bios = nvxx_bios(&drm->client.device); + struct nvkm_bios *bios = nvxx_bios(drm); struct nvbios *legacy = &drm->vbios; memset(legacy, 0, sizeof(struct nvbios)); @@ -2090,7 +2086,7 @@ nouveau_bios_init(struct drm_device *dev) /* only relevant for PCI devices */ if (!dev_is_pci(dev->dev) || - nvkm_gsp_rm(nvxx_device(&drm->client.device)->gsp)) + nvkm_gsp_rm(nvxx_device(drm)->gsp)) return 0; if (!NVInitVBIOS(dev)) diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 18eb061ccafb..62b5f5889041 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -48,6 +48,7 @@ struct bit_entry { int bit_table(struct drm_device *, u8 id, struct bit_entry *); +#include <subdev/bios.h> #include <subdev/bios/dcb.h> #include <subdev/bios/conn.h> diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 00cc7d1abaa3..db961eade225 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -58,7 +58,7 @@ nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg, { struct nouveau_drm *drm = nouveau_drm(dev); int i = reg - drm->tile.reg; - struct nvkm_fb *fb = nvxx_fb(&drm->client.device); + struct nvkm_fb *fb = nvxx_fb(drm); struct nvkm_fb_tile *tile = &fb->tile.region[i]; nouveau_fence_unref(®->fence); @@ -109,7 +109,7 @@ nv10_bo_set_tiling(struct drm_device *dev, u32 addr, u32 size, u32 pitch, u32 zeta) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_fb *fb = nvxx_fb(&drm->client.device); + struct nvkm_fb *fb = nvxx_fb(drm); struct nouveau_drm_tile *tile, *found = NULL; int i; @@ -241,28 +241,28 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 domain, } nvbo->contig = !(tile_flags & NOUVEAU_GEM_TILE_NONCONTIG); - if (!nouveau_cli_uvmm(cli) || internal) { - /* for BO noVM allocs, don't assign kinds */ - if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) { - nvbo->kind = (tile_flags & 0x0000ff00) >> 8; - if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { - kfree(nvbo); - return ERR_PTR(-EINVAL); - } - nvbo->comp = mmu->kind[nvbo->kind] != nvbo->kind; - } else if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { - nvbo->kind = (tile_flags & 0x00007f00) >> 8; - nvbo->comp = (tile_flags & 0x00030000) >> 16; - if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { - kfree(nvbo); - return ERR_PTR(-EINVAL); - } - } else { - nvbo->zeta = (tile_flags & 0x00000007); + if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) { + nvbo->kind = (tile_flags & 0x0000ff00) >> 8; + if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { + kfree(nvbo); + return ERR_PTR(-EINVAL); } - nvbo->mode = tile_mode; + nvbo->comp = mmu->kind[nvbo->kind] != nvbo->kind; + } else if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { + nvbo->kind = (tile_flags & 0x00007f00) >> 8; + nvbo->comp = (tile_flags & 0x00030000) >> 16; + if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { + kfree(nvbo); + return ERR_PTR(-EINVAL); + } + } else { + nvbo->zeta = (tile_flags & 0x00000007); + } + nvbo->mode = tile_mode; + + if (!nouveau_cli_uvmm(cli) || internal) { /* Determine the desirable target GPU page size for the buffer. */ for (i = 0; i < vmm->page_nr; i++) { /* Because we cannot currently allow VMM maps to fail @@ -304,12 +304,6 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 domain, } nvbo->page = vmm->page[pi].shift; } else { - /* reject other tile flags when in VM mode. */ - if (tile_mode) - return ERR_PTR(-EINVAL); - if (tile_flags & ~NOUVEAU_GEM_TILE_NONCONTIG) - return ERR_PTR(-EINVAL); - /* Determine the desirable target GPU page size for the buffer. */ for (i = 0; i < vmm->page_nr; i++) { /* Because we cannot currently allow VMM maps to fail @@ -405,27 +399,6 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, } static void -set_placement_list(struct ttm_place *pl, unsigned *n, uint32_t domain) -{ - *n = 0; - - if (domain & NOUVEAU_GEM_DOMAIN_VRAM) { - pl[*n].mem_type = TTM_PL_VRAM; - pl[*n].flags = 0; - (*n)++; - } - if (domain & NOUVEAU_GEM_DOMAIN_GART) { - pl[*n].mem_type = TTM_PL_TT; - pl[*n].flags = 0; - (*n)++; - } - if (domain & NOUVEAU_GEM_DOMAIN_CPU) { - pl[*n].mem_type = TTM_PL_SYSTEM; - pl[(*n)++].flags = 0; - } -} - -static void set_placement_range(struct nouveau_bo *nvbo, uint32_t domain) { struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); @@ -452,10 +425,6 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t domain) nvbo->placements[i].fpfn = fpfn; nvbo->placements[i].lpfn = lpfn; } - for (i = 0; i < nvbo->placement.num_busy_placement; ++i) { - nvbo->busy_placements[i].fpfn = fpfn; - nvbo->busy_placements[i].lpfn = lpfn; - } } } @@ -463,29 +432,43 @@ void nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t domain, uint32_t busy) { - struct ttm_placement *pl = &nvbo->placement; + unsigned int *n = &nvbo->placement.num_placement; + struct ttm_place *pl = nvbo->placements; - pl->placement = nvbo->placements; - set_placement_list(nvbo->placements, &pl->num_placement, domain); + domain |= busy; - pl->busy_placement = nvbo->busy_placements; - set_placement_list(nvbo->busy_placements, &pl->num_busy_placement, - domain | busy); + *n = 0; + if (domain & NOUVEAU_GEM_DOMAIN_VRAM) { + pl[*n].mem_type = TTM_PL_VRAM; + pl[*n].flags = busy & NOUVEAU_GEM_DOMAIN_VRAM ? + TTM_PL_FLAG_FALLBACK : 0; + (*n)++; + } + if (domain & NOUVEAU_GEM_DOMAIN_GART) { + pl[*n].mem_type = TTM_PL_TT; + pl[*n].flags = busy & NOUVEAU_GEM_DOMAIN_GART ? + TTM_PL_FLAG_FALLBACK : 0; + (*n)++; + } + if (domain & NOUVEAU_GEM_DOMAIN_CPU) { + pl[*n].mem_type = TTM_PL_SYSTEM; + pl[*n].flags = busy & NOUVEAU_GEM_DOMAIN_CPU ? + TTM_PL_FLAG_FALLBACK : 0; + (*n)++; + } + nvbo->placement.placement = nvbo->placements; set_placement_range(nvbo, domain); } -int -nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t domain, bool contig) +int nouveau_bo_pin_locked(struct nouveau_bo *nvbo, uint32_t domain, bool contig) { struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct ttm_buffer_object *bo = &nvbo->bo; bool force = false, evict = false; - int ret; + int ret = 0; - ret = ttm_bo_reserve(bo, false, false, NULL); - if (ret) - return ret; + dma_resv_assert_held(bo->base.resv); if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA && domain == NOUVEAU_GEM_DOMAIN_VRAM && contig) { @@ -548,20 +531,15 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t domain, bool contig) out: if (force && ret) nvbo->contig = false; - ttm_bo_unreserve(bo); return ret; } -int -nouveau_bo_unpin(struct nouveau_bo *nvbo) +void nouveau_bo_unpin_locked(struct nouveau_bo *nvbo) { struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct ttm_buffer_object *bo = &nvbo->bo; - int ret; - ret = ttm_bo_reserve(bo, false, false, NULL); - if (ret) - return ret; + dma_resv_assert_held(bo->base.resv); ttm_bo_unpin(&nvbo->bo); if (!nvbo->bo.pin_count) { @@ -576,8 +554,33 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo) break; } } +} +int nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t domain, bool contig) +{ + struct ttm_buffer_object *bo = &nvbo->bo; + int ret; + + ret = ttm_bo_reserve(bo, false, false, NULL); + if (ret) + return ret; + ret = nouveau_bo_pin_locked(nvbo, domain, contig); + ttm_bo_unreserve(bo); + + return ret; +} + +int nouveau_bo_unpin(struct nouveau_bo *nvbo) +{ + struct ttm_buffer_object *bo = &nvbo->bo; + int ret; + + ret = ttm_bo_reserve(bo, false, false, NULL); + if (ret) + return ret; + nouveau_bo_unpin_locked(nvbo); ttm_bo_unreserve(bo); + return 0; } @@ -856,7 +859,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, { struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct nouveau_channel *chan = drm->ttm.chan; - struct nouveau_cli *cli = (void *)chan->user.client; + struct nouveau_cli *cli = chan->cli; struct nouveau_fence *fence; int ret; @@ -1168,7 +1171,7 @@ static int nouveau_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *reg) { struct nouveau_drm *drm = nouveau_bdev(bdev); - struct nvkm_device *device = nvxx_device(&drm->client.device); + struct nvkm_device *device = nvxx_device(drm); struct nouveau_mem *mem = nouveau_mem(reg); struct nvif_mmu *mmu = &drm->client.mmu; int ret; @@ -1264,6 +1267,8 @@ out: drm_vma_node_unmap(&nvbo->bo.base.vma_node, bdev->dev_mapping); nouveau_ttm_io_mem_free_locked(drm, nvbo->bo.resource); + nvbo->bo.resource->bus.offset = 0; + nvbo->bo.resource->bus.addr = NULL; goto retry; } @@ -1286,7 +1291,7 @@ vm_fault_t nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) { struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct nouveau_bo *nvbo = nouveau_bo(bo); - struct nvkm_device *device = nvxx_device(&drm->client.device); + struct nvkm_device *device = nvxx_device(drm); u32 mappable = device->func->resource_size(device, 1) >> PAGE_SHIFT; int i, ret; @@ -1314,11 +1319,6 @@ vm_fault_t nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) nvbo->placements[i].lpfn = mappable; } - for (i = 0; i < nvbo->placement.num_busy_placement; ++i) { - nvbo->busy_placements[i].fpfn = 0; - nvbo->busy_placements[i].lpfn = mappable; - } - nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, 0); } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index 70c551921a9e..596a63a50a20 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h @@ -15,7 +15,6 @@ struct nouveau_bo { struct ttm_placement placement; u32 valid_domains; struct ttm_place placements[3]; - struct ttm_place busy_placements[3]; bool force_coherent; struct ttm_bo_kmap_obj kmap; struct list_head head; @@ -54,25 +53,10 @@ nouveau_bo(struct ttm_buffer_object *bo) return container_of(bo, struct nouveau_bo, bo); } -static inline int -nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo) +static inline void +nouveau_bo_fini(struct nouveau_bo *bo) { - struct nouveau_bo *prev; - - if (!pnvbo) - return -EINVAL; - prev = *pnvbo; - - if (ref) { - ttm_bo_get(&ref->bo); - *pnvbo = nouveau_bo(&ref->bo); - } else { - *pnvbo = NULL; - } - if (prev) - ttm_bo_put(&prev->bo); - - return 0; + ttm_bo_put(&bo->bo); } extern struct ttm_device_funcs nouveau_bo_driver; @@ -86,6 +70,8 @@ int nouveau_bo_new(struct nouveau_cli *, u64 size, int align, u32 domain, u32 tile_mode, u32 tile_flags, struct sg_table *sg, struct dma_resv *robj, struct nouveau_bo **); +int nouveau_bo_pin_locked(struct nouveau_bo *nvbo, uint32_t domain, bool contig); +void nouveau_bo_unpin_locked(struct nouveau_bo *nvbo); int nouveau_bo_pin(struct nouveau_bo *, u32 flags, bool contig); int nouveau_bo_unpin(struct nouveau_bo *); int nouveau_bo_map(struct nouveau_bo *); @@ -114,35 +100,6 @@ nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo) return ioptr; } -static inline void -nouveau_bo_unmap_unpin_unref(struct nouveau_bo **pnvbo) -{ - if (*pnvbo) { - nouveau_bo_unmap(*pnvbo); - nouveau_bo_unpin(*pnvbo); - nouveau_bo_ref(NULL, pnvbo); - } -} - -static inline int -nouveau_bo_new_pin_map(struct nouveau_cli *cli, u64 size, int align, u32 domain, - struct nouveau_bo **pnvbo) -{ - int ret = nouveau_bo_new(cli, size, align, domain, - 0, 0, NULL, NULL, pnvbo); - if (ret == 0) { - ret = nouveau_bo_pin(*pnvbo, domain, true); - if (ret == 0) { - ret = nouveau_bo_map(*pnvbo); - if (ret == 0) - return ret; - nouveau_bo_unpin(*pnvbo); - } - nouveau_bo_ref(NULL, pnvbo); - } - return ret; -} - int nv04_bo_move_init(struct nouveau_channel *, u32); int nv04_bo_move_m2mf(struct nouveau_channel *, struct ttm_buffer_object *, struct ttm_resource *, struct ttm_resource *); diff --git a/drivers/gpu/drm/nouveau/nouveau_bo0039.c b/drivers/gpu/drm/nouveau/nouveau_bo0039.c index e2ce44adaa5c..0b6758e024a1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo0039.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo0039.c @@ -47,7 +47,7 @@ int nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_resource *old_reg, struct ttm_resource *new_reg) { - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; u32 src_ctxdma = nouveau_bo_mem_ctxdma(bo, chan, old_reg); u32 src_offset = old_reg->start << PAGE_SHIFT; u32 dst_ctxdma = nouveau_bo_mem_ctxdma(bo, chan, new_reg); @@ -96,7 +96,7 @@ nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, int nv04_bo_move_init(struct nouveau_channel *chan, u32 handle) { - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; int ret; ret = PUSH_WAIT(push, 4); @@ -104,6 +104,6 @@ nv04_bo_move_init(struct nouveau_channel *chan, u32 handle) return ret; PUSH_MTHD(push, NV039, SET_OBJECT, handle); - PUSH_MTHD(push, NV039, SET_CONTEXT_DMA_NOTIFIES, chan->drm->ntfy.handle); + PUSH_MTHD(push, NV039, SET_CONTEXT_DMA_NOTIFIES, chan->cli->drm->ntfy.handle); return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo5039.c b/drivers/gpu/drm/nouveau/nouveau_bo5039.c index c6cf3629a9f9..c3de17548d97 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo5039.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo5039.c @@ -40,7 +40,7 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_resource *old_reg, struct ttm_resource *new_reg) { struct nouveau_mem *mem = nouveau_mem(old_reg); - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; u64 length = new_reg->size; u64 src_offset = mem->vma[0].addr; u64 dst_offset = mem->vma[1].addr; @@ -136,7 +136,7 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, int nv50_bo_move_init(struct nouveau_channel *chan, u32 handle) { - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; int ret; ret = PUSH_WAIT(push, 6); @@ -144,7 +144,7 @@ nv50_bo_move_init(struct nouveau_channel *chan, u32 handle) return ret; PUSH_MTHD(push, NV5039, SET_OBJECT, handle); - PUSH_MTHD(push, NV5039, SET_CONTEXT_DMA_NOTIFY, chan->drm->ntfy.handle, + PUSH_MTHD(push, NV5039, SET_CONTEXT_DMA_NOTIFY, chan->cli->drm->ntfy.handle, SET_CONTEXT_DMA_BUFFER_IN, chan->vram.handle, SET_CONTEXT_DMA_BUFFER_OUT, chan->vram.handle); return 0; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo74c1.c b/drivers/gpu/drm/nouveau/nouveau_bo74c1.c index 9b7ba31fae13..e6ef79de2498 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo74c1.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo74c1.c @@ -37,7 +37,7 @@ nv84_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_resource *old_reg, struct ttm_resource *new_reg) { struct nouveau_mem *mem = nouveau_mem(old_reg); - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; int ret; ret = PUSH_WAIT(push, 7); diff --git a/drivers/gpu/drm/nouveau/nouveau_bo85b5.c b/drivers/gpu/drm/nouveau/nouveau_bo85b5.c index a15a38a87a95..c4861d073ad4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo85b5.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo85b5.c @@ -41,7 +41,7 @@ nva3_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_resource *old_reg, struct ttm_resource *new_reg) { struct nouveau_mem *mem = nouveau_mem(old_reg); - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; u64 src_offset = mem->vma[0].addr; u64 dst_offset = mem->vma[1].addr; u32 page_count = PFN_UP(new_reg->size); diff --git a/drivers/gpu/drm/nouveau/nouveau_bo9039.c b/drivers/gpu/drm/nouveau/nouveau_bo9039.c index d2bb2687d401..ad82269c7725 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo9039.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo9039.c @@ -38,7 +38,7 @@ int nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_resource *old_reg, struct ttm_resource *new_reg) { - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; struct nouveau_mem *mem = nouveau_mem(old_reg); u64 src_offset = mem->vma[0].addr; u64 dst_offset = mem->vma[1].addr; @@ -86,7 +86,7 @@ nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, int nvc0_bo_move_init(struct nouveau_channel *chan, u32 handle) { - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; int ret; ret = PUSH_WAIT(push, 2); diff --git a/drivers/gpu/drm/nouveau/nouveau_bo90b5.c b/drivers/gpu/drm/nouveau/nouveau_bo90b5.c index 4618f4f5ab56..5eaeef9d25e4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo90b5.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo90b5.c @@ -34,7 +34,7 @@ nvc0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_resource *old_reg, struct ttm_resource *new_reg) { struct nouveau_mem *mem = nouveau_mem(old_reg); - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; u64 src_offset = mem->vma[0].addr; u64 dst_offset = mem->vma[1].addr; u32 page_count = PFN_UP(new_reg->size); diff --git a/drivers/gpu/drm/nouveau/nouveau_boa0b5.c b/drivers/gpu/drm/nouveau/nouveau_boa0b5.c index 07a5c6302c98..dff2ae0e1e45 100644 --- a/drivers/gpu/drm/nouveau/nouveau_boa0b5.c +++ b/drivers/gpu/drm/nouveau/nouveau_boa0b5.c @@ -39,7 +39,7 @@ nve0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_resource *old_reg, struct ttm_resource *new_reg) { struct nouveau_mem *mem = nouveau_mem(old_reg); - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; int ret; ret = PUSH_WAIT(push, 10); @@ -78,7 +78,7 @@ nve0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, int nve0_bo_move_init(struct nouveau_channel *chan, u32 handle) { - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; int ret; ret = PUSH_WAIT(push, 2); diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 7c97b2886807..cd659b9fd1d9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -52,7 +52,7 @@ static int nouveau_channel_killed(struct nvif_event *event, void *repv, u32 repc) { struct nouveau_channel *chan = container_of(event, typeof(*chan), kill); - struct nouveau_cli *cli = (void *)chan->user.client; + struct nouveau_cli *cli = chan->cli; NV_PRINTK(warn, cli, "channel %d killed!\n", chan->chid); @@ -66,7 +66,7 @@ int nouveau_channel_idle(struct nouveau_channel *chan) { if (likely(chan && chan->fence && !atomic_read(&chan->killed))) { - struct nouveau_cli *cli = (void *)chan->user.client; + struct nouveau_cli *cli = chan->cli; struct nouveau_fence *fence = NULL; int ret; @@ -78,7 +78,7 @@ nouveau_channel_idle(struct nouveau_channel *chan) if (ret) { NV_PRINTK(err, cli, "failed to idle channel %d [%s]\n", - chan->chid, nvxx_client(&cli->base)->name); + chan->chid, cli->name); return ret; } } @@ -90,12 +90,10 @@ nouveau_channel_del(struct nouveau_channel **pchan) { struct nouveau_channel *chan = *pchan; if (chan) { - struct nouveau_cli *cli = (void *)chan->user.client; - if (chan->fence) - nouveau_fence(chan->drm)->context_del(chan); + nouveau_fence(chan->cli->drm)->context_del(chan); - if (cli) + if (nvif_object_constructed(&chan->user)) nouveau_svmm_part(chan->vmm->svmm, chan->inst); nvif_object_dtor(&chan->blit); @@ -110,7 +108,7 @@ nouveau_channel_del(struct nouveau_channel **pchan) nouveau_bo_unmap(chan->push.buffer); if (chan->push.buffer && chan->push.buffer->bo.pin_count) nouveau_bo_unpin(chan->push.buffer); - nouveau_bo_ref(NULL, &chan->push.buffer); + nouveau_bo_fini(chan->push.buffer); kfree(chan); } *pchan = NULL; @@ -119,33 +117,34 @@ nouveau_channel_del(struct nouveau_channel **pchan) static void nouveau_channel_kick(struct nvif_push *push) { - struct nouveau_channel *chan = container_of(push, typeof(*chan), chan._push); - chan->dma.cur = chan->dma.cur + (chan->chan._push.cur - chan->chan._push.bgn); + struct nouveau_channel *chan = container_of(push, typeof(*chan), chan.push); + chan->dma.cur = chan->dma.cur + (chan->chan.push.cur - chan->chan.push.bgn); FIRE_RING(chan); - chan->chan._push.bgn = chan->chan._push.cur; + chan->chan.push.bgn = chan->chan.push.cur; } static int nouveau_channel_wait(struct nvif_push *push, u32 size) { - struct nouveau_channel *chan = container_of(push, typeof(*chan), chan._push); + struct nouveau_channel *chan = container_of(push, typeof(*chan), chan.push); int ret; - chan->dma.cur = chan->dma.cur + (chan->chan._push.cur - chan->chan._push.bgn); + chan->dma.cur = chan->dma.cur + (chan->chan.push.cur - chan->chan.push.bgn); ret = RING_SPACE(chan, size); if (ret == 0) { - chan->chan._push.bgn = chan->chan._push.mem.object.map.ptr; - chan->chan._push.bgn = chan->chan._push.bgn + chan->dma.cur; - chan->chan._push.cur = chan->chan._push.bgn; - chan->chan._push.end = chan->chan._push.bgn + size; + chan->chan.push.bgn = chan->chan.push.mem.object.map.ptr; + chan->chan.push.bgn = chan->chan.push.bgn + chan->dma.cur; + chan->chan.push.cur = chan->chan.push.bgn; + chan->chan.push.end = chan->chan.push.bgn + size; } return ret; } static int -nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, +nouveau_channel_prep(struct nouveau_cli *cli, u32 size, struct nouveau_channel **pchan) { - struct nouveau_cli *cli = (void *)device->object.client; + struct nouveau_drm *drm = cli->drm; + struct nvif_device *device = &cli->device; struct nv_dma_v0 args = {}; struct nouveau_channel *chan; u32 target; @@ -155,8 +154,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, if (!chan) return -ENOMEM; - chan->device = device; - chan->drm = drm; + chan->cli = cli; chan->vmm = nouveau_cli_vmm(cli); atomic_set(&chan->killed, 0); @@ -178,13 +176,12 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, return ret; } - chan->chan._push.mem.object.parent = cli->base.object.parent; - chan->chan._push.mem.object.client = &cli->base; - chan->chan._push.mem.object.name = "chanPush"; - chan->chan._push.mem.object.map.ptr = chan->push.buffer->kmap.virtual; - chan->chan._push.wait = nouveau_channel_wait; - chan->chan._push.kick = nouveau_channel_kick; - chan->chan.push = &chan->chan._push; + chan->chan.push.mem.object.parent = cli->base.object.parent; + chan->chan.push.mem.object.client = &cli->base; + chan->chan.push.mem.object.name = "chanPush"; + chan->chan.push.mem.object.map.ptr = chan->push.buffer->kmap.virtual; + chan->chan.push.wait = nouveau_channel_wait; + chan->chan.push.kick = nouveau_channel_kick; /* create dma object covering the *entire* memory space that the * pushbuf lives in, this is because the GEM code requires that @@ -218,8 +215,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, */ args.target = NV_DMA_V0_TARGET_PCI; args.access = NV_DMA_V0_ACCESS_RDWR; - args.start = nvxx_device(device)->func-> - resource_addr(nvxx_device(device), 1); + args.start = nvxx_device(drm)->func->resource_addr(nvxx_device(drm), 1); args.limit = args.start + device->info.ram_user - 1; } else { args.target = NV_DMA_V0_TARGET_VRAM; @@ -228,12 +224,11 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, args.limit = device->info.ram_user - 1; } } else { - if (chan->drm->agp.bridge) { + if (drm->agp.bridge) { args.target = NV_DMA_V0_TARGET_AGP; args.access = NV_DMA_V0_ACCESS_RDWR; - args.start = chan->drm->agp.base; - args.limit = chan->drm->agp.base + - chan->drm->agp.size - 1; + args.start = drm->agp.base; + args.limit = drm->agp.base + drm->agp.size - 1; } else { args.target = NV_DMA_V0_TARGET_VM; args.access = NV_DMA_V0_ACCESS_RDWR; @@ -254,7 +249,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, } static int -nouveau_channel_ctor(struct nouveau_drm *drm, struct nvif_device *device, bool priv, u64 runm, +nouveau_channel_ctor(struct nouveau_cli *cli, bool priv, u64 runm, struct nouveau_channel **pchan) { const struct nvif_mclass hosts[] = { @@ -279,12 +274,11 @@ nouveau_channel_ctor(struct nouveau_drm *drm, struct nvif_device *device, bool p struct nvif_chan_v0 chan; char name[TASK_COMM_LEN+16]; } args; - struct nouveau_cli *cli = (void *)device->object.client; + struct nvif_device *device = &cli->device; struct nouveau_channel *chan; const u64 plength = 0x10000; const u64 ioffset = plength; const u64 ilength = 0x02000; - char name[TASK_COMM_LEN]; int cid, ret; u64 size; @@ -298,7 +292,7 @@ nouveau_channel_ctor(struct nouveau_drm *drm, struct nvif_device *device, bool p size = ioffset + ilength; /* allocate dma push buffer */ - ret = nouveau_channel_prep(drm, device, size, &chan); + ret = nouveau_channel_prep(cli, size, &chan); *pchan = chan; if (ret) return ret; @@ -343,8 +337,7 @@ nouveau_channel_ctor(struct nouveau_drm *drm, struct nvif_device *device, bool p chan->userd = &chan->user; } - get_task_comm(name, current); - snprintf(args.name, sizeof(args.name), "%s[%d]", name, task_pid_nr(current)); + snprintf(args.name, sizeof(args.name), "%s[%d]", current->comm, task_pid_nr(current)); ret = nvif_object_ctor(&device->object, "abi16ChanUser", 0, hosts[cid].oclass, &args, sizeof(args), &chan->user); @@ -363,8 +356,9 @@ nouveau_channel_ctor(struct nouveau_drm *drm, struct nvif_device *device, bool p static int nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) { - struct nvif_device *device = chan->device; - struct nouveau_drm *drm = chan->drm; + struct nouveau_cli *cli = chan->cli; + struct nouveau_drm *drm = cli->drm; + struct nvif_device *device = &cli->device; struct nv_dma_v0 args = {}; int ret, i; @@ -419,12 +413,11 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) args.start = 0; args.limit = chan->vmm->vmm.limit - 1; } else - if (chan->drm->agp.bridge) { + if (drm->agp.bridge) { args.target = NV_DMA_V0_TARGET_AGP; args.access = NV_DMA_V0_ACCESS_RDWR; - args.start = chan->drm->agp.base; - args.limit = chan->drm->agp.base + - chan->drm->agp.size - 1; + args.start = drm->agp.base; + args.limit = drm->agp.base + drm->agp.size - 1; } else { args.target = NV_DMA_V0_TARGET_VM; args.access = NV_DMA_V0_ACCESS_RDWR; @@ -465,12 +458,12 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) chan->dma.cur = chan->dma.put; chan->dma.free = chan->dma.max - chan->dma.cur; - ret = PUSH_WAIT(chan->chan.push, NOUVEAU_DMA_SKIPS); + ret = PUSH_WAIT(&chan->chan.push, NOUVEAU_DMA_SKIPS); if (ret) return ret; for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) - PUSH_DATA(chan->chan.push, 0x00000000); + PUSH_DATA(&chan->chan.push, 0x00000000); /* allocate software object class (used for fences on <= nv05) */ if (device->info.family < NV_DEVICE_INFO_V0_CELSIUS) { @@ -480,26 +473,25 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) if (ret) return ret; - ret = PUSH_WAIT(chan->chan.push, 2); + ret = PUSH_WAIT(&chan->chan.push, 2); if (ret) return ret; - PUSH_NVSQ(chan->chan.push, NV_SW, 0x0000, chan->nvsw.handle); - PUSH_KICK(chan->chan.push); + PUSH_NVSQ(&chan->chan.push, NV_SW, 0x0000, chan->nvsw.handle); + PUSH_KICK(&chan->chan.push); } /* initialise synchronisation */ - return nouveau_fence(chan->drm)->context_new(chan); + return nouveau_fence(drm)->context_new(chan); } int -nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, +nouveau_channel_new(struct nouveau_cli *cli, bool priv, u64 runm, u32 vram, u32 gart, struct nouveau_channel **pchan) { - struct nouveau_cli *cli = (void *)device->object.client; int ret; - ret = nouveau_channel_ctor(drm, device, priv, runm, pchan); + ret = nouveau_channel_ctor(cli, priv, runm, pchan); if (ret) { NV_PRINTK(dbg, cli, "channel create, %d\n", ret); return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h index 5de2ef4e98c2..016f668c0bc1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.h +++ b/drivers/gpu/drm/nouveau/nouveau_chan.h @@ -8,12 +8,10 @@ struct nvif_device; struct nouveau_channel { struct { - struct nvif_push _push; - struct nvif_push *push; + struct nvif_push push; } chan; - struct nvif_device *device; - struct nouveau_drm *drm; + struct nouveau_cli *cli; struct nouveau_vmm *vmm; struct nvif_mem mem_userd; @@ -62,7 +60,7 @@ struct nouveau_channel { int nouveau_channels_init(struct nouveau_drm *); void nouveau_channels_fini(struct nouveau_drm *); -int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, bool priv, u64 runm, +int nouveau_channel_new(struct nouveau_cli *, bool priv, u64 runm, u32 vram, u32 gart, struct nouveau_channel **); void nouveau_channel_del(struct nouveau_channel **); int nouveau_channel_idle(struct nouveau_channel *); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 856b3ef5edb8..eac0d1d2dbda 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -477,14 +477,14 @@ nouveau_connector_of_detect(struct drm_connector *connector) struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder; struct pci_dev *pdev = to_pci_dev(dev->dev); - struct device_node *cn, *dn = pci_device_to_OF_node(pdev); + struct device_node *dn = pci_device_to_OF_node(pdev); if (!dn || !((nv_encoder = find_encoder(connector, DCB_OUTPUT_TMDS)) || (nv_encoder = find_encoder(connector, DCB_OUTPUT_ANALOG)))) return NULL; - for_each_child_of_node(dn, cn) { + for_each_child_of_node_scoped(dn, cn) { const char *name = of_get_property(cn, "name", NULL); const void *edid = of_get_property(cn, "EDID", NULL); int idx = name ? name[strlen(name) - 1] - 'A' : 0; @@ -492,7 +492,6 @@ nouveau_connector_of_detect(struct drm_connector *connector) if (nv_encoder->dcb->i2c_index == idx && edid) { nv_connector->edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL); - of_node_put(cn); return nv_encoder; } } @@ -776,7 +775,6 @@ nouveau_connector_force(struct drm_connector *connector) if (!nv_encoder) { NV_ERROR(drm, "can't find encoder to force %s on!\n", connector->name); - connector->status = connector_status_disconnected; return; } @@ -1001,6 +999,9 @@ nouveau_connector_get_modes(struct drm_connector *connector) struct drm_display_mode *mode; mode = drm_mode_duplicate(dev, nv_connector->native_mode); + if (!mode) + return 0; + drm_mode_probed_add(connector, mode); ret = 1; } @@ -1034,7 +1035,7 @@ get_tmds_link_bandwidth(struct drm_connector *connector) unsigned duallink_scale = nouveau_duallink && nv_encoder->dcb->duallink_possible ? 2 : 1; - if (drm_detect_hdmi_monitor(nv_connector->edid)) { + if (nv_connector->base.display_info.is_hdmi) { info = &nv_connector->base.display_info; duallink_scale = 1; } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index a2df4918340c..0608cabed058 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -35,7 +35,6 @@ #include <drm/display/drm_dp_helper.h> #include <drm/drm_crtc.h> -#include <drm/drm_edid.h> #include <drm/drm_encoder.h> #include <drm/drm_util.h> @@ -44,6 +43,7 @@ struct nvkm_i2c_port; struct dcb_output; +struct edid; #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT struct nouveau_backlight { diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c index e83db051e851..200e65a7cefc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c @@ -313,3 +313,19 @@ nouveau_debugfs_fini(struct nouveau_drm *drm) kfree(drm->debugfs); drm->debugfs = NULL; } + +int +nouveau_module_debugfs_init(void) +{ + nouveau_debugfs_root = debugfs_create_dir("nouveau", NULL); + if (IS_ERR(nouveau_debugfs_root)) + return PTR_ERR(nouveau_debugfs_root); + + return 0; +} + +void +nouveau_module_debugfs_fini(void) +{ + debugfs_remove(nouveau_debugfs_root); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.h b/drivers/gpu/drm/nouveau/nouveau_debugfs.h index 77f0323b38ba..b7617b344ee2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_debugfs.h +++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.h @@ -21,6 +21,11 @@ nouveau_debugfs(struct drm_device *dev) extern void nouveau_drm_debugfs_init(struct drm_minor *); extern int nouveau_debugfs_init(struct nouveau_drm *); extern void nouveau_debugfs_fini(struct nouveau_drm *); + +extern struct dentry *nouveau_debugfs_root; + +int nouveau_module_debugfs_init(void); +void nouveau_module_debugfs_fini(void); #else static inline void nouveau_drm_debugfs_init(struct drm_minor *minor) @@ -37,6 +42,17 @@ nouveau_debugfs_fini(struct nouveau_drm *drm) { } +static inline int +nouveau_module_debugfs_init(void) +{ + return 0; +} + +static inline void +nouveau_module_debugfs_fini(void) +{ +} + #endif #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index f28f9a857458..add006fc8d81 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -28,8 +28,8 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_client_event.h> #include <drm/drm_crtc_helper.h> -#include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_probe_helper.h> @@ -44,6 +44,7 @@ #include <nvif/if0011.h> #include <nvif/if0013.h> #include <dispnv50/crc.h> +#include <dispnv50/tile.h> int nouveau_display_vblank_enable(struct drm_crtc *crtc) @@ -83,7 +84,7 @@ static bool nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) { - struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); struct nvif_head *head = &nouveau_crtc(crtc)->head; struct nvif_head_scanoutpos_v0 args; int retry = 20; @@ -220,69 +221,29 @@ nouveau_validate_decode_mod(struct nouveau_drm *drm, return 0; } -static inline uint32_t -nouveau_get_width_in_blocks(uint32_t stride) -{ - /* GOBs per block in the x direction is always one, and GOBs are - * 64 bytes wide - */ - static const uint32_t log_block_width = 6; - - return (stride + (1 << log_block_width) - 1) >> log_block_width; -} - -static inline uint32_t -nouveau_get_height_in_blocks(struct nouveau_drm *drm, - uint32_t height, - uint32_t log_block_height_in_gobs) -{ - uint32_t log_gob_height; - uint32_t log_block_height; - - BUG_ON(drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA); - - if (drm->client.device.info.family < NV_DEVICE_INFO_V0_FERMI) - log_gob_height = 2; - else - log_gob_height = 3; - - log_block_height = log_block_height_in_gobs + log_gob_height; - - return (height + (1 << log_block_height) - 1) >> log_block_height; -} - static int nouveau_check_bl_size(struct nouveau_drm *drm, struct nouveau_bo *nvbo, uint32_t offset, uint32_t stride, uint32_t h, uint32_t tile_mode) { - uint32_t gob_size, bw, bh; + uint32_t gob_size, bw, bh, gobs_in_block; uint64_t bl_size; BUG_ON(drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA); - if (drm->client.device.info.chipset >= 0xc0) { - if (tile_mode & 0xF) - return -EINVAL; - tile_mode >>= 4; - } - - if (tile_mode & 0xFFFFFFF0) + if (nouveau_check_tile_mode(tile_mode, drm->client.device.info.chipset)) return -EINVAL; - if (drm->client.device.info.family < NV_DEVICE_INFO_V0_FERMI) - gob_size = 256; - else - gob_size = 512; - + gobs_in_block = nouveau_get_gobs_in_block(tile_mode, drm->client.device.info.chipset); bw = nouveau_get_width_in_blocks(stride); - bh = nouveau_get_height_in_blocks(drm, h, tile_mode); + bh = nouveau_get_height_in_blocks(h, gobs_in_block, drm->client.device.info.family); + gob_size = nouveau_get_gob_size(drm->client.device.info.family); - bl_size = bw * bh * (1 << tile_mode) * gob_size; + bl_size = bw * bh * gobs_in_block * gob_size; - DRM_DEBUG_KMS("offset=%u stride=%u h=%u tile_mode=0x%02x bw=%u bh=%u gob_size=%u bl_size=%llu size=%zu\n", - offset, stride, h, tile_mode, bw, bh, gob_size, bl_size, - nvbo->bo.base.size); + DRM_DEBUG_KMS("offset=%u stride=%u h=%u gobs_in_block=%u bw=%u bh=%u gob_size=%u bl_size=%llu size=%zu\n", + offset, stride, h, gobs_in_block, bw, bh, gob_size, + bl_size, nvbo->bo.base.size); if (bl_size + offset > nvbo->bo.base.size) return -ERANGE; @@ -391,7 +352,6 @@ nouveau_user_framebuffer_create(struct drm_device *dev, static const struct drm_mode_config_funcs nouveau_mode_config_funcs = { .fb_create = nouveau_user_framebuffer_create, - .output_poll_changed = drm_fb_helper_output_poll_changed, }; @@ -446,9 +406,10 @@ static struct nouveau_drm_prop_enum_list dither_depth[] = { } while(0) void -nouveau_display_hpd_resume(struct drm_device *dev) +nouveau_display_hpd_resume(struct nouveau_drm *drm) { - struct nouveau_drm *drm = nouveau_drm(dev); + if (drm->headless) + return; spin_lock_irq(&drm->hpd_lock); drm->hpd_pending = ~0; @@ -635,7 +596,7 @@ nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime) } drm_connector_list_iter_end(&conn_iter); - if (!runtime) + if (!runtime && !drm->headless) cancel_work_sync(&drm->hpd_work); drm_kms_helper_poll_disable(dev); @@ -729,6 +690,7 @@ nouveau_display_create(struct drm_device *dev) /* no display hw */ if (ret == -ENODEV) { ret = 0; + drm->headless = true; goto disp_create_err; } @@ -803,8 +765,7 @@ nouveau_display_suspend(struct drm_device *dev, bool runtime) { struct nouveau_display *disp = nouveau_display(dev); - /* Disable console. */ - drm_fb_helper_set_suspend_unlocked(dev->fb_helper, true); + drm_client_dev_suspend(dev, false); if (drm_drv_uses_atomic_modeset(dev)) { if (!runtime) { @@ -835,8 +796,7 @@ nouveau_display_resume(struct drm_device *dev, bool runtime) } } - /* Enable console. */ - drm_fb_helper_set_suspend_unlocked(dev->fb_helper, false); + drm_client_dev_resume(dev, false); } int diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index 2ab2ddb1eadf..1f506f8b289c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -45,7 +45,7 @@ nouveau_display(struct drm_device *dev) int nouveau_display_create(struct drm_device *dev); void nouveau_display_destroy(struct drm_device *dev); int nouveau_display_init(struct drm_device *dev, bool resume, bool runtime); -void nouveau_display_hpd_resume(struct drm_device *dev); +void nouveau_display_hpd_resume(struct nouveau_drm *); void nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime); int nouveau_display_suspend(struct drm_device *dev, bool runtime); void nouveau_display_resume(struct drm_device *dev, bool runtime); diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index b01c029f3a90..a1f329ef0641 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -72,7 +72,7 @@ void nv50_dma_push(struct nouveau_channel *chan, u64 offset, u32 length, bool no_prefetch) { - struct nvif_user *user = &chan->drm->client.device.user; + struct nvif_user *user = &chan->cli->drm->client.device.user; struct nouveau_bo *pb = chan->push.buffer; int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base; diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c index 12feecf71e75..1a072568cef6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dmem.c +++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c @@ -193,7 +193,7 @@ static vm_fault_t nouveau_dmem_migrate_to_ram(struct vm_fault *vmf) if (!spage || !(src & MIGRATE_PFN_MIGRATE)) goto done; - dpage = alloc_page_vma(GFP_HIGHUSER, vmf->vma, vmf->address); + dpage = alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vmf->vma, vmf->address); if (!dpage) goto done; @@ -294,7 +294,7 @@ nouveau_dmem_chunk_alloc(struct nouveau_drm *drm, struct page **ppage) out_bo_unpin: nouveau_bo_unpin(chunk->bo); out_bo_free: - nouveau_bo_ref(NULL, &chunk->bo); + nouveau_bo_fini(chunk->bo); out_release: release_mem_region(chunk->pagemap.range.start, range_len(&chunk->pagemap.range)); out_free: @@ -378,9 +378,9 @@ nouveau_dmem_evict_chunk(struct nouveau_dmem_chunk *chunk) dma_addr_t *dma_addrs; struct nouveau_fence *fence; - src_pfns = kcalloc(npages, sizeof(*src_pfns), GFP_KERNEL); - dst_pfns = kcalloc(npages, sizeof(*dst_pfns), GFP_KERNEL); - dma_addrs = kcalloc(npages, sizeof(*dma_addrs), GFP_KERNEL); + src_pfns = kvcalloc(npages, sizeof(*src_pfns), GFP_KERNEL | __GFP_NOFAIL); + dst_pfns = kvcalloc(npages, sizeof(*dst_pfns), GFP_KERNEL | __GFP_NOFAIL); + dma_addrs = kvcalloc(npages, sizeof(*dma_addrs), GFP_KERNEL | __GFP_NOFAIL); migrate_device_range(src_pfns, chunk->pagemap.range.start >> PAGE_SHIFT, npages); @@ -406,11 +406,11 @@ nouveau_dmem_evict_chunk(struct nouveau_dmem_chunk *chunk) migrate_device_pages(src_pfns, dst_pfns, npages); nouveau_dmem_fence_done(&fence); migrate_device_finalize(src_pfns, dst_pfns, npages); - kfree(src_pfns); - kfree(dst_pfns); + kvfree(src_pfns); + kvfree(dst_pfns); for (i = 0; i < npages; i++) dma_unmap_page(chunk->drm->dev->dev, dma_addrs[i], PAGE_SIZE, DMA_BIDIRECTIONAL); - kfree(dma_addrs); + kvfree(dma_addrs); } void @@ -426,7 +426,7 @@ nouveau_dmem_fini(struct nouveau_drm *drm) list_for_each_entry_safe(chunk, tmp, &drm->dmem->chunks, list) { nouveau_dmem_evict_chunk(chunk); nouveau_bo_unpin(chunk->bo); - nouveau_bo_ref(NULL, &chunk->bo); + nouveau_bo_fini(chunk->bo); WARN_ON(chunk->callocated); list_del(&chunk->list); memunmap_pages(&chunk->pagemap); @@ -443,7 +443,7 @@ nvc0b5_migrate_copy(struct nouveau_drm *drm, u64 npages, enum nouveau_aper dst_aper, u64 dst_addr, enum nouveau_aper src_aper, u64 src_addr) { - struct nvif_push *push = drm->dmem->migrate.chan->chan.push; + struct nvif_push *push = &drm->dmem->migrate.chan->chan.push; u32 launch_dma = 0; int ret; @@ -516,7 +516,7 @@ static int nvc0b5_migrate_clear(struct nouveau_drm *drm, u32 length, enum nouveau_aper dst_aper, u64 dst_addr) { - struct nvif_push *push = drm->dmem->migrate.chan->chan.push; + struct nvif_push *push = &drm->dmem->migrate.chan->chan.push; u32 launch_dma = 0; int ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 7de7707ec6a8..bcda0105160f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -181,7 +181,7 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, if (nouveau_mst) { mstm = outp->dp.mstm; if (mstm) - mstm->can_mst = drm_dp_read_mst_cap(aux, dpcd); + mstm->can_mst = drm_dp_read_mst_cap(aux, dpcd) == DRM_DP_MST; } if (nouveau_dp_has_sink_count(connector, outp)) { @@ -225,12 +225,18 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, u8 *dpcd = nv_encoder->dp.dpcd; int ret = NOUVEAU_DP_NONE, hpd; - /* If we've already read the DPCD on an eDP device, we don't need to - * reread it as it won't change + /* eDP ports don't support hotplugging - so there's no point in probing eDP ports unless we + * haven't probed them once before. */ - if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && - dpcd[DP_DPCD_REV] != 0) - return NOUVEAU_DP_SST; + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + if (connector->status == connector_status_connected) + return NOUVEAU_DP_SST; + else if (connector->status == connector_status_disconnected) + return NOUVEAU_DP_NONE; + } + + // Ensure that the aux bus is enabled for probing + drm_dp_dpcd_set_powered(&nv_connector->aux, true); mutex_lock(&nv_encoder->dp.hpd_irq_lock); if (mstm) { @@ -293,6 +299,13 @@ out: if (mstm && !mstm->suspended && ret != NOUVEAU_DP_MST) nv50_mstm_remove(mstm); + /* GSP doesn't like when we try to do aux transactions on a port it considers disconnected, + * and since we don't really have a usecase for that anyway - just disable the aux bus here + * if we've decided the connector is disconnected + */ + if (ret == NOUVEAU_DP_NONE) + drm_dp_dpcd_set_powered(&nv_connector->aux, false); + mutex_unlock(&nv_encoder->dp.hpd_irq_lock); return ret; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index a947e1d5f309..5664c4c71faf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ +#include <linux/aperture.h> #include <linux/delay.h> #include <linux/module.h> #include <linux/pci.h> @@ -29,10 +30,11 @@ #include <linux/vga_switcheroo.h> #include <linux/mmu_notifier.h> #include <linux/dynamic_debug.h> +#include <linux/debugfs.h> -#include <drm/drm_aperture.h> +#include <drm/clients/drm_client_setup.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_ttm.h> #include <drm/drm_gem_ttm_helper.h> #include <drm/drm_ioctl.h> #include <drm/drm_vblank.h> @@ -46,6 +48,7 @@ #include <nvif/fifo.h> #include <nvif/push006c.h> #include <nvif/user.h> +#include <nvif/log.h> #include <nvif/class.h> #include <nvif/cl0002.h> @@ -63,7 +66,6 @@ #include "nouveau_abi16.h" #include "nouveau_fence.h" #include "nouveau_debugfs.h" -#include "nouveau_usif.h" #include "nouveau_connector.h" #include "nouveau_platform.h" #include "nouveau_svm.h" @@ -113,6 +115,20 @@ static struct drm_driver driver_stub; static struct drm_driver driver_pci; static struct drm_driver driver_platform; +#ifdef CONFIG_DEBUG_FS +struct dentry *nouveau_debugfs_root; + +/** + * gsp_logs - list of nvif_log GSP-RM logging buffers + * + * Head pointer to a a list of nvif_log buffers that is created for each GPU + * upon GSP shutdown if the "keep_gsp_logging" command-line parameter is + * specified. This is used to track the alternative debugfs entries for the + * GSP-RM logs. + */ +NVIF_LOGS_DECLARE(gsp_logs); +#endif + static u64 nouveau_pci_name(struct pci_dev *pdev) { @@ -200,7 +216,6 @@ nouveau_cli_fini(struct nouveau_cli *cli) flush_work(&cli->work); WARN_ON(!list_empty(&cli->worker)); - usif_client_fini(cli); if (cli->sched) nouveau_sched_destroy(&cli->sched); if (uvmm) @@ -208,10 +223,11 @@ nouveau_cli_fini(struct nouveau_cli *cli) nouveau_vmm_fini(&cli->svm); nouveau_vmm_fini(&cli->vmm); nvif_mmu_dtor(&cli->mmu); + cli->device.object.map.ptr = NULL; nvif_device_dtor(&cli->device); - mutex_lock(&cli->drm->master.lock); + mutex_lock(&cli->drm->client_mutex); nvif_client_dtor(&cli->base); - mutex_unlock(&cli->drm->master.lock); + mutex_unlock(&cli->drm->client_mutex); } static int @@ -226,13 +242,6 @@ nouveau_cli_init(struct nouveau_drm *drm, const char *sname, {} }; static const struct nvif_mclass - mmus[] = { - { NVIF_CLASS_MMU_GF100, -1 }, - { NVIF_CLASS_MMU_NV50 , -1 }, - { NVIF_CLASS_MMU_NV04 , -1 }, - {} - }; - static const struct nvif_mclass vmms[] = { { NVIF_CLASS_VMM_GP100, -1 }, { NVIF_CLASS_VMM_GM200, -1 }, @@ -241,50 +250,33 @@ nouveau_cli_init(struct nouveau_drm *drm, const char *sname, { NVIF_CLASS_VMM_NV04 , -1 }, {} }; - u64 device = nouveau_name(drm->dev); int ret; snprintf(cli->name, sizeof(cli->name), "%s", sname); cli->drm = drm; mutex_init(&cli->mutex); - usif_client_init(cli); INIT_WORK(&cli->work, nouveau_cli_work); INIT_LIST_HEAD(&cli->worker); mutex_init(&cli->lock); - if (cli == &drm->master) { - ret = nvif_driver_init(NULL, nouveau_config, nouveau_debug, - cli->name, device, &cli->base); - } else { - mutex_lock(&drm->master.lock); - ret = nvif_client_ctor(&drm->master.base, cli->name, device, - &cli->base); - mutex_unlock(&drm->master.lock); - } + mutex_lock(&drm->client_mutex); + ret = nvif_client_ctor(&drm->_client, cli->name, &cli->base); + mutex_unlock(&drm->client_mutex); if (ret) { NV_PRINTK(err, cli, "Client allocation failed: %d\n", ret); goto done; } - ret = nvif_device_ctor(&cli->base.object, "drmDevice", 0, NV_DEVICE, - &(struct nv_device_v0) { - .device = ~0, - .priv = true, - }, sizeof(struct nv_device_v0), - &cli->device); + ret = nvif_device_ctor(&cli->base, "drmDevice", &cli->device); if (ret) { NV_PRINTK(err, cli, "Device allocation failed: %d\n", ret); goto done; } - ret = nvif_mclass(&cli->device.object, mmus); - if (ret < 0) { - NV_PRINTK(err, cli, "No supported MMU class\n"); - goto done; - } + cli->device.object.map.ptr = drm->device.object.map.ptr; - ret = nvif_mmu_ctor(&cli->device.object, "drmMmu", mmus[ret].oclass, + ret = nvif_mmu_ctor(&cli->device.object, "drmMmu", drm->mmu.object.oclass, &cli->mmu); if (ret) { NV_PRINTK(err, cli, "MMU allocation failed: %d\n", ret); @@ -356,7 +348,7 @@ nouveau_accel_ce_init(struct nouveau_drm *drm) return; } - ret = nouveau_channel_new(drm, device, false, runm, NvDmaFB, NvDmaTT, &drm->cechan); + ret = nouveau_channel_new(&drm->client, true, runm, NvDmaFB, NvDmaTT, &drm->cechan); if (ret) NV_ERROR(drm, "failed to create ce channel, %d\n", ret); } @@ -384,7 +376,7 @@ nouveau_accel_gr_init(struct nouveau_drm *drm) return; } - ret = nouveau_channel_new(drm, device, false, runm, NvDmaFB, NvDmaTT, &drm->channel); + ret = nouveau_channel_new(&drm->client, false, runm, NvDmaFB, NvDmaTT, &drm->channel); if (ret) { NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); nouveau_accel_gr_fini(drm); @@ -407,7 +399,8 @@ nouveau_accel_gr_init(struct nouveau_drm *drm) } if (ret == 0) { - struct nvif_push *push = drm->channel->chan.push; + struct nvif_push *push = &drm->channel->chan.push; + ret = PUSH_WAIT(push, 8); if (ret == 0) { if (device->info.chipset >= 0x11) { @@ -432,8 +425,7 @@ nouveau_accel_gr_init(struct nouveau_drm *drm) * any GPU where it's possible we'll end up using M2MF for BO moves. */ if (device->info.family < NV_DEVICE_INFO_V0_FERMI) { - ret = nvkm_gpuobj_new(nvxx_device(device), 32, 0, false, NULL, - &drm->notify); + ret = nvkm_gpuobj_new(nvxx_device(drm), 32, 0, false, NULL, &drm->notify); if (ret) { NV_ERROR(drm, "failed to allocate notifier, %d\n", ret); nouveau_accel_gr_fini(drm); @@ -578,37 +570,70 @@ nouveau_parent = { .errorf = nouveau_drm_errorf, }; -static int -nouveau_drm_device_init(struct drm_device *dev) +static void +nouveau_drm_device_fini(struct nouveau_drm *drm) { - struct nouveau_drm *drm; - int ret; + struct drm_device *dev = drm->dev; + struct nouveau_cli *cli, *temp_cli; - if (!(drm = kzalloc(sizeof(*drm), GFP_KERNEL))) - return -ENOMEM; - dev->dev_private = drm; - drm->dev = dev; + if (nouveau_pmops_runtime()) { + pm_runtime_get_sync(dev->dev); + pm_runtime_forbid(dev->dev); + } - nvif_parent_ctor(&nouveau_parent, &drm->parent); - drm->master.base.object.parent = &drm->parent; + nouveau_led_fini(dev); + nouveau_dmem_fini(drm); + nouveau_svm_fini(drm); + nouveau_hwmon_fini(dev); + nouveau_debugfs_fini(drm); - drm->sched_wq = alloc_workqueue("nouveau_sched_wq_shared", 0, - WQ_MAX_ACTIVE); - if (!drm->sched_wq) { - ret = -ENOMEM; - goto fail_alloc; + if (dev->mode_config.num_crtc) + nouveau_display_fini(dev, false, false); + nouveau_display_destroy(dev); + + nouveau_accel_fini(drm); + nouveau_bios_takedown(dev); + + nouveau_ttm_fini(drm); + nouveau_vga_fini(drm); + + /* + * There may be existing clients from as-yet unclosed files. For now, + * clean them up here rather than deferring until the file is closed, + * but this likely not correct if we want to support hot-unplugging + * properly. + */ + mutex_lock(&drm->clients_lock); + list_for_each_entry_safe(cli, temp_cli, &drm->clients, head) { + list_del(&cli->head); + mutex_lock(&cli->mutex); + if (cli->abi16) + nouveau_abi16_fini(cli->abi16); + mutex_unlock(&cli->mutex); + nouveau_cli_fini(cli); + kfree(cli); } + mutex_unlock(&drm->clients_lock); - ret = nouveau_cli_init(drm, "DRM-master", &drm->master); - if (ret) - goto fail_wq; + nouveau_cli_fini(&drm->client); + destroy_workqueue(drm->sched_wq); + mutex_destroy(&drm->clients_lock); +} + +static int +nouveau_drm_device_init(struct nouveau_drm *drm) +{ + struct drm_device *dev = drm->dev; + int ret; + + drm->sched_wq = alloc_workqueue("nouveau_sched_wq_shared", 0, + WQ_MAX_ACTIVE); + if (!drm->sched_wq) + return -ENOMEM; ret = nouveau_cli_init(drm, "DRM", &drm->client); if (ret) - goto fail_master; - - nvxx_client(&drm->client.base)->debug = - nvkm_dbgopt(nouveau_debug, "DRM"); + goto fail_wq; INIT_LIST_HEAD(&drm->clients); mutex_init(&drm->clients_lock); @@ -658,6 +683,12 @@ nouveau_drm_device_init(struct drm_device *dev) pm_runtime_put(dev->dev); } + ret = drm_dev_register(drm->dev, 0); + if (ret) { + nouveau_drm_device_fini(drm); + return ret; + } + return 0; fail_dispinit: nouveau_display_destroy(dev); @@ -669,67 +700,95 @@ fail_bios: fail_ttm: nouveau_vga_fini(drm); nouveau_cli_fini(&drm->client); -fail_master: - nouveau_cli_fini(&drm->master); fail_wq: destroy_workqueue(drm->sched_wq); -fail_alloc: - nvif_parent_dtor(&drm->parent); - kfree(drm); return ret; } static void -nouveau_drm_device_fini(struct drm_device *dev) +nouveau_drm_device_del(struct nouveau_drm *drm) { - struct nouveau_cli *cli, *temp_cli; - struct nouveau_drm *drm = nouveau_drm(dev); + if (drm->dev) + drm_dev_put(drm->dev); - if (nouveau_pmops_runtime()) { - pm_runtime_get_sync(dev->dev); - pm_runtime_forbid(dev->dev); + nvif_mmu_dtor(&drm->mmu); + nvif_device_dtor(&drm->device); + nvif_client_dtor(&drm->_client); + nvif_parent_dtor(&drm->parent); + + mutex_destroy(&drm->client_mutex); + kfree(drm); +} + +static struct nouveau_drm * +nouveau_drm_device_new(const struct drm_driver *drm_driver, struct device *parent, + struct nvkm_device *device) +{ + static const struct nvif_mclass + mmus[] = { + { NVIF_CLASS_MMU_GF100, -1 }, + { NVIF_CLASS_MMU_NV50 , -1 }, + { NVIF_CLASS_MMU_NV04 , -1 }, + {} + }; + struct nouveau_drm *drm; + int ret; + + drm = kzalloc(sizeof(*drm), GFP_KERNEL); + if (!drm) + return ERR_PTR(-ENOMEM); + + drm->nvkm = device; + + drm->dev = drm_dev_alloc(drm_driver, parent); + if (IS_ERR(drm->dev)) { + ret = PTR_ERR(drm->dev); + goto done; } - nouveau_led_fini(dev); - nouveau_dmem_fini(drm); - nouveau_svm_fini(drm); - nouveau_hwmon_fini(dev); - nouveau_debugfs_fini(drm); + drm->dev->dev_private = drm; + dev_set_drvdata(parent, drm); - if (dev->mode_config.num_crtc) - nouveau_display_fini(dev, false, false); - nouveau_display_destroy(dev); + nvif_parent_ctor(&nouveau_parent, &drm->parent); + mutex_init(&drm->client_mutex); + drm->_client.object.parent = &drm->parent; - nouveau_accel_fini(drm); - nouveau_bios_takedown(dev); + ret = nvif_driver_init(NULL, nouveau_config, nouveau_debug, "drm", + nouveau_name(drm->dev), &drm->_client); + if (ret) + goto done; - nouveau_ttm_fini(drm); - nouveau_vga_fini(drm); + ret = nvif_device_ctor(&drm->_client, "drmDevice", &drm->device); + if (ret) { + NV_ERROR(drm, "Device allocation failed: %d\n", ret); + goto done; + } - /* - * There may be existing clients from as-yet unclosed files. For now, - * clean them up here rather than deferring until the file is closed, - * but this likely not correct if we want to support hot-unplugging - * properly. - */ - mutex_lock(&drm->clients_lock); - list_for_each_entry_safe(cli, temp_cli, &drm->clients, head) { - list_del(&cli->head); - mutex_lock(&cli->mutex); - if (cli->abi16) - nouveau_abi16_fini(cli->abi16); - mutex_unlock(&cli->mutex); - nouveau_cli_fini(cli); - kfree(cli); + ret = nvif_device_map(&drm->device); + if (ret) { + NV_ERROR(drm, "Failed to map PRI: %d\n", ret); + goto done; } - mutex_unlock(&drm->clients_lock); - nouveau_cli_fini(&drm->client); - nouveau_cli_fini(&drm->master); - destroy_workqueue(drm->sched_wq); - nvif_parent_dtor(&drm->parent); - mutex_destroy(&drm->clients_lock); - kfree(drm); + ret = nvif_mclass(&drm->device.object, mmus); + if (ret < 0) { + NV_ERROR(drm, "No supported MMU class\n"); + goto done; + } + + ret = nvif_mmu_ctor(&drm->device.object, "drmMmu", mmus[ret].oclass, &drm->mmu); + if (ret) { + NV_ERROR(drm, "MMU allocation failed: %d\n", ret); + goto done; + } + +done: + if (ret) { + nouveau_drm_device_del(drm); + drm = NULL; + } + + return ret ? ERR_PTR(ret) : drm; } /* @@ -774,8 +833,7 @@ nouveau_drm_device_fini(struct drm_device *dev) static void quirk_broken_nv_runpm(struct pci_dev *pdev) { - struct drm_device *dev = pci_get_drvdata(pdev); - struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_drm *drm = pci_get_drvdata(pdev); struct pci_dev *bridge = pci_upstream_bridge(pdev); if (!bridge || bridge->vendor != PCI_VENDOR_ID_INTEL) @@ -794,7 +852,8 @@ static int nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent) { struct nvkm_device *device; - struct drm_device *drm_dev; + struct nouveau_drm *drm; + const struct drm_format_info *format; int ret; if (vga_switcheroo_client_probe_defer(pdev)) @@ -803,20 +862,12 @@ static int nouveau_drm_probe(struct pci_dev *pdev, /* We need to check that the chipset is supported before booting * fbdev off the hardware, as there's no way to put it back. */ - ret = nvkm_device_pci_new(pdev, nouveau_config, "error", - true, false, 0, &device); + ret = nvkm_device_pci_new(pdev, nouveau_config, nouveau_debug, &device); if (ret) return ret; - nvkm_device_del(&device); - /* Remove conflicting drivers (vesafb, efifb etc). */ - ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &driver_pci); - if (ret) - return ret; - - ret = nvkm_device_pci_new(pdev, nouveau_config, nouveau_debug, - true, true, ~0ULL, &device); + ret = aperture_remove_conflicting_pci_devices(pdev, driver_pci.name); if (ret) return ret; @@ -825,9 +876,9 @@ static int nouveau_drm_probe(struct pci_dev *pdev, if (nouveau_atomic) driver_pci.driver_features |= DRIVER_ATOMIC; - drm_dev = drm_dev_alloc(&driver_pci, &pdev->dev); - if (IS_ERR(drm_dev)) { - ret = PTR_ERR(drm_dev); + drm = nouveau_drm_device_new(&driver_pci, &pdev->dev, device); + if (IS_ERR(drm)) { + ret = PTR_ERR(drm); goto fail_nvkm; } @@ -835,69 +886,57 @@ static int nouveau_drm_probe(struct pci_dev *pdev, if (ret) goto fail_drm; - pci_set_drvdata(pdev, drm_dev); - - ret = nouveau_drm_device_init(drm_dev); + ret = nouveau_drm_device_init(drm); if (ret) goto fail_pci; - ret = drm_dev_register(drm_dev, pent->driver_data); - if (ret) - goto fail_drm_dev_init; - - if (nouveau_drm(drm_dev)->client.device.info.ram_size <= 32 * 1024 * 1024) - drm_fbdev_generic_setup(drm_dev, 8); + if (drm->client.device.info.ram_size <= 32 * 1024 * 1024) + format = drm_format_info(DRM_FORMAT_C8); else - drm_fbdev_generic_setup(drm_dev, 32); + format = NULL; + + drm_client_setup(drm->dev, format); quirk_broken_nv_runpm(pdev); return 0; -fail_drm_dev_init: - nouveau_drm_device_fini(drm_dev); fail_pci: pci_disable_device(pdev); fail_drm: - drm_dev_put(drm_dev); + nouveau_drm_device_del(drm); fail_nvkm: nvkm_device_del(&device); return ret; } void -nouveau_drm_device_remove(struct drm_device *dev) +nouveau_drm_device_remove(struct nouveau_drm *drm) { - struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_client *client; - struct nvkm_device *device; - - drm_dev_unplug(dev); + struct nvkm_device *device = drm->nvkm; - client = nvxx_client(&drm->client.base); - device = nvkm_device_find(client->device); + drm_dev_unplug(drm->dev); - nouveau_drm_device_fini(dev); - drm_dev_put(dev); + nouveau_drm_device_fini(drm); + nouveau_drm_device_del(drm); nvkm_device_del(&device); } static void nouveau_drm_remove(struct pci_dev *pdev) { - struct drm_device *dev = pci_get_drvdata(pdev); - struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_drm *drm = pci_get_drvdata(pdev); /* revert our workaround */ if (drm->old_pm_cap) pdev->pm_cap = drm->old_pm_cap; - nouveau_drm_device_remove(dev); + nouveau_drm_device_remove(drm); pci_disable_device(pdev); } static int -nouveau_do_suspend(struct drm_device *dev, bool runtime) +nouveau_do_suspend(struct nouveau_drm *drm, bool runtime) { - struct nouveau_drm *drm = nouveau_drm(dev); + struct drm_device *dev = drm->dev; struct ttm_resource_manager *man; int ret; @@ -939,7 +978,7 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime) } NV_DEBUG(drm, "suspending object tree...\n"); - ret = nvif_client_suspend(&drm->master.base); + ret = nvif_client_suspend(&drm->_client); if (ret) goto fail_client; @@ -958,13 +997,13 @@ fail_display: } static int -nouveau_do_resume(struct drm_device *dev, bool runtime) +nouveau_do_resume(struct nouveau_drm *drm, bool runtime) { + struct drm_device *dev = drm->dev; int ret = 0; - struct nouveau_drm *drm = nouveau_drm(dev); NV_DEBUG(drm, "resuming object tree...\n"); - ret = nvif_client_resume(&drm->master.base); + ret = nvif_client_resume(&drm->_client); if (ret) { NV_ERROR(drm, "Client resume failed with error: %d\n", ret); return ret; @@ -991,14 +1030,14 @@ int nouveau_pmops_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct nouveau_drm *drm = pci_get_drvdata(pdev); int ret; - if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF || - drm_dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF) + if (drm->dev->switch_power_state == DRM_SWITCH_POWER_OFF || + drm->dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF) return 0; - ret = nouveau_do_suspend(drm_dev, false); + ret = nouveau_do_suspend(drm, false); if (ret) return ret; @@ -1013,11 +1052,11 @@ int nouveau_pmops_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct nouveau_drm *drm = pci_get_drvdata(pdev); int ret; - if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF || - drm_dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF) + if (drm->dev->switch_power_state == DRM_SWITCH_POWER_OFF || + drm->dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF) return 0; pci_set_power_state(pdev, PCI_D0); @@ -1027,10 +1066,10 @@ nouveau_pmops_resume(struct device *dev) return ret; pci_set_master(pdev); - ret = nouveau_do_resume(drm_dev, false); + ret = nouveau_do_resume(drm, false); /* Monitors may have been connected / disconnected during suspend */ - nouveau_display_hpd_resume(drm_dev); + nouveau_display_hpd_resume(drm); return ret; } @@ -1038,17 +1077,17 @@ nouveau_pmops_resume(struct device *dev) static int nouveau_pmops_freeze(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct drm_device *drm_dev = pci_get_drvdata(pdev); - return nouveau_do_suspend(drm_dev, false); + struct nouveau_drm *drm = dev_get_drvdata(dev); + + return nouveau_do_suspend(drm, false); } static int nouveau_pmops_thaw(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct drm_device *drm_dev = pci_get_drvdata(pdev); - return nouveau_do_resume(drm_dev, false); + struct nouveau_drm *drm = dev_get_drvdata(dev); + + return nouveau_do_resume(drm, false); } bool @@ -1063,7 +1102,7 @@ static int nouveau_pmops_runtime_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct nouveau_drm *drm = pci_get_drvdata(pdev); int ret; if (!nouveau_pmops_runtime()) { @@ -1072,12 +1111,12 @@ nouveau_pmops_runtime_suspend(struct device *dev) } nouveau_switcheroo_optimus_dsm(); - ret = nouveau_do_suspend(drm_dev, true); + ret = nouveau_do_suspend(drm, true); pci_save_state(pdev); pci_disable_device(pdev); pci_ignore_hotplug(pdev); pci_set_power_state(pdev, PCI_D3cold); - drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; + drm->dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; return ret; } @@ -1085,9 +1124,8 @@ static int nouveau_pmops_runtime_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - struct drm_device *drm_dev = pci_get_drvdata(pdev); - struct nouveau_drm *drm = nouveau_drm(drm_dev); - struct nvif_device *device = &nouveau_drm(drm_dev)->client.device; + struct nouveau_drm *drm = pci_get_drvdata(pdev); + struct nvif_device *device = &drm->client.device; int ret; if (!nouveau_pmops_runtime()) { @@ -1102,7 +1140,7 @@ nouveau_pmops_runtime_resume(struct device *dev) return ret; pci_set_master(pdev); - ret = nouveau_do_resume(drm_dev, true); + ret = nouveau_do_resume(drm, true); if (ret) { NV_ERROR(drm, "resume failed with: %d\n", ret); return ret; @@ -1110,10 +1148,10 @@ nouveau_pmops_runtime_resume(struct device *dev) /* do magic */ nvif_mask(&device->object, 0x088488, (1 << 25), (1 << 25)); - drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; + drm->dev->switch_power_state = DRM_SWITCH_POWER_ON; /* Monitors may have been connected / disconnected during suspend */ - nouveau_display_hpd_resume(drm_dev); + nouveau_display_hpd_resume(drm); return ret; } @@ -1137,7 +1175,7 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) { struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_cli *cli; - char name[32], tmpname[TASK_COMM_LEN]; + char name[32]; int ret; /* need to bring up power immediately if opening device */ @@ -1147,10 +1185,9 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) return ret; } - get_task_comm(tmpname, current); rcu_read_lock(); snprintf(name, sizeof(name), "%s[%d]", - tmpname, pid_nr(rcu_dereference(fpriv->pid))); + current->comm, pid_nr(rcu_dereference(fpriv->pid))); rcu_read_unlock(); if (!(cli = kzalloc(sizeof(*cli), GFP_KERNEL))) { @@ -1249,7 +1286,7 @@ nouveau_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) switch (_IOC_NR(cmd) - DRM_COMMAND_BASE) { case DRM_NOUVEAU_NVIF: - ret = usif_ioctl(filp, (void __user *)arg, _IOC_SIZE(cmd)); + ret = nouveau_abi16_ioctl(filp, (void __user *)arg, _IOC_SIZE(cmd)); break; default: ret = drm_ioctl(file, cmd, arg); @@ -1274,6 +1311,7 @@ nouveau_driver_fops = { .compat_ioctl = nouveau_compat_ioctl, #endif .llseek = noop_llseek, + .fop_flags = FOP_UNSIGNED_OFFSET, }; static struct drm_driver @@ -1285,7 +1323,6 @@ driver_stub = { DRIVER_RENDER, .open = nouveau_drm_open, .postclose = nouveau_drm_postclose, - .lastclose = nouveau_vga_lastclose, #if defined(CONFIG_DEBUG_FS) .debugfs_init = nouveau_drm_debugfs_init, @@ -1300,13 +1337,10 @@ driver_stub = { .dumb_create = nouveau_display_dumb_create, .dumb_map_offset = drm_gem_ttm_dumb_map_offset, + DRM_FBDEV_TTM_DRIVER_OPS, + .name = DRIVER_NAME, .desc = DRIVER_DESC, -#ifdef GIT_REVISION - .date = GIT_REVISION, -#else - .date = DRIVER_DATE, -#endif .major = DRIVER_MAJOR, .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, @@ -1369,15 +1403,14 @@ nouveau_platform_device_create(const struct nvkm_device_tegra_func *func, struct platform_device *pdev, struct nvkm_device **pdevice) { - struct drm_device *drm; + struct nouveau_drm *drm; int err; - err = nvkm_device_tegra_new(func, pdev, nouveau_config, nouveau_debug, - true, true, ~0ULL, pdevice); + err = nvkm_device_tegra_new(func, pdev, nouveau_config, nouveau_debug, pdevice); if (err) goto err_free; - drm = drm_dev_alloc(&driver_platform, &pdev->dev); + drm = nouveau_drm_device_new(&driver_platform, &pdev->dev, *pdevice); if (IS_ERR(drm)) { err = PTR_ERR(drm); goto err_free; @@ -1387,12 +1420,10 @@ nouveau_platform_device_create(const struct nvkm_device_tegra_func *func, if (err) goto err_put; - platform_set_drvdata(pdev, drm); - - return drm; + return drm->dev; err_put: - drm_dev_put(drm); + nouveau_drm_device_del(drm); err_free: nvkm_device_del(pdevice); @@ -1402,6 +1433,8 @@ err_free: static int __init nouveau_drm_init(void) { + int ret; + driver_pci = driver_stub; driver_platform = driver_stub; @@ -1415,6 +1448,10 @@ nouveau_drm_init(void) if (!nouveau_modeset) return 0; + ret = nouveau_module_debugfs_init(); + if (ret) + return ret; + #ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER platform_driver_register(&nouveau_platform_driver); #endif @@ -1423,10 +1460,14 @@ nouveau_drm_init(void) nouveau_backlight_ctor(); #ifdef CONFIG_PCI - return pci_register_driver(&nouveau_drm_pci_driver); -#else - return 0; + ret = pci_register_driver(&nouveau_drm_pci_driver); + if (ret) { + nouveau_module_debugfs_fini(); + return ret; + } #endif + + return 0; } static void __exit @@ -1446,6 +1487,12 @@ nouveau_drm_exit(void) #endif if (IS_ENABLED(CONFIG_DRM_NOUVEAU_SVM)) mmu_notifier_synchronize(); + +#ifdef CONFIG_DEBUG_FS + nvif_log_shutdown(&gsp_logs); +#endif + + nouveau_module_debugfs_fini(); } module_init(nouveau_drm_init); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index e239c6bf4afa..55abc510067b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -7,7 +7,6 @@ #define DRIVER_NAME "nouveau" #define DRIVER_DESC "nVidia Riva/TNT/GeForce/Quadro/Tesla/Tegra K1+" -#define DRIVER_DATE "20120801" #define DRIVER_MAJOR 1 #define DRIVER_MINOR 4 @@ -201,8 +200,13 @@ u_memcpya(uint64_t user, unsigned int nmemb, unsigned int size) #include <nvif/parent.h> struct nouveau_drm { + struct nvkm_device *nvkm; struct nvif_parent parent; - struct nouveau_cli master; + struct mutex client_mutex; + struct nvif_client _client; + struct nvif_device device; + struct nvif_mmu mmu; + struct nouveau_cli client; struct drm_device *dev; @@ -276,6 +280,7 @@ struct nouveau_drm { /* modesetting */ struct nvbios vbios; struct nouveau_display *display; + bool headless; struct work_struct hpd_work; spinlock_t hpd_lock; u32 hpd_pending; @@ -325,25 +330,28 @@ bool nouveau_pmops_runtime(void); struct drm_device * nouveau_platform_device_create(const struct nvkm_device_tegra_func *, struct platform_device *, struct nvkm_device **); -void nouveau_drm_device_remove(struct drm_device *dev); +void nouveau_drm_device_remove(struct nouveau_drm *); #define NV_PRINTK(l,c,f,a...) do { \ struct nouveau_cli *_cli = (c); \ dev_##l(_cli->drm->dev->dev, "%s: "f, _cli->name, ##a); \ } while(0) -#define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a) -#define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a) -#define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a) -#define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a) +#define NV_PRINTK_(l,drm,f,a...) do { \ + dev_##l((drm)->nvkm->dev, "drm: "f, ##a); \ +} while(0) +#define NV_FATAL(drm,f,a...) NV_PRINTK_(crit, (drm), f, ##a) +#define NV_ERROR(drm,f,a...) NV_PRINTK_(err, (drm), f, ##a) +#define NV_WARN(drm,f,a...) NV_PRINTK_(warn, (drm), f, ##a) +#define NV_INFO(drm,f,a...) NV_PRINTK_(info, (drm), f, ##a) #define NV_DEBUG(drm,f,a...) do { \ if (drm_debug_enabled(DRM_UT_DRIVER)) \ - NV_PRINTK(info, &(drm)->client, f, ##a); \ + NV_PRINTK_(info, (drm), f, ##a); \ } while(0) #define NV_ATOMIC(drm,f,a...) do { \ if (drm_debug_enabled(DRM_UT_ATOMIC)) \ - NV_PRINTK(info, &(drm)->client, f, ##a); \ + NV_PRINTK_(info, (drm), f, ##a); \ } while(0) #define NV_PRINTK_ONCE(l,c,f,a...) NV_PRINTK(l##_once,c,f, ##a) @@ -354,4 +362,41 @@ void nouveau_drm_device_remove(struct drm_device *dev); extern int nouveau_modeset; +/*XXX: Don't use these in new code. + * + * These accessors are used in a few places (mostly older code paths) + * to get direct access to NVKM structures, where a more well-defined + * interface doesn't exist. Outside of the current use, these should + * not be relied on, and instead be implemented as NVIF. + * + * This is especially important when considering GSP-RM, as a lot the + * modules don't exist, or are "stub" implementations that just allow + * the GSP-RM paths to be bootstrapped. + */ +#include <subdev/bios.h> +#include <subdev/fb.h> +#include <subdev/gpio.h> +#include <subdev/clk.h> +#include <subdev/i2c.h> +#include <subdev/timer.h> +#include <subdev/therm.h> + +static inline struct nvkm_device * +nvxx_device(struct nouveau_drm *drm) +{ + return drm->nvkm; +} + +#define nvxx_bios(a) nvxx_device(a)->bios +#define nvxx_fb(a) nvxx_device(a)->fb +#define nvxx_gpio(a) nvxx_device(a)->gpio +#define nvxx_clk(a) nvxx_device(a)->clk +#define nvxx_i2c(a) nvxx_device(a)->i2c +#define nvxx_iccsense(a) nvxx_device(a)->iccsense +#define nvxx_therm(a) nvxx_device(a)->therm +#define nvxx_volt(a) nvxx_device(a)->volt + +#include <engine/gr.h> + +#define nvxx_gr(a) nvxx_device(a)->gr #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c b/drivers/gpu/drm/nouveau/nouveau_exec.c index e65c0ef23bc7..a0b5f1b16e8b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_exec.c +++ b/drivers/gpu/drm/nouveau/nouveau_exec.c @@ -188,7 +188,7 @@ nouveau_exec_job_timeout(struct nouveau_job *job) return DRM_GPU_SCHED_STAT_NOMINAL; } -static struct nouveau_job_ops nouveau_exec_job_ops = { +static const struct nouveau_job_ops nouveau_exec_job_ops = { .submit = nouveau_exec_job_submit, .armed_submit = nouveau_exec_job_armed_submit, .run = nouveau_exec_job_run, diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 93f08f9479d8..7cc84472cece 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -181,8 +181,9 @@ nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 repc void nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx) { - struct nouveau_fence_priv *priv = (void*)chan->drm->fence; - struct nouveau_cli *cli = (void *)chan->user.client; + struct nouveau_cli *cli = chan->cli; + struct nouveau_drm *drm = cli->drm; + struct nouveau_fence_priv *priv = (void*)drm->fence; struct { struct nvif_event_v0 base; struct nvif_chan_event_v0 host; @@ -193,14 +194,14 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha INIT_LIST_HEAD(&fctx->flip); INIT_LIST_HEAD(&fctx->pending); spin_lock_init(&fctx->lock); - fctx->context = chan->drm->runl[chan->runlist].context_base + chan->chid; + fctx->context = drm->runl[chan->runlist].context_base + chan->chid; - if (chan == chan->drm->cechan) + if (chan == drm->cechan) strcpy(fctx->name, "copy engine channel"); - else if (chan == chan->drm->channel) + else if (chan == drm->channel) strcpy(fctx->name, "generic kernel channel"); else - strcpy(fctx->name, nvxx_client(&cli->base)->name); + strcpy(fctx->name, cli->name); kref_init(&fctx->fence_ref); if (!priv->uevent) @@ -221,7 +222,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) { struct nouveau_channel *chan = unrcu_pointer(fence->channel); struct nouveau_fence_chan *fctx = chan->fence; - struct nouveau_fence_priv *priv = (void*)chan->drm->fence; + struct nouveau_fence_priv *priv = (void*)chan->cli->drm->fence; int ret; fence->timeout = jiffies + (15 * HZ); @@ -382,15 +383,17 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, if (i == 0 && usage == DMA_RESV_USAGE_WRITE) continue; - f = nouveau_local_fence(fence, chan->drm); + f = nouveau_local_fence(fence, chan->cli->drm); if (f) { struct nouveau_channel *prev; bool must_wait = true; + bool local; rcu_read_lock(); prev = rcu_dereference(f->channel); - if (prev && (prev == chan || - fctx->sync(f, prev, chan) == 0)) + local = prev && prev->cli->drm == chan->cli->drm; + if (local && (prev == chan || + fctx->sync(f, prev, chan) == 0)) must_wait = false; rcu_read_unlock(); if (!must_wait) diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 5a887d67dc0e..9ae2cee1c7c5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -567,10 +567,11 @@ retry: } static int -validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, +validate_list(struct nouveau_channel *chan, struct list_head *list, struct drm_nouveau_gem_pushbuf_bo *pbbo) { - struct nouveau_drm *drm = chan->drm; + struct nouveau_cli *cli = chan->cli; + struct nouveau_drm *drm = cli->drm; struct nouveau_bo *nvbo; int ret, relocs = 0; @@ -642,7 +643,7 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, return ret; } - ret = validate_list(chan, cli, &op->list, pbbo); + ret = validate_list(chan, &op->list, pbbo); if (unlikely(ret < 0)) { if (ret != -ERESTARTSYS) NV_PRINTK(err, cli, "validating bo list\n"); @@ -870,7 +871,7 @@ revalidate: } } else if (drm->client.device.info.chipset >= 0x25) { - ret = PUSH_WAIT(chan->chan.push, req->nr_push * 2); + ret = PUSH_WAIT(&chan->chan.push, req->nr_push * 2); if (ret) { NV_PRINTK(err, cli, "cal_space: %d\n", ret); goto out; @@ -880,11 +881,11 @@ revalidate: struct nouveau_bo *nvbo = (void *)(unsigned long) bo[push[i].bo_index].user_priv; - PUSH_CALL(chan->chan.push, nvbo->offset + push[i].offset); - PUSH_DATA(chan->chan.push, 0); + PUSH_CALL(&chan->chan.push, nvbo->offset + push[i].offset); + PUSH_DATA(&chan->chan.push, 0); } } else { - ret = PUSH_WAIT(chan->chan.push, req->nr_push * (2 + NOUVEAU_DMA_SKIPS)); + ret = PUSH_WAIT(&chan->chan.push, req->nr_push * (2 + NOUVEAU_DMA_SKIPS)); if (ret) { NV_PRINTK(err, cli, "jmp_space: %d\n", ret); goto out; @@ -913,10 +914,10 @@ revalidate: push[i].length - 8) / 4, cmd); } - PUSH_JUMP(chan->chan.push, nvbo->offset + push[i].offset); - PUSH_DATA(chan->chan.push, 0); + PUSH_JUMP(&chan->chan.push, nvbo->offset + push[i].offset); + PUSH_DATA(&chan->chan.push, 0); for (j = 0; j < NOUVEAU_DMA_SKIPS; j++) - PUSH_DATA(chan->chan.push, 0); + PUSH_DATA(&chan->chan.push, 0); } } diff --git a/drivers/gpu/drm/nouveau/nouveau_hwmon.c b/drivers/gpu/drm/nouveau/nouveau_hwmon.c index db30a4c2cd4d..5c07a9ee8b77 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hwmon.c +++ b/drivers/gpu/drm/nouveau/nouveau_hwmon.c @@ -52,7 +52,7 @@ nouveau_hwmon_temp1_auto_point1_temp(struct device *d, { struct drm_device *dev = dev_get_drvdata(d); struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); return sysfs_emit(buf, "%d\n", therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST) * 1000); @@ -64,7 +64,7 @@ nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d, { struct drm_device *dev = dev_get_drvdata(d); struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); long value; if (kstrtol(buf, 10, &value)) @@ -85,7 +85,7 @@ nouveau_hwmon_temp1_auto_point1_temp_hyst(struct device *d, { struct drm_device *dev = dev_get_drvdata(d); struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); return sysfs_emit(buf, "%d\n", therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000); @@ -97,7 +97,7 @@ nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d, { struct drm_device *dev = dev_get_drvdata(d); struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); long value; if (kstrtol(buf, 10, &value)) @@ -118,7 +118,7 @@ nouveau_hwmon_get_pwm1_max(struct device *d, { struct drm_device *dev = dev_get_drvdata(d); struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); int ret; ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY); @@ -134,7 +134,7 @@ nouveau_hwmon_get_pwm1_min(struct device *d, { struct drm_device *dev = dev_get_drvdata(d); struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); int ret; ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MIN_DUTY); @@ -150,7 +150,7 @@ nouveau_hwmon_set_pwm1_min(struct device *d, struct device_attribute *a, { struct drm_device *dev = dev_get_drvdata(d); struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); long value; int ret; @@ -173,7 +173,7 @@ nouveau_hwmon_set_pwm1_max(struct device *d, struct device_attribute *a, { struct drm_device *dev = dev_get_drvdata(d); struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); long value; int ret; @@ -247,7 +247,7 @@ static umode_t nouveau_power_is_visible(const void *data, u32 attr, int channel) { struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data); - struct nvkm_iccsense *iccsense = nvxx_iccsense(&drm->client.device); + struct nvkm_iccsense *iccsense = nvxx_iccsense(drm); if (!iccsense || !iccsense->data_valid || list_empty(&iccsense->rails)) return 0; @@ -272,7 +272,7 @@ static umode_t nouveau_temp_is_visible(const void *data, u32 attr, int channel) { struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); if (!therm || !therm->attr_get || nvkm_therm_temp_get(therm) < 0) return 0; @@ -296,7 +296,7 @@ static umode_t nouveau_pwm_is_visible(const void *data, u32 attr, int channel) { struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); if (!therm || !therm->attr_get || !therm->fan_get || therm->fan_get(therm) < 0) @@ -315,7 +315,7 @@ static umode_t nouveau_input_is_visible(const void *data, u32 attr, int channel) { struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data); - struct nvkm_volt *volt = nvxx_volt(&drm->client.device); + struct nvkm_volt *volt = nvxx_volt(drm); if (!volt || nvkm_volt_get(volt) < 0) return 0; @@ -335,7 +335,7 @@ static umode_t nouveau_fan_is_visible(const void *data, u32 attr, int channel) { struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); if (!therm || !therm->attr_get || nvkm_therm_fan_sense(therm) < 0) return 0; @@ -367,7 +367,7 @@ nouveau_temp_read(struct device *dev, u32 attr, int channel, long *val) { struct drm_device *drm_dev = dev_get_drvdata(dev); struct nouveau_drm *drm = nouveau_drm(drm_dev); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); int ret; if (!therm || !therm->attr_get) @@ -416,7 +416,7 @@ nouveau_fan_read(struct device *dev, u32 attr, int channel, long *val) { struct drm_device *drm_dev = dev_get_drvdata(dev); struct nouveau_drm *drm = nouveau_drm(drm_dev); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); if (!therm) return -EOPNOTSUPP; @@ -439,7 +439,7 @@ nouveau_in_read(struct device *dev, u32 attr, int channel, long *val) { struct drm_device *drm_dev = dev_get_drvdata(dev); struct nouveau_drm *drm = nouveau_drm(drm_dev); - struct nvkm_volt *volt = nvxx_volt(&drm->client.device); + struct nvkm_volt *volt = nvxx_volt(drm); int ret; if (!volt) @@ -470,7 +470,7 @@ nouveau_pwm_read(struct device *dev, u32 attr, int channel, long *val) { struct drm_device *drm_dev = dev_get_drvdata(dev); struct nouveau_drm *drm = nouveau_drm(drm_dev); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); if (!therm || !therm->attr_get || !therm->fan_get) return -EOPNOTSUPP; @@ -496,7 +496,7 @@ nouveau_power_read(struct device *dev, u32 attr, int channel, long *val) { struct drm_device *drm_dev = dev_get_drvdata(dev); struct nouveau_drm *drm = nouveau_drm(drm_dev); - struct nvkm_iccsense *iccsense = nvxx_iccsense(&drm->client.device); + struct nvkm_iccsense *iccsense = nvxx_iccsense(drm); if (!iccsense) return -EOPNOTSUPP; @@ -525,7 +525,7 @@ nouveau_temp_write(struct device *dev, u32 attr, int channel, long val) { struct drm_device *drm_dev = dev_get_drvdata(dev); struct nouveau_drm *drm = nouveau_drm(drm_dev); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); if (!therm || !therm->attr_set) return -EOPNOTSUPP; @@ -559,7 +559,7 @@ nouveau_pwm_write(struct device *dev, u32 attr, int channel, long val) { struct drm_device *drm_dev = dev_get_drvdata(dev); struct nouveau_drm *drm = nouveau_drm(drm_dev); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); + struct nvkm_therm *therm = nvxx_therm(drm); if (!therm || !therm->attr_set) return -EOPNOTSUPP; @@ -664,9 +664,9 @@ nouveau_hwmon_init(struct drm_device *dev) { #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_iccsense *iccsense = nvxx_iccsense(&drm->client.device); - struct nvkm_therm *therm = nvxx_therm(&drm->client.device); - struct nvkm_volt *volt = nvxx_volt(&drm->client.device); + struct nvkm_iccsense *iccsense = nvxx_iccsense(drm); + struct nvkm_therm *therm = nvxx_therm(drm); + struct nvkm_volt *volt = nvxx_volt(drm); const struct attribute_group *special_groups[N_ATTR_GROUPS]; struct nouveau_hwmon *hwmon; struct device *hwmon_dev; diff --git a/drivers/gpu/drm/nouveau/nouveau_ioc32.c b/drivers/gpu/drm/nouveau/nouveau_ioc32.c index adf01ca9e035..2af3615c5205 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ioc32.c +++ b/drivers/gpu/drm/nouveau/nouveau_ioc32.c @@ -1,4 +1,4 @@ -/** +/* * \file mga_ioc32.c * * 32-bit ioctl compatibility routines for the MGA DRM. @@ -38,7 +38,7 @@ #include "nouveau_ioctl.h" -/** +/* * Called whenever a 32-bit process running under a 64-bit kernel * performs an ioctl on /dev/dri/card<n>. * diff --git a/drivers/gpu/drm/nouveau/nouveau_led.c b/drivers/gpu/drm/nouveau/nouveau_led.c index 2c5e0628da12..ac950518a820 100644 --- a/drivers/gpu/drm/nouveau/nouveau_led.c +++ b/drivers/gpu/drm/nouveau/nouveau_led.c @@ -78,7 +78,7 @@ int nouveau_led_init(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_gpio *gpio = nvxx_gpio(&drm->client.device); + struct nvkm_gpio *gpio = nvxx_gpio(drm); struct dcb_gpio_func logo_led; int ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 25f31d5169e5..fac92fdbf9cc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -78,20 +78,19 @@ nouveau_mem_map(struct nouveau_mem *mem, void nouveau_mem_fini(struct nouveau_mem *mem) { - nvif_vmm_put(&mem->cli->drm->client.vmm.vmm, &mem->vma[1]); - nvif_vmm_put(&mem->cli->drm->client.vmm.vmm, &mem->vma[0]); - mutex_lock(&mem->cli->drm->master.lock); + nvif_vmm_put(&mem->drm->client.vmm.vmm, &mem->vma[1]); + nvif_vmm_put(&mem->drm->client.vmm.vmm, &mem->vma[0]); + mutex_lock(&mem->drm->client_mutex); nvif_mem_dtor(&mem->mem); - mutex_unlock(&mem->cli->drm->master.lock); + mutex_unlock(&mem->drm->client_mutex); } int nouveau_mem_host(struct ttm_resource *reg, struct ttm_tt *tt) { struct nouveau_mem *mem = nouveau_mem(reg); - struct nouveau_cli *cli = mem->cli; - struct nouveau_drm *drm = cli->drm; - struct nvif_mmu *mmu = &cli->mmu; + struct nouveau_drm *drm = mem->drm; + struct nvif_mmu *mmu = &drm->mmu; struct nvif_mem_ram_v0 args = {}; u8 type; int ret; @@ -114,11 +113,11 @@ nouveau_mem_host(struct ttm_resource *reg, struct ttm_tt *tt) else args.dma = tt->dma_address; - mutex_lock(&drm->master.lock); - ret = nvif_mem_ctor_type(mmu, "ttmHostMem", cli->mem->oclass, type, PAGE_SHIFT, + mutex_lock(&drm->client_mutex); + ret = nvif_mem_ctor_type(mmu, "ttmHostMem", mmu->mem, type, PAGE_SHIFT, reg->size, &args, sizeof(args), &mem->mem); - mutex_unlock(&drm->master.lock); + mutex_unlock(&drm->client_mutex); return ret; } @@ -126,16 +125,15 @@ int nouveau_mem_vram(struct ttm_resource *reg, bool contig, u8 page) { struct nouveau_mem *mem = nouveau_mem(reg); - struct nouveau_cli *cli = mem->cli; - struct nouveau_drm *drm = cli->drm; - struct nvif_mmu *mmu = &cli->mmu; + struct nouveau_drm *drm = mem->drm; + struct nvif_mmu *mmu = &drm->mmu; u64 size = ALIGN(reg->size, 1 << page); int ret; - mutex_lock(&drm->master.lock); - switch (cli->mem->oclass) { + mutex_lock(&drm->client_mutex); + switch (mmu->mem) { case NVIF_CLASS_MEM_GF100: - ret = nvif_mem_ctor_type(mmu, "ttmVram", cli->mem->oclass, + ret = nvif_mem_ctor_type(mmu, "ttmVram", mmu->mem, drm->ttm.type_vram, page, size, &(struct gf100_mem_v0) { .contig = contig, @@ -143,7 +141,7 @@ nouveau_mem_vram(struct ttm_resource *reg, bool contig, u8 page) &mem->mem); break; case NVIF_CLASS_MEM_NV50: - ret = nvif_mem_ctor_type(mmu, "ttmVram", cli->mem->oclass, + ret = nvif_mem_ctor_type(mmu, "ttmVram", mmu->mem, drm->ttm.type_vram, page, size, &(struct nv50_mem_v0) { .bankswz = mmu->kind[mem->kind] == 2, @@ -156,7 +154,7 @@ nouveau_mem_vram(struct ttm_resource *reg, bool contig, u8 page) WARN_ON(1); break; } - mutex_unlock(&drm->master.lock); + mutex_unlock(&drm->client_mutex); reg->start = mem->mem.addr >> PAGE_SHIFT; return ret; @@ -173,7 +171,7 @@ nouveau_mem_del(struct ttm_resource_manager *man, struct ttm_resource *reg) } int -nouveau_mem_new(struct nouveau_cli *cli, u8 kind, u8 comp, +nouveau_mem_new(struct nouveau_drm *drm, u8 kind, u8 comp, struct ttm_resource **res) { struct nouveau_mem *mem; @@ -181,7 +179,7 @@ nouveau_mem_new(struct nouveau_cli *cli, u8 kind, u8 comp, if (!(mem = kzalloc(sizeof(*mem), GFP_KERNEL))) return -ENOMEM; - mem->cli = cli; + mem->drm = drm; mem->kind = kind; mem->comp = comp; diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.h b/drivers/gpu/drm/nouveau/nouveau_mem.h index 5365a3d3a17f..a070ee049f6b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.h +++ b/drivers/gpu/drm/nouveau/nouveau_mem.h @@ -8,7 +8,7 @@ struct ttm_tt; struct nouveau_mem { struct ttm_resource base; - struct nouveau_cli *cli; + struct nouveau_drm *drm; u8 kind; u8 comp; struct nvif_mem mem; @@ -21,7 +21,7 @@ nouveau_mem(struct ttm_resource *reg) return container_of(reg, struct nouveau_mem, base); } -int nouveau_mem_new(struct nouveau_cli *, u8 kind, u8 comp, +int nouveau_mem_new(struct nouveau_drm *, u8 kind, u8 comp, struct ttm_resource **); void nouveau_mem_del(struct ttm_resource_manager *man, struct ttm_resource *); diff --git a/drivers/gpu/drm/nouveau/nouveau_nvif.c b/drivers/gpu/drm/nouveau/nouveau_nvif.c index 1d49ebdfd5dc..adb802421fda 100644 --- a/drivers/gpu/drm/nouveau/nouveau_nvif.c +++ b/drivers/gpu/drm/nouveau/nouveau_nvif.c @@ -35,7 +35,6 @@ #include <nvif/ioctl.h> #include "nouveau_drv.h" -#include "nouveau_usif.h" static void nvkm_client_unmap(void *priv, void __iomem *ptr, u32 size) @@ -98,5 +97,4 @@ nvif_driver_nvkm = { .ioctl = nvkm_client_ioctl, .map = nvkm_client_map, .unmap = nvkm_client_unmap, - .keep = false, }; diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c index bf2dc7567ea4..a5ce8eb4a3be 100644 --- a/drivers/gpu/drm/nouveau/nouveau_platform.c +++ b/drivers/gpu/drm/nouveau/nouveau_platform.c @@ -26,7 +26,6 @@ static int nouveau_platform_probe(struct platform_device *pdev) const struct nvkm_device_tegra_func *func; struct nvkm_device *device = NULL; struct drm_device *drm; - int ret; func = of_device_get_match_data(&pdev->dev); @@ -34,19 +33,14 @@ static int nouveau_platform_probe(struct platform_device *pdev) if (IS_ERR(drm)) return PTR_ERR(drm); - ret = drm_dev_register(drm, 0); - if (ret < 0) { - drm_dev_put(drm); - return ret; - } - return 0; } static void nouveau_platform_remove(struct platform_device *pdev) { - struct drm_device *dev = platform_get_drvdata(pdev); - nouveau_drm_device_remove(dev); + struct nouveau_drm *drm = platform_get_drvdata(pdev); + + nouveau_drm_device_remove(drm); } #if IS_ENABLED(CONFIG_OF) @@ -92,5 +86,5 @@ struct platform_driver nouveau_platform_driver = { .of_match_table = of_match_ptr(nouveau_platform_match), }, .probe = nouveau_platform_probe, - .remove_new = nouveau_platform_remove, + .remove = nouveau_platform_remove, }; diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index 1b2ff0c40fc1..cd95446d6851 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -64,7 +64,8 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev, * to the caller, instead of a normal nouveau_bo ttm reference. */ ret = drm_gem_object_init(dev, &nvbo->bo.base, size); if (ret) { - nouveau_bo_ref(NULL, &nvbo); + drm_gem_object_release(&nvbo->bo.base); + kfree(nvbo); obj = ERR_PTR(-ENOMEM); goto unlock; } @@ -89,18 +90,18 @@ int nouveau_gem_prime_pin(struct drm_gem_object *obj) int ret; /* pin buffer into GTT */ - ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_GART, false); + ret = nouveau_bo_pin_locked(nvbo, NOUVEAU_GEM_DOMAIN_GART, false); if (ret) - return -EINVAL; + ret = -EINVAL; - return 0; + return ret; } void nouveau_gem_prime_unpin(struct drm_gem_object *obj) { struct nouveau_bo *nvbo = nouveau_gem_object(obj); - nouveau_bo_unpin(nvbo); + nouveau_bo_unpin_locked(nvbo); } struct dma_buf *nouveau_gem_prime_export(struct drm_gem_object *gobj, diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c b/drivers/gpu/drm/nouveau/nouveau_sched.c index 32fa2e273965..4412f2711fb5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sched.c +++ b/drivers/gpu/drm/nouveau/nouveau_sched.c @@ -379,7 +379,7 @@ nouveau_sched_timedout_job(struct drm_sched_job *sched_job) else NV_PRINTK(warn, job->cli, "Generic job timeout.\n"); - drm_sched_start(sched, true); + drm_sched_start(sched, 0); return stat; } @@ -404,7 +404,7 @@ nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm, { struct drm_gpu_scheduler *drm_sched = &sched->base; struct drm_sched_entity *entity = &sched->entity; - long job_hang_limit = msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); + const long timeout = msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); int ret; if (!wq) { @@ -418,7 +418,7 @@ nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm, ret = drm_sched_init(drm_sched, &nouveau_sched_ops, wq, NOUVEAU_SCHED_PRIORITY_COUNT, - credit_limit, 0, job_hang_limit, + credit_limit, 0, timeout, NULL, NULL, "nouveau_sched", drm->dev->dev); if (ret) goto fail_wq; diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.h b/drivers/gpu/drm/nouveau/nouveau_sched.h index e1f01a23e6f6..20cd1da8db73 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sched.h +++ b/drivers/gpu/drm/nouveau/nouveau_sched.h @@ -42,7 +42,7 @@ struct nouveau_job_args { u32 count; } out_sync; - struct nouveau_job_ops *ops; + const struct nouveau_job_ops *ops; }; struct nouveau_job { @@ -73,7 +73,7 @@ struct nouveau_job { u32 count; } out_sync; - struct nouveau_job_ops { + const struct nouveau_job_ops { /* If .submit() returns without any error, it is guaranteed that * armed_submit() is called. */ diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index b14895f75b3c..bd870028514b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -43,7 +43,7 @@ nouveau_sgdma_bind(struct ttm_device *bdev, struct ttm_tt *ttm, struct ttm_resou return ret; if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) { - ret = nouveau_mem_map(mem, &mem->cli->vmm.vmm, &mem->vma[0]); + ret = nouveau_mem_map(mem, &drm->client.vmm.vmm, &mem->vma[0]); if (ret) { nouveau_mem_fini(mem); return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c index 5e4565c5011a..8ea98f06d39a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_svm.c +++ b/drivers/gpu/drm/nouveau/nouveau_svm.c @@ -112,7 +112,7 @@ nouveau_svmm_bind(struct drm_device *dev, void *data, { struct nouveau_cli *cli = nouveau_cli(file_priv); struct drm_nouveau_svm_bind *args = data; - unsigned target, cmd, priority; + unsigned target, cmd; unsigned long addr, end; struct mm_struct *mm; @@ -136,9 +136,6 @@ nouveau_svmm_bind(struct drm_device *dev, void *data, return -EINVAL; } - priority = args->header >> NOUVEAU_SVM_BIND_PRIORITY_SHIFT; - priority &= NOUVEAU_SVM_BIND_PRIORITY_MASK; - /* FIXME support CPU target ie all target value < GPU_VRAM */ target = args->header >> NOUVEAU_SVM_BIND_TARGET_SHIFT; target &= NOUVEAU_SVM_BIND_TARGET_MASK; @@ -593,6 +590,7 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm, unsigned long timeout = jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); struct mm_struct *mm = svmm->notifier.mm; + struct folio *folio; struct page *page; unsigned long start = args->p.addr; unsigned long notifier_seq; @@ -619,12 +617,16 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm, ret = -EINVAL; goto out; } + folio = page_folio(page); mutex_lock(&svmm->mutex); if (!mmu_interval_read_retry(¬ifier->notifier, notifier_seq)) break; mutex_unlock(&svmm->mutex); + + folio_unlock(folio); + folio_put(folio); } /* Map the page on the GPU. */ @@ -640,8 +642,8 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm, ret = nvif_object_ioctl(&svmm->vmm->vmm.object, args, size, NULL); mutex_unlock(&svmm->mutex); - unlock_page(page); - put_page(page); + folio_unlock(folio); + folio_put(folio); out: mmu_interval_notifier_remove(¬ifier->notifier); @@ -926,15 +928,14 @@ nouveau_pfns_map(struct nouveau_svmm *svmm, struct mm_struct *mm, unsigned long addr, u64 *pfns, unsigned long npages) { struct nouveau_pfnmap_args *args = nouveau_pfns_to_args(pfns); - int ret; args->p.addr = addr; args->p.size = npages << PAGE_SHIFT; mutex_lock(&svmm->mutex); - ret = nvif_object_ioctl(&svmm->vmm->vmm.object, args, - struct_size(args, p.phys, npages), NULL); + nvif_object_ioctl(&svmm->vmm->vmm.object, args, + struct_size(args, p.phys, npages), NULL); mutex_unlock(&svmm->mutex); } diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 486f39f31a38..e244927eb5d4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -73,7 +73,7 @@ nouveau_vram_manager_new(struct ttm_resource_manager *man, if (drm->client.device.info.ram_size == 0) return -ENOMEM; - ret = nouveau_mem_new(&drm->master, nvbo->kind, nvbo->comp, res); + ret = nouveau_mem_new(drm, nvbo->kind, nvbo->comp, res); if (ret) return ret; @@ -105,7 +105,7 @@ nouveau_gart_manager_new(struct ttm_resource_manager *man, struct nouveau_drm *drm = nouveau_bdev(bo->bdev); int ret; - ret = nouveau_mem_new(&drm->master, nvbo->kind, nvbo->comp, res); + ret = nouveau_mem_new(drm, nvbo->kind, nvbo->comp, res); if (ret) return ret; @@ -132,13 +132,13 @@ nv04_gart_manager_new(struct ttm_resource_manager *man, struct nouveau_mem *mem; int ret; - ret = nouveau_mem_new(&drm->master, nvbo->kind, nvbo->comp, res); + ret = nouveau_mem_new(drm, nvbo->kind, nvbo->comp, res); if (ret) return ret; mem = nouveau_mem(*res); ttm_resource_init(bo, place, *res); - ret = nvif_vmm_get(&mem->cli->vmm.vmm, PTES, false, 12, 0, + ret = nvif_vmm_get(&drm->client.vmm.vmm, PTES, false, 12, 0, (long)(*res)->size, &mem->vma[0]); if (ret) { nouveau_mem_del(man, *res); @@ -261,7 +261,7 @@ nouveau_ttm_fini_gtt(struct nouveau_drm *drm) int nouveau_ttm_init(struct nouveau_drm *drm) { - struct nvkm_device *device = nvxx_device(&drm->client.device); + struct nvkm_device *device = nvxx_device(drm); struct nvkm_pci *pci = device->pci; struct nvif_mmu *mmu = &drm->client.mmu; struct drm_device *dev = drm->dev; @@ -348,7 +348,7 @@ nouveau_ttm_init(struct nouveau_drm *drm) void nouveau_ttm_fini(struct nouveau_drm *drm) { - struct nvkm_device *device = nvxx_device(&drm->client.device); + struct nvkm_device *device = nvxx_device(drm); nouveau_ttm_fini_vram(drm); nouveau_ttm_fini_gtt(drm); diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c b/drivers/gpu/drm/nouveau/nouveau_usif.c deleted file mode 100644 index 002d1479ba89..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_usif.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2014 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ - -#include "nouveau_drv.h" -#include "nouveau_usif.h" -#include "nouveau_abi16.h" - -#include <nvif/unpack.h> -#include <nvif/client.h> -#include <nvif/ioctl.h> - -#include <nvif/class.h> -#include <nvif/cl0080.h> - -struct usif_object { - struct list_head head; - u8 route; - u64 token; -}; - -static void -usif_object_dtor(struct usif_object *object) -{ - list_del(&object->head); - kfree(object); -} - -static int -usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc, bool parent_abi16) -{ - struct nouveau_cli *cli = nouveau_cli(f); - struct nvif_client *client = &cli->base; - union { - struct nvif_ioctl_new_v0 v0; - } *args = data; - struct usif_object *object; - int ret = -ENOSYS; - - if ((ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) - return ret; - - switch (args->v0.oclass) { - case NV_DMA_FROM_MEMORY: - case NV_DMA_TO_MEMORY: - case NV_DMA_IN_MEMORY: - return -EINVAL; - case NV_DEVICE: { - union { - struct nv_device_v0 v0; - } *args = data; - - if ((ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) - return ret; - - args->v0.priv = false; - break; - } - default: - if (!parent_abi16) - return -EINVAL; - break; - } - - if (!(object = kmalloc(sizeof(*object), GFP_KERNEL))) - return -ENOMEM; - list_add(&object->head, &cli->objects); - - object->route = args->v0.route; - object->token = args->v0.token; - args->v0.route = NVDRM_OBJECT_USIF; - args->v0.token = (unsigned long)(void *)object; - ret = nvif_client_ioctl(client, argv, argc); - if (ret) { - usif_object_dtor(object); - return ret; - } - - args->v0.token = object->token; - args->v0.route = object->route; - return 0; -} - -int -usif_ioctl(struct drm_file *filp, void __user *user, u32 argc) -{ - struct nouveau_cli *cli = nouveau_cli(filp); - struct nvif_client *client = &cli->base; - void *data = kmalloc(argc, GFP_KERNEL); - u32 size = argc; - union { - struct nvif_ioctl_v0 v0; - } *argv = data; - struct usif_object *object; - bool abi16 = false; - u8 owner; - int ret; - - if (ret = -ENOMEM, !argv) - goto done; - if (ret = -EFAULT, copy_from_user(argv, user, size)) - goto done; - - if (!(ret = nvif_unpack(-ENOSYS, &data, &size, argv->v0, 0, 0, true))) { - /* block access to objects not created via this interface */ - owner = argv->v0.owner; - if (argv->v0.object == 0ULL && - argv->v0.type != NVIF_IOCTL_V0_DEL) - argv->v0.owner = NVDRM_OBJECT_ANY; /* except client */ - else - argv->v0.owner = NVDRM_OBJECT_USIF; - } else - goto done; - - /* USIF slightly abuses some return-only ioctl members in order - * to provide interoperability with the older ABI16 objects - */ - mutex_lock(&cli->mutex); - if (argv->v0.route) { - if (ret = -EINVAL, argv->v0.route == 0xff) - ret = nouveau_abi16_usif(filp, argv, argc); - if (ret) { - mutex_unlock(&cli->mutex); - goto done; - } - - abi16 = true; - } - - switch (argv->v0.type) { - case NVIF_IOCTL_V0_NEW: - ret = usif_object_new(filp, data, size, argv, argc, abi16); - break; - default: - ret = nvif_client_ioctl(client, argv, argc); - break; - } - if (argv->v0.route == NVDRM_OBJECT_USIF) { - object = (void *)(unsigned long)argv->v0.token; - argv->v0.route = object->route; - argv->v0.token = object->token; - if (ret == 0 && argv->v0.type == NVIF_IOCTL_V0_DEL) { - list_del(&object->head); - kfree(object); - } - } else { - argv->v0.route = NVIF_IOCTL_V0_ROUTE_HIDDEN; - argv->v0.token = 0; - } - argv->v0.owner = owner; - mutex_unlock(&cli->mutex); - - if (copy_to_user(user, argv, argc)) - ret = -EFAULT; -done: - kfree(argv); - return ret; -} - -void -usif_client_fini(struct nouveau_cli *cli) -{ - struct usif_object *object, *otemp; - - list_for_each_entry_safe(object, otemp, &cli->objects, head) { - usif_object_dtor(object); - } -} - -void -usif_client_init(struct nouveau_cli *cli) -{ - INIT_LIST_HEAD(&cli->objects); -} diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.h b/drivers/gpu/drm/nouveau/nouveau_usif.h deleted file mode 100644 index dc90d4a9d0d9..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_usif.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NOUVEAU_USIF_H__ -#define __NOUVEAU_USIF_H__ - -void usif_client_init(struct nouveau_cli *); -void usif_client_fini(struct nouveau_cli *); -int usif_ioctl(struct drm_file *, void __user *, u32); -int usif_notify(const void *, u32, const void *, u32); - -#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c index 0a0a11dc9ec0..48f105239f42 100644 --- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c +++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c @@ -812,15 +812,15 @@ op_remap(struct drm_gpuva_op_remap *r, struct drm_gpuva_op_unmap *u = r->unmap; struct nouveau_uvma *uvma = uvma_from_va(u->va); u64 addr = uvma->va.va.addr; - u64 range = uvma->va.va.range; + u64 end = uvma->va.va.addr + uvma->va.va.range; if (r->prev) addr = r->prev->va.addr + r->prev->va.range; if (r->next) - range = r->next->va.addr - addr; + end = r->next->va.addr; - op_unmap_range(u, addr, range); + op_unmap_range(u, addr, end - addr); } static int @@ -1534,7 +1534,7 @@ nouveau_uvmm_bind_job_cleanup(struct nouveau_job *job) nouveau_uvmm_bind_job_put(bind_job); } -static struct nouveau_job_ops nouveau_bind_job_ops = { +static const struct nouveau_job_ops nouveau_bind_job_ops = { .submit = nouveau_uvmm_bind_job_submit, .armed_submit = nouveau_uvmm_bind_job_armed_submit, .run = nouveau_uvmm_bind_job_run, @@ -1803,6 +1803,7 @@ nouveau_uvmm_bo_validate(struct drm_gpuvm_bo *vm_bo, struct drm_exec *exec) { struct nouveau_bo *nvbo = nouveau_gem_object(vm_bo->obj); + nouveau_bo_placement_set(nvbo, nvbo->valid_domains, 0); return nouveau_bo_validate(nvbo, true, false); } diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index f8bf0ec26844..a6c375a24154 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -2,7 +2,7 @@ #include <linux/vgaarb.h> #include <linux/vga_switcheroo.h> -#include <drm/drm_fb_helper.h> +#include <drm/drm_client_event.h> #include "nouveau_drv.h" #include "nouveau_acpi.h" @@ -11,7 +11,7 @@ static unsigned int nouveau_vga_set_decode(struct pci_dev *pdev, bool state) { - struct nouveau_drm *drm = nouveau_drm(pci_get_drvdata(pdev)); + struct nouveau_drm *drm = pci_get_drvdata(pdev); struct nvif_object *device = &drm->client.device.object; if (drm->client.device.info.family == NV_DEVICE_INFO_V0_CURIE && @@ -34,7 +34,8 @@ static void nouveau_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) { - struct drm_device *dev = pci_get_drvdata(pdev); + struct nouveau_drm *drm = pci_get_drvdata(pdev); + struct drm_device *dev = drm->dev; if ((nouveau_is_optimus() || nouveau_is_v1_dsm()) && state == VGA_SWITCHEROO_OFF) return; @@ -56,21 +57,23 @@ nouveau_switcheroo_set_state(struct pci_dev *pdev, static void nouveau_switcheroo_reprobe(struct pci_dev *pdev) { - struct drm_device *dev = pci_get_drvdata(pdev); - drm_fb_helper_output_poll_changed(dev); + struct nouveau_drm *drm = pci_get_drvdata(pdev); + struct drm_device *dev = drm->dev; + + drm_client_dev_hotplug(dev); } static bool nouveau_switcheroo_can_switch(struct pci_dev *pdev) { - struct drm_device *dev = pci_get_drvdata(pdev); + struct nouveau_drm *drm = pci_get_drvdata(pdev); /* * FIXME: open_count is protected by drm_global_mutex but that would lead to * locking inversion with the driver load path. And the access here is * completely racy anyway. So don't bother with locking for now. */ - return atomic_read(&dev->open_count) == 0; + return atomic_read(&drm->dev->open_count) == 0; } static const struct vga_switcheroo_client_ops @@ -125,10 +128,3 @@ nouveau_vga_fini(struct nouveau_drm *drm) if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus()) vga_switcheroo_fini_domain_pm_ops(drm->dev->dev); } - - -void -nouveau_vga_lastclose(struct drm_device *dev) -{ - vga_switcheroo_process_delayed_switch(); -} diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.h b/drivers/gpu/drm/nouveau/nouveau_vga.h index 951a83f984dd..63be415d2a44 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.h +++ b/drivers/gpu/drm/nouveau/nouveau_vga.h @@ -4,6 +4,5 @@ void nouveau_vga_init(struct nouveau_drm *); void nouveau_vga_fini(struct nouveau_drm *); -void nouveau_vga_lastclose(struct drm_device *dev); #endif diff --git a/drivers/gpu/drm/nouveau/nv04_fence.c b/drivers/gpu/drm/nouveau/nv04_fence.c index cdbc75e3d1f6..fa5c6029f783 100644 --- a/drivers/gpu/drm/nouveau/nv04_fence.c +++ b/drivers/gpu/drm/nouveau/nv04_fence.c @@ -39,7 +39,7 @@ struct nv04_fence_priv { static int nv04_fence_emit(struct nouveau_fence *fence) { - struct nvif_push *push = unrcu_pointer(fence->channel)->chan.push; + struct nvif_push *push = &unrcu_pointer(fence->channel)->chan.push; int ret = PUSH_WAIT(push, 2); if (ret == 0) { PUSH_NVSQ(push, NV_SW, 0x0150, fence->base.seqno); diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c index c6a0db5b9e21..8c73f40e3bda 100644 --- a/drivers/gpu/drm/nouveau/nv10_fence.c +++ b/drivers/gpu/drm/nouveau/nv10_fence.c @@ -32,7 +32,7 @@ int nv10_fence_emit(struct nouveau_fence *fence) { - struct nvif_push *push = fence->channel->chan.push; + struct nvif_push *push = &fence->channel->chan.push; int ret = PUSH_WAIT(push, 2); if (ret == 0) { PUSH_MTHD(push, NV06E, SET_REFERENCE, fence->base.seqno); @@ -88,7 +88,7 @@ nv10_fence_destroy(struct nouveau_drm *drm) nouveau_bo_unmap(priv->bo); if (priv->bo) nouveau_bo_unpin(priv->bo); - nouveau_bo_ref(NULL, &priv->bo); + nouveau_bo_fini(priv->bo); drm->fence = NULL; kfree(priv); } diff --git a/drivers/gpu/drm/nouveau/nv17_fence.c b/drivers/gpu/drm/nouveau/nv17_fence.c index 07c2e0878c24..d09bfd11369f 100644 --- a/drivers/gpu/drm/nouveau/nv17_fence.c +++ b/drivers/gpu/drm/nouveau/nv17_fence.c @@ -36,11 +36,11 @@ int nv17_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *prev, struct nouveau_channel *chan) { - struct nouveau_cli *cli = (void *)prev->user.client; - struct nv10_fence_priv *priv = chan->drm->fence; + struct nouveau_cli *cli = prev->cli; + struct nv10_fence_priv *priv = cli->drm->fence; struct nv10_fence_chan *fctx = chan->fence; - struct nvif_push *ppush = prev->chan.push; - struct nvif_push *npush = chan->chan.push; + struct nvif_push *ppush = &prev->chan.push; + struct nvif_push *npush = &chan->chan.push; u32 value; int ret; @@ -76,7 +76,7 @@ nv17_fence_sync(struct nouveau_fence *fence, static int nv17_fence_context_new(struct nouveau_channel *chan) { - struct nv10_fence_priv *priv = chan->drm->fence; + struct nv10_fence_priv *priv = chan->cli->drm->fence; struct ttm_resource *reg = priv->bo->bo.resource; struct nv10_fence_chan *fctx; u32 start = reg->start * PAGE_SIZE; @@ -141,7 +141,7 @@ nv17_fence_create(struct nouveau_drm *drm) nouveau_bo_unpin(priv->bo); } if (ret) - nouveau_bo_ref(NULL, &priv->bo); + nouveau_bo_fini(priv->bo); } if (ret) { diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c index ea1e1f480bfe..62e28dddf87c 100644 --- a/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/drivers/gpu/drm/nouveau/nv50_fence.c @@ -35,7 +35,7 @@ static int nv50_fence_context_new(struct nouveau_channel *chan) { - struct nv10_fence_priv *priv = chan->drm->fence; + struct nv10_fence_priv *priv = chan->cli->drm->fence; struct nv10_fence_chan *fctx; struct ttm_resource *reg = priv->bo->bo.resource; u32 start = reg->start * PAGE_SIZE; @@ -92,7 +92,7 @@ nv50_fence_create(struct nouveau_drm *drm) nouveau_bo_unpin(priv->bo); } if (ret) - nouveau_bo_ref(NULL, &priv->bo); + nouveau_bo_fini(priv->bo); } if (ret) { diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index 812b8c62eeba..aa7dd0c5d917 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -35,7 +35,7 @@ static int nv84_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence) { - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; int ret = PUSH_WAIT(push, 8); if (ret == 0) { PUSH_MTHD(push, NV826F, SET_CONTEXT_DMA_SEMAPHORE, chan->vram.handle); @@ -58,7 +58,7 @@ nv84_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence) static int nv84_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence) { - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; int ret = PUSH_WAIT(push, 7); if (ret == 0) { PUSH_MTHD(push, NV826F, SET_CONTEXT_DMA_SEMAPHORE, chan->vram.handle); @@ -79,7 +79,7 @@ nv84_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence) static inline u32 nv84_fence_chid(struct nouveau_channel *chan) { - return chan->drm->runl[chan->runlist].chan_id_base + chan->chid; + return chan->cli->drm->runl[chan->runlist].chan_id_base + chan->chid; } static int @@ -105,14 +105,14 @@ nv84_fence_sync(struct nouveau_fence *fence, static u32 nv84_fence_read(struct nouveau_channel *chan) { - struct nv84_fence_priv *priv = chan->drm->fence; + struct nv84_fence_priv *priv = chan->cli->drm->fence; return nouveau_bo_rd32(priv->bo, nv84_fence_chid(chan) * 16/4); } static void nv84_fence_context_del(struct nouveau_channel *chan) { - struct nv84_fence_priv *priv = chan->drm->fence; + struct nv84_fence_priv *priv = chan->cli->drm->fence; struct nv84_fence_chan *fctx = chan->fence; nouveau_bo_wr32(priv->bo, nv84_fence_chid(chan) * 16 / 4, fctx->base.sequence); @@ -127,7 +127,7 @@ nv84_fence_context_del(struct nouveau_channel *chan) int nv84_fence_context_new(struct nouveau_channel *chan) { - struct nv84_fence_priv *priv = chan->drm->fence; + struct nv84_fence_priv *priv = chan->cli->drm->fence; struct nv84_fence_chan *fctx; int ret; @@ -188,7 +188,7 @@ nv84_fence_destroy(struct nouveau_drm *drm) nouveau_bo_unmap(priv->bo); if (priv->bo) nouveau_bo_unpin(priv->bo); - nouveau_bo_ref(NULL, &priv->bo); + nouveau_bo_fini(priv->bo); drm->fence = NULL; kfree(priv); } @@ -232,7 +232,7 @@ nv84_fence_create(struct nouveau_drm *drm) nouveau_bo_unpin(priv->bo); } if (ret) - nouveau_bo_ref(NULL, &priv->bo); + nouveau_bo_fini(priv->bo); } if (ret) diff --git a/drivers/gpu/drm/nouveau/nvc0_fence.c b/drivers/gpu/drm/nouveau/nvc0_fence.c index e1461c0b0779..a5e98d0d4217 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fence.c +++ b/drivers/gpu/drm/nouveau/nvc0_fence.c @@ -34,7 +34,7 @@ static int nvc0_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence) { - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; int ret = PUSH_WAIT(push, 6); if (ret == 0) { PUSH_MTHD(push, NV906F, SEMAPHOREA, @@ -57,7 +57,7 @@ nvc0_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence) static int nvc0_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence) { - struct nvif_push *push = chan->chan.push; + struct nvif_push *push = &chan->chan.push; int ret = PUSH_WAIT(push, 5); if (ret == 0) { PUSH_MTHD(push, NV906F, SEMAPHOREA, diff --git a/drivers/gpu/drm/nouveau/nvif/client.c b/drivers/gpu/drm/nouveau/nvif/client.c index 3a27245f467f..fdf5054ed7d8 100644 --- a/drivers/gpu/drm/nouveau/nvif/client.c +++ b/drivers/gpu/drm/nouveau/nvif/client.c @@ -30,12 +30,6 @@ #include <nvif/if0000.h> int -nvif_client_ioctl(struct nvif_client *client, void *data, u32 size) -{ - return client->driver->ioctl(client->object.priv, data, size, NULL); -} - -int nvif_client_suspend(struct nvif_client *client) { return client->driver->suspend(client->object.priv); @@ -51,22 +45,13 @@ void nvif_client_dtor(struct nvif_client *client) { nvif_object_dtor(&client->object); - if (client->driver) { - if (client->driver->fini) - client->driver->fini(client->object.priv); - client->driver = NULL; - } + client->driver = NULL; } int -nvif_client_ctor(struct nvif_client *parent, const char *name, u64 device, - struct nvif_client *client) +nvif_client_ctor(struct nvif_client *parent, const char *name, struct nvif_client *client) { - struct nvif_client_v0 args = { .device = device }; - struct { - struct nvif_ioctl_v0 ioctl; - struct nvif_ioctl_nop_v0 nop; - } nop = {}; + struct nvif_client_v0 args = {}; int ret; strscpy_pad(args.name, name, sizeof(args.name)); @@ -79,15 +64,6 @@ nvif_client_ctor(struct nvif_client *parent, const char *name, u64 device, client->object.client = client; client->object.handle = ~0; - client->route = NVIF_IOCTL_V0_ROUTE_NVIF; client->driver = parent->driver; - - if (ret == 0) { - ret = nvif_client_ioctl(client, &nop, sizeof(nop)); - client->version = nop.nop.version; - } - - if (ret) - nvif_client_dtor(client); - return ret; + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvif/device.c b/drivers/gpu/drm/nouveau/nvif/device.c index 8c3d883f3313..24880931039f 100644 --- a/drivers/gpu/drm/nouveau/nvif/device.c +++ b/drivers/gpu/drm/nouveau/nvif/device.c @@ -21,8 +21,8 @@ * * Authors: Ben Skeggs <bskeggs@redhat.com> */ - #include <nvif/device.h> +#include <nvif/client.h> u64 nvif_device_time(struct nvif_device *device) @@ -38,6 +38,12 @@ nvif_device_time(struct nvif_device *device) return device->user.func->time(&device->user); } +int +nvif_device_map(struct nvif_device *device) +{ + return nvif_object_map(&device->object, NULL, 0); +} + void nvif_device_dtor(struct nvif_device *device) { @@ -48,11 +54,10 @@ nvif_device_dtor(struct nvif_device *device) } int -nvif_device_ctor(struct nvif_object *parent, const char *name, u32 handle, - s32 oclass, void *data, u32 size, struct nvif_device *device) +nvif_device_ctor(struct nvif_client *client, const char *name, struct nvif_device *device) { - int ret = nvif_object_ctor(parent, name ? name : "nvifDevice", handle, - oclass, data, size, &device->object); + int ret = nvif_object_ctor(&client->object, name ? name : "nvifDevice", 0, + 0x0080, NULL, 0, &device->object); device->runlist = NULL; device->user.func = NULL; if (ret == 0) { diff --git a/drivers/gpu/drm/nouveau/nvif/driver.c b/drivers/gpu/drm/nouveau/nvif/driver.c index 5e00dd07afed..78706e97a6a2 100644 --- a/drivers/gpu/drm/nouveau/nvif/driver.c +++ b/drivers/gpu/drm/nouveau/nvif/driver.c @@ -24,35 +24,17 @@ #include <nvif/driver.h> #include <nvif/client.h> -static const struct nvif_driver * -nvif_driver[] = { -#ifdef __KERNEL__ - &nvif_driver_nvkm, -#else - &nvif_driver_drm, - &nvif_driver_lib, - &nvif_driver_null, -#endif - NULL -}; - int nvif_driver_init(const char *drv, const char *cfg, const char *dbg, const char *name, u64 device, struct nvif_client *client) { - int ret = -EINVAL, i; + int ret; + + client->driver = &nvif_driver_nvkm; - for (i = 0; (client->driver = nvif_driver[i]); i++) { - if (!drv || !strcmp(client->driver->name, drv)) { - ret = client->driver->init(name, device, cfg, dbg, - &client->object.priv); - if (ret == 0) - break; - client->driver->fini(client->object.priv); - } - } + ret = client->driver->init(name, device, cfg, dbg, &client->object.priv); + if (ret) + return ret; - if (ret == 0) - ret = nvif_client_ctor(client, name, device, client); - return ret; + return nvif_client_ctor(client, name, client); } diff --git a/drivers/gpu/drm/nouveau/nvif/object.c b/drivers/gpu/drm/nouveau/nvif/object.c index 4d1aaee8fe15..0b87278ac0f8 100644 --- a/drivers/gpu/drm/nouveau/nvif/object.c +++ b/drivers/gpu/drm/nouveau/nvif/object.c @@ -40,7 +40,6 @@ nvif_object_ioctl(struct nvif_object *object, void *data, u32 size, void **hack) args->v0.object = nvif_handle(object); else args->v0.object = 0; - args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY; } else return -ENOSYS; @@ -98,43 +97,6 @@ nvif_object_sclass_get(struct nvif_object *object, struct nvif_sclass **psclass) return ret; } -u32 -nvif_object_rd(struct nvif_object *object, int size, u64 addr) -{ - struct { - struct nvif_ioctl_v0 ioctl; - struct nvif_ioctl_rd_v0 rd; - } args = { - .ioctl.type = NVIF_IOCTL_V0_RD, - .rd.size = size, - .rd.addr = addr, - }; - int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL); - if (ret) { - /*XXX: warn? */ - return 0; - } - return args.rd.data; -} - -void -nvif_object_wr(struct nvif_object *object, int size, u64 addr, u32 data) -{ - struct { - struct nvif_ioctl_v0 ioctl; - struct nvif_ioctl_wr_v0 wr; - } args = { - .ioctl.type = NVIF_IOCTL_V0_WR, - .wr.size = size, - .wr.addr = addr, - .wr.data = data, - }; - int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL); - if (ret) { - /*XXX: warn? */ - } -} - int nvif_object_mthd(struct nvif_object *object, u32 mthd, void *data, u32 size) { @@ -142,11 +104,16 @@ nvif_object_mthd(struct nvif_object *object, u32 mthd, void *data, u32 size) struct nvif_ioctl_v0 ioctl; struct nvif_ioctl_mthd_v0 mthd; } *args; + u32 args_size; u8 stack[128]; int ret; - if (sizeof(*args) + size > sizeof(stack)) { - if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL))) + if (check_add_overflow(sizeof(*args), size, &args_size)) + return -ENOMEM; + + if (args_size > sizeof(stack)) { + args = kmalloc(args_size, GFP_KERNEL); + if (!args) return -ENOMEM; } else { args = (void *)stack; @@ -157,7 +124,7 @@ nvif_object_mthd(struct nvif_object *object, u32 mthd, void *data, u32 size) args->mthd.method = mthd; memcpy(args->mthd.data, data, size); - ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL); + ret = nvif_object_ioctl(object, args, args_size, NULL); memcpy(data, args->mthd.data, size); if (args != (void *)stack) kfree(args); @@ -276,7 +243,15 @@ nvif_object_ctor(struct nvif_object *parent, const char *name, u32 handle, object->map.size = 0; if (parent) { - if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL))) { + u32 args_size; + + if (check_add_overflow(sizeof(*args), size, &args_size)) { + nvif_object_dtor(object); + return -ENOMEM; + } + + args = kmalloc(args_size, GFP_KERNEL); + if (!args) { nvif_object_dtor(object); return -ENOMEM; } @@ -286,15 +261,12 @@ nvif_object_ctor(struct nvif_object *parent, const char *name, u32 handle, args->ioctl.version = 0; args->ioctl.type = NVIF_IOCTL_V0_NEW; args->new.version = 0; - args->new.route = parent->client->route; - args->new.token = nvif_handle(object); args->new.object = nvif_handle(object); args->new.handle = handle; args->new.oclass = oclass; memcpy(args->new.data, data, size); - ret = nvif_object_ioctl(parent, args, sizeof(*args) + size, - &object->priv); + ret = nvif_object_ioctl(parent, args, args_size, &object->priv); memcpy(data, args->new.data, size); kfree(args); if (ret == 0) diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c index 5d3190c05250..6daeb7f0b09b 100644 --- a/drivers/gpu/drm/nouveau/nvif/outp.c +++ b/drivers/gpu/drm/nouveau/nvif/outp.c @@ -452,13 +452,12 @@ nvif_outp_edid_get(struct nvif_outp *outp, u8 **pedid) if (ret) goto done; - *pedid = kmalloc(args->size, GFP_KERNEL); + *pedid = kmemdup(args->data, args->size, GFP_KERNEL); if (!*pedid) { ret = -ENOMEM; goto done; } - memcpy(*pedid, args->data, args->size); ret = args->size; done: kfree(args); diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c index c55662937ab2..72c88db627a5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/client.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c @@ -42,7 +42,7 @@ nvkm_uclient_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))){ args->v0.name[sizeof(args->v0.name) - 1] = 0; - ret = nvkm_client_new(args->v0.name, args->v0.device, NULL, + ret = nvkm_client_new(args->v0.name, oclass->client->device, NULL, NULL, oclass->client->event, &client); if (ret) return ret; @@ -51,8 +51,6 @@ nvkm_uclient_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, client->object.client = oclass->client; client->object.handle = oclass->handle; - client->object.route = oclass->route; - client->object.token = oclass->token; client->object.object = oclass->object; client->debug = oclass->client->debug; *pobject = &client->object; @@ -67,58 +65,6 @@ nvkm_uclient_sclass = { .ctor = nvkm_uclient_new, }; -static const struct nvkm_object_func nvkm_client; -struct nvkm_client * -nvkm_client_search(struct nvkm_client *client, u64 handle) -{ - struct nvkm_object *object; - - object = nvkm_object_search(client, handle, &nvkm_client); - if (IS_ERR(object)) - return (void *)object; - - return nvkm_client(object); -} - -static int -nvkm_client_mthd_devlist(struct nvkm_client *client, void *data, u32 size) -{ - union { - struct nvif_client_devlist_v0 v0; - } *args = data; - int ret = -ENOSYS; - - nvif_ioctl(&client->object, "client devlist size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { - nvif_ioctl(&client->object, "client devlist vers %d count %d\n", - args->v0.version, args->v0.count); - if (size == sizeof(args->v0.device[0]) * args->v0.count) { - ret = nvkm_device_list(args->v0.device, args->v0.count); - if (ret >= 0) { - args->v0.count = ret; - ret = 0; - } - } else { - ret = -EINVAL; - } - } - - return ret; -} - -static int -nvkm_client_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) -{ - struct nvkm_client *client = nvkm_client(object); - switch (mthd) { - case NVIF_CLIENT_V0_DEVLIST: - return nvkm_client_mthd_devlist(client, data, size); - default: - break; - } - return -EINVAL; -} - static int nvkm_client_child_new(const struct nvkm_oclass *oclass, void *data, u32 size, struct nvkm_object **pobject) @@ -144,12 +90,6 @@ nvkm_client_child_get(struct nvkm_object *object, int index, return 0; } -static int -nvkm_client_fini(struct nvkm_object *object, bool suspend) -{ - return 0; -} - static void * nvkm_client_dtor(struct nvkm_object *object) { @@ -159,8 +99,6 @@ nvkm_client_dtor(struct nvkm_object *object) static const struct nvkm_object_func nvkm_client = { .dtor = nvkm_client_dtor, - .fini = nvkm_client_fini, - .mthd = nvkm_client_mthd, .sclass = nvkm_client_child_get, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c index adc60b25f8e6..0af01a0ec601 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c @@ -205,7 +205,8 @@ nvkm_firmware_dtor(struct nvkm_firmware *fw) break; case NVKM_FIRMWARE_IMG_DMA: nvkm_memory_unref(&memory); - dma_free_coherent(fw->device->dev, sg_dma_len(&fw->mem.sgl), fw->img, fw->phys); + dma_free_noncoherent(fw->device->dev, sg_dma_len(&fw->mem.sgl), + fw->img, fw->phys, DMA_TO_DEVICE); break; case NVKM_FIRMWARE_IMG_SGT: nvkm_memory_unref(&memory); @@ -236,10 +237,12 @@ nvkm_firmware_ctor(const struct nvkm_firmware_func *func, const char *name, break; case NVKM_FIRMWARE_IMG_DMA: { dma_addr_t addr; - len = ALIGN(fw->len, PAGE_SIZE); - fw->img = dma_alloc_coherent(fw->device->dev, len, &addr, GFP_KERNEL); + fw->img = dma_alloc_noncoherent(fw->device->dev, + len, &addr, + DMA_TO_DEVICE, + GFP_KERNEL); if (fw->img) { memcpy(fw->img, src, fw->len); fw->phys = addr; diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c index 0b33287e43a7..45051a1249da 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c @@ -33,18 +33,7 @@ static int nvkm_ioctl_nop(struct nvkm_client *client, struct nvkm_object *object, void *data, u32 size) { - union { - struct nvif_ioctl_nop_v0 v0; - } *args = data; - int ret = -ENOSYS; - - nvif_ioctl(object, "nop size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "nop vers %lld\n", args->v0.version); - args->v0.version = NVIF_VERSION_LATEST; - } - - return ret; + return -ENOSYS; } #include <nvif/class.h> @@ -112,10 +101,9 @@ nvkm_ioctl_new(struct nvkm_client *client, nvif_ioctl(parent, "new size %d\n", size); if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { - nvif_ioctl(parent, "new vers %d handle %08x class %08x " - "route %02x token %llx object %016llx\n", + nvif_ioctl(parent, "new vers %d handle %08x class %08x object %016llx\n", args->v0.version, args->v0.handle, args->v0.oclass, - args->v0.route, args->v0.token, args->v0.object); + args->v0.object); } else return ret; @@ -127,8 +115,6 @@ nvkm_ioctl_new(struct nvkm_client *client, do { memset(&oclass, 0x00, sizeof(oclass)); oclass.handle = args->v0.handle; - oclass.route = args->v0.route; - oclass.token = args->v0.token; oclass.object = args->v0.object; oclass.client = client; oclass.parent = parent; @@ -205,69 +191,14 @@ static int nvkm_ioctl_rd(struct nvkm_client *client, struct nvkm_object *object, void *data, u32 size) { - union { - struct nvif_ioctl_rd_v0 v0; - } *args = data; - union { - u8 b08; - u16 b16; - u32 b32; - } v; - int ret = -ENOSYS; - - nvif_ioctl(object, "rd size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "rd vers %d size %d addr %016llx\n", - args->v0.version, args->v0.size, args->v0.addr); - switch (args->v0.size) { - case 1: - ret = nvkm_object_rd08(object, args->v0.addr, &v.b08); - args->v0.data = v.b08; - break; - case 2: - ret = nvkm_object_rd16(object, args->v0.addr, &v.b16); - args->v0.data = v.b16; - break; - case 4: - ret = nvkm_object_rd32(object, args->v0.addr, &v.b32); - args->v0.data = v.b32; - break; - default: - ret = -EINVAL; - break; - } - } - - return ret; + return -ENOSYS; } static int nvkm_ioctl_wr(struct nvkm_client *client, struct nvkm_object *object, void *data, u32 size) { - union { - struct nvif_ioctl_wr_v0 v0; - } *args = data; - int ret = -ENOSYS; - - nvif_ioctl(object, "wr size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, - "wr vers %d size %d addr %016llx data %08x\n", - args->v0.version, args->v0.size, args->v0.addr, - args->v0.data); - } else - return ret; - - switch (args->v0.size) { - case 1: return nvkm_object_wr08(object, args->v0.addr, args->v0.data); - case 2: return nvkm_object_wr16(object, args->v0.addr, args->v0.data); - case 4: return nvkm_object_wr32(object, args->v0.addr, args->v0.data); - default: - break; - } - - return -EINVAL; + return -ENOSYS; } static int @@ -331,7 +262,7 @@ nvkm_ioctl_v0[] = { static int nvkm_ioctl_path(struct nvkm_client *client, u64 handle, u32 type, - void *data, u32 size, u8 owner, u8 *route, u64 *token) + void *data, u32 size) { struct nvkm_object *object; int ret; @@ -342,13 +273,6 @@ nvkm_ioctl_path(struct nvkm_client *client, u64 handle, u32 type, return PTR_ERR(object); } - if (owner != NVIF_IOCTL_V0_OWNER_ANY && owner != object->route) { - nvif_ioctl(&client->object, "route != owner\n"); - return -EACCES; - } - *route = object->route; - *token = object->token; - if (ret = -EINVAL, type < ARRAY_SIZE(nvkm_ioctl_v0)) { if (nvkm_ioctl_v0[type].version == 0) ret = nvkm_ioctl_v0[type].func(client, object, data, size); @@ -374,8 +298,7 @@ nvkm_ioctl(struct nvkm_client *client, void *data, u32 size, void **hack) args->v0.version, args->v0.type, args->v0.object, args->v0.owner); ret = nvkm_ioctl_path(client, args->v0.object, args->v0.type, - data, size, args->v0.owner, - &args->v0.route, &args->v0.token); + data, size); } if (ret != 1) { diff --git a/drivers/gpu/drm/nouveau/nvkm/core/object.c b/drivers/gpu/drm/nouveau/nvkm/core/object.c index aea3ba72027a..390c265cf8af 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/object.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/object.c @@ -133,54 +133,6 @@ nvkm_object_unmap(struct nvkm_object *object) } int -nvkm_object_rd08(struct nvkm_object *object, u64 addr, u8 *data) -{ - if (likely(object->func->rd08)) - return object->func->rd08(object, addr, data); - return -ENODEV; -} - -int -nvkm_object_rd16(struct nvkm_object *object, u64 addr, u16 *data) -{ - if (likely(object->func->rd16)) - return object->func->rd16(object, addr, data); - return -ENODEV; -} - -int -nvkm_object_rd32(struct nvkm_object *object, u64 addr, u32 *data) -{ - if (likely(object->func->rd32)) - return object->func->rd32(object, addr, data); - return -ENODEV; -} - -int -nvkm_object_wr08(struct nvkm_object *object, u64 addr, u8 data) -{ - if (likely(object->func->wr08)) - return object->func->wr08(object, addr, data); - return -ENODEV; -} - -int -nvkm_object_wr16(struct nvkm_object *object, u64 addr, u16 data) -{ - if (likely(object->func->wr16)) - return object->func->wr16(object, addr, data); - return -ENODEV; -} - -int -nvkm_object_wr32(struct nvkm_object *object, u64 addr, u32 data) -{ - if (likely(object->func->wr32)) - return object->func->wr32(object, addr, data); - return -ENODEV; -} - -int nvkm_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *gpuobj, int align, struct nvkm_gpuobj **pgpuobj) { @@ -313,8 +265,6 @@ nvkm_object_ctor(const struct nvkm_object_func *func, object->engine = nvkm_engine_ref(oclass->engine); object->oclass = oclass->base.oclass; object->handle = oclass->handle; - object->route = oclass->route; - object->token = oclass->token; object->object = oclass->object; INIT_LIST_HEAD(&object->head); INIT_LIST_HEAD(&object->tree); diff --git a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c index 3385528da650..5db80d1780f0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c @@ -56,42 +56,6 @@ nvkm_oproxy_unmap(struct nvkm_object *object) } static int -nvkm_oproxy_rd08(struct nvkm_object *object, u64 addr, u8 *data) -{ - return nvkm_object_rd08(nvkm_oproxy(object)->object, addr, data); -} - -static int -nvkm_oproxy_rd16(struct nvkm_object *object, u64 addr, u16 *data) -{ - return nvkm_object_rd16(nvkm_oproxy(object)->object, addr, data); -} - -static int -nvkm_oproxy_rd32(struct nvkm_object *object, u64 addr, u32 *data) -{ - return nvkm_object_rd32(nvkm_oproxy(object)->object, addr, data); -} - -static int -nvkm_oproxy_wr08(struct nvkm_object *object, u64 addr, u8 data) -{ - return nvkm_object_wr08(nvkm_oproxy(object)->object, addr, data); -} - -static int -nvkm_oproxy_wr16(struct nvkm_object *object, u64 addr, u16 data) -{ - return nvkm_object_wr16(nvkm_oproxy(object)->object, addr, data); -} - -static int -nvkm_oproxy_wr32(struct nvkm_object *object, u64 addr, u32 data) -{ - return nvkm_object_wr32(nvkm_oproxy(object)->object, addr, data); -} - -static int nvkm_oproxy_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, int align, struct nvkm_gpuobj **pgpuobj) { @@ -197,12 +161,6 @@ nvkm_oproxy_func = { .ntfy = nvkm_oproxy_ntfy, .map = nvkm_oproxy_map, .unmap = nvkm_oproxy_unmap, - .rd08 = nvkm_oproxy_rd08, - .rd16 = nvkm_oproxy_rd16, - .rd32 = nvkm_oproxy_rd32, - .wr08 = nvkm_oproxy_wr08, - .wr16 = nvkm_oproxy_wr16, - .wr32 = nvkm_oproxy_wr32, .bind = nvkm_oproxy_bind, .sclass = nvkm_oproxy_sclass, .uevent = nvkm_oproxy_uevent, diff --git a/drivers/gpu/drm/nouveau/nvkm/core/uevent.c b/drivers/gpu/drm/nouveau/nvkm/core/uevent.c index ba9d9edaec75..cc254c390a57 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/uevent.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/uevent.c @@ -116,9 +116,9 @@ nvkm_uevent_ntfy(struct nvkm_event_ntfy *ntfy, u32 bits) struct nvkm_client *client = uevent->object.client; if (uevent->func) - return uevent->func(uevent->parent, uevent->object.token, bits); + return uevent->func(uevent->parent, uevent->object.object, bits); - return client->event(uevent->object.token, NULL, 0); + return client->event(uevent->object.object, NULL, 0); } int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/Kbuild index bfaaff645a34..2e48b0816670 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/Kbuild @@ -19,7 +19,6 @@ include $(src)/nvkm/engine/nvenc/Kbuild include $(src)/nvkm/engine/nvdec/Kbuild include $(src)/nvkm/engine/nvjpg/Kbuild include $(src)/nvkm/engine/ofa/Kbuild -include $(src)/nvkm/engine/pm/Kbuild include $(src)/nvkm/engine/sec/Kbuild include $(src)/nvkm/engine/sec2/Kbuild include $(src)/nvkm/engine/sw/Kbuild diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 31ed3da32fe7..9093d89b16f3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -53,26 +53,6 @@ nvkm_device_find(u64 handle) return device; } -int -nvkm_device_list(u64 *name, int size) -{ - struct nvkm_device *device; - int nr = 0; - mutex_lock(&nv_devices_mutex); - list_for_each_entry(device, &nv_devices, head) { - if (nr++ < size) - name[nr - 1] = device->handle; - } - mutex_unlock(&nv_devices_mutex); - return nr; -} - -static const struct nvkm_device_chip -null_chipset = { - .name = "NULL", - .bios = { 0x00000001, nvkm_bios_new }, -}; - static const struct nvkm_device_chip nv4_chipset = { .name = "NV04", @@ -490,7 +470,6 @@ nv40_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv40_gr_new }, .mpeg = { 0x00000001, nv40_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -516,7 +495,6 @@ nv41_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv40_gr_new }, .mpeg = { 0x00000001, nv40_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -542,7 +520,6 @@ nv42_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv40_gr_new }, .mpeg = { 0x00000001, nv40_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -568,7 +545,6 @@ nv43_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv40_gr_new }, .mpeg = { 0x00000001, nv40_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -594,7 +570,6 @@ nv44_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv44_gr_new }, .mpeg = { 0x00000001, nv44_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -620,7 +595,6 @@ nv45_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv40_gr_new }, .mpeg = { 0x00000001, nv44_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -646,7 +620,6 @@ nv46_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv44_gr_new }, .mpeg = { 0x00000001, nv44_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -672,7 +645,6 @@ nv47_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv40_gr_new }, .mpeg = { 0x00000001, nv44_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -698,7 +670,6 @@ nv49_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv40_gr_new }, .mpeg = { 0x00000001, nv44_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -724,7 +695,6 @@ nv4a_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv44_gr_new }, .mpeg = { 0x00000001, nv44_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -750,7 +720,6 @@ nv4b_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv40_gr_new }, .mpeg = { 0x00000001, nv44_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -776,7 +745,6 @@ nv4c_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv44_gr_new }, .mpeg = { 0x00000001, nv44_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -802,7 +770,6 @@ nv4e_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv44_gr_new }, .mpeg = { 0x00000001, nv44_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -831,7 +798,6 @@ nv50_chipset = { .fifo = { 0x00000001, nv50_fifo_new }, .gr = { 0x00000001, nv50_gr_new }, .mpeg = { 0x00000001, nv50_mpeg_new }, - .pm = { 0x00000001, nv50_pm_new }, .sw = { 0x00000001, nv50_sw_new }, }; @@ -857,7 +823,6 @@ nv63_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv44_gr_new }, .mpeg = { 0x00000001, nv44_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -883,7 +848,6 @@ nv67_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv44_gr_new }, .mpeg = { 0x00000001, nv44_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -909,7 +873,6 @@ nv68_chipset = { .fifo = { 0x00000001, nv40_fifo_new }, .gr = { 0x00000001, nv44_gr_new }, .mpeg = { 0x00000001, nv44_mpeg_new }, - .pm = { 0x00000001, nv40_pm_new }, .sw = { 0x00000001, nv10_sw_new }, }; @@ -940,7 +903,6 @@ nv84_chipset = { .fifo = { 0x00000001, g84_fifo_new }, .gr = { 0x00000001, g84_gr_new }, .mpeg = { 0x00000001, g84_mpeg_new }, - .pm = { 0x00000001, g84_pm_new }, .sw = { 0x00000001, nv50_sw_new }, .vp = { 0x00000001, g84_vp_new }, }; @@ -972,7 +934,6 @@ nv86_chipset = { .fifo = { 0x00000001, g84_fifo_new }, .gr = { 0x00000001, g84_gr_new }, .mpeg = { 0x00000001, g84_mpeg_new }, - .pm = { 0x00000001, g84_pm_new }, .sw = { 0x00000001, nv50_sw_new }, .vp = { 0x00000001, g84_vp_new }, }; @@ -1004,7 +965,6 @@ nv92_chipset = { .fifo = { 0x00000001, g84_fifo_new }, .gr = { 0x00000001, g84_gr_new }, .mpeg = { 0x00000001, g84_mpeg_new }, - .pm = { 0x00000001, g84_pm_new }, .sw = { 0x00000001, nv50_sw_new }, .vp = { 0x00000001, g84_vp_new }, }; @@ -1036,7 +996,6 @@ nv94_chipset = { .fifo = { 0x00000001, g84_fifo_new }, .gr = { 0x00000001, g84_gr_new }, .mpeg = { 0x00000001, g84_mpeg_new }, - .pm = { 0x00000001, g84_pm_new }, .sw = { 0x00000001, nv50_sw_new }, .vp = { 0x00000001, g84_vp_new }, }; @@ -1068,7 +1027,6 @@ nv96_chipset = { .fifo = { 0x00000001, g84_fifo_new }, .gr = { 0x00000001, g84_gr_new }, .mpeg = { 0x00000001, g84_mpeg_new }, - .pm = { 0x00000001, g84_pm_new }, .sw = { 0x00000001, nv50_sw_new }, .vp = { 0x00000001, g84_vp_new }, }; @@ -1100,7 +1058,6 @@ nv98_chipset = { .mspdec = { 0x00000001, g98_mspdec_new }, .msppp = { 0x00000001, g98_msppp_new }, .msvld = { 0x00000001, g98_msvld_new }, - .pm = { 0x00000001, g84_pm_new }, .sec = { 0x00000001, g98_sec_new }, .sw = { 0x00000001, nv50_sw_new }, }; @@ -1132,7 +1089,6 @@ nva0_chipset = { .fifo = { 0x00000001, g84_fifo_new }, .gr = { 0x00000001, gt200_gr_new }, .mpeg = { 0x00000001, g84_mpeg_new }, - .pm = { 0x00000001, gt200_pm_new }, .sw = { 0x00000001, nv50_sw_new }, .vp = { 0x00000001, g84_vp_new }, }; @@ -1167,7 +1123,6 @@ nva3_chipset = { .mspdec = { 0x00000001, gt215_mspdec_new }, .msppp = { 0x00000001, gt215_msppp_new }, .msvld = { 0x00000001, gt215_msvld_new }, - .pm = { 0x00000001, gt215_pm_new }, .sw = { 0x00000001, nv50_sw_new }, }; @@ -1200,7 +1155,6 @@ nva5_chipset = { .mspdec = { 0x00000001, gt215_mspdec_new }, .msppp = { 0x00000001, gt215_msppp_new }, .msvld = { 0x00000001, gt215_msvld_new }, - .pm = { 0x00000001, gt215_pm_new }, .sw = { 0x00000001, nv50_sw_new }, }; @@ -1233,7 +1187,6 @@ nva8_chipset = { .mspdec = { 0x00000001, gt215_mspdec_new }, .msppp = { 0x00000001, gt215_msppp_new }, .msvld = { 0x00000001, gt215_msvld_new }, - .pm = { 0x00000001, gt215_pm_new }, .sw = { 0x00000001, nv50_sw_new }, }; @@ -1264,7 +1217,6 @@ nvaa_chipset = { .mspdec = { 0x00000001, g98_mspdec_new }, .msppp = { 0x00000001, g98_msppp_new }, .msvld = { 0x00000001, g98_msvld_new }, - .pm = { 0x00000001, g84_pm_new }, .sec = { 0x00000001, g98_sec_new }, .sw = { 0x00000001, nv50_sw_new }, }; @@ -1296,7 +1248,6 @@ nvac_chipset = { .mspdec = { 0x00000001, g98_mspdec_new }, .msppp = { 0x00000001, g98_msppp_new }, .msvld = { 0x00000001, g98_msvld_new }, - .pm = { 0x00000001, g84_pm_new }, .sec = { 0x00000001, g98_sec_new }, .sw = { 0x00000001, nv50_sw_new }, }; @@ -1330,7 +1281,6 @@ nvaf_chipset = { .mspdec = { 0x00000001, gt215_mspdec_new }, .msppp = { 0x00000001, gt215_msppp_new }, .msvld = { 0x00000001, mcp89_msvld_new }, - .pm = { 0x00000001, gt215_pm_new }, .sw = { 0x00000001, nv50_sw_new }, }; @@ -1366,7 +1316,6 @@ nvc0_chipset = { .mspdec = { 0x00000001, gf100_mspdec_new }, .msppp = { 0x00000001, gf100_msppp_new }, .msvld = { 0x00000001, gf100_msvld_new }, - .pm = { 0x00000001, gf100_pm_new }, .sw = { 0x00000001, gf100_sw_new }, }; @@ -1402,7 +1351,6 @@ nvc1_chipset = { .mspdec = { 0x00000001, gf100_mspdec_new }, .msppp = { 0x00000001, gf100_msppp_new }, .msvld = { 0x00000001, gf100_msvld_new }, - .pm = { 0x00000001, gf108_pm_new }, .sw = { 0x00000001, gf100_sw_new }, }; @@ -1438,7 +1386,6 @@ nvc3_chipset = { .mspdec = { 0x00000001, gf100_mspdec_new }, .msppp = { 0x00000001, gf100_msppp_new }, .msvld = { 0x00000001, gf100_msvld_new }, - .pm = { 0x00000001, gf100_pm_new }, .sw = { 0x00000001, gf100_sw_new }, }; @@ -1474,7 +1421,6 @@ nvc4_chipset = { .mspdec = { 0x00000001, gf100_mspdec_new }, .msppp = { 0x00000001, gf100_msppp_new }, .msvld = { 0x00000001, gf100_msvld_new }, - .pm = { 0x00000001, gf100_pm_new }, .sw = { 0x00000001, gf100_sw_new }, }; @@ -1510,7 +1456,6 @@ nvc8_chipset = { .mspdec = { 0x00000001, gf100_mspdec_new }, .msppp = { 0x00000001, gf100_msppp_new }, .msvld = { 0x00000001, gf100_msvld_new }, - .pm = { 0x00000001, gf100_pm_new }, .sw = { 0x00000001, gf100_sw_new }, }; @@ -1546,7 +1491,6 @@ nvce_chipset = { .mspdec = { 0x00000001, gf100_mspdec_new }, .msppp = { 0x00000001, gf100_msppp_new }, .msvld = { 0x00000001, gf100_msvld_new }, - .pm = { 0x00000001, gf100_pm_new }, .sw = { 0x00000001, gf100_sw_new }, }; @@ -1582,7 +1526,6 @@ nvcf_chipset = { .mspdec = { 0x00000001, gf100_mspdec_new }, .msppp = { 0x00000001, gf100_msppp_new }, .msvld = { 0x00000001, gf100_msvld_new }, - .pm = { 0x00000001, gf100_pm_new }, .sw = { 0x00000001, gf100_sw_new }, }; @@ -1617,7 +1560,6 @@ nvd7_chipset = { .mspdec = { 0x00000001, gf100_mspdec_new }, .msppp = { 0x00000001, gf100_msppp_new }, .msvld = { 0x00000001, gf100_msvld_new }, - .pm = { 0x00000001, gf117_pm_new }, .sw = { 0x00000001, gf100_sw_new }, }; @@ -1653,7 +1595,6 @@ nvd9_chipset = { .mspdec = { 0x00000001, gf100_mspdec_new }, .msppp = { 0x00000001, gf100_msppp_new }, .msvld = { 0x00000001, gf100_msvld_new }, - .pm = { 0x00000001, gf117_pm_new }, .sw = { 0x00000001, gf100_sw_new }, }; @@ -1690,7 +1631,6 @@ nve4_chipset = { .mspdec = { 0x00000001, gk104_mspdec_new }, .msppp = { 0x00000001, gf100_msppp_new }, .msvld = { 0x00000001, gk104_msvld_new }, - .pm = { 0x00000001, gk104_pm_new }, .sw = { 0x00000001, gf100_sw_new }, }; @@ -1727,7 +1667,6 @@ nve6_chipset = { .mspdec = { 0x00000001, gk104_mspdec_new }, .msppp = { 0x00000001, gf100_msppp_new }, .msvld = { 0x00000001, gk104_msvld_new }, - .pm = { 0x00000001, gk104_pm_new }, .sw = { 0x00000001, gf100_sw_new }, }; @@ -1764,7 +1703,6 @@ nve7_chipset = { .mspdec = { 0x00000001, gk104_mspdec_new }, .msppp = { 0x00000001, gf100_msppp_new }, .msvld = { 0x00000001, gk104_msvld_new }, - .pm = { 0x00000001, gk104_pm_new }, .sw = { 0x00000001, gf100_sw_new }, }; @@ -1789,7 +1727,6 @@ nvea_chipset = { .dma = { 0x00000001, gf119_dma_new }, .fifo = { 0x00000001, gk20a_fifo_new }, .gr = { 0x00000001, gk20a_gr_new }, - .pm = { 0x00000001, gk104_pm_new }, .sw = { 0x00000001, gf100_sw_new }, }; @@ -3104,7 +3041,6 @@ nvkm_device_ctor(const struct nvkm_device_func *func, const struct nvkm_device_quirk *quirk, struct device *dev, enum nvkm_device_type type, u64 handle, const char *name, const char *cfg, const char *dbg, - bool detect, bool mmio, u64 subdev_mask, struct nvkm_device *device) { struct nvkm_subdev *subdev; @@ -3132,233 +3068,228 @@ nvkm_device_ctor(const struct nvkm_device_func *func, mmio_base = device->func->resource_addr(device, 0); mmio_size = device->func->resource_size(device, 0); - if (detect || mmio) { - device->pri = ioremap(mmio_base, mmio_size); - if (device->pri == NULL) { - nvdev_error(device, "unable to map PRI\n"); - ret = -ENOMEM; - goto done; - } + device->pri = ioremap(mmio_base, mmio_size); + if (device->pri == NULL) { + nvdev_error(device, "unable to map PRI\n"); + ret = -ENOMEM; + goto done; } /* identify the chipset, and determine classes of subdev/engines */ - if (detect) { - /* switch mmio to cpu's native endianness */ - if (!nvkm_device_endianness(device)) { - nvdev_error(device, - "Couldn't switch GPU to CPUs endianness\n"); - ret = -ENOSYS; - goto done; - } - boot0 = nvkm_rd32(device, 0x000000); - - /* chipset can be overridden for devel/testing purposes */ - chipset = nvkm_longopt(device->cfgopt, "NvChipset", 0); - if (chipset) { - u32 override_boot0; - - if (chipset >= 0x10) { - override_boot0 = ((chipset & 0x1ff) << 20); - override_boot0 |= 0x000000a1; - } else { - if (chipset != 0x04) - override_boot0 = 0x20104000; - else - override_boot0 = 0x20004000; - } + /* switch mmio to cpu's native endianness */ + if (!nvkm_device_endianness(device)) { + nvdev_error(device, + "Couldn't switch GPU to CPUs endianness\n"); + ret = -ENOSYS; + goto done; + } - nvdev_warn(device, "CHIPSET OVERRIDE: %08x -> %08x\n", - boot0, override_boot0); - boot0 = override_boot0; - } + boot0 = nvkm_rd32(device, 0x000000); - /* determine chipset and derive architecture from it */ - if ((boot0 & 0x1f000000) > 0) { - device->chipset = (boot0 & 0x1ff00000) >> 20; - device->chiprev = (boot0 & 0x000000ff); - switch (device->chipset & 0x1f0) { - case 0x010: { - if (0x461 & (1 << (device->chipset & 0xf))) - device->card_type = NV_10; - else - device->card_type = NV_11; - device->chiprev = 0x00; - break; - } - case 0x020: device->card_type = NV_20; break; - case 0x030: device->card_type = NV_30; break; - case 0x040: - case 0x060: device->card_type = NV_40; break; - case 0x050: - case 0x080: - case 0x090: - case 0x0a0: device->card_type = NV_50; break; - case 0x0c0: - case 0x0d0: device->card_type = NV_C0; break; - case 0x0e0: - case 0x0f0: - case 0x100: device->card_type = NV_E0; break; - case 0x110: - case 0x120: device->card_type = GM100; break; - case 0x130: device->card_type = GP100; break; - case 0x140: device->card_type = GV100; break; - case 0x160: device->card_type = TU100; break; - case 0x170: device->card_type = GA100; break; - case 0x190: device->card_type = AD100; break; - default: - break; - } - } else - if ((boot0 & 0xff00fff0) == 0x20004000) { - if (boot0 & 0x00f00000) - device->chipset = 0x05; + /* chipset can be overridden for devel/testing purposes */ + chipset = nvkm_longopt(device->cfgopt, "NvChipset", 0); + if (chipset) { + u32 override_boot0; + + if (chipset >= 0x10) { + override_boot0 = ((chipset & 0x1ff) << 20); + override_boot0 |= 0x000000a1; + } else { + if (chipset != 0x04) + override_boot0 = 0x20104000; else - device->chipset = 0x04; - device->card_type = NV_04; + override_boot0 = 0x20004000; } - switch (device->chipset) { - case 0x004: device->chip = &nv4_chipset; break; - case 0x005: device->chip = &nv5_chipset; break; - case 0x010: device->chip = &nv10_chipset; break; - case 0x011: device->chip = &nv11_chipset; break; - case 0x015: device->chip = &nv15_chipset; break; - case 0x017: device->chip = &nv17_chipset; break; - case 0x018: device->chip = &nv18_chipset; break; - case 0x01a: device->chip = &nv1a_chipset; break; - case 0x01f: device->chip = &nv1f_chipset; break; - case 0x020: device->chip = &nv20_chipset; break; - case 0x025: device->chip = &nv25_chipset; break; - case 0x028: device->chip = &nv28_chipset; break; - case 0x02a: device->chip = &nv2a_chipset; break; - case 0x030: device->chip = &nv30_chipset; break; - case 0x031: device->chip = &nv31_chipset; break; - case 0x034: device->chip = &nv34_chipset; break; - case 0x035: device->chip = &nv35_chipset; break; - case 0x036: device->chip = &nv36_chipset; break; - case 0x040: device->chip = &nv40_chipset; break; - case 0x041: device->chip = &nv41_chipset; break; - case 0x042: device->chip = &nv42_chipset; break; - case 0x043: device->chip = &nv43_chipset; break; - case 0x044: device->chip = &nv44_chipset; break; - case 0x045: device->chip = &nv45_chipset; break; - case 0x046: device->chip = &nv46_chipset; break; - case 0x047: device->chip = &nv47_chipset; break; - case 0x049: device->chip = &nv49_chipset; break; - case 0x04a: device->chip = &nv4a_chipset; break; - case 0x04b: device->chip = &nv4b_chipset; break; - case 0x04c: device->chip = &nv4c_chipset; break; - case 0x04e: device->chip = &nv4e_chipset; break; - case 0x050: device->chip = &nv50_chipset; break; - case 0x063: device->chip = &nv63_chipset; break; - case 0x067: device->chip = &nv67_chipset; break; - case 0x068: device->chip = &nv68_chipset; break; - case 0x084: device->chip = &nv84_chipset; break; - case 0x086: device->chip = &nv86_chipset; break; - case 0x092: device->chip = &nv92_chipset; break; - case 0x094: device->chip = &nv94_chipset; break; - case 0x096: device->chip = &nv96_chipset; break; - case 0x098: device->chip = &nv98_chipset; break; - case 0x0a0: device->chip = &nva0_chipset; break; - case 0x0a3: device->chip = &nva3_chipset; break; - case 0x0a5: device->chip = &nva5_chipset; break; - case 0x0a8: device->chip = &nva8_chipset; break; - case 0x0aa: device->chip = &nvaa_chipset; break; - case 0x0ac: device->chip = &nvac_chipset; break; - case 0x0af: device->chip = &nvaf_chipset; break; - case 0x0c0: device->chip = &nvc0_chipset; break; - case 0x0c1: device->chip = &nvc1_chipset; break; - case 0x0c3: device->chip = &nvc3_chipset; break; - case 0x0c4: device->chip = &nvc4_chipset; break; - case 0x0c8: device->chip = &nvc8_chipset; break; - case 0x0ce: device->chip = &nvce_chipset; break; - case 0x0cf: device->chip = &nvcf_chipset; break; - case 0x0d7: device->chip = &nvd7_chipset; break; - case 0x0d9: device->chip = &nvd9_chipset; break; - case 0x0e4: device->chip = &nve4_chipset; break; - case 0x0e6: device->chip = &nve6_chipset; break; - case 0x0e7: device->chip = &nve7_chipset; break; - case 0x0ea: device->chip = &nvea_chipset; break; - case 0x0f0: device->chip = &nvf0_chipset; break; - case 0x0f1: device->chip = &nvf1_chipset; break; - case 0x106: device->chip = &nv106_chipset; break; - case 0x108: device->chip = &nv108_chipset; break; - case 0x117: device->chip = &nv117_chipset; break; - case 0x118: device->chip = &nv118_chipset; break; - case 0x120: device->chip = &nv120_chipset; break; - case 0x124: device->chip = &nv124_chipset; break; - case 0x126: device->chip = &nv126_chipset; break; - case 0x12b: device->chip = &nv12b_chipset; break; - case 0x130: device->chip = &nv130_chipset; break; - case 0x132: device->chip = &nv132_chipset; break; - case 0x134: device->chip = &nv134_chipset; break; - case 0x136: device->chip = &nv136_chipset; break; - case 0x137: device->chip = &nv137_chipset; break; - case 0x138: device->chip = &nv138_chipset; break; - case 0x13b: device->chip = &nv13b_chipset; break; - case 0x140: device->chip = &nv140_chipset; break; - case 0x162: device->chip = &nv162_chipset; break; - case 0x164: device->chip = &nv164_chipset; break; - case 0x166: device->chip = &nv166_chipset; break; - case 0x167: device->chip = &nv167_chipset; break; - case 0x168: device->chip = &nv168_chipset; break; - case 0x172: device->chip = &nv172_chipset; break; - case 0x173: device->chip = &nv173_chipset; break; - case 0x174: device->chip = &nv174_chipset; break; - case 0x176: device->chip = &nv176_chipset; break; - case 0x177: device->chip = &nv177_chipset; break; - case 0x192: device->chip = &nv192_chipset; break; - case 0x193: device->chip = &nv193_chipset; break; - case 0x194: device->chip = &nv194_chipset; break; - case 0x196: device->chip = &nv196_chipset; break; - case 0x197: device->chip = &nv197_chipset; break; - default: - if (nvkm_boolopt(device->cfgopt, "NvEnableUnsupportedChipsets", false)) { - switch (device->chipset) { - case 0x170: device->chip = &nv170_chipset; break; - default: - break; - } - } + nvdev_warn(device, "CHIPSET OVERRIDE: %08x -> %08x\n", + boot0, override_boot0); + boot0 = override_boot0; + } - if (!device->chip) { - nvdev_error(device, "unknown chipset (%08x)\n", boot0); - ret = -ENODEV; - goto done; - } + /* determine chipset and derive architecture from it */ + if ((boot0 & 0x1f000000) > 0) { + device->chipset = (boot0 & 0x1ff00000) >> 20; + device->chiprev = (boot0 & 0x000000ff); + switch (device->chipset & 0x1f0) { + case 0x010: { + if (0x461 & (1 << (device->chipset & 0xf))) + device->card_type = NV_10; + else + device->card_type = NV_11; + device->chiprev = 0x00; + break; + } + case 0x020: device->card_type = NV_20; break; + case 0x030: device->card_type = NV_30; break; + case 0x040: + case 0x060: device->card_type = NV_40; break; + case 0x050: + case 0x080: + case 0x090: + case 0x0a0: device->card_type = NV_50; break; + case 0x0c0: + case 0x0d0: device->card_type = NV_C0; break; + case 0x0e0: + case 0x0f0: + case 0x100: device->card_type = NV_E0; break; + case 0x110: + case 0x120: device->card_type = GM100; break; + case 0x130: device->card_type = GP100; break; + case 0x140: device->card_type = GV100; break; + case 0x160: device->card_type = TU100; break; + case 0x170: device->card_type = GA100; break; + case 0x190: device->card_type = AD100; break; + default: break; } + } else + if ((boot0 & 0xff00fff0) == 0x20004000) { + if (boot0 & 0x00f00000) + device->chipset = 0x05; + else + device->chipset = 0x04; + device->card_type = NV_04; + } - nvdev_info(device, "NVIDIA %s (%08x)\n", - device->chip->name, boot0); + switch (device->chipset) { + case 0x004: device->chip = &nv4_chipset; break; + case 0x005: device->chip = &nv5_chipset; break; + case 0x010: device->chip = &nv10_chipset; break; + case 0x011: device->chip = &nv11_chipset; break; + case 0x015: device->chip = &nv15_chipset; break; + case 0x017: device->chip = &nv17_chipset; break; + case 0x018: device->chip = &nv18_chipset; break; + case 0x01a: device->chip = &nv1a_chipset; break; + case 0x01f: device->chip = &nv1f_chipset; break; + case 0x020: device->chip = &nv20_chipset; break; + case 0x025: device->chip = &nv25_chipset; break; + case 0x028: device->chip = &nv28_chipset; break; + case 0x02a: device->chip = &nv2a_chipset; break; + case 0x030: device->chip = &nv30_chipset; break; + case 0x031: device->chip = &nv31_chipset; break; + case 0x034: device->chip = &nv34_chipset; break; + case 0x035: device->chip = &nv35_chipset; break; + case 0x036: device->chip = &nv36_chipset; break; + case 0x040: device->chip = &nv40_chipset; break; + case 0x041: device->chip = &nv41_chipset; break; + case 0x042: device->chip = &nv42_chipset; break; + case 0x043: device->chip = &nv43_chipset; break; + case 0x044: device->chip = &nv44_chipset; break; + case 0x045: device->chip = &nv45_chipset; break; + case 0x046: device->chip = &nv46_chipset; break; + case 0x047: device->chip = &nv47_chipset; break; + case 0x049: device->chip = &nv49_chipset; break; + case 0x04a: device->chip = &nv4a_chipset; break; + case 0x04b: device->chip = &nv4b_chipset; break; + case 0x04c: device->chip = &nv4c_chipset; break; + case 0x04e: device->chip = &nv4e_chipset; break; + case 0x050: device->chip = &nv50_chipset; break; + case 0x063: device->chip = &nv63_chipset; break; + case 0x067: device->chip = &nv67_chipset; break; + case 0x068: device->chip = &nv68_chipset; break; + case 0x084: device->chip = &nv84_chipset; break; + case 0x086: device->chip = &nv86_chipset; break; + case 0x092: device->chip = &nv92_chipset; break; + case 0x094: device->chip = &nv94_chipset; break; + case 0x096: device->chip = &nv96_chipset; break; + case 0x098: device->chip = &nv98_chipset; break; + case 0x0a0: device->chip = &nva0_chipset; break; + case 0x0a3: device->chip = &nva3_chipset; break; + case 0x0a5: device->chip = &nva5_chipset; break; + case 0x0a8: device->chip = &nva8_chipset; break; + case 0x0aa: device->chip = &nvaa_chipset; break; + case 0x0ac: device->chip = &nvac_chipset; break; + case 0x0af: device->chip = &nvaf_chipset; break; + case 0x0c0: device->chip = &nvc0_chipset; break; + case 0x0c1: device->chip = &nvc1_chipset; break; + case 0x0c3: device->chip = &nvc3_chipset; break; + case 0x0c4: device->chip = &nvc4_chipset; break; + case 0x0c8: device->chip = &nvc8_chipset; break; + case 0x0ce: device->chip = &nvce_chipset; break; + case 0x0cf: device->chip = &nvcf_chipset; break; + case 0x0d7: device->chip = &nvd7_chipset; break; + case 0x0d9: device->chip = &nvd9_chipset; break; + case 0x0e4: device->chip = &nve4_chipset; break; + case 0x0e6: device->chip = &nve6_chipset; break; + case 0x0e7: device->chip = &nve7_chipset; break; + case 0x0ea: device->chip = &nvea_chipset; break; + case 0x0f0: device->chip = &nvf0_chipset; break; + case 0x0f1: device->chip = &nvf1_chipset; break; + case 0x106: device->chip = &nv106_chipset; break; + case 0x108: device->chip = &nv108_chipset; break; + case 0x117: device->chip = &nv117_chipset; break; + case 0x118: device->chip = &nv118_chipset; break; + case 0x120: device->chip = &nv120_chipset; break; + case 0x124: device->chip = &nv124_chipset; break; + case 0x126: device->chip = &nv126_chipset; break; + case 0x12b: device->chip = &nv12b_chipset; break; + case 0x130: device->chip = &nv130_chipset; break; + case 0x132: device->chip = &nv132_chipset; break; + case 0x134: device->chip = &nv134_chipset; break; + case 0x136: device->chip = &nv136_chipset; break; + case 0x137: device->chip = &nv137_chipset; break; + case 0x138: device->chip = &nv138_chipset; break; + case 0x13b: device->chip = &nv13b_chipset; break; + case 0x140: device->chip = &nv140_chipset; break; + case 0x162: device->chip = &nv162_chipset; break; + case 0x164: device->chip = &nv164_chipset; break; + case 0x166: device->chip = &nv166_chipset; break; + case 0x167: device->chip = &nv167_chipset; break; + case 0x168: device->chip = &nv168_chipset; break; + case 0x172: device->chip = &nv172_chipset; break; + case 0x173: device->chip = &nv173_chipset; break; + case 0x174: device->chip = &nv174_chipset; break; + case 0x176: device->chip = &nv176_chipset; break; + case 0x177: device->chip = &nv177_chipset; break; + case 0x192: device->chip = &nv192_chipset; break; + case 0x193: device->chip = &nv193_chipset; break; + case 0x194: device->chip = &nv194_chipset; break; + case 0x196: device->chip = &nv196_chipset; break; + case 0x197: device->chip = &nv197_chipset; break; + default: + if (nvkm_boolopt(device->cfgopt, "NvEnableUnsupportedChipsets", false)) { + switch (device->chipset) { + case 0x170: device->chip = &nv170_chipset; break; + default: + break; + } + } - /* vGPU detection */ - boot1 = nvkm_rd32(device, 0x0000004); - if (device->card_type >= TU100 && (boot1 & 0x00030000)) { - nvdev_info(device, "vGPUs are not supported\n"); + if (!device->chip) { + nvdev_error(device, "unknown chipset (%08x)\n", boot0); ret = -ENODEV; goto done; } + break; + } - /* read strapping information */ - strap = nvkm_rd32(device, 0x101000); + nvdev_info(device, "NVIDIA %s (%08x)\n", + device->chip->name, boot0); - /* determine frequency of timing crystal */ - if ( device->card_type <= NV_10 || device->chipset < 0x17 || - (device->chipset >= 0x20 && device->chipset < 0x25)) - strap &= 0x00000040; - else - strap &= 0x00400040; + /* vGPU detection */ + boot1 = nvkm_rd32(device, 0x0000004); + if (device->card_type >= TU100 && (boot1 & 0x00030000)) { + nvdev_info(device, "vGPUs are not supported\n"); + ret = -ENODEV; + goto done; + } - switch (strap) { - case 0x00000000: device->crystal = 13500; break; - case 0x00000040: device->crystal = 14318; break; - case 0x00400000: device->crystal = 27000; break; - case 0x00400040: device->crystal = 25000; break; - } - } else { - device->chip = &null_chipset; + /* read strapping information */ + strap = nvkm_rd32(device, 0x101000); + + /* determine frequency of timing crystal */ + if ( device->card_type <= NV_10 || device->chipset < 0x17 || + (device->chipset >= 0x20 && device->chipset < 0x25)) + strap &= 0x00000040; + else + strap &= 0x00400040; + + switch (strap) { + case 0x00000000: device->crystal = 13500; break; + case 0x00000040: device->crystal = 14318; break; + case 0x00400000: device->crystal = 27000; break; + case 0x00400040: device->crystal = 25000; break; } if (!device->name) @@ -3368,7 +3299,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, nvkm_intr_ctor(device); #define NVKM_LAYOUT_ONCE(type,data,ptr) \ - if (device->chip->ptr.inst && (subdev_mask & (BIT_ULL(type)))) { \ + if (device->chip->ptr.inst) { \ WARN_ON(device->chip->ptr.inst != 0x00000001); \ ret = device->chip->ptr.ctor(device, (type), -1, &device->ptr); \ subdev = nvkm_device_subdev(device, (type), 0); \ @@ -3387,7 +3318,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, #define NVKM_LAYOUT_INST(type,data,ptr,cnt) \ WARN_ON(device->chip->ptr.inst & ~((1 << ARRAY_SIZE(device->ptr)) - 1)); \ for (j = 0; device->chip->ptr.inst && j < ARRAY_SIZE(device->ptr); j++) { \ - if ((device->chip->ptr.inst & BIT(j)) && (subdev_mask & BIT_ULL(type))) { \ + if (device->chip->ptr.inst & BIT(j)) { \ ret = device->chip->ptr.ctor(device, (type), (j), &device->ptr[j]); \ subdev = nvkm_device_subdev(device, (type), (j)); \ if (ret) { \ @@ -3409,7 +3340,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, ret = nvkm_intr_install(device); done: - if (device->pri && (!mmio || ret)) { + if (ret && device->pri) { iounmap(device->pri); device->pri = NULL; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c index abccb2bb68a6..3ff6436007fa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c @@ -1626,7 +1626,6 @@ nvkm_device_pci_func = { int nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, - bool detect, bool mmio, u64 subdev_mask, struct nvkm_device **pdevice) { const struct nvkm_device_quirk *quirk = NULL; @@ -1680,8 +1679,7 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, pci_dev->bus->number << 16 | PCI_SLOT(pci_dev->devfn) << 8 | PCI_FUNC(pci_dev->devfn), name, - cfg, dbg, detect, mmio, subdev_mask, - &pdev->device); + cfg, dbg, &pdev->device); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h index bf3176bec18a..e42b18820a95 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h @@ -45,7 +45,6 @@ #include <engine/nvdec.h> #include <engine/nvjpg.h> #include <engine/ofa.h> -#include <engine/pm.h> #include <engine/sec.h> #include <engine/sec2.h> #include <engine/sw.h> @@ -56,7 +55,6 @@ int nvkm_device_ctor(const struct nvkm_device_func *, const struct nvkm_device_quirk *, struct device *, enum nvkm_device_type, u64 handle, const char *name, const char *cfg, const char *dbg, - bool detect, bool mmio, u64 subdev_mask, struct nvkm_device *); int nvkm_device_init(struct nvkm_device *); int nvkm_device_fini(struct nvkm_device *, bool suspend); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c index 87caa4a72921..78a83f904bbd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c @@ -120,8 +120,8 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev) mutex_init(&tdev->iommu.mutex); if (device_iommu_mapped(dev)) { - tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type); - if (!tdev->iommu.domain) + tdev->iommu.domain = iommu_paging_domain_alloc(dev); + if (IS_ERR(tdev->iommu.domain)) goto error; /* @@ -237,7 +237,6 @@ int nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, struct platform_device *pdev, const char *cfg, const char *dbg, - bool detect, bool mmio, u64 subdev_mask, struct nvkm_device **pdevice) { struct nvkm_device_tegra *tdev; @@ -311,8 +310,7 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, tdev->gpu_speedo_id = tegra_sku_info.gpu_speedo_id; ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev, NVKM_DEVICE_TEGRA, pdev->id, NULL, - cfg, dbg, detect, mmio, subdev_mask, - &tdev->device); + cfg, dbg, &tdev->device); if (ret) goto powerdown; @@ -333,7 +331,6 @@ int nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, struct platform_device *pdev, const char *cfg, const char *dbg, - bool detect, bool mmio, u64 subdev_mask, struct nvkm_device **pdevice) { return -ENOSYS; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c index 7fd4800a876a..d7f75b3a43c8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c @@ -203,54 +203,6 @@ nvkm_udevice_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) } static int -nvkm_udevice_rd08(struct nvkm_object *object, u64 addr, u8 *data) -{ - struct nvkm_udevice *udev = nvkm_udevice(object); - *data = nvkm_rd08(udev->device, addr); - return 0; -} - -static int -nvkm_udevice_rd16(struct nvkm_object *object, u64 addr, u16 *data) -{ - struct nvkm_udevice *udev = nvkm_udevice(object); - *data = nvkm_rd16(udev->device, addr); - return 0; -} - -static int -nvkm_udevice_rd32(struct nvkm_object *object, u64 addr, u32 *data) -{ - struct nvkm_udevice *udev = nvkm_udevice(object); - *data = nvkm_rd32(udev->device, addr); - return 0; -} - -static int -nvkm_udevice_wr08(struct nvkm_object *object, u64 addr, u8 data) -{ - struct nvkm_udevice *udev = nvkm_udevice(object); - nvkm_wr08(udev->device, addr, data); - return 0; -} - -static int -nvkm_udevice_wr16(struct nvkm_object *object, u64 addr, u16 data) -{ - struct nvkm_udevice *udev = nvkm_udevice(object); - nvkm_wr16(udev->device, addr, data); - return 0; -} - -static int -nvkm_udevice_wr32(struct nvkm_object *object, u64 addr, u32 data) -{ - struct nvkm_udevice *udev = nvkm_udevice(object); - nvkm_wr32(udev->device, addr, data); - return 0; -} - -static int nvkm_udevice_map(struct nvkm_object *object, void *argv, u32 argc, enum nvkm_object_map *type, u64 *addr, u64 *size) { @@ -322,8 +274,7 @@ nvkm_udevice_child_get(struct nvkm_object *object, int index, struct nvkm_engine *engine; u64 mask = (1ULL << NVKM_ENGINE_DMAOBJ) | (1ULL << NVKM_ENGINE_FIFO) | - (1ULL << NVKM_ENGINE_DISP) | - (1ULL << NVKM_ENGINE_PM); + (1ULL << NVKM_ENGINE_DISP); const struct nvkm_device_oclass *sclass = NULL; int i; @@ -358,25 +309,11 @@ nvkm_udevice_child_get(struct nvkm_object *object, int index, } static const struct nvkm_object_func -nvkm_udevice_super = { - .init = nvkm_udevice_init, - .fini = nvkm_udevice_fini, - .mthd = nvkm_udevice_mthd, - .map = nvkm_udevice_map, - .rd08 = nvkm_udevice_rd08, - .rd16 = nvkm_udevice_rd16, - .rd32 = nvkm_udevice_rd32, - .wr08 = nvkm_udevice_wr08, - .wr16 = nvkm_udevice_wr16, - .wr32 = nvkm_udevice_wr32, - .sclass = nvkm_udevice_child_get, -}; - -static const struct nvkm_object_func nvkm_udevice = { .init = nvkm_udevice_init, .fini = nvkm_udevice_fini, .mthd = nvkm_udevice_mthd, + .map = nvkm_udevice_map, .sclass = nvkm_udevice_child_get, }; @@ -384,38 +321,16 @@ static int nvkm_udevice_new(const struct nvkm_oclass *oclass, void *data, u32 size, struct nvkm_object **pobject) { - union { - struct nv_device_v0 v0; - } *args = data; struct nvkm_client *client = oclass->client; - struct nvkm_object *parent = &client->object; - const struct nvkm_object_func *func; struct nvkm_udevice *udev; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create device size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create device v%d device %016llx\n", - args->v0.version, args->v0.device); - } else - return ret; - - /* give priviledged clients register access */ - if (args->v0.priv) - func = &nvkm_udevice_super; - else - func = &nvkm_udevice; if (!(udev = kzalloc(sizeof(*udev), GFP_KERNEL))) return -ENOMEM; - nvkm_object_ctor(func, oclass, &udev->object); + nvkm_object_ctor(&nvkm_udevice, oclass, &udev->object); *pobject = &udev->object; /* find the device that matches what the client requested */ - if (args->v0.device != ~0) - udev->device = nvkm_device_find(args->v0.device); - else - udev->device = nvkm_device_find(client->device); + udev->device = nvkm_device_find(client->device); if (!udev->device) return -ENODEV; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c index d5e18daed79f..4e43ee383c34 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c @@ -27,28 +27,6 @@ #include <nvif/if0014.h> static int -nvkm_disp_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data) -{ - struct nvkm_disp_chan *chan = nvkm_disp_chan(object); - struct nvkm_device *device = chan->disp->engine.subdev.device; - u64 size, base = chan->func->user(chan, &size); - - *data = nvkm_rd32(device, base + addr); - return 0; -} - -static int -nvkm_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data) -{ - struct nvkm_disp_chan *chan = nvkm_disp_chan(object); - struct nvkm_device *device = chan->disp->engine.subdev.device; - u64 size, base = chan->func->user(chan, &size); - - nvkm_wr32(device, base + addr, data); - return 0; -} - -static int nvkm_disp_chan_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **pevent) { struct nvkm_disp_chan *chan = nvkm_disp_chan(object); @@ -188,8 +166,6 @@ nvkm_disp_chan = { .dtor = nvkm_disp_chan_dtor, .init = nvkm_disp_chan_init, .fini = nvkm_disp_chan_fini, - .rd32 = nvkm_disp_chan_rd32, - .wr32 = nvkm_disp_chan_wr32, .ntfy = nvkm_disp_chan_ntfy, .map = nvkm_disp_chan_map, .sclass = nvkm_disp_chan_child_get, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c index 841e3b69fcaf..5a0c9b8a79f3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c @@ -31,6 +31,7 @@ mcp77_sor = { .state = g94_sor_state, .power = nv50_sor_power, .clock = nv50_sor_clock, + .bl = &nv50_sor_bl, .hdmi = &g84_sor_hdmi, .dp = &g94_sor_dp, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c index 6a0a4d3b8902..99110ab2f44d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c @@ -992,7 +992,7 @@ r535_dp_train_target(struct nvkm_outp *outp, u8 target, bool mst, u8 link_nr, u8 ctrl->data = data; ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl)); - if (ret == -EAGAIN && ctrl->retryTimeMs) { + if ((ret == -EAGAIN || ret == -EBUSY) && ctrl->retryTimeMs) { /* * Device (likely an eDP panel) isn't ready yet, wait for the time specified * by GSP before retrying again @@ -1060,33 +1060,44 @@ r535_dp_aux_xfer(struct nvkm_outp *outp, u8 type, u32 addr, u8 *data, u8 *psize) NV0073_CTRL_DP_AUXCH_CTRL_PARAMS *ctrl; u8 size = *psize; int ret; + int retries; - ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom, NV0073_CTRL_CMD_DP_AUXCH_CTRL, sizeof(*ctrl)); - if (IS_ERR(ctrl)) - return PTR_ERR(ctrl); + for (retries = 0; retries < 3; ++retries) { + ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom, NV0073_CTRL_CMD_DP_AUXCH_CTRL, sizeof(*ctrl)); + if (IS_ERR(ctrl)) + return PTR_ERR(ctrl); - ctrl->subDeviceInstance = 0; - ctrl->displayId = BIT(outp->index); - ctrl->bAddrOnly = !size; - ctrl->cmd = type; - if (ctrl->bAddrOnly) { - ctrl->cmd = NVDEF_SET(ctrl->cmd, NV0073_CTRL, DP_AUXCH_CMD, REQ_TYPE, WRITE); - ctrl->cmd = NVDEF_SET(ctrl->cmd, NV0073_CTRL, DP_AUXCH_CMD, I2C_MOT, FALSE); - } - ctrl->addr = addr; - ctrl->size = !ctrl->bAddrOnly ? (size - 1) : 0; - memcpy(ctrl->data, data, size); + ctrl->subDeviceInstance = 0; + ctrl->displayId = BIT(outp->index); + ctrl->bAddrOnly = !size; + ctrl->cmd = type; + if (ctrl->bAddrOnly) { + ctrl->cmd = NVDEF_SET(ctrl->cmd, NV0073_CTRL, DP_AUXCH_CMD, REQ_TYPE, WRITE); + ctrl->cmd = NVDEF_SET(ctrl->cmd, NV0073_CTRL, DP_AUXCH_CMD, I2C_MOT, FALSE); + } + ctrl->addr = addr; + ctrl->size = !ctrl->bAddrOnly ? (size - 1) : 0; + memcpy(ctrl->data, data, size); - ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl)); - if (ret) { - nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl); - return PTR_ERR(ctrl); + ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl)); + if ((ret == -EAGAIN || ret == -EBUSY) && ctrl->retryTimeMs) { + /* + * Device (likely an eDP panel) isn't ready yet, wait for the time specified + * by GSP before retrying again + */ + nvkm_debug(&disp->engine.subdev, + "Waiting %dms for GSP LT panel delay before retrying in AUX\n", + ctrl->retryTimeMs); + msleep(ctrl->retryTimeMs); + nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl); + } else { + memcpy(data, ctrl->data, size); + *psize = ctrl->size; + ret = ctrl->replyType; + nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl); + break; + } } - - memcpy(data, ctrl->data, size); - *psize = ctrl->size; - ret = ctrl->replyType; - nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index c494a1ff2d57..3ea447f6a45b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -420,7 +420,7 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, return ret; } else { ret = nvkm_memory_map(gr->attrib_cb, 0, chan->vmm, chan->attrib_cb, - &args, sizeof(args));; + &args, sizeof(args)); if (ret) return ret; } @@ -443,6 +443,7 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, ret = gf100_grctx_generate(gr, chan, fifoch->inst); if (ret) { nvkm_error(&base->engine.subdev, "failed to construct context\n"); + mutex_unlock(&gr->fecs.mutex); return ret; } } @@ -1040,7 +1041,7 @@ gf100_gr_zbc_init(struct gf100_gr *gr) } } -/** +/* * Wait until GR goes idle. GR is considered idle if it is disabled by the * MC (0x200) register, or GR is not busy and a context switch is not in * progress. diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/pm/Kbuild deleted file mode 100644 index 2cc8a5f6fe0c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/Kbuild +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: MIT -nvkm-y += nvkm/engine/pm/base.o -nvkm-y += nvkm/engine/pm/nv40.o -nvkm-y += nvkm/engine/pm/nv50.o -nvkm-y += nvkm/engine/pm/g84.o -nvkm-y += nvkm/engine/pm/gt200.o -nvkm-y += nvkm/engine/pm/gt215.o -nvkm-y += nvkm/engine/pm/gf100.o -nvkm-y += nvkm/engine/pm/gf108.o -nvkm-y += nvkm/engine/pm/gf117.o -nvkm-y += nvkm/engine/pm/gk104.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c deleted file mode 100644 index 131db2645f84..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c +++ /dev/null @@ -1,867 +0,0 @@ -/* - * Copyright 2013 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "priv.h" - -#include <core/client.h> -#include <core/option.h> - -#include <nvif/class.h> -#include <nvif/if0002.h> -#include <nvif/if0003.h> -#include <nvif/ioctl.h> -#include <nvif/unpack.h> - -static u8 -nvkm_pm_count_perfdom(struct nvkm_pm *pm) -{ - struct nvkm_perfdom *dom; - u8 domain_nr = 0; - - list_for_each_entry(dom, &pm->domains, head) - domain_nr++; - return domain_nr; -} - -static u16 -nvkm_perfdom_count_perfsig(struct nvkm_perfdom *dom) -{ - u16 signal_nr = 0; - int i; - - if (dom) { - for (i = 0; i < dom->signal_nr; i++) { - if (dom->signal[i].name) - signal_nr++; - } - } - return signal_nr; -} - -static struct nvkm_perfdom * -nvkm_perfdom_find(struct nvkm_pm *pm, int di) -{ - struct nvkm_perfdom *dom; - int tmp = 0; - - list_for_each_entry(dom, &pm->domains, head) { - if (tmp++ == di) - return dom; - } - return NULL; -} - -static struct nvkm_perfsig * -nvkm_perfsig_find(struct nvkm_pm *pm, u8 di, u8 si, struct nvkm_perfdom **pdom) -{ - struct nvkm_perfdom *dom = *pdom; - - if (dom == NULL) { - dom = nvkm_perfdom_find(pm, di); - if (dom == NULL) - return NULL; - *pdom = dom; - } - - if (!dom->signal[si].name) - return NULL; - return &dom->signal[si]; -} - -static u8 -nvkm_perfsig_count_perfsrc(struct nvkm_perfsig *sig) -{ - u8 source_nr = 0, i; - - for (i = 0; i < ARRAY_SIZE(sig->source); i++) { - if (sig->source[i]) - source_nr++; - } - return source_nr; -} - -static struct nvkm_perfsrc * -nvkm_perfsrc_find(struct nvkm_pm *pm, struct nvkm_perfsig *sig, int si) -{ - struct nvkm_perfsrc *src; - bool found = false; - int tmp = 1; /* Sources ID start from 1 */ - u8 i; - - for (i = 0; i < ARRAY_SIZE(sig->source) && sig->source[i]; i++) { - if (sig->source[i] == si) { - found = true; - break; - } - } - - if (found) { - list_for_each_entry(src, &pm->sources, head) { - if (tmp++ == si) - return src; - } - } - - return NULL; -} - -static int -nvkm_perfsrc_enable(struct nvkm_pm *pm, struct nvkm_perfctr *ctr) -{ - struct nvkm_subdev *subdev = &pm->engine.subdev; - struct nvkm_device *device = subdev->device; - struct nvkm_perfdom *dom = NULL; - struct nvkm_perfsig *sig; - struct nvkm_perfsrc *src; - u32 mask, value; - int i, j; - - for (i = 0; i < 4; i++) { - for (j = 0; j < 8 && ctr->source[i][j]; j++) { - sig = nvkm_perfsig_find(pm, ctr->domain, - ctr->signal[i], &dom); - if (!sig) - return -EINVAL; - - src = nvkm_perfsrc_find(pm, sig, ctr->source[i][j]); - if (!src) - return -EINVAL; - - /* set enable bit if needed */ - mask = value = 0x00000000; - if (src->enable) - mask = value = 0x80000000; - mask |= (src->mask << src->shift); - value |= ((ctr->source[i][j] >> 32) << src->shift); - - /* enable the source */ - nvkm_mask(device, src->addr, mask, value); - nvkm_debug(subdev, - "enabled source %08x %08x %08x\n", - src->addr, mask, value); - } - } - return 0; -} - -static int -nvkm_perfsrc_disable(struct nvkm_pm *pm, struct nvkm_perfctr *ctr) -{ - struct nvkm_subdev *subdev = &pm->engine.subdev; - struct nvkm_device *device = subdev->device; - struct nvkm_perfdom *dom = NULL; - struct nvkm_perfsig *sig; - struct nvkm_perfsrc *src; - u32 mask; - int i, j; - - for (i = 0; i < 4; i++) { - for (j = 0; j < 8 && ctr->source[i][j]; j++) { - sig = nvkm_perfsig_find(pm, ctr->domain, - ctr->signal[i], &dom); - if (!sig) - return -EINVAL; - - src = nvkm_perfsrc_find(pm, sig, ctr->source[i][j]); - if (!src) - return -EINVAL; - - /* unset enable bit if needed */ - mask = 0x00000000; - if (src->enable) - mask = 0x80000000; - mask |= (src->mask << src->shift); - - /* disable the source */ - nvkm_mask(device, src->addr, mask, 0); - nvkm_debug(subdev, "disabled source %08x %08x\n", - src->addr, mask); - } - } - return 0; -} - -/******************************************************************************* - * Perfdom object classes - ******************************************************************************/ -static int -nvkm_perfdom_init(struct nvkm_perfdom *dom, void *data, u32 size) -{ - union { - struct nvif_perfdom_init none; - } *args = data; - struct nvkm_object *object = &dom->object; - struct nvkm_pm *pm = dom->perfmon->pm; - int ret = -ENOSYS, i; - - nvif_ioctl(object, "perfdom init size %d\n", size); - if (!(ret = nvif_unvers(ret, &data, &size, args->none))) { - nvif_ioctl(object, "perfdom init\n"); - } else - return ret; - - for (i = 0; i < 4; i++) { - if (dom->ctr[i]) { - dom->func->init(pm, dom, dom->ctr[i]); - - /* enable sources */ - nvkm_perfsrc_enable(pm, dom->ctr[i]); - } - } - - /* start next batch of counters for sampling */ - dom->func->next(pm, dom); - return 0; -} - -static int -nvkm_perfdom_sample(struct nvkm_perfdom *dom, void *data, u32 size) -{ - union { - struct nvif_perfdom_sample none; - } *args = data; - struct nvkm_object *object = &dom->object; - struct nvkm_pm *pm = dom->perfmon->pm; - int ret = -ENOSYS; - - nvif_ioctl(object, "perfdom sample size %d\n", size); - if (!(ret = nvif_unvers(ret, &data, &size, args->none))) { - nvif_ioctl(object, "perfdom sample\n"); - } else - return ret; - pm->sequence++; - - /* sample previous batch of counters */ - list_for_each_entry(dom, &pm->domains, head) - dom->func->next(pm, dom); - - return 0; -} - -static int -nvkm_perfdom_read(struct nvkm_perfdom *dom, void *data, u32 size) -{ - union { - struct nvif_perfdom_read_v0 v0; - } *args = data; - struct nvkm_object *object = &dom->object; - struct nvkm_pm *pm = dom->perfmon->pm; - int ret = -ENOSYS, i; - - nvif_ioctl(object, "perfdom read size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "perfdom read vers %d\n", args->v0.version); - } else - return ret; - - for (i = 0; i < 4; i++) { - if (dom->ctr[i]) - dom->func->read(pm, dom, dom->ctr[i]); - } - - if (!dom->clk) - return -EAGAIN; - - for (i = 0; i < 4; i++) - if (dom->ctr[i]) - args->v0.ctr[i] = dom->ctr[i]->ctr; - args->v0.clk = dom->clk; - return 0; -} - -static int -nvkm_perfdom_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) -{ - struct nvkm_perfdom *dom = nvkm_perfdom(object); - switch (mthd) { - case NVIF_PERFDOM_V0_INIT: - return nvkm_perfdom_init(dom, data, size); - case NVIF_PERFDOM_V0_SAMPLE: - return nvkm_perfdom_sample(dom, data, size); - case NVIF_PERFDOM_V0_READ: - return nvkm_perfdom_read(dom, data, size); - default: - break; - } - return -EINVAL; -} - -static void * -nvkm_perfdom_dtor(struct nvkm_object *object) -{ - struct nvkm_perfdom *dom = nvkm_perfdom(object); - struct nvkm_pm *pm = dom->perfmon->pm; - int i; - - for (i = 0; i < 4; i++) { - struct nvkm_perfctr *ctr = dom->ctr[i]; - if (ctr) { - nvkm_perfsrc_disable(pm, ctr); - if (ctr->head.next) - list_del(&ctr->head); - } - kfree(ctr); - } - - return dom; -} - -static int -nvkm_perfctr_new(struct nvkm_perfdom *dom, int slot, u8 domain, - struct nvkm_perfsig *signal[4], u64 source[4][8], - u16 logic_op, struct nvkm_perfctr **pctr) -{ - struct nvkm_perfctr *ctr; - int i, j; - - if (!dom) - return -EINVAL; - - ctr = *pctr = kzalloc(sizeof(*ctr), GFP_KERNEL); - if (!ctr) - return -ENOMEM; - - ctr->domain = domain; - ctr->logic_op = logic_op; - ctr->slot = slot; - for (i = 0; i < 4; i++) { - if (signal[i]) { - ctr->signal[i] = signal[i] - dom->signal; - for (j = 0; j < 8; j++) - ctr->source[i][j] = source[i][j]; - } - } - list_add_tail(&ctr->head, &dom->list); - - return 0; -} - -static const struct nvkm_object_func -nvkm_perfdom = { - .dtor = nvkm_perfdom_dtor, - .mthd = nvkm_perfdom_mthd, -}; - -static int -nvkm_perfdom_new_(struct nvkm_perfmon *perfmon, - const struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - union { - struct nvif_perfdom_v0 v0; - } *args = data; - struct nvkm_pm *pm = perfmon->pm; - struct nvkm_object *parent = oclass->parent; - struct nvkm_perfdom *sdom = NULL; - struct nvkm_perfctr *ctr[4] = {}; - struct nvkm_perfdom *dom; - int c, s, m; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create perfdom size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create perfdom vers %d dom %d mode %02x\n", - args->v0.version, args->v0.domain, args->v0.mode); - } else - return ret; - - for (c = 0; c < ARRAY_SIZE(args->v0.ctr); c++) { - struct nvkm_perfsig *sig[4] = {}; - u64 src[4][8] = {}; - - for (s = 0; s < ARRAY_SIZE(args->v0.ctr[c].signal); s++) { - sig[s] = nvkm_perfsig_find(pm, args->v0.domain, - args->v0.ctr[c].signal[s], - &sdom); - if (args->v0.ctr[c].signal[s] && !sig[s]) - return -EINVAL; - - for (m = 0; m < 8; m++) { - src[s][m] = args->v0.ctr[c].source[s][m]; - if (src[s][m] && !nvkm_perfsrc_find(pm, sig[s], - src[s][m])) - return -EINVAL; - } - } - - ret = nvkm_perfctr_new(sdom, c, args->v0.domain, sig, src, - args->v0.ctr[c].logic_op, &ctr[c]); - if (ret) - return ret; - } - - if (!sdom) - return -EINVAL; - - if (!(dom = kzalloc(sizeof(*dom), GFP_KERNEL))) - return -ENOMEM; - nvkm_object_ctor(&nvkm_perfdom, oclass, &dom->object); - dom->perfmon = perfmon; - *pobject = &dom->object; - - dom->func = sdom->func; - dom->addr = sdom->addr; - dom->mode = args->v0.mode; - for (c = 0; c < ARRAY_SIZE(ctr); c++) - dom->ctr[c] = ctr[c]; - return 0; -} - -/******************************************************************************* - * Perfmon object classes - ******************************************************************************/ -static int -nvkm_perfmon_mthd_query_domain(struct nvkm_perfmon *perfmon, - void *data, u32 size) -{ - union { - struct nvif_perfmon_query_domain_v0 v0; - } *args = data; - struct nvkm_object *object = &perfmon->object; - struct nvkm_pm *pm = perfmon->pm; - struct nvkm_perfdom *dom; - u8 domain_nr; - int di, ret = -ENOSYS; - - nvif_ioctl(object, "perfmon query domain size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, "perfmon domain vers %d iter %02x\n", - args->v0.version, args->v0.iter); - di = (args->v0.iter & 0xff) - 1; - } else - return ret; - - domain_nr = nvkm_pm_count_perfdom(pm); - if (di >= (int)domain_nr) - return -EINVAL; - - if (di >= 0) { - dom = nvkm_perfdom_find(pm, di); - if (dom == NULL) - return -EINVAL; - - args->v0.id = di; - args->v0.signal_nr = nvkm_perfdom_count_perfsig(dom); - strscpy(args->v0.name, dom->name, sizeof(args->v0.name)); - - /* Currently only global counters (PCOUNTER) are implemented - * but this will be different for local counters (MP). */ - args->v0.counter_nr = 4; - } - - if (++di < domain_nr) { - args->v0.iter = ++di; - return 0; - } - - args->v0.iter = 0xff; - return 0; -} - -static int -nvkm_perfmon_mthd_query_signal(struct nvkm_perfmon *perfmon, - void *data, u32 size) -{ - union { - struct nvif_perfmon_query_signal_v0 v0; - } *args = data; - struct nvkm_object *object = &perfmon->object; - struct nvkm_pm *pm = perfmon->pm; - struct nvkm_device *device = pm->engine.subdev.device; - struct nvkm_perfdom *dom; - struct nvkm_perfsig *sig; - const bool all = nvkm_boolopt(device->cfgopt, "NvPmShowAll", false); - const bool raw = nvkm_boolopt(device->cfgopt, "NvPmUnnamed", all); - int ret = -ENOSYS, si; - - nvif_ioctl(object, "perfmon query signal size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, - "perfmon query signal vers %d dom %d iter %04x\n", - args->v0.version, args->v0.domain, args->v0.iter); - si = (args->v0.iter & 0xffff) - 1; - } else - return ret; - - dom = nvkm_perfdom_find(pm, args->v0.domain); - if (dom == NULL || si >= (int)dom->signal_nr) - return -EINVAL; - - if (si >= 0) { - sig = &dom->signal[si]; - if (raw || !sig->name) { - snprintf(args->v0.name, sizeof(args->v0.name), - "/%s/%02x", dom->name, si); - } else { - strscpy(args->v0.name, sig->name, sizeof(args->v0.name)); - } - - args->v0.signal = si; - args->v0.source_nr = nvkm_perfsig_count_perfsrc(sig); - } - - while (++si < dom->signal_nr) { - if (all || dom->signal[si].name) { - args->v0.iter = ++si; - return 0; - } - } - - args->v0.iter = 0xffff; - return 0; -} - -static int -nvkm_perfmon_mthd_query_source(struct nvkm_perfmon *perfmon, - void *data, u32 size) -{ - union { - struct nvif_perfmon_query_source_v0 v0; - } *args = data; - struct nvkm_object *object = &perfmon->object; - struct nvkm_pm *pm = perfmon->pm; - struct nvkm_perfdom *dom = NULL; - struct nvkm_perfsig *sig; - struct nvkm_perfsrc *src; - u8 source_nr = 0; - int si, ret = -ENOSYS; - - nvif_ioctl(object, "perfmon query source size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(object, - "perfmon source vers %d dom %d sig %02x iter %02x\n", - args->v0.version, args->v0.domain, args->v0.signal, - args->v0.iter); - si = (args->v0.iter & 0xff) - 1; - } else - return ret; - - sig = nvkm_perfsig_find(pm, args->v0.domain, args->v0.signal, &dom); - if (!sig) - return -EINVAL; - - source_nr = nvkm_perfsig_count_perfsrc(sig); - if (si >= (int)source_nr) - return -EINVAL; - - if (si >= 0) { - src = nvkm_perfsrc_find(pm, sig, sig->source[si]); - if (!src) - return -EINVAL; - - args->v0.source = sig->source[si]; - args->v0.mask = src->mask; - strscpy(args->v0.name, src->name, sizeof(args->v0.name)); - } - - if (++si < source_nr) { - args->v0.iter = ++si; - return 0; - } - - args->v0.iter = 0xff; - return 0; -} - -static int -nvkm_perfmon_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) -{ - struct nvkm_perfmon *perfmon = nvkm_perfmon(object); - switch (mthd) { - case NVIF_PERFMON_V0_QUERY_DOMAIN: - return nvkm_perfmon_mthd_query_domain(perfmon, data, size); - case NVIF_PERFMON_V0_QUERY_SIGNAL: - return nvkm_perfmon_mthd_query_signal(perfmon, data, size); - case NVIF_PERFMON_V0_QUERY_SOURCE: - return nvkm_perfmon_mthd_query_source(perfmon, data, size); - default: - break; - } - return -EINVAL; -} - -static int -nvkm_perfmon_child_new(const struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nvkm_perfmon *perfmon = nvkm_perfmon(oclass->parent); - return nvkm_perfdom_new_(perfmon, oclass, data, size, pobject); -} - -static int -nvkm_perfmon_child_get(struct nvkm_object *object, int index, - struct nvkm_oclass *oclass) -{ - if (index == 0) { - oclass->base.oclass = NVIF_CLASS_PERFDOM; - oclass->base.minver = 0; - oclass->base.maxver = 0; - oclass->ctor = nvkm_perfmon_child_new; - return 0; - } - return -EINVAL; -} - -static void * -nvkm_perfmon_dtor(struct nvkm_object *object) -{ - struct nvkm_perfmon *perfmon = nvkm_perfmon(object); - struct nvkm_pm *pm = perfmon->pm; - spin_lock(&pm->client.lock); - if (pm->client.object == &perfmon->object) - pm->client.object = NULL; - spin_unlock(&pm->client.lock); - return perfmon; -} - -static const struct nvkm_object_func -nvkm_perfmon = { - .dtor = nvkm_perfmon_dtor, - .mthd = nvkm_perfmon_mthd, - .sclass = nvkm_perfmon_child_get, -}; - -static int -nvkm_perfmon_new(struct nvkm_pm *pm, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nvkm_perfmon *perfmon; - - if (!(perfmon = kzalloc(sizeof(*perfmon), GFP_KERNEL))) - return -ENOMEM; - nvkm_object_ctor(&nvkm_perfmon, oclass, &perfmon->object); - perfmon->pm = pm; - *pobject = &perfmon->object; - return 0; -} - -/******************************************************************************* - * PPM engine/subdev functions - ******************************************************************************/ - -static int -nvkm_pm_oclass_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nvkm_pm *pm = nvkm_pm(oclass->engine); - int ret; - - ret = nvkm_perfmon_new(pm, oclass, data, size, pobject); - if (ret) - return ret; - - spin_lock(&pm->client.lock); - if (pm->client.object == NULL) - pm->client.object = *pobject; - ret = (pm->client.object == *pobject) ? 0 : -EBUSY; - spin_unlock(&pm->client.lock); - return ret; -} - -static const struct nvkm_device_oclass -nvkm_pm_oclass = { - .base.oclass = NVIF_CLASS_PERFMON, - .base.minver = -1, - .base.maxver = -1, - .ctor = nvkm_pm_oclass_new, -}; - -static int -nvkm_pm_oclass_get(struct nvkm_oclass *oclass, int index, - const struct nvkm_device_oclass **class) -{ - if (index == 0) { - oclass->base = nvkm_pm_oclass.base; - *class = &nvkm_pm_oclass; - return index; - } - return 1; -} - -static int -nvkm_perfsrc_new(struct nvkm_pm *pm, struct nvkm_perfsig *sig, - const struct nvkm_specsrc *spec) -{ - const struct nvkm_specsrc *ssrc; - const struct nvkm_specmux *smux; - struct nvkm_perfsrc *src; - u8 source_nr = 0; - - if (!spec) { - /* No sources are defined for this signal. */ - return 0; - } - - ssrc = spec; - while (ssrc->name) { - smux = ssrc->mux; - while (smux->name) { - bool found = false; - u8 source_id = 0; - u32 len; - - list_for_each_entry(src, &pm->sources, head) { - if (src->addr == ssrc->addr && - src->shift == smux->shift) { - found = true; - break; - } - source_id++; - } - - if (!found) { - src = kzalloc(sizeof(*src), GFP_KERNEL); - if (!src) - return -ENOMEM; - - src->addr = ssrc->addr; - src->mask = smux->mask; - src->shift = smux->shift; - src->enable = smux->enable; - - len = strlen(ssrc->name) + - strlen(smux->name) + 2; - src->name = kzalloc(len, GFP_KERNEL); - if (!src->name) { - kfree(src); - return -ENOMEM; - } - snprintf(src->name, len, "%s_%s", ssrc->name, - smux->name); - - list_add_tail(&src->head, &pm->sources); - } - - sig->source[source_nr++] = source_id + 1; - smux++; - } - ssrc++; - } - - return 0; -} - -int -nvkm_perfdom_new(struct nvkm_pm *pm, const char *name, u32 mask, - u32 base, u32 size_unit, u32 size_domain, - const struct nvkm_specdom *spec) -{ - const struct nvkm_specdom *sdom; - const struct nvkm_specsig *ssig; - struct nvkm_perfdom *dom; - int ret, i; - - for (i = 0; i == 0 || mask; i++) { - u32 addr = base + (i * size_unit); - if (i && !(mask & (1 << i))) - continue; - - sdom = spec; - while (sdom->signal_nr) { - dom = kzalloc(struct_size(dom, signal, sdom->signal_nr), - GFP_KERNEL); - if (!dom) - return -ENOMEM; - - if (mask) { - snprintf(dom->name, sizeof(dom->name), - "%s/%02x/%02x", name, i, - (int)(sdom - spec)); - } else { - snprintf(dom->name, sizeof(dom->name), - "%s/%02x", name, (int)(sdom - spec)); - } - - list_add_tail(&dom->head, &pm->domains); - INIT_LIST_HEAD(&dom->list); - dom->func = sdom->func; - dom->addr = addr; - dom->signal_nr = sdom->signal_nr; - - ssig = (sdom++)->signal; - while (ssig->name) { - struct nvkm_perfsig *sig = - &dom->signal[ssig->signal]; - sig->name = ssig->name; - ret = nvkm_perfsrc_new(pm, sig, ssig->source); - if (ret) - return ret; - ssig++; - } - - addr += size_domain; - } - - mask &= ~(1 << i); - } - - return 0; -} - -static int -nvkm_pm_fini(struct nvkm_engine *engine, bool suspend) -{ - struct nvkm_pm *pm = nvkm_pm(engine); - if (pm->func->fini) - pm->func->fini(pm); - return 0; -} - -static void * -nvkm_pm_dtor(struct nvkm_engine *engine) -{ - struct nvkm_pm *pm = nvkm_pm(engine); - struct nvkm_perfdom *dom, *next_dom; - struct nvkm_perfsrc *src, *next_src; - - list_for_each_entry_safe(dom, next_dom, &pm->domains, head) { - list_del(&dom->head); - kfree(dom); - } - - list_for_each_entry_safe(src, next_src, &pm->sources, head) { - list_del(&src->head); - kfree(src->name); - kfree(src); - } - - return pm; -} - -static const struct nvkm_engine_func -nvkm_pm = { - .dtor = nvkm_pm_dtor, - .fini = nvkm_pm_fini, - .base.sclass = nvkm_pm_oclass_get, -}; - -int -nvkm_pm_ctor(const struct nvkm_pm_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_pm *pm) -{ - pm->func = func; - INIT_LIST_HEAD(&pm->domains); - INIT_LIST_HEAD(&pm->sources); - spin_lock_init(&pm->client.lock); - return nvkm_engine_ctor(&nvkm_pm, device, type, inst, true, &pm->engine); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/g84.c deleted file mode 100644 index 0086d00eb162..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/g84.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2013 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "nv40.h" - -const struct nvkm_specsrc -g84_vfetch_sources[] = { - { 0x400c0c, (const struct nvkm_specmux[]) { - { 0x3, 0, "unk0" }, - {} - }, "pgraph_vfetch_unk0c" }, - {} -}; - -static const struct nvkm_specsrc -g84_prop_sources[] = { - { 0x408e50, (const struct nvkm_specmux[]) { - { 0x1f, 0, "sel", true }, - {} - }, "pgraph_tpc0_prop_pm_mux" }, - {} -}; - -static const struct nvkm_specsrc -g84_crop_sources[] = { - { 0x407008, (const struct nvkm_specmux[]) { - { 0xf, 0, "sel0", true }, - { 0x7, 16, "sel1", true }, - {} - }, "pgraph_rop0_crop_pm_mux" }, - {} -}; - -static const struct nvkm_specsrc -g84_tex_sources[] = { - { 0x408808, (const struct nvkm_specmux[]) { - { 0xfffff, 0, "unk0" }, - {} - }, "pgraph_tpc0_tex_unk08" }, - {} -}; - -static const struct nvkm_specdom -g84_pm[] = { - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0xf0, (const struct nvkm_specsig[]) { - { 0xbd, "pc01_gr_idle" }, - { 0x5e, "pc01_strmout_00" }, - { 0x5f, "pc01_strmout_01" }, - { 0xd2, "pc01_trast_00" }, - { 0xd3, "pc01_trast_01" }, - { 0xd4, "pc01_trast_02" }, - { 0xd5, "pc01_trast_03" }, - { 0xd8, "pc01_trast_04" }, - { 0xd9, "pc01_trast_05" }, - { 0x5c, "pc01_vattr_00" }, - { 0x5d, "pc01_vattr_01" }, - { 0x66, "pc01_vfetch_00", g84_vfetch_sources }, - { 0x67, "pc01_vfetch_01", g84_vfetch_sources }, - { 0x68, "pc01_vfetch_02", g84_vfetch_sources }, - { 0x69, "pc01_vfetch_03", g84_vfetch_sources }, - { 0x6a, "pc01_vfetch_04", g84_vfetch_sources }, - { 0x6b, "pc01_vfetch_05", g84_vfetch_sources }, - { 0x6c, "pc01_vfetch_06", g84_vfetch_sources }, - { 0x6d, "pc01_vfetch_07", g84_vfetch_sources }, - { 0x6e, "pc01_vfetch_08", g84_vfetch_sources }, - { 0x6f, "pc01_vfetch_09", g84_vfetch_sources }, - { 0x70, "pc01_vfetch_0a", g84_vfetch_sources }, - { 0x71, "pc01_vfetch_0b", g84_vfetch_sources }, - { 0x72, "pc01_vfetch_0c", g84_vfetch_sources }, - { 0x73, "pc01_vfetch_0d", g84_vfetch_sources }, - { 0x74, "pc01_vfetch_0e", g84_vfetch_sources }, - { 0x75, "pc01_vfetch_0f", g84_vfetch_sources }, - { 0x76, "pc01_vfetch_10", g84_vfetch_sources }, - { 0x77, "pc01_vfetch_11", g84_vfetch_sources }, - { 0x78, "pc01_vfetch_12", g84_vfetch_sources }, - { 0x79, "pc01_vfetch_13", g84_vfetch_sources }, - { 0x7a, "pc01_vfetch_14", g84_vfetch_sources }, - { 0x7b, "pc01_vfetch_15", g84_vfetch_sources }, - { 0x7c, "pc01_vfetch_16", g84_vfetch_sources }, - { 0x7d, "pc01_vfetch_17", g84_vfetch_sources }, - { 0x7e, "pc01_vfetch_18", g84_vfetch_sources }, - { 0x7f, "pc01_vfetch_19", g84_vfetch_sources }, - { 0x07, "pc01_zcull_00", nv50_zcull_sources }, - { 0x08, "pc01_zcull_01", nv50_zcull_sources }, - { 0x09, "pc01_zcull_02", nv50_zcull_sources }, - { 0x0a, "pc01_zcull_03", nv50_zcull_sources }, - { 0x0b, "pc01_zcull_04", nv50_zcull_sources }, - { 0x0c, "pc01_zcull_05", nv50_zcull_sources }, - { 0xa4, "pc01_unk00" }, - { 0xec, "pc01_trailer" }, - {} - }, &nv40_perfctr_func }, - { 0xa0, (const struct nvkm_specsig[]) { - { 0x30, "pc02_crop_00", g84_crop_sources }, - { 0x31, "pc02_crop_01", g84_crop_sources }, - { 0x32, "pc02_crop_02", g84_crop_sources }, - { 0x33, "pc02_crop_03", g84_crop_sources }, - { 0x00, "pc02_prop_00", g84_prop_sources }, - { 0x01, "pc02_prop_01", g84_prop_sources }, - { 0x02, "pc02_prop_02", g84_prop_sources }, - { 0x03, "pc02_prop_03", g84_prop_sources }, - { 0x04, "pc02_prop_04", g84_prop_sources }, - { 0x05, "pc02_prop_05", g84_prop_sources }, - { 0x06, "pc02_prop_06", g84_prop_sources }, - { 0x07, "pc02_prop_07", g84_prop_sources }, - { 0x48, "pc02_tex_00", g84_tex_sources }, - { 0x49, "pc02_tex_01", g84_tex_sources }, - { 0x4a, "pc02_tex_02", g84_tex_sources }, - { 0x4b, "pc02_tex_03", g84_tex_sources }, - { 0x1a, "pc02_tex_04", g84_tex_sources }, - { 0x1b, "pc02_tex_05", g84_tex_sources }, - { 0x1c, "pc02_tex_06", g84_tex_sources }, - { 0x44, "pc02_zrop_00", nv50_zrop_sources }, - { 0x45, "pc02_zrop_01", nv50_zrop_sources }, - { 0x46, "pc02_zrop_02", nv50_zrop_sources }, - { 0x47, "pc02_zrop_03", nv50_zrop_sources }, - { 0x8c, "pc02_trailer" }, - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - {} -}; - -int -g84_pm_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_pm **ppm) -{ - return nv40_pm_new_(g84_pm, device, type, inst, ppm); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c deleted file mode 100644 index 8e02701def8e..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2013 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "gf100.h" - -const struct nvkm_specsrc -gf100_pbfb_sources[] = { - { 0x10f100, (const struct nvkm_specmux[]) { - { 0x1, 0, "unk0" }, - { 0x3f, 4, "unk4" }, - {} - }, "pbfb_broadcast_pm_unk100" }, - {} -}; - -const struct nvkm_specsrc -gf100_pmfb_sources[] = { - { 0x140028, (const struct nvkm_specmux[]) { - { 0x3fff, 0, "unk0" }, - { 0x7, 16, "unk16" }, - { 0x3, 24, "unk24" }, - { 0x2, 29, "unk29" }, - {} - }, "pmfb0_pm_unk28" }, - {} -}; - -static const struct nvkm_specsrc -gf100_l1_sources[] = { - { 0x5044a8, (const struct nvkm_specmux[]) { - { 0x3f, 0, "sel", true }, - {} - }, "pgraph_gpc0_tpc0_l1_pm_mux" }, - {} -}; - -static const struct nvkm_specsrc -gf100_tex_sources[] = { - { 0x5042c0, (const struct nvkm_specmux[]) { - { 0xf, 0, "sel0", true }, - { 0x7, 8, "sel1", true }, - {} - }, "pgraph_gpc0_tpc0_tex_pm_mux_c_d" }, - {} -}; - -static const struct nvkm_specsrc -gf100_unk400_sources[] = { - { 0x50440c, (const struct nvkm_specmux[]) { - { 0x3f, 0, "sel", true }, - {} - }, "pgraph_gpc0_tpc0_unk400_pm_mux" }, - {} -}; - -static const struct nvkm_specdom -gf100_pm_hub[] = { - {} -}; - -const struct nvkm_specdom -gf100_pm_gpc[] = { - { 0xe0, (const struct nvkm_specsig[]) { - { 0x00, "gpc00_l1_00", gf100_l1_sources }, - { 0x01, "gpc00_l1_01", gf100_l1_sources }, - { 0x02, "gpc00_l1_02", gf100_l1_sources }, - { 0x03, "gpc00_l1_03", gf100_l1_sources }, - { 0x05, "gpc00_l1_04", gf100_l1_sources }, - { 0x06, "gpc00_l1_05", gf100_l1_sources }, - { 0x0a, "gpc00_tex_00", gf100_tex_sources }, - { 0x0b, "gpc00_tex_01", gf100_tex_sources }, - { 0x0c, "gpc00_tex_02", gf100_tex_sources }, - { 0x0d, "gpc00_tex_03", gf100_tex_sources }, - { 0x0e, "gpc00_tex_04", gf100_tex_sources }, - { 0x0f, "gpc00_tex_05", gf100_tex_sources }, - { 0x10, "gpc00_tex_06", gf100_tex_sources }, - { 0x11, "gpc00_tex_07", gf100_tex_sources }, - { 0x12, "gpc00_tex_08", gf100_tex_sources }, - { 0x26, "gpc00_unk400_00", gf100_unk400_sources }, - {} - }, &gf100_perfctr_func }, - {} -}; - -static const struct nvkm_specdom -gf100_pm_part[] = { - { 0xe0, (const struct nvkm_specsig[]) { - { 0x0f, "part00_pbfb_00", gf100_pbfb_sources }, - { 0x10, "part00_pbfb_01", gf100_pbfb_sources }, - { 0x21, "part00_pmfb_00", gf100_pmfb_sources }, - { 0x04, "part00_pmfb_01", gf100_pmfb_sources }, - { 0x00, "part00_pmfb_02", gf100_pmfb_sources }, - { 0x02, "part00_pmfb_03", gf100_pmfb_sources }, - { 0x01, "part00_pmfb_04", gf100_pmfb_sources }, - { 0x2e, "part00_pmfb_05", gf100_pmfb_sources }, - { 0x2f, "part00_pmfb_06", gf100_pmfb_sources }, - { 0x1b, "part00_pmfb_07", gf100_pmfb_sources }, - { 0x1c, "part00_pmfb_08", gf100_pmfb_sources }, - { 0x1d, "part00_pmfb_09", gf100_pmfb_sources }, - { 0x1e, "part00_pmfb_0a", gf100_pmfb_sources }, - { 0x1f, "part00_pmfb_0b", gf100_pmfb_sources }, - {} - }, &gf100_perfctr_func }, - {} -}; - -static void -gf100_perfctr_init(struct nvkm_pm *pm, struct nvkm_perfdom *dom, - struct nvkm_perfctr *ctr) -{ - struct nvkm_device *device = pm->engine.subdev.device; - u32 log = ctr->logic_op; - u32 src = 0x00000000; - int i; - - for (i = 0; i < 4; i++) - src |= ctr->signal[i] << (i * 8); - - nvkm_wr32(device, dom->addr + 0x09c, 0x00040002 | (dom->mode << 3)); - nvkm_wr32(device, dom->addr + 0x100, 0x00000000); - nvkm_wr32(device, dom->addr + 0x040 + (ctr->slot * 0x08), src); - nvkm_wr32(device, dom->addr + 0x044 + (ctr->slot * 0x08), log); -} - -static void -gf100_perfctr_read(struct nvkm_pm *pm, struct nvkm_perfdom *dom, - struct nvkm_perfctr *ctr) -{ - struct nvkm_device *device = pm->engine.subdev.device; - - switch (ctr->slot) { - case 0: ctr->ctr = nvkm_rd32(device, dom->addr + 0x08c); break; - case 1: ctr->ctr = nvkm_rd32(device, dom->addr + 0x088); break; - case 2: ctr->ctr = nvkm_rd32(device, dom->addr + 0x080); break; - case 3: ctr->ctr = nvkm_rd32(device, dom->addr + 0x090); break; - } - dom->clk = nvkm_rd32(device, dom->addr + 0x070); -} - -static void -gf100_perfctr_next(struct nvkm_pm *pm, struct nvkm_perfdom *dom) -{ - struct nvkm_device *device = pm->engine.subdev.device; - nvkm_wr32(device, dom->addr + 0x06c, dom->signal_nr - 0x40 + 0x27); - nvkm_wr32(device, dom->addr + 0x0ec, 0x00000011); -} - -const struct nvkm_funcdom -gf100_perfctr_func = { - .init = gf100_perfctr_init, - .read = gf100_perfctr_read, - .next = gf100_perfctr_next, -}; - -static void -gf100_pm_fini(struct nvkm_pm *pm) -{ - struct nvkm_device *device = pm->engine.subdev.device; - nvkm_mask(device, 0x000200, 0x10000000, 0x00000000); - nvkm_mask(device, 0x000200, 0x10000000, 0x10000000); -} - -static const struct nvkm_pm_func -gf100_pm_ = { - .fini = gf100_pm_fini, -}; - -int -gf100_pm_new_(const struct gf100_pm_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_pm **ppm) -{ - struct nvkm_pm *pm; - u32 mask; - int ret; - - if (!(pm = *ppm = kzalloc(sizeof(*pm), GFP_KERNEL))) - return -ENOMEM; - - ret = nvkm_pm_ctor(&gf100_pm_, device, type, inst, pm); - if (ret) - return ret; - - /* HUB */ - ret = nvkm_perfdom_new(pm, "hub", 0, 0x1b0000, 0, 0x200, - func->doms_hub); - if (ret) - return ret; - - /* GPC */ - mask = (1 << nvkm_rd32(device, 0x022430)) - 1; - mask &= ~nvkm_rd32(device, 0x022504); - mask &= ~nvkm_rd32(device, 0x022584); - - ret = nvkm_perfdom_new(pm, "gpc", mask, 0x180000, - 0x1000, 0x200, func->doms_gpc); - if (ret) - return ret; - - /* PART */ - mask = (1 << nvkm_rd32(device, 0x022438)) - 1; - mask &= ~nvkm_rd32(device, 0x022548); - mask &= ~nvkm_rd32(device, 0x0225c8); - - ret = nvkm_perfdom_new(pm, "part", mask, 0x1a0000, - 0x1000, 0x200, func->doms_part); - if (ret) - return ret; - - return 0; -} - -static const struct gf100_pm_func -gf100_pm = { - .doms_gpc = gf100_pm_gpc, - .doms_hub = gf100_pm_hub, - .doms_part = gf100_pm_part, -}; - -int -gf100_pm_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_pm **ppm) -{ - return gf100_pm_new_(&gf100_pm, device, type, inst, ppm); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.h deleted file mode 100644 index bc4b014c4e8e..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVKM_PM_NVC0_H__ -#define __NVKM_PM_NVC0_H__ -#include "priv.h" - -struct gf100_pm_func { - const struct nvkm_specdom *doms_hub; - const struct nvkm_specdom *doms_gpc; - const struct nvkm_specdom *doms_part; -}; - -int gf100_pm_new_(const struct gf100_pm_func *, struct nvkm_device *, enum nvkm_subdev_type, int, - struct nvkm_pm **); - -extern const struct nvkm_funcdom gf100_perfctr_func; -extern const struct nvkm_specdom gf100_pm_gpc[]; - -extern const struct nvkm_specsrc gf100_pbfb_sources[]; -extern const struct nvkm_specsrc gf100_pmfb_sources[]; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf108.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf108.c deleted file mode 100644 index 505565866b59..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf108.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2015 Samuel Pitoiset - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Samuel Pitoiset - */ -#include "gf100.h" - -static const struct nvkm_specdom -gf108_pm_hub[] = { - {} -}; - -static const struct nvkm_specdom -gf108_pm_part[] = { - { 0xe0, (const struct nvkm_specsig[]) { - { 0x14, "part00_pbfb_00", gf100_pbfb_sources }, - { 0x15, "part00_pbfb_01", gf100_pbfb_sources }, - { 0x20, "part00_pbfb_02", gf100_pbfb_sources }, - { 0x21, "part00_pbfb_03", gf100_pbfb_sources }, - { 0x01, "part00_pmfb_00", gf100_pmfb_sources }, - { 0x04, "part00_pmfb_01", gf100_pmfb_sources }, - { 0x05, "part00_pmfb_02", gf100_pmfb_sources}, - { 0x07, "part00_pmfb_03", gf100_pmfb_sources }, - { 0x0d, "part00_pmfb_04", gf100_pmfb_sources }, - { 0x12, "part00_pmfb_05", gf100_pmfb_sources }, - { 0x13, "part00_pmfb_06", gf100_pmfb_sources }, - { 0x2c, "part00_pmfb_07", gf100_pmfb_sources }, - { 0x2d, "part00_pmfb_08", gf100_pmfb_sources }, - { 0x2e, "part00_pmfb_09", gf100_pmfb_sources }, - { 0x2f, "part00_pmfb_0a", gf100_pmfb_sources }, - { 0x30, "part00_pmfb_0b", gf100_pmfb_sources }, - {} - }, &gf100_perfctr_func }, - {} -}; - -static const struct gf100_pm_func -gf108_pm = { - .doms_gpc = gf100_pm_gpc, - .doms_hub = gf108_pm_hub, - .doms_part = gf108_pm_part, -}; - -int -gf108_pm_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_pm **ppm) -{ - return gf100_pm_new_(&gf108_pm, device, type, inst, ppm); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf117.c deleted file mode 100644 index c61e8c010bb3..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf117.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2015 Samuel Pitoiset - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Samuel Pitoiset - */ -#include "gf100.h" - -static const struct nvkm_specsrc -gf117_pmfb_sources[] = { - { 0x140028, (const struct nvkm_specmux[]) { - { 0x3fff, 0, "unk0" }, - { 0x7, 16, "unk16" }, - { 0x3, 24, "unk24" }, - { 0x2, 28, "unk28" }, - {} - }, "pmfb0_pm_unk28" }, - { 0x14125c, (const struct nvkm_specmux[]) { - { 0x3fff, 0, "unk0" }, - {} - }, "pmfb0_subp0_pm_unk25c" }, - {} -}; - -static const struct nvkm_specdom -gf117_pm_hub[] = { - {} -}; - -static const struct nvkm_specdom -gf117_pm_part[] = { - { 0xe0, (const struct nvkm_specsig[]) { - { 0x00, "part00_pbfb_00", gf100_pbfb_sources }, - { 0x01, "part00_pbfb_01", gf100_pbfb_sources }, - { 0x12, "part00_pmfb_00", gf117_pmfb_sources }, - { 0x15, "part00_pmfb_01", gf117_pmfb_sources }, - { 0x16, "part00_pmfb_02", gf117_pmfb_sources }, - { 0x18, "part00_pmfb_03", gf117_pmfb_sources }, - { 0x1e, "part00_pmfb_04", gf117_pmfb_sources }, - { 0x23, "part00_pmfb_05", gf117_pmfb_sources }, - { 0x24, "part00_pmfb_06", gf117_pmfb_sources }, - { 0x0c, "part00_pmfb_07", gf117_pmfb_sources }, - { 0x0d, "part00_pmfb_08", gf117_pmfb_sources }, - { 0x0e, "part00_pmfb_09", gf117_pmfb_sources }, - { 0x0f, "part00_pmfb_0a", gf117_pmfb_sources }, - { 0x10, "part00_pmfb_0b", gf117_pmfb_sources }, - {} - }, &gf100_perfctr_func }, - {} -}; - -static const struct gf100_pm_func -gf117_pm = { - .doms_gpc = gf100_pm_gpc, - .doms_hub = gf117_pm_hub, - .doms_part = gf117_pm_part, -}; - -int -gf117_pm_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_pm **ppm) -{ - return gf100_pm_new_(&gf117_pm, device, type, inst, ppm); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk104.c deleted file mode 100644 index 75bf3df1cb18..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk104.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2013 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "gf100.h" - -static const struct nvkm_specsrc -gk104_pmfb_sources[] = { - { 0x140028, (const struct nvkm_specmux[]) { - { 0x3fff, 0, "unk0" }, - { 0x7, 16, "unk16" }, - { 0x3, 24, "unk24" }, - { 0x2, 28, "unk28" }, - {} - }, "pmfb0_pm_unk28" }, - { 0x14125c, (const struct nvkm_specmux[]) { - { 0x3fff, 0, "unk0" }, - {} - }, "pmfb0_subp0_pm_unk25c" }, - { 0x14165c, (const struct nvkm_specmux[]) { - { 0x3fff, 0, "unk0" }, - {} - }, "pmfb0_subp1_pm_unk25c" }, - { 0x141a5c, (const struct nvkm_specmux[]) { - { 0x3fff, 0, "unk0" }, - {} - }, "pmfb0_subp2_pm_unk25c" }, - { 0x141e5c, (const struct nvkm_specmux[]) { - { 0x3fff, 0, "unk0" }, - {} - }, "pmfb0_subp3_pm_unk25c" }, - {} -}; - -static const struct nvkm_specsrc -gk104_tex_sources[] = { - { 0x5042c0, (const struct nvkm_specmux[]) { - { 0xf, 0, "sel0", true }, - { 0x7, 8, "sel1", true }, - {} - }, "pgraph_gpc0_tpc0_tex_pm_mux_c_d" }, - { 0x5042c8, (const struct nvkm_specmux[]) { - { 0x1f, 0, "sel", true }, - {} - }, "pgraph_gpc0_tpc0_tex_pm_unkc8" }, - { 0x5042b8, (const struct nvkm_specmux[]) { - { 0xff, 0, "sel", true }, - {} - }, "pgraph_gpc0_tpc0_tex_pm_unkb8" }, - {} -}; - -static const struct nvkm_specdom -gk104_pm_hub[] = { - { 0x60, (const struct nvkm_specsig[]) { - { 0x47, "hub00_user_0" }, - {} - }, &gf100_perfctr_func }, - { 0x40, (const struct nvkm_specsig[]) { - { 0x27, "hub01_user_0" }, - {} - }, &gf100_perfctr_func }, - { 0x60, (const struct nvkm_specsig[]) { - { 0x47, "hub02_user_0" }, - {} - }, &gf100_perfctr_func }, - { 0x60, (const struct nvkm_specsig[]) { - { 0x47, "hub03_user_0" }, - {} - }, &gf100_perfctr_func }, - { 0x40, (const struct nvkm_specsig[]) { - { 0x03, "host_mmio_rd" }, - { 0x27, "hub04_user_0" }, - {} - }, &gf100_perfctr_func }, - { 0x60, (const struct nvkm_specsig[]) { - { 0x47, "hub05_user_0" }, - {} - }, &gf100_perfctr_func }, - { 0xc0, (const struct nvkm_specsig[]) { - { 0x74, "host_fb_rd3x" }, - { 0x75, "host_fb_rd3x_2" }, - { 0xa7, "hub06_user_0" }, - {} - }, &gf100_perfctr_func }, - { 0x60, (const struct nvkm_specsig[]) { - { 0x47, "hub07_user_0" }, - {} - }, &gf100_perfctr_func }, - {} -}; - -static const struct nvkm_specdom -gk104_pm_gpc[] = { - { 0xe0, (const struct nvkm_specsig[]) { - { 0xc7, "gpc00_user_0" }, - {} - }, &gf100_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &gf100_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - { 0x00, "gpc02_tex_00", gk104_tex_sources }, - { 0x01, "gpc02_tex_01", gk104_tex_sources }, - { 0x02, "gpc02_tex_02", gk104_tex_sources }, - { 0x03, "gpc02_tex_03", gk104_tex_sources }, - { 0x04, "gpc02_tex_04", gk104_tex_sources }, - { 0x05, "gpc02_tex_05", gk104_tex_sources }, - { 0x06, "gpc02_tex_06", gk104_tex_sources }, - { 0x07, "gpc02_tex_07", gk104_tex_sources }, - { 0x08, "gpc02_tex_08", gk104_tex_sources }, - { 0x0a, "gpc02_tex_0a", gk104_tex_sources }, - { 0x0b, "gpc02_tex_0b", gk104_tex_sources }, - { 0x0d, "gpc02_tex_0c", gk104_tex_sources }, - { 0x0c, "gpc02_tex_0d", gk104_tex_sources }, - { 0x0e, "gpc02_tex_0e", gk104_tex_sources }, - { 0x0f, "gpc02_tex_0f", gk104_tex_sources }, - { 0x10, "gpc02_tex_10", gk104_tex_sources }, - { 0x11, "gpc02_tex_11", gk104_tex_sources }, - { 0x12, "gpc02_tex_12", gk104_tex_sources }, - {} - }, &gf100_perfctr_func }, - {} -}; - -static const struct nvkm_specdom -gk104_pm_part[] = { - { 0x60, (const struct nvkm_specsig[]) { - { 0x00, "part00_pbfb_00", gf100_pbfb_sources }, - { 0x01, "part00_pbfb_01", gf100_pbfb_sources }, - { 0x0c, "part00_pmfb_00", gk104_pmfb_sources }, - { 0x0d, "part00_pmfb_01", gk104_pmfb_sources }, - { 0x0e, "part00_pmfb_02", gk104_pmfb_sources }, - { 0x0f, "part00_pmfb_03", gk104_pmfb_sources }, - { 0x10, "part00_pmfb_04", gk104_pmfb_sources }, - { 0x12, "part00_pmfb_05", gk104_pmfb_sources }, - { 0x15, "part00_pmfb_06", gk104_pmfb_sources }, - { 0x16, "part00_pmfb_07", gk104_pmfb_sources }, - { 0x18, "part00_pmfb_08", gk104_pmfb_sources }, - { 0x21, "part00_pmfb_09", gk104_pmfb_sources }, - { 0x25, "part00_pmfb_0a", gk104_pmfb_sources }, - { 0x26, "part00_pmfb_0b", gk104_pmfb_sources }, - { 0x27, "part00_pmfb_0c", gk104_pmfb_sources }, - { 0x47, "part00_user_0" }, - {} - }, &gf100_perfctr_func }, - { 0x60, (const struct nvkm_specsig[]) { - { 0x47, "part01_user_0" }, - {} - }, &gf100_perfctr_func }, - {} -}; - -static const struct gf100_pm_func -gk104_pm = { - .doms_gpc = gk104_pm_gpc, - .doms_hub = gk104_pm_hub, - .doms_part = gk104_pm_part, -}; - -int -gk104_pm_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_pm **ppm) -{ - return gf100_pm_new_(&gk104_pm, device, type, inst, ppm); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gt200.c deleted file mode 100644 index 25874c541486..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gt200.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2015 Nouveau project - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Samuel Pitoiset - */ -#include "nv40.h" - -const struct nvkm_specsrc -gt200_crop_sources[] = { - { 0x407008, (const struct nvkm_specmux[]) { - { 0xf, 0, "sel0", true }, - { 0x1f, 16, "sel1", true }, - {} - }, "pgraph_rop0_crop_pm_mux" }, - {} -}; - -const struct nvkm_specsrc -gt200_prop_sources[] = { - { 0x408750, (const struct nvkm_specmux[]) { - { 0x3f, 0, "sel", true }, - {} - }, "pgraph_tpc0_prop_pm_mux" }, - {} -}; - -const struct nvkm_specsrc -gt200_tex_sources[] = { - { 0x408508, (const struct nvkm_specmux[]) { - { 0xfffff, 0, "unk0" }, - {} - }, "pgraph_tpc0_tex_unk08" }, - {} -}; - -static const struct nvkm_specdom -gt200_pm[] = { - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0xf0, (const struct nvkm_specsig[]) { - { 0xc9, "pc01_gr_idle" }, - { 0x84, "pc01_strmout_00" }, - { 0x85, "pc01_strmout_01" }, - { 0xde, "pc01_trast_00" }, - { 0xdf, "pc01_trast_01" }, - { 0xe0, "pc01_trast_02" }, - { 0xe1, "pc01_trast_03" }, - { 0xe4, "pc01_trast_04" }, - { 0xe5, "pc01_trast_05" }, - { 0x82, "pc01_vattr_00" }, - { 0x83, "pc01_vattr_01" }, - { 0x46, "pc01_vfetch_00", g84_vfetch_sources }, - { 0x47, "pc01_vfetch_01", g84_vfetch_sources }, - { 0x48, "pc01_vfetch_02", g84_vfetch_sources }, - { 0x49, "pc01_vfetch_03", g84_vfetch_sources }, - { 0x4a, "pc01_vfetch_04", g84_vfetch_sources }, - { 0x4b, "pc01_vfetch_05", g84_vfetch_sources }, - { 0x4c, "pc01_vfetch_06", g84_vfetch_sources }, - { 0x4d, "pc01_vfetch_07", g84_vfetch_sources }, - { 0x4e, "pc01_vfetch_08", g84_vfetch_sources }, - { 0x4f, "pc01_vfetch_09", g84_vfetch_sources }, - { 0x50, "pc01_vfetch_0a", g84_vfetch_sources }, - { 0x51, "pc01_vfetch_0b", g84_vfetch_sources }, - { 0x52, "pc01_vfetch_0c", g84_vfetch_sources }, - { 0x53, "pc01_vfetch_0d", g84_vfetch_sources }, - { 0x54, "pc01_vfetch_0e", g84_vfetch_sources }, - { 0x55, "pc01_vfetch_0f", g84_vfetch_sources }, - { 0x56, "pc01_vfetch_10", g84_vfetch_sources }, - { 0x57, "pc01_vfetch_11", g84_vfetch_sources }, - { 0x58, "pc01_vfetch_12", g84_vfetch_sources }, - { 0x59, "pc01_vfetch_13", g84_vfetch_sources }, - { 0x5a, "pc01_vfetch_14", g84_vfetch_sources }, - { 0x5b, "pc01_vfetch_15", g84_vfetch_sources }, - { 0x5c, "pc01_vfetch_16", g84_vfetch_sources }, - { 0x5d, "pc01_vfetch_17", g84_vfetch_sources }, - { 0x5e, "pc01_vfetch_18", g84_vfetch_sources }, - { 0x5f, "pc01_vfetch_19", g84_vfetch_sources }, - { 0x07, "pc01_zcull_00", nv50_zcull_sources }, - { 0x08, "pc01_zcull_01", nv50_zcull_sources }, - { 0x09, "pc01_zcull_02", nv50_zcull_sources }, - { 0x0a, "pc01_zcull_03", nv50_zcull_sources }, - { 0x0b, "pc01_zcull_04", nv50_zcull_sources }, - { 0x0c, "pc01_zcull_05", nv50_zcull_sources }, - - { 0xb0, "pc01_unk00" }, - { 0xec, "pc01_trailer" }, - {} - }, &nv40_perfctr_func }, - { 0xf0, (const struct nvkm_specsig[]) { - { 0x55, "pc02_crop_00", gt200_crop_sources }, - { 0x56, "pc02_crop_01", gt200_crop_sources }, - { 0x57, "pc02_crop_02", gt200_crop_sources }, - { 0x58, "pc02_crop_03", gt200_crop_sources }, - { 0x00, "pc02_prop_00", gt200_prop_sources }, - { 0x01, "pc02_prop_01", gt200_prop_sources }, - { 0x02, "pc02_prop_02", gt200_prop_sources }, - { 0x03, "pc02_prop_03", gt200_prop_sources }, - { 0x04, "pc02_prop_04", gt200_prop_sources }, - { 0x05, "pc02_prop_05", gt200_prop_sources }, - { 0x06, "pc02_prop_06", gt200_prop_sources }, - { 0x07, "pc02_prop_07", gt200_prop_sources }, - { 0x78, "pc02_tex_00", gt200_tex_sources }, - { 0x79, "pc02_tex_01", gt200_tex_sources }, - { 0x7a, "pc02_tex_02", gt200_tex_sources }, - { 0x7b, "pc02_tex_03", gt200_tex_sources }, - { 0x32, "pc02_tex_04", gt200_tex_sources }, - { 0x33, "pc02_tex_05", gt200_tex_sources }, - { 0x34, "pc02_tex_06", gt200_tex_sources }, - { 0x74, "pc02_zrop_00", nv50_zrop_sources }, - { 0x75, "pc02_zrop_01", nv50_zrop_sources }, - { 0x76, "pc02_zrop_02", nv50_zrop_sources }, - { 0x77, "pc02_zrop_03", nv50_zrop_sources }, - { 0xec, "pc02_trailer" }, - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - {} -}; - -int -gt200_pm_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_pm **ppm) -{ - return nv40_pm_new_(gt200_pm, device, type, inst, ppm); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gt215.c deleted file mode 100644 index 54c23e2b6645..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gt215.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2013 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "nv40.h" - -static const struct nvkm_specsrc -gt215_zcull_sources[] = { - { 0x402ca4, (const struct nvkm_specmux[]) { - { 0x7fff, 0, "unk0" }, - { 0xff, 24, "unk24" }, - {} - }, "pgraph_zcull_pm_unka4" }, - {} -}; - -static const struct nvkm_specdom -gt215_pm[] = { - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0xf0, (const struct nvkm_specsig[]) { - { 0xcb, "pc01_gr_idle" }, - { 0x86, "pc01_strmout_00" }, - { 0x87, "pc01_strmout_01" }, - { 0xe0, "pc01_trast_00" }, - { 0xe1, "pc01_trast_01" }, - { 0xe2, "pc01_trast_02" }, - { 0xe3, "pc01_trast_03" }, - { 0xe6, "pc01_trast_04" }, - { 0xe7, "pc01_trast_05" }, - { 0x84, "pc01_vattr_00" }, - { 0x85, "pc01_vattr_01" }, - { 0x46, "pc01_vfetch_00", g84_vfetch_sources }, - { 0x47, "pc01_vfetch_01", g84_vfetch_sources }, - { 0x48, "pc01_vfetch_02", g84_vfetch_sources }, - { 0x49, "pc01_vfetch_03", g84_vfetch_sources }, - { 0x4a, "pc01_vfetch_04", g84_vfetch_sources }, - { 0x4b, "pc01_vfetch_05", g84_vfetch_sources }, - { 0x4c, "pc01_vfetch_06", g84_vfetch_sources }, - { 0x4d, "pc01_vfetch_07", g84_vfetch_sources }, - { 0x4e, "pc01_vfetch_08", g84_vfetch_sources }, - { 0x4f, "pc01_vfetch_09", g84_vfetch_sources }, - { 0x50, "pc01_vfetch_0a", g84_vfetch_sources }, - { 0x51, "pc01_vfetch_0b", g84_vfetch_sources }, - { 0x52, "pc01_vfetch_0c", g84_vfetch_sources }, - { 0x53, "pc01_vfetch_0d", g84_vfetch_sources }, - { 0x54, "pc01_vfetch_0e", g84_vfetch_sources }, - { 0x55, "pc01_vfetch_0f", g84_vfetch_sources }, - { 0x56, "pc01_vfetch_10", g84_vfetch_sources }, - { 0x57, "pc01_vfetch_11", g84_vfetch_sources }, - { 0x58, "pc01_vfetch_12", g84_vfetch_sources }, - { 0x59, "pc01_vfetch_13", g84_vfetch_sources }, - { 0x5a, "pc01_vfetch_14", g84_vfetch_sources }, - { 0x5b, "pc01_vfetch_15", g84_vfetch_sources }, - { 0x5c, "pc01_vfetch_16", g84_vfetch_sources }, - { 0x5d, "pc01_vfetch_17", g84_vfetch_sources }, - { 0x5e, "pc01_vfetch_18", g84_vfetch_sources }, - { 0x5f, "pc01_vfetch_19", g84_vfetch_sources }, - { 0x07, "pc01_zcull_00", gt215_zcull_sources }, - { 0x08, "pc01_zcull_01", gt215_zcull_sources }, - { 0x09, "pc01_zcull_02", gt215_zcull_sources }, - { 0x0a, "pc01_zcull_03", gt215_zcull_sources }, - { 0x0b, "pc01_zcull_04", gt215_zcull_sources }, - { 0x0c, "pc01_zcull_05", gt215_zcull_sources }, - { 0xb2, "pc01_unk00" }, - { 0xec, "pc01_trailer" }, - {} - }, &nv40_perfctr_func }, - { 0xe0, (const struct nvkm_specsig[]) { - { 0x64, "pc02_crop_00", gt200_crop_sources }, - { 0x65, "pc02_crop_01", gt200_crop_sources }, - { 0x66, "pc02_crop_02", gt200_crop_sources }, - { 0x67, "pc02_crop_03", gt200_crop_sources }, - { 0x00, "pc02_prop_00", gt200_prop_sources }, - { 0x01, "pc02_prop_01", gt200_prop_sources }, - { 0x02, "pc02_prop_02", gt200_prop_sources }, - { 0x03, "pc02_prop_03", gt200_prop_sources }, - { 0x04, "pc02_prop_04", gt200_prop_sources }, - { 0x05, "pc02_prop_05", gt200_prop_sources }, - { 0x06, "pc02_prop_06", gt200_prop_sources }, - { 0x07, "pc02_prop_07", gt200_prop_sources }, - { 0x80, "pc02_tex_00", gt200_tex_sources }, - { 0x81, "pc02_tex_01", gt200_tex_sources }, - { 0x82, "pc02_tex_02", gt200_tex_sources }, - { 0x83, "pc02_tex_03", gt200_tex_sources }, - { 0x3a, "pc02_tex_04", gt200_tex_sources }, - { 0x3b, "pc02_tex_05", gt200_tex_sources }, - { 0x3c, "pc02_tex_06", gt200_tex_sources }, - { 0x7c, "pc02_zrop_00", nv50_zrop_sources }, - { 0x7d, "pc02_zrop_01", nv50_zrop_sources }, - { 0x7e, "pc02_zrop_02", nv50_zrop_sources }, - { 0x7f, "pc02_zrop_03", nv50_zrop_sources }, - { 0xcc, "pc02_trailer" }, - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - {} -}; - -int -gt215_pm_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_pm **ppm) -{ - return nv40_pm_new_(gt215_pm, device, type, inst, ppm); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c deleted file mode 100644 index eba5b3b79340..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2013 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "nv40.h" - -static void -nv40_perfctr_init(struct nvkm_pm *pm, struct nvkm_perfdom *dom, - struct nvkm_perfctr *ctr) -{ - struct nvkm_device *device = pm->engine.subdev.device; - u32 log = ctr->logic_op; - u32 src = 0x00000000; - int i; - - for (i = 0; i < 4; i++) - src |= ctr->signal[i] << (i * 8); - - nvkm_wr32(device, 0x00a7c0 + dom->addr, 0x00000001 | (dom->mode << 4)); - nvkm_wr32(device, 0x00a400 + dom->addr + (ctr->slot * 0x40), src); - nvkm_wr32(device, 0x00a420 + dom->addr + (ctr->slot * 0x40), log); -} - -static void -nv40_perfctr_read(struct nvkm_pm *pm, struct nvkm_perfdom *dom, - struct nvkm_perfctr *ctr) -{ - struct nvkm_device *device = pm->engine.subdev.device; - - switch (ctr->slot) { - case 0: ctr->ctr = nvkm_rd32(device, 0x00a700 + dom->addr); break; - case 1: ctr->ctr = nvkm_rd32(device, 0x00a6c0 + dom->addr); break; - case 2: ctr->ctr = nvkm_rd32(device, 0x00a680 + dom->addr); break; - case 3: ctr->ctr = nvkm_rd32(device, 0x00a740 + dom->addr); break; - } - dom->clk = nvkm_rd32(device, 0x00a600 + dom->addr); -} - -static void -nv40_perfctr_next(struct nvkm_pm *pm, struct nvkm_perfdom *dom) -{ - struct nvkm_device *device = pm->engine.subdev.device; - struct nv40_pm *nv40pm = container_of(pm, struct nv40_pm, base); - - if (nv40pm->sequence != pm->sequence) { - nvkm_wr32(device, 0x400084, 0x00000020); - nv40pm->sequence = pm->sequence; - } -} - -const struct nvkm_funcdom -nv40_perfctr_func = { - .init = nv40_perfctr_init, - .read = nv40_perfctr_read, - .next = nv40_perfctr_next, -}; - -static const struct nvkm_pm_func -nv40_pm_ = { -}; - -int -nv40_pm_new_(const struct nvkm_specdom *doms, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_pm **ppm) -{ - struct nv40_pm *pm; - int ret; - - if (!(pm = kzalloc(sizeof(*pm), GFP_KERNEL))) - return -ENOMEM; - *ppm = &pm->base; - - ret = nvkm_pm_ctor(&nv40_pm_, device, type, inst, &pm->base); - if (ret) - return ret; - - return nvkm_perfdom_new(&pm->base, "pc", 0, 0, 0, 4, doms); -} - -static const struct nvkm_specdom -nv40_pm[] = { - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - {} -}; - -int -nv40_pm_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_pm **ppm) -{ - return nv40_pm_new_(nv40_pm, device, type, inst, ppm); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.h b/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.h deleted file mode 100644 index afb79843723d..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVKM_PM_NV40_H__ -#define __NVKM_PM_NV40_H__ -#define nv40_pm(p) container_of((p), struct nv40_pm, base) -#include "priv.h" - -struct nv40_pm { - struct nvkm_pm base; - u32 sequence; -}; - -int nv40_pm_new_(const struct nvkm_specdom *, struct nvkm_device *, enum nvkm_subdev_type, int, - struct nvkm_pm **); -extern const struct nvkm_funcdom nv40_perfctr_func; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv50.c deleted file mode 100644 index bbd3404901f9..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv50.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2013 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "nv40.h" - -const struct nvkm_specsrc -nv50_zcull_sources[] = { - { 0x402ca4, (const struct nvkm_specmux[]) { - { 0x7fff, 0, "unk0" }, - {} - }, "pgraph_zcull_pm_unka4" }, - {} -}; - -const struct nvkm_specsrc -nv50_zrop_sources[] = { - { 0x40708c, (const struct nvkm_specmux[]) { - { 0xf, 0, "sel0", true }, - { 0xf, 16, "sel1", true }, - {} - }, "pgraph_rop0_zrop_pm_mux" }, - {} -}; - -static const struct nvkm_specsrc -nv50_prop_sources[] = { - { 0x40be50, (const struct nvkm_specmux[]) { - { 0x1f, 0, "sel", true }, - {} - }, "pgraph_tpc3_prop_pm_mux" }, - {} -}; - -static const struct nvkm_specsrc -nv50_crop_sources[] = { - { 0x407008, (const struct nvkm_specmux[]) { - { 0x7, 0, "sel0", true }, - { 0x7, 16, "sel1", true }, - {} - }, "pgraph_rop0_crop_pm_mux" }, - {} -}; - -static const struct nvkm_specsrc -nv50_tex_sources[] = { - { 0x40b808, (const struct nvkm_specmux[]) { - { 0x3fff, 0, "unk0" }, - {} - }, "pgraph_tpc3_tex_unk08" }, - {} -}; - -static const struct nvkm_specsrc -nv50_vfetch_sources[] = { - { 0x400c0c, (const struct nvkm_specmux[]) { - { 0x1, 0, "unk0" }, - {} - }, "pgraph_vfetch_unk0c" }, - {} -}; - -static const struct nvkm_specdom -nv50_pm[] = { - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0xf0, (const struct nvkm_specsig[]) { - { 0xc8, "pc01_gr_idle" }, - { 0x7f, "pc01_strmout_00" }, - { 0x80, "pc01_strmout_01" }, - { 0xdc, "pc01_trast_00" }, - { 0xdd, "pc01_trast_01" }, - { 0xde, "pc01_trast_02" }, - { 0xdf, "pc01_trast_03" }, - { 0xe2, "pc01_trast_04" }, - { 0xe3, "pc01_trast_05" }, - { 0x7c, "pc01_vattr_00" }, - { 0x7d, "pc01_vattr_01" }, - { 0x26, "pc01_vfetch_00", nv50_vfetch_sources }, - { 0x27, "pc01_vfetch_01", nv50_vfetch_sources }, - { 0x28, "pc01_vfetch_02", nv50_vfetch_sources }, - { 0x29, "pc01_vfetch_03", nv50_vfetch_sources }, - { 0x2a, "pc01_vfetch_04", nv50_vfetch_sources }, - { 0x2b, "pc01_vfetch_05", nv50_vfetch_sources }, - { 0x2c, "pc01_vfetch_06", nv50_vfetch_sources }, - { 0x2d, "pc01_vfetch_07", nv50_vfetch_sources }, - { 0x2e, "pc01_vfetch_08", nv50_vfetch_sources }, - { 0x2f, "pc01_vfetch_09", nv50_vfetch_sources }, - { 0x30, "pc01_vfetch_0a", nv50_vfetch_sources }, - { 0x31, "pc01_vfetch_0b", nv50_vfetch_sources }, - { 0x32, "pc01_vfetch_0c", nv50_vfetch_sources }, - { 0x33, "pc01_vfetch_0d", nv50_vfetch_sources }, - { 0x34, "pc01_vfetch_0e", nv50_vfetch_sources }, - { 0x35, "pc01_vfetch_0f", nv50_vfetch_sources }, - { 0x36, "pc01_vfetch_10", nv50_vfetch_sources }, - { 0x37, "pc01_vfetch_11", nv50_vfetch_sources }, - { 0x38, "pc01_vfetch_12", nv50_vfetch_sources }, - { 0x39, "pc01_vfetch_13", nv50_vfetch_sources }, - { 0x3a, "pc01_vfetch_14", nv50_vfetch_sources }, - { 0x3b, "pc01_vfetch_15", nv50_vfetch_sources }, - { 0x3c, "pc01_vfetch_16", nv50_vfetch_sources }, - { 0x3d, "pc01_vfetch_17", nv50_vfetch_sources }, - { 0x3e, "pc01_vfetch_18", nv50_vfetch_sources }, - { 0x3f, "pc01_vfetch_19", nv50_vfetch_sources }, - { 0x20, "pc01_zcull_00", nv50_zcull_sources }, - { 0x21, "pc01_zcull_01", nv50_zcull_sources }, - { 0x22, "pc01_zcull_02", nv50_zcull_sources }, - { 0x23, "pc01_zcull_03", nv50_zcull_sources }, - { 0x24, "pc01_zcull_04", nv50_zcull_sources }, - { 0x25, "pc01_zcull_05", nv50_zcull_sources }, - { 0xae, "pc01_unk00" }, - { 0xee, "pc01_trailer" }, - {} - }, &nv40_perfctr_func }, - { 0xf0, (const struct nvkm_specsig[]) { - { 0x52, "pc02_crop_00", nv50_crop_sources }, - { 0x53, "pc02_crop_01", nv50_crop_sources }, - { 0x54, "pc02_crop_02", nv50_crop_sources }, - { 0x55, "pc02_crop_03", nv50_crop_sources }, - { 0x00, "pc02_prop_00", nv50_prop_sources }, - { 0x01, "pc02_prop_01", nv50_prop_sources }, - { 0x02, "pc02_prop_02", nv50_prop_sources }, - { 0x03, "pc02_prop_03", nv50_prop_sources }, - { 0x04, "pc02_prop_04", nv50_prop_sources }, - { 0x05, "pc02_prop_05", nv50_prop_sources }, - { 0x06, "pc02_prop_06", nv50_prop_sources }, - { 0x07, "pc02_prop_07", nv50_prop_sources }, - { 0x70, "pc02_tex_00", nv50_tex_sources }, - { 0x71, "pc02_tex_01", nv50_tex_sources }, - { 0x72, "pc02_tex_02", nv50_tex_sources }, - { 0x73, "pc02_tex_03", nv50_tex_sources }, - { 0x40, "pc02_tex_04", nv50_tex_sources }, - { 0x41, "pc02_tex_05", nv50_tex_sources }, - { 0x42, "pc02_tex_06", nv50_tex_sources }, - { 0x6c, "pc02_zrop_00", nv50_zrop_sources }, - { 0x6d, "pc02_zrop_01", nv50_zrop_sources }, - { 0x6e, "pc02_zrop_02", nv50_zrop_sources }, - { 0x6f, "pc02_zrop_03", nv50_zrop_sources }, - { 0xee, "pc02_trailer" }, - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - { 0x20, (const struct nvkm_specsig[]) { - {} - }, &nv40_perfctr_func }, - {} -}; - -int -nv50_pm_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_pm **ppm) -{ - return nv40_pm_new_(nv50_pm, device, type, inst, ppm); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h deleted file mode 100644 index c011227f7052..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h +++ /dev/null @@ -1,105 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVKM_PM_PRIV_H__ -#define __NVKM_PM_PRIV_H__ -#define nvkm_pm(p) container_of((p), struct nvkm_pm, engine) -#include <engine/pm.h> - -int nvkm_pm_ctor(const struct nvkm_pm_func *, struct nvkm_device *, enum nvkm_subdev_type, int, - struct nvkm_pm *); - -struct nvkm_pm_func { - void (*fini)(struct nvkm_pm *); -}; - -struct nvkm_perfctr { - struct list_head head; - u8 domain; - u8 signal[4]; - u64 source[4][8]; - int slot; - u32 logic_op; - u32 ctr; -}; - -struct nvkm_specmux { - u32 mask; - u8 shift; - const char *name; - bool enable; -}; - -struct nvkm_specsrc { - u32 addr; - const struct nvkm_specmux *mux; - const char *name; -}; - -struct nvkm_perfsrc { - struct list_head head; - char *name; - u32 addr; - u32 mask; - u8 shift; - bool enable; -}; - -extern const struct nvkm_specsrc nv50_zcull_sources[]; -extern const struct nvkm_specsrc nv50_zrop_sources[]; -extern const struct nvkm_specsrc g84_vfetch_sources[]; -extern const struct nvkm_specsrc gt200_crop_sources[]; -extern const struct nvkm_specsrc gt200_prop_sources[]; -extern const struct nvkm_specsrc gt200_tex_sources[]; - -struct nvkm_specsig { - u8 signal; - const char *name; - const struct nvkm_specsrc *source; -}; - -struct nvkm_perfsig { - const char *name; - u8 source[8]; -}; - -struct nvkm_specdom { - u16 signal_nr; - const struct nvkm_specsig *signal; - const struct nvkm_funcdom *func; -}; - -#define nvkm_perfdom(p) container_of((p), struct nvkm_perfdom, object) -#include <core/object.h> - -struct nvkm_perfdom { - struct nvkm_object object; - struct nvkm_perfmon *perfmon; - struct list_head head; - struct list_head list; - const struct nvkm_funcdom *func; - struct nvkm_perfctr *ctr[4]; - char name[32]; - u32 addr; - u8 mode; - u32 clk; - u16 signal_nr; - struct nvkm_perfsig signal[] __counted_by(signal_nr); -}; - -struct nvkm_funcdom { - void (*init)(struct nvkm_pm *, struct nvkm_perfdom *, - struct nvkm_perfctr *); - void (*read)(struct nvkm_pm *, struct nvkm_perfdom *, - struct nvkm_perfctr *); - void (*next)(struct nvkm_pm *, struct nvkm_perfdom *); -}; - -int nvkm_perfdom_new(struct nvkm_pm *, const char *, u32, u32, u32, u32, - const struct nvkm_specdom *); - -#define nvkm_perfmon(p) container_of((p), struct nvkm_perfmon, object) - -struct nvkm_perfmon { - struct nvkm_object object; - struct nvkm_pm *pm; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c b/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c index 80a480b12174..cac6d64ab67d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c @@ -89,6 +89,7 @@ nvkm_falcon_fw_boot(struct nvkm_falcon_fw *fw, struct nvkm_subdev *user, nvkm_falcon_fw_dtor_sigs(fw); } + FLCNFW_DBG(fw, "resetting"); fw->func->reset(fw); @@ -99,6 +100,12 @@ nvkm_falcon_fw_boot(struct nvkm_falcon_fw *fw, struct nvkm_subdev *user, goto done; } + /* after last write to the img, sync dma mappings */ + dma_sync_single_for_device(fw->fw.device->dev, + fw->fw.phys, + sg_dma_len(&fw->fw.mem.sgl), + DMA_TO_DEVICE); + ret = fw->func->load(fw); if (ret) goto done; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c index f36a359d4531..bd104a030243 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c @@ -218,7 +218,7 @@ nvkm_acr_lsfw_load_sig_image_desc_v2(struct nvkm_subdev *subdev, const struct firmware *hsbl; const struct nvfw_ls_hsbl_bin_hdr *hdr; const struct nvfw_ls_hsbl_hdr *hshdr; - u32 loc, sig, cnt, *meta; + u32 sig, cnt, *meta; ret = nvkm_firmware_load_name(subdev, path, "hs_bl_sig", ver, &hsbl); if (ret) @@ -227,7 +227,6 @@ nvkm_acr_lsfw_load_sig_image_desc_v2(struct nvkm_subdev *subdev, hdr = nvfw_ls_hsbl_bin_hdr(subdev, hsbl->data); hshdr = nvfw_ls_hsbl_hdr(subdev, hsbl->data + hdr->header_offset); meta = (u32 *)(hsbl->data + hshdr->meta_data_offset); - loc = *(u32 *)(hsbl->data + hshdr->patch_loc); sig = *(u32 *)(hsbl->data + hshdr->patch_sig); cnt = *(u32 *)(hsbl->data + hshdr->num_sig); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c index 142079403864..b54f044c4483 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c @@ -575,7 +575,7 @@ init_tmds_reg(struct nvbios_init *init, u8 tmds) * init opcode handlers *****************************************************************************/ -/** +/* * init_reserved - stub for various unknown/unused single-byte opcodes * */ @@ -602,7 +602,7 @@ init_reserved(struct nvbios_init *init) init->offset += length; } -/** +/* * INIT_DONE - opcode 0x71 * */ @@ -613,7 +613,7 @@ init_done(struct nvbios_init *init) init->offset = 0x0000; } -/** +/* * INIT_IO_RESTRICT_PROG - opcode 0x32 * */ @@ -650,7 +650,7 @@ init_io_restrict_prog(struct nvbios_init *init) trace("}]\n"); } -/** +/* * INIT_REPEAT - opcode 0x33 * */ @@ -676,7 +676,7 @@ init_repeat(struct nvbios_init *init) init->repeat = repeat; } -/** +/* * INIT_IO_RESTRICT_PLL - opcode 0x34 * */ @@ -716,7 +716,7 @@ init_io_restrict_pll(struct nvbios_init *init) trace("}]\n"); } -/** +/* * INIT_END_REPEAT - opcode 0x36 * */ @@ -732,7 +732,7 @@ init_end_repeat(struct nvbios_init *init) } } -/** +/* * INIT_COPY - opcode 0x37 * */ @@ -759,7 +759,7 @@ init_copy(struct nvbios_init *init) init_wrvgai(init, port, index, data); } -/** +/* * INIT_NOT - opcode 0x38 * */ @@ -771,7 +771,7 @@ init_not(struct nvbios_init *init) init_exec_inv(init); } -/** +/* * INIT_IO_FLAG_CONDITION - opcode 0x39 * */ @@ -788,7 +788,7 @@ init_io_flag_condition(struct nvbios_init *init) init_exec_set(init, false); } -/** +/* * INIT_GENERIC_CONDITION - opcode 0x3a * */ @@ -840,7 +840,7 @@ init_generic_condition(struct nvbios_init *init) } } -/** +/* * INIT_IO_MASK_OR - opcode 0x3b * */ @@ -859,7 +859,7 @@ init_io_mask_or(struct nvbios_init *init) init_wrvgai(init, 0x03d4, index, data &= ~(1 << or)); } -/** +/* * INIT_IO_OR - opcode 0x3c * */ @@ -878,7 +878,7 @@ init_io_or(struct nvbios_init *init) init_wrvgai(init, 0x03d4, index, data | (1 << or)); } -/** +/* * INIT_ANDN_REG - opcode 0x47 * */ @@ -895,7 +895,7 @@ init_andn_reg(struct nvbios_init *init) init_mask(init, reg, mask, 0); } -/** +/* * INIT_OR_REG - opcode 0x48 * */ @@ -912,7 +912,7 @@ init_or_reg(struct nvbios_init *init) init_mask(init, reg, 0, mask); } -/** +/* * INIT_INDEX_ADDRESS_LATCHED - opcode 0x49 * */ @@ -942,7 +942,7 @@ init_idx_addr_latched(struct nvbios_init *init) } } -/** +/* * INIT_IO_RESTRICT_PLL2 - opcode 0x4a * */ @@ -977,7 +977,7 @@ init_io_restrict_pll2(struct nvbios_init *init) trace("}]\n"); } -/** +/* * INIT_PLL2 - opcode 0x4b * */ @@ -994,7 +994,7 @@ init_pll2(struct nvbios_init *init) init_prog_pll(init, reg, freq); } -/** +/* * INIT_I2C_BYTE - opcode 0x4c * */ @@ -1025,7 +1025,7 @@ init_i2c_byte(struct nvbios_init *init) } } -/** +/* * INIT_ZM_I2C_BYTE - opcode 0x4d * */ @@ -1051,7 +1051,7 @@ init_zm_i2c_byte(struct nvbios_init *init) } } -/** +/* * INIT_ZM_I2C - opcode 0x4e * */ @@ -1085,7 +1085,7 @@ init_zm_i2c(struct nvbios_init *init) } } -/** +/* * INIT_TMDS - opcode 0x4f * */ @@ -1111,7 +1111,7 @@ init_tmds(struct nvbios_init *init) init_wr32(init, reg + 0, addr); } -/** +/* * INIT_ZM_TMDS_GROUP - opcode 0x50 * */ @@ -1138,7 +1138,7 @@ init_zm_tmds_group(struct nvbios_init *init) } } -/** +/* * INIT_CR_INDEX_ADDRESS_LATCHED - opcode 0x51 * */ @@ -1168,7 +1168,7 @@ init_cr_idx_adr_latch(struct nvbios_init *init) init_wrvgai(init, 0x03d4, addr0, save0); } -/** +/* * INIT_CR - opcode 0x52 * */ @@ -1188,7 +1188,7 @@ init_cr(struct nvbios_init *init) init_wrvgai(init, 0x03d4, addr, val | data); } -/** +/* * INIT_ZM_CR - opcode 0x53 * */ @@ -1205,7 +1205,7 @@ init_zm_cr(struct nvbios_init *init) init_wrvgai(init, 0x03d4, addr, data); } -/** +/* * INIT_ZM_CR_GROUP - opcode 0x54 * */ @@ -1229,7 +1229,7 @@ init_zm_cr_group(struct nvbios_init *init) } } -/** +/* * INIT_CONDITION_TIME - opcode 0x56 * */ @@ -1256,7 +1256,7 @@ init_condition_time(struct nvbios_init *init) init_exec_set(init, false); } -/** +/* * INIT_LTIME - opcode 0x57 * */ @@ -1273,7 +1273,7 @@ init_ltime(struct nvbios_init *init) mdelay(msec); } -/** +/* * INIT_ZM_REG_SEQUENCE - opcode 0x58 * */ @@ -1298,7 +1298,7 @@ init_zm_reg_sequence(struct nvbios_init *init) } } -/** +/* * INIT_PLL_INDIRECT - opcode 0x59 * */ @@ -1317,7 +1317,7 @@ init_pll_indirect(struct nvbios_init *init) init_prog_pll(init, reg, freq); } -/** +/* * INIT_ZM_REG_INDIRECT - opcode 0x5a * */ @@ -1336,7 +1336,7 @@ init_zm_reg_indirect(struct nvbios_init *init) init_wr32(init, addr, data); } -/** +/* * INIT_SUB_DIRECT - opcode 0x5b * */ @@ -1362,7 +1362,7 @@ init_sub_direct(struct nvbios_init *init) init->offset += 3; } -/** +/* * INIT_JUMP - opcode 0x5c * */ @@ -1380,7 +1380,7 @@ init_jump(struct nvbios_init *init) init->offset += 3; } -/** +/* * INIT_I2C_IF - opcode 0x5e * */ @@ -1407,7 +1407,7 @@ init_i2c_if(struct nvbios_init *init) init_exec_force(init, false); } -/** +/* * INIT_COPY_NV_REG - opcode 0x5f * */ @@ -1433,7 +1433,7 @@ init_copy_nv_reg(struct nvbios_init *init) init_mask(init, dreg, ~dmask, (data & smask) ^ sxor); } -/** +/* * INIT_ZM_INDEX_IO - opcode 0x62 * */ @@ -1451,7 +1451,7 @@ init_zm_index_io(struct nvbios_init *init) init_wrvgai(init, port, index, data); } -/** +/* * INIT_COMPUTE_MEM - opcode 0x63 * */ @@ -1469,7 +1469,7 @@ init_compute_mem(struct nvbios_init *init) init_exec_force(init, false); } -/** +/* * INIT_RESET - opcode 0x65 * */ @@ -1496,7 +1496,7 @@ init_reset(struct nvbios_init *init) init_exec_force(init, false); } -/** +/* * INIT_CONFIGURE_MEM - opcode 0x66 * */ @@ -1555,7 +1555,7 @@ init_configure_mem(struct nvbios_init *init) init_exec_force(init, false); } -/** +/* * INIT_CONFIGURE_CLK - opcode 0x67 * */ @@ -1589,7 +1589,7 @@ init_configure_clk(struct nvbios_init *init) init_exec_force(init, false); } -/** +/* * INIT_CONFIGURE_PREINIT - opcode 0x68 * */ @@ -1615,7 +1615,7 @@ init_configure_preinit(struct nvbios_init *init) init_exec_force(init, false); } -/** +/* * INIT_IO - opcode 0x69 * */ @@ -1655,7 +1655,7 @@ init_io(struct nvbios_init *init) init_wrport(init, port, data | value); } -/** +/* * INIT_SUB - opcode 0x6b * */ @@ -1682,7 +1682,7 @@ init_sub(struct nvbios_init *init) init->offset += 2; } -/** +/* * INIT_RAM_CONDITION - opcode 0x6d * */ @@ -1701,7 +1701,7 @@ init_ram_condition(struct nvbios_init *init) init_exec_set(init, false); } -/** +/* * INIT_NV_REG - opcode 0x6e * */ @@ -1719,7 +1719,7 @@ init_nv_reg(struct nvbios_init *init) init_mask(init, reg, ~mask, data); } -/** +/* * INIT_MACRO - opcode 0x6f * */ @@ -1743,7 +1743,7 @@ init_macro(struct nvbios_init *init) init->offset += 2; } -/** +/* * INIT_RESUME - opcode 0x72 * */ @@ -1755,7 +1755,7 @@ init_resume(struct nvbios_init *init) init_exec_set(init, true); } -/** +/* * INIT_STRAP_CONDITION - opcode 0x73 * */ @@ -1773,7 +1773,7 @@ init_strap_condition(struct nvbios_init *init) init_exec_set(init, false); } -/** +/* * INIT_TIME - opcode 0x74 * */ @@ -1794,7 +1794,7 @@ init_time(struct nvbios_init *init) } } -/** +/* * INIT_CONDITION - opcode 0x75 * */ @@ -1811,7 +1811,7 @@ init_condition(struct nvbios_init *init) init_exec_set(init, false); } -/** +/* * INIT_IO_CONDITION - opcode 0x76 * */ @@ -1828,7 +1828,7 @@ init_io_condition(struct nvbios_init *init) init_exec_set(init, false); } -/** +/* * INIT_ZM_REG16 - opcode 0x77 * */ @@ -1845,7 +1845,7 @@ init_zm_reg16(struct nvbios_init *init) init_wr32(init, addr, data); } -/** +/* * INIT_INDEX_IO - opcode 0x78 * */ @@ -1867,7 +1867,7 @@ init_index_io(struct nvbios_init *init) init_wrvgai(init, port, index, data | value); } -/** +/* * INIT_PLL - opcode 0x79 * */ @@ -1884,7 +1884,7 @@ init_pll(struct nvbios_init *init) init_prog_pll(init, reg, freq); } -/** +/* * INIT_ZM_REG - opcode 0x7a * */ @@ -1904,7 +1904,7 @@ init_zm_reg(struct nvbios_init *init) init_wr32(init, addr, data); } -/** +/* * INIT_RAM_RESTRICT_PLL - opcde 0x87 * */ @@ -1934,7 +1934,7 @@ init_ram_restrict_pll(struct nvbios_init *init) } } -/** +/* * INIT_RESET_BEGUN - opcode 0x8c * */ @@ -1945,7 +1945,7 @@ init_reset_begun(struct nvbios_init *init) init->offset += 1; } -/** +/* * INIT_RESET_END - opcode 0x8d * */ @@ -1956,7 +1956,7 @@ init_reset_end(struct nvbios_init *init) init->offset += 1; } -/** +/* * INIT_GPIO - opcode 0x8e * */ @@ -1972,7 +1972,7 @@ init_gpio(struct nvbios_init *init) nvkm_gpio_reset(gpio, DCB_GPIO_UNUSED); } -/** +/* * INIT_RAM_RESTRICT_ZM_GROUP - opcode 0x8f * */ @@ -2010,7 +2010,7 @@ init_ram_restrict_zm_reg_group(struct nvbios_init *init) } } -/** +/* * INIT_COPY_ZM_REG - opcode 0x90 * */ @@ -2027,7 +2027,7 @@ init_copy_zm_reg(struct nvbios_init *init) init_wr32(init, dreg, init_rd32(init, sreg)); } -/** +/* * INIT_ZM_REG_GROUP - opcode 0x91 * */ @@ -2049,7 +2049,7 @@ init_zm_reg_group(struct nvbios_init *init) } } -/** +/* * INIT_XLAT - opcode 0x96 * */ @@ -2077,7 +2077,7 @@ init_xlat(struct nvbios_init *init) init_mask(init, daddr, ~dmask, data); } -/** +/* * INIT_ZM_MASK_ADD - opcode 0x97 * */ @@ -2098,7 +2098,7 @@ init_zm_mask_add(struct nvbios_init *init) init_wr32(init, addr, data); } -/** +/* * INIT_AUXCH - opcode 0x98 * */ @@ -2122,7 +2122,7 @@ init_auxch(struct nvbios_init *init) } } -/** +/* * INIT_AUXCH - opcode 0x99 * */ @@ -2144,7 +2144,7 @@ init_zm_auxch(struct nvbios_init *init) } } -/** +/* * INIT_I2C_LONG_IF - opcode 0x9a * */ @@ -2183,7 +2183,7 @@ init_i2c_long_if(struct nvbios_init *init) init_exec_set(init, false); } -/** +/* * INIT_GPIO_NE - opcode 0xa9 * */ diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c index 4bf486b57101..cb05f7f48a98 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c @@ -66,11 +66,16 @@ of_init(struct nvkm_bios *bios, const char *name) return ERR_PTR(-EINVAL); } +static void of_fini(void *p) +{ + kfree(p); +} + const struct nvbios_source nvbios_of = { .name = "OpenFirmware", .init = of_init, - .fini = (void(*)(void *))kfree, + .fini = of_fini, .read = of_read, .size = of_size, .rw = false, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c index 7bcbc4895ec2..271bfa038f5b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c @@ -25,6 +25,7 @@ #include <subdev/bios.h> #include <subdev/bios/init.h> +#include <subdev/gsp.h> void gm107_devinit_disable(struct nvkm_devinit *init) @@ -33,10 +34,13 @@ gm107_devinit_disable(struct nvkm_devinit *init) u32 r021c00 = nvkm_rd32(device, 0x021c00); u32 r021c04 = nvkm_rd32(device, 0x021c04); - if (r021c00 & 0x00000001) - nvkm_subdev_disable(device, NVKM_ENGINE_CE, 0); - if (r021c00 & 0x00000004) - nvkm_subdev_disable(device, NVKM_ENGINE_CE, 2); + /* gsp only wants to enable/disable display */ + if (!nvkm_gsp_rm(device->gsp)) { + if (r021c00 & 0x00000001) + nvkm_subdev_disable(device, NVKM_ENGINE_CE, 0); + if (r021c00 & 0x00000004) + nvkm_subdev_disable(device, NVKM_ENGINE_CE, 2); + } if (r021c04 & 0x00000001) nvkm_subdev_disable(device, NVKM_ENGINE_DISP, 0); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h index 50f0c1914f58..4c3f74396579 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h @@ -46,6 +46,8 @@ u32 gm107_ram_probe_fbp(const struct nvkm_ram_func *, u32 gm200_ram_probe_fbp_amount(const struct nvkm_ram_func *, u32, struct nvkm_device *, int, int *); +int gp100_ram_init(struct nvkm_ram *); + /* RAM type-specific MR calculation routines */ int nvkm_sddr2_calc(struct nvkm_ram *); int nvkm_sddr3_calc(struct nvkm_ram *); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c index 378f6fb70990..8987a21e81d1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c @@ -27,7 +27,7 @@ #include <subdev/bios/init.h> #include <subdev/bios/rammap.h> -static int +int gp100_ram_init(struct nvkm_ram *ram) { struct nvkm_subdev *subdev = &ram->fb->subdev; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp102.c index 8550f5e47347..b6b6ee59019d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp102.c @@ -5,6 +5,7 @@ static const struct nvkm_ram_func gp102_ram = { + .init = gp100_ram_init, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/fwsec.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/fwsec.c index 330d72b1a4af..52412965fac1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/fwsec.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/fwsec.c @@ -324,7 +324,7 @@ nvkm_gsp_fwsec_sb(struct nvkm_gsp *gsp) return ret; /* Verify. */ - err = nvkm_rd32(device, 0x001400 + (0xf * 4)) & 0x0000ffff; + err = nvkm_rd32(device, 0x001400 + (0x15 * 4)) & 0x0000ffff; if (err) { nvkm_error(subdev, "fwsec-sb: 0x%04x\n", err); return -EIO; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index a73a5b589790..58502102926b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -26,6 +26,7 @@ #include <subdev/vfn.h> #include <engine/fifo/chan.h> #include <engine/sec2.h> +#include <nvif/log.h> #include <nvfw/fw.h> @@ -54,6 +55,10 @@ #include <nvrm/535.113.01/nvidia/kernel/inc/vgpu/rpc_global_enums.h> #include <linux/acpi.h> +#include <linux/ctype.h> +#include <linux/parser.h> + +extern struct dentry *nouveau_debugfs_root; #define GSP_MSG_MIN_SIZE GSP_PAGE_SIZE #define GSP_MSG_MAX_SIZE GSP_PAGE_MIN_SIZE * 16 @@ -76,7 +81,7 @@ r535_rpc_status_to_errno(uint32_t rpc_status) switch (rpc_status) { case 0x55: /* NV_ERR_NOT_READY */ case 0x66: /* NV_ERR_TIMEOUT_RETRY */ - return -EAGAIN; + return -EBUSY; case 0x51: /* NV_ERR_NO_MEMORY */ return -ENOMEM; default: @@ -119,6 +124,8 @@ r535_gsp_msgq_wait(struct nvkm_gsp *gsp, u32 repc, u32 *prepc, int *ptime) return mqe->data; } + size = ALIGN(repc + GSP_MSG_HDR_SIZE, GSP_PAGE_SIZE); + msg = kvmalloc(repc, GFP_KERNEL); if (!msg) return ERR_PTR(-ENOMEM); @@ -127,19 +134,15 @@ r535_gsp_msgq_wait(struct nvkm_gsp *gsp, u32 repc, u32 *prepc, int *ptime) len = min_t(u32, repc, len); memcpy(msg, mqe->data, len); - rptr += DIV_ROUND_UP(len, GSP_PAGE_SIZE); - if (rptr == gsp->msgq.cnt) - rptr = 0; - repc -= len; if (repc) { mqe = (void *)((u8 *)gsp->shm.msgq.ptr + 0x1000 + 0 * 0x1000); memcpy(msg + len, mqe, repc); - - rptr += DIV_ROUND_UP(repc, GSP_PAGE_SIZE); } + rptr = (rptr + DIV_ROUND_UP(size, GSP_PAGE_SIZE)) % gsp->msgq.cnt; + mb(); (*gsp->msgq.rptr) = rptr; return msg; @@ -161,7 +164,7 @@ r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *argv) u64 *end; u64 csum = 0; int free, time = 1000000; - u32 wptr, size; + u32 wptr, size, step; u32 off = 0; argc = ALIGN(GSP_MSG_HDR_SIZE + argc, GSP_PAGE_SIZE); @@ -195,7 +198,9 @@ r535_gsp_cmdq_push(struct nvkm_gsp *gsp, void *argv) } cqe = (void *)((u8 *)gsp->shm.cmdq.ptr + 0x1000 + wptr * 0x1000); - size = min_t(u32, argc, (gsp->cmdq.cnt - wptr) * GSP_PAGE_SIZE); + step = min_t(u32, free, (gsp->cmdq.cnt - wptr)); + size = min_t(u32, argc, step * GSP_PAGE_SIZE); + memcpy(cqe, (u8 *)cmd + off, size); wptr += DIV_ROUND_UP(size, 0x1000); @@ -599,7 +604,7 @@ r535_gsp_rpc_rm_alloc_push(struct nvkm_gsp_object *object, void *argv, u32 repc) if (rpc->status) { ret = ERR_PTR(r535_rpc_status_to_errno(rpc->status)); - if (PTR_ERR(ret) != -EAGAIN) + if (PTR_ERR(ret) != -EAGAIN && PTR_ERR(ret) != -EBUSY) nvkm_error(&gsp->subdev, "RM_ALLOC: 0x%x\n", rpc->status); } else { ret = repc ? rpc->params : NULL; @@ -658,7 +663,7 @@ r535_gsp_rpc_rm_ctrl_push(struct nvkm_gsp_object *object, void **argv, u32 repc) if (rpc->status) { ret = r535_rpc_status_to_errno(rpc->status); - if (ret != -EAGAIN) + if (ret != -EAGAIN && ret != -EBUSY) nvkm_error(&gsp->subdev, "cli:0x%08x obj:0x%08x ctrl cmd:0x%08x failed: 0x%08x\n", object->client->object.handle, object->handle, rpc->cmd, rpc->status); } @@ -998,7 +1003,7 @@ r535_gsp_rpc_get_gsp_static_info(struct nvkm_gsp *gsp) } static void -nvkm_gsp_mem_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_mem *mem) +nvkm_gsp_mem_dtor(struct nvkm_gsp_mem *mem) { if (mem->data) { /* @@ -1007,19 +1012,35 @@ nvkm_gsp_mem_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_mem *mem) */ memset(mem->data, 0xFF, mem->size); - dma_free_coherent(gsp->subdev.device->dev, mem->size, mem->data, mem->addr); + dma_free_coherent(mem->dev, mem->size, mem->data, mem->addr); + put_device(mem->dev); + memset(mem, 0, sizeof(*mem)); } } +/** + * nvkm_gsp_mem_ctor - constructor for nvkm_gsp_mem objects + * @gsp: gsp pointer + * @size: number of bytes to allocate + * @mem: nvkm_gsp_mem object to initialize + * + * Allocates a block of memory for use with GSP. + * + * This memory block can potentially out-live the driver's remove() callback, + * so we take a device reference to ensure its lifetime. The reference is + * dropped in the destructor. + */ static int nvkm_gsp_mem_ctor(struct nvkm_gsp *gsp, size_t size, struct nvkm_gsp_mem *mem) { - mem->size = size; mem->data = dma_alloc_coherent(gsp->subdev.device->dev, size, &mem->addr, GFP_KERNEL); if (WARN_ON(!mem->data)) return -ENOMEM; + mem->size = size; + mem->dev = get_device(gsp->subdev.device->dev); + return 0; } @@ -1052,8 +1073,8 @@ r535_gsp_postinit(struct nvkm_gsp *gsp) nvkm_wr32(device, 0x110004, 0x00000040); /* Release the DMA buffers that were needed only for boot and init */ - nvkm_gsp_mem_dtor(gsp, &gsp->boot.fw); - nvkm_gsp_mem_dtor(gsp, &gsp->libos); + nvkm_gsp_mem_dtor(&gsp->boot.fw); + nvkm_gsp_mem_dtor(&gsp->libos); return ret; } @@ -1080,53 +1101,365 @@ r535_gsp_rpc_unloading_guest_driver(struct nvkm_gsp *gsp, bool suspend) return nvkm_gsp_rpc_wr(gsp, rpc, true); } +enum registry_type { + REGISTRY_TABLE_ENTRY_TYPE_DWORD = 1, /* 32-bit unsigned integer */ + REGISTRY_TABLE_ENTRY_TYPE_BINARY = 2, /* Binary blob */ + REGISTRY_TABLE_ENTRY_TYPE_STRING = 3, /* Null-terminated string */ +}; + +/* An arbitrary limit to the length of a registry key */ +#define REGISTRY_MAX_KEY_LENGTH 64 + +/** + * registry_list_entry - linked list member for a registry key/value + * @head: list_head struct + * @type: dword, binary, or string + * @klen: the length of name of the key + * @vlen: the length of the value + * @key: the key name + * @dword: the data, if REGISTRY_TABLE_ENTRY_TYPE_DWORD + * @binary: the data, if TYPE_BINARY or TYPE_STRING + * + * Every registry key/value is represented internally by this struct. + * + * Type DWORD is a simple 32-bit unsigned integer, and its value is stored in + * @dword. + * + * Types BINARY and STRING are variable-length binary blobs. The only real + * difference between BINARY and STRING is that STRING is null-terminated and + * is expected to contain only printable characters. + * + * Note: it is technically possible to have multiple keys with the same name + * but different types, but this is not useful since GSP-RM expects keys to + * have only one specific type. + */ +struct registry_list_entry { + struct list_head head; + enum registry_type type; + size_t klen; + char key[REGISTRY_MAX_KEY_LENGTH]; + size_t vlen; + u32 dword; /* TYPE_DWORD */ + u8 binary[] __counted_by(vlen); /* TYPE_BINARY or TYPE_STRING */ +}; + +/** + * add_registry -- adds a registry entry + * @gsp: gsp pointer + * @key: name of the registry key + * @type: type of data + * @data: pointer to value + * @length: size of data, in bytes + * + * Adds a registry key/value pair to the registry database. + * + * This function collects the registry information in a linked list. After + * all registry keys have been added, build_registry() is used to create the + * RPC data structure. + * + * registry_rpc_size is a running total of the size of all registry keys. + * It's used to avoid an O(n) calculation of the size when the RPC is built. + * + * Returns 0 on success, or negative error code on error. + */ +static int add_registry(struct nvkm_gsp *gsp, const char *key, + enum registry_type type, const void *data, size_t length) +{ + struct registry_list_entry *reg; + const size_t nlen = strnlen(key, REGISTRY_MAX_KEY_LENGTH) + 1; + size_t alloc_size; /* extra bytes to alloc for binary or string value */ + + if (nlen > REGISTRY_MAX_KEY_LENGTH) + return -EINVAL; + + alloc_size = (type == REGISTRY_TABLE_ENTRY_TYPE_DWORD) ? 0 : length; + + reg = kmalloc(sizeof(*reg) + alloc_size, GFP_KERNEL); + if (!reg) + return -ENOMEM; + + switch (type) { + case REGISTRY_TABLE_ENTRY_TYPE_DWORD: + reg->dword = *(const u32 *)(data); + break; + case REGISTRY_TABLE_ENTRY_TYPE_BINARY: + case REGISTRY_TABLE_ENTRY_TYPE_STRING: + memcpy(reg->binary, data, alloc_size); + break; + default: + nvkm_error(&gsp->subdev, "unrecognized registry type %u for '%s'\n", + type, key); + kfree(reg); + return -EINVAL; + } + + memcpy(reg->key, key, nlen); + reg->klen = nlen; + reg->vlen = length; + reg->type = type; + + list_add_tail(®->head, &gsp->registry_list); + gsp->registry_rpc_size += sizeof(PACKED_REGISTRY_ENTRY) + nlen + alloc_size; + + return 0; +} + +static int add_registry_num(struct nvkm_gsp *gsp, const char *key, u32 value) +{ + return add_registry(gsp, key, REGISTRY_TABLE_ENTRY_TYPE_DWORD, + &value, sizeof(u32)); +} + +static int add_registry_string(struct nvkm_gsp *gsp, const char *key, const char *value) +{ + return add_registry(gsp, key, REGISTRY_TABLE_ENTRY_TYPE_STRING, + value, strlen(value) + 1); +} + +/** + * build_registry -- create the registry RPC data + * @gsp: gsp pointer + * @registry: pointer to the RPC payload to fill + * + * After all registry key/value pairs have been added, call this function to + * build the RPC. + * + * The registry RPC looks like this: + * + * +-----------------+ + * |NvU32 size; | + * |NvU32 numEntries;| + * +-----------------+ + * +----------------------------------------+ + * |PACKED_REGISTRY_ENTRY | + * +----------------------------------------+ + * |Null-terminated key (string) for entry 0| + * +----------------------------------------+ + * |Binary/string data value for entry 0 | (only if necessary) + * +----------------------------------------+ + * + * +----------------------------------------+ + * |PACKED_REGISTRY_ENTRY | + * +----------------------------------------+ + * |Null-terminated key (string) for entry 1| + * +----------------------------------------+ + * |Binary/string data value for entry 1 | (only if necessary) + * +----------------------------------------+ + * ... (and so on, one copy for each entry) + * + * + * The 'data' field of an entry is either a 32-bit integer (for type DWORD) + * or an offset into the PACKED_REGISTRY_TABLE (for types BINARY and STRING). + * + * All memory allocated by add_registry() is released. + */ +static void build_registry(struct nvkm_gsp *gsp, PACKED_REGISTRY_TABLE *registry) +{ + struct registry_list_entry *reg, *n; + size_t str_offset; + unsigned int i = 0; + + registry->numEntries = list_count_nodes(&gsp->registry_list); + str_offset = struct_size(registry, entries, registry->numEntries); + + list_for_each_entry_safe(reg, n, &gsp->registry_list, head) { + registry->entries[i].type = reg->type; + registry->entries[i].length = reg->vlen; + + /* Append the key name to the table */ + registry->entries[i].nameOffset = str_offset; + memcpy((void *)registry + str_offset, reg->key, reg->klen); + str_offset += reg->klen; + + switch (reg->type) { + case REGISTRY_TABLE_ENTRY_TYPE_DWORD: + registry->entries[i].data = reg->dword; + break; + case REGISTRY_TABLE_ENTRY_TYPE_BINARY: + case REGISTRY_TABLE_ENTRY_TYPE_STRING: + /* If the type is binary or string, also append the value */ + memcpy((void *)registry + str_offset, reg->binary, reg->vlen); + registry->entries[i].data = str_offset; + str_offset += reg->vlen; + break; + default: + break; + } + + i++; + list_del(®->head); + kfree(reg); + } + + /* Double-check that we calculated the sizes correctly */ + WARN_ON(gsp->registry_rpc_size != str_offset); + + registry->size = gsp->registry_rpc_size; +} + +/** + * clean_registry -- clean up registry memory in case of error + * @gsp: gsp pointer + * + * Call this function to clean up all memory allocated by add_registry() + * in case of error and build_registry() is not called. + */ +static void clean_registry(struct nvkm_gsp *gsp) +{ + struct registry_list_entry *reg, *n; + + list_for_each_entry_safe(reg, n, &gsp->registry_list, head) { + list_del(®->head); + kfree(reg); + } + + gsp->registry_rpc_size = sizeof(PACKED_REGISTRY_TABLE); +} + +MODULE_PARM_DESC(NVreg_RegistryDwords, + "A semicolon-separated list of key=integer pairs of GSP-RM registry keys"); +static char *NVreg_RegistryDwords; +module_param(NVreg_RegistryDwords, charp, 0400); + /* dword only */ struct nv_gsp_registry_entries { const char *name; u32 value; }; +/** + * r535_registry_entries - required registry entries for GSP-RM + * + * This array lists registry entries that are required for GSP-RM to + * function correctly. + * + * RMSecBusResetEnable - enables PCI secondary bus reset + * RMForcePcieConfigSave - forces GSP-RM to preserve PCI configuration + * registers on any PCI reset. + */ static const struct nv_gsp_registry_entries r535_registry_entries[] = { { "RMSecBusResetEnable", 1 }, { "RMForcePcieConfigSave", 1 }, }; #define NV_GSP_REG_NUM_ENTRIES ARRAY_SIZE(r535_registry_entries) +/** + * strip - strips all characters in 'reject' from 's' + * @s: string to strip + * @reject: string of characters to remove + * + * 's' is modified. + * + * Returns the length of the new string. + */ +static size_t strip(char *s, const char *reject) +{ + char *p = s, *p2 = s; + size_t length = 0; + char c; + + do { + while ((c = *p2) && strchr(reject, c)) + p2++; + + *p++ = c = *p2++; + length++; + } while (c); + + return length; +} + +/** + * r535_gsp_rpc_set_registry - build registry RPC and call GSP-RM + * @gsp: gsp pointer + * + * The GSP-RM registry is a set of key/value pairs that configure some aspects + * of GSP-RM. The keys are strings, and the values are 32-bit integers. + * + * The registry is built from a combination of a static hard-coded list (see + * above) and entries passed on the driver's command line. + */ static int r535_gsp_rpc_set_registry(struct nvkm_gsp *gsp) { PACKED_REGISTRY_TABLE *rpc; - char *strings; - int str_offset; - int i; - size_t rpc_size = struct_size(rpc, entries, NV_GSP_REG_NUM_ENTRIES); + unsigned int i; + int ret; - /* add strings + null terminator */ - for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++) - rpc_size += strlen(r535_registry_entries[i].name) + 1; + INIT_LIST_HEAD(&gsp->registry_list); + gsp->registry_rpc_size = sizeof(PACKED_REGISTRY_TABLE); - rpc = nvkm_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_SET_REGISTRY, rpc_size); - if (IS_ERR(rpc)) - return PTR_ERR(rpc); + for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++) { + ret = add_registry_num(gsp, r535_registry_entries[i].name, + r535_registry_entries[i].value); + if (ret) + goto fail; + } - rpc->numEntries = NV_GSP_REG_NUM_ENTRIES; + /* + * The NVreg_RegistryDwords parameter is a string of key=value + * pairs separated by semicolons. We need to extract and trim each + * substring, and then parse the substring to extract the key and + * value. + */ + if (NVreg_RegistryDwords) { + char *p = kstrdup(NVreg_RegistryDwords, GFP_KERNEL); + char *start, *next = p, *equal; + + if (!p) { + ret = -ENOMEM; + goto fail; + } - str_offset = offsetof(typeof(*rpc), entries[NV_GSP_REG_NUM_ENTRIES]); - strings = (char *)&rpc->entries[NV_GSP_REG_NUM_ENTRIES]; - for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++) { - int name_len = strlen(r535_registry_entries[i].name) + 1; + /* Remove any whitespace from the parameter string */ + strip(p, " \t\n"); + + while ((start = strsep(&next, ";"))) { + long value; + + equal = strchr(start, '='); + if (!equal || equal == start || equal[1] == 0) { + nvkm_error(&gsp->subdev, + "ignoring invalid registry string '%s'\n", + start); + continue; + } + + /* Truncate the key=value string to just key */ + *equal = 0; - rpc->entries[i].nameOffset = str_offset; - rpc->entries[i].type = 1; - rpc->entries[i].data = r535_registry_entries[i].value; - rpc->entries[i].length = 4; - memcpy(strings, r535_registry_entries[i].name, name_len); - strings += name_len; - str_offset += name_len; + ret = kstrtol(equal + 1, 0, &value); + if (!ret) { + ret = add_registry_num(gsp, start, value); + } else { + /* Not a number, so treat it as a string */ + ret = add_registry_string(gsp, start, equal + 1); + } + + if (ret) { + nvkm_error(&gsp->subdev, + "ignoring invalid registry key/value '%s=%s'\n", + start, equal + 1); + continue; + } + } + + kfree(p); } - rpc->size = str_offset; + + rpc = nvkm_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_SET_REGISTRY, gsp->registry_rpc_size); + if (IS_ERR(rpc)) { + ret = PTR_ERR(rpc); + goto fail; + } + + build_registry(gsp, rpc); return nvkm_gsp_rpc_wr(gsp, rpc, false); + +fail: + clean_registry(gsp); + return ret; } #if defined(CONFIG_ACPI) && defined(CONFIG_X86) @@ -1430,6 +1763,10 @@ r535_gsp_msg_post_event(void *priv, u32 fn, void *repv, u32 repc) /** * r535_gsp_msg_run_cpu_sequencer() -- process I/O commands from the GSP + * @priv: gsp pointer + * @fn: function number (ignored) + * @repv: pointer to libos print RPC + * @repc: message size * * The GSP sequencer is a list of I/O commands that the GSP can send to * the driver to perform for various purposes. The most common usage is to @@ -1620,7 +1957,7 @@ r535_gsp_wpr_meta_init(struct nvkm_gsp *gsp) meta->magic = GSP_FW_WPR_META_MAGIC; meta->revision = GSP_FW_WPR_META_REVISION; - meta->sysmemAddrOfRadix3Elf = gsp->radix3.mem[0].addr; + meta->sysmemAddrOfRadix3Elf = gsp->radix3.lvl0.addr; meta->sizeOfRadix3Elf = gsp->fb.wpr2.elf.size; meta->sysmemAddrOfBootloader = gsp->boot.fw.addr; @@ -1742,6 +2079,215 @@ r535_gsp_rmargs_init(struct nvkm_gsp *gsp, bool resume) return 0; } +#ifdef CONFIG_DEBUG_FS + +/* + * If GSP-RM load fails, then the GSP nvkm object will be deleted, the logging + * debugfs entries will be deleted, and it will not be possible to debug the + * load failure. The keep_gsp_logging parameter tells Nouveau to copy the + * logging buffers to new debugfs entries, and these entries are retained + * until the driver unloads. + */ +static bool keep_gsp_logging; +module_param(keep_gsp_logging, bool, 0444); +MODULE_PARM_DESC(keep_gsp_logging, + "Migrate the GSP-RM logging debugfs entries upon exit"); + +/* + * GSP-RM uses a pseudo-class mechanism to define of a variety of per-"engine" + * data structures, and each engine has a "class ID" genererated by a + * pre-processor. This is the class ID for the PMU. + */ +#define NV_GSP_MSG_EVENT_UCODE_LIBOS_CLASS_PMU 0xf3d722 + +/** + * rpc_ucode_libos_print_v1E_08 - RPC payload for libos print buffers + * @ucode_eng_desc: the engine descriptor + * @libos_print_buf_size: the size of the libos_print_buf[] + * @libos_print_buf: the actual buffer + * + * The engine descriptor is divided into 31:8 "class ID" and 7:0 "instance + * ID". We only care about messages from PMU. + */ +struct rpc_ucode_libos_print_v1e_08 { + u32 ucode_eng_desc; + u32 libos_print_buf_size; + u8 libos_print_buf[]; +}; + +/** + * r535_gsp_msg_libos_print - capture log message from the PMU + * @priv: gsp pointer + * @fn: function number (ignored) + * @repv: pointer to libos print RPC + * @repc: message size + * + * Called when we receive a UCODE_LIBOS_PRINT event RPC from GSP-RM. This RPC + * contains the contents of the libos print buffer from PMU. It is typically + * only written to when PMU encounters an error. + * + * Technically this RPC can be used to pass print buffers from any number of + * GSP-RM engines, but we only expect to receive them for the PMU. + * + * For the PMU, the buffer is 4K in size and the RPC always contains the full + * contents. + */ +static int +r535_gsp_msg_libos_print(void *priv, u32 fn, void *repv, u32 repc) +{ + struct nvkm_gsp *gsp = priv; + struct nvkm_subdev *subdev = &gsp->subdev; + struct rpc_ucode_libos_print_v1e_08 *rpc = repv; + unsigned int class = rpc->ucode_eng_desc >> 8; + + nvkm_debug(subdev, "received libos print from class 0x%x for %u bytes\n", + class, rpc->libos_print_buf_size); + + if (class != NV_GSP_MSG_EVENT_UCODE_LIBOS_CLASS_PMU) { + nvkm_warn(subdev, + "received libos print from unknown class 0x%x\n", + class); + return -ENOMSG; + } + + if (rpc->libos_print_buf_size > GSP_PAGE_SIZE) { + nvkm_error(subdev, "libos print is too large (%u bytes)\n", + rpc->libos_print_buf_size); + return -E2BIG; + } + + memcpy(gsp->blob_pmu.data, rpc->libos_print_buf, rpc->libos_print_buf_size); + + return 0; +} + +/** + * create_debufgs - create a blob debugfs entry + * @gsp: gsp pointer + * @name: name of this dentry + * @blob: blob wrapper + * + * Creates a debugfs entry for a logging buffer with the name 'name'. + */ +static struct dentry *create_debugfs(struct nvkm_gsp *gsp, const char *name, + struct debugfs_blob_wrapper *blob) +{ + struct dentry *dent; + + dent = debugfs_create_blob(name, 0444, gsp->debugfs.parent, blob); + if (IS_ERR(dent)) { + nvkm_error(&gsp->subdev, + "failed to create %s debugfs entry\n", name); + return NULL; + } + + /* + * For some reason, debugfs_create_blob doesn't set the size of the + * dentry, so do that here. See [1] + * + * [1] https://lore.kernel.org/r/linux-fsdevel/20240207200619.3354549-1-ttabi@nvidia.com/ + */ + i_size_write(d_inode(dent), blob->size); + + return dent; +} + +/** + * r535_gsp_libos_debugfs_init - create logging debugfs entries + * @gsp: gsp pointer + * + * Create the debugfs entries. This exposes the log buffers to userspace so + * that an external tool can parse it. + * + * The 'logpmu' contains exception dumps from the PMU. It is written via an + * RPC sent from GSP-RM and must be only 4KB. We create it here because it's + * only useful if there is a debugfs entry to expose it. If we get the PMU + * logging RPC and there is no debugfs entry, the RPC is just ignored. + * + * The blob_init, blob_rm, and blob_pmu objects can't be transient + * because debugfs_create_blob doesn't copy them. + * + * NOTE: OpenRM loads the logging elf image and prints the log messages + * in real-time. We may add that capability in the future, but that + * requires loading ELF images that are not distributed with the driver and + * adding the parsing code to Nouveau. + * + * Ideally, this should be part of nouveau_debugfs_init(), but that function + * is called too late. We really want to create these debugfs entries before + * r535_gsp_booter_load() is called, so that if GSP-RM fails to initialize, + * there could still be a log to capture. + */ +static void +r535_gsp_libos_debugfs_init(struct nvkm_gsp *gsp) +{ + struct device *dev = gsp->subdev.device->dev; + + /* Create a new debugfs directory with a name unique to this GPU. */ + gsp->debugfs.parent = debugfs_create_dir(dev_name(dev), nouveau_debugfs_root); + if (IS_ERR(gsp->debugfs.parent)) { + nvkm_error(&gsp->subdev, + "failed to create %s debugfs root\n", dev_name(dev)); + return; + } + + gsp->blob_init.data = gsp->loginit.data; + gsp->blob_init.size = gsp->loginit.size; + gsp->blob_intr.data = gsp->logintr.data; + gsp->blob_intr.size = gsp->logintr.size; + gsp->blob_rm.data = gsp->logrm.data; + gsp->blob_rm.size = gsp->logrm.size; + + gsp->debugfs.init = create_debugfs(gsp, "loginit", &gsp->blob_init); + if (!gsp->debugfs.init) + goto error; + + gsp->debugfs.intr = create_debugfs(gsp, "logintr", &gsp->blob_intr); + if (!gsp->debugfs.intr) + goto error; + + gsp->debugfs.rm = create_debugfs(gsp, "logrm", &gsp->blob_rm); + if (!gsp->debugfs.rm) + goto error; + + /* + * Since the PMU buffer is copied from an RPC, it doesn't need to be + * a DMA buffer. + */ + gsp->blob_pmu.size = GSP_PAGE_SIZE; + gsp->blob_pmu.data = kzalloc(gsp->blob_pmu.size, GFP_KERNEL); + if (!gsp->blob_pmu.data) + goto error; + + gsp->debugfs.pmu = create_debugfs(gsp, "logpmu", &gsp->blob_pmu); + if (!gsp->debugfs.pmu) { + kfree(gsp->blob_pmu.data); + goto error; + } + + i_size_write(d_inode(gsp->debugfs.init), gsp->blob_init.size); + i_size_write(d_inode(gsp->debugfs.intr), gsp->blob_intr.size); + i_size_write(d_inode(gsp->debugfs.rm), gsp->blob_rm.size); + i_size_write(d_inode(gsp->debugfs.pmu), gsp->blob_pmu.size); + + r535_gsp_msg_ntfy_add(gsp, NV_VGPU_MSG_EVENT_UCODE_LIBOS_PRINT, + r535_gsp_msg_libos_print, gsp); + + nvkm_debug(&gsp->subdev, "created debugfs GSP-RM logging entries\n"); + + if (keep_gsp_logging) { + nvkm_info(&gsp->subdev, + "logging buffers will be retained on failure\n"); + } + + return; + +error: + debugfs_remove(gsp->debugfs.parent); + gsp->debugfs.parent = NULL; +} + +#endif + static inline u64 r535_gsp_libos_id8(const char *name) { @@ -1781,6 +2327,7 @@ static void create_pte_array(u64 *ptes, dma_addr_t addr, size_t size) /** * r535_gsp_libos_init() -- create the libos arguments structure + * @gsp: gsp pointer * * The logging buffers are byte queues that contain encoded printf-like * messages from GSP-RM. They need to be decoded by a special application @@ -1791,7 +2338,11 @@ static void create_pte_array(u64 *ptes, dma_addr_t addr, size_t size) * written to directly by GSP-RM and can be any multiple of GSP_PAGE_SIZE. * * The physical address map for the log buffer is stored in the buffer - * itself, starting with offset 1. Offset 0 contains the "put" pointer. + * itself, starting with offset 1. Offset 0 contains the "put" pointer (pp). + * Initially, pp is equal to 0. If the buffer has valid logging data in it, + * then pp points to index into the buffer where the next logging entry will + * be written. Therefore, the logging data is valid if: + * 1 <= pp < sizeof(buffer)/sizeof(u64) * * The GSP only understands 4K pages (GSP_PAGE_SIZE), so even if the kernel is * configured for a larger page size (e.g. 64K pages), we need to give @@ -1862,6 +2413,11 @@ r535_gsp_libos_init(struct nvkm_gsp *gsp) args[3].size = gsp->rmargs.size; args[3].kind = LIBOS_MEMORY_REGION_CONTIGUOUS; args[3].loc = LIBOS_MEMORY_REGION_LOC_SYSMEM; + +#ifdef CONFIG_DEBUG_FS + r535_gsp_libos_debugfs_init(gsp); +#endif + return 0; } @@ -1914,12 +2470,17 @@ nvkm_gsp_sg(struct nvkm_device *device, u64 size, struct sg_table *sgt) static void nvkm_gsp_radix3_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_radix3 *rx3) { - for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--) - nvkm_gsp_mem_dtor(gsp, &rx3->mem[i]); + nvkm_gsp_sg_free(gsp->subdev.device, &rx3->lvl2); + nvkm_gsp_mem_dtor(&rx3->lvl1); + nvkm_gsp_mem_dtor(&rx3->lvl0); } /** * nvkm_gsp_radix3_sg - build a radix3 table from a S/G list + * @gsp: gsp pointer + * @sgt: S/G list to traverse + * @size: size of the image, in bytes + * @rx3: radix3 array to update * * The GSP uses a three-level page table, called radix3, to map the firmware. * Each 64-bit "pointer" in the table is either the bus address of an entry in @@ -1951,36 +2512,60 @@ static int nvkm_gsp_radix3_sg(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size, struct nvkm_gsp_radix3 *rx3) { - u64 addr; + struct sg_dma_page_iter sg_dma_iter; + struct scatterlist *sg; + size_t bufsize; + u64 *pte; + int ret, i, page_idx = 0; - for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--) { - u64 *ptes; - size_t bufsize; - int ret, idx; + ret = nvkm_gsp_mem_ctor(gsp, GSP_PAGE_SIZE, &rx3->lvl0); + if (ret) + return ret; - bufsize = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), GSP_PAGE_SIZE); - ret = nvkm_gsp_mem_ctor(gsp, bufsize, &rx3->mem[i]); - if (ret) - return ret; + ret = nvkm_gsp_mem_ctor(gsp, GSP_PAGE_SIZE, &rx3->lvl1); + if (ret) + goto lvl1_fail; - ptes = rx3->mem[i].data; - if (i == 2) { - struct scatterlist *sgl; + // Allocate level 2 + bufsize = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), GSP_PAGE_SIZE); + ret = nvkm_gsp_sg(gsp->subdev.device, bufsize, &rx3->lvl2); + if (ret) + goto lvl2_fail; - for_each_sgtable_dma_sg(sgt, sgl, idx) { - for (int j = 0; j < sg_dma_len(sgl) / GSP_PAGE_SIZE; j++) - *ptes++ = sg_dma_address(sgl) + (GSP_PAGE_SIZE * j); - } - } else { - for (int j = 0; j < size / GSP_PAGE_SIZE; j++) - *ptes++ = addr + GSP_PAGE_SIZE * j; + // Write the bus address of level 1 to level 0 + pte = rx3->lvl0.data; + *pte = rx3->lvl1.addr; + + // Write the bus address of each page in level 2 to level 1 + pte = rx3->lvl1.data; + for_each_sgtable_dma_page(&rx3->lvl2, &sg_dma_iter, 0) + *pte++ = sg_page_iter_dma_address(&sg_dma_iter); + + // Finally, write the bus address of each page in sgt to level 2 + for_each_sgtable_sg(&rx3->lvl2, sg, i) { + void *sgl_end; + + pte = sg_virt(sg); + sgl_end = (void *)pte + sg->length; + + for_each_sgtable_dma_page(sgt, &sg_dma_iter, page_idx) { + *pte++ = sg_page_iter_dma_address(&sg_dma_iter); + page_idx++; + + // Go to the next scatterlist for level 2 if we've reached the end + if ((void *)pte >= sgl_end) + break; } + } - size = rx3->mem[i].size; - addr = rx3->mem[i].addr; + if (ret) { +lvl2_fail: + nvkm_gsp_mem_dtor(&rx3->lvl1); +lvl1_fail: + nvkm_gsp_mem_dtor(&rx3->lvl0); } - return 0; + return ret; } int @@ -2012,7 +2597,7 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend) sr = gsp->sr.meta.data; sr->magic = GSP_FW_SR_META_MAGIC; sr->revision = GSP_FW_SR_META_REVISION; - sr->sysmemAddrOfSuspendResumeData = gsp->sr.radix3.mem[0].addr; + sr->sysmemAddrOfSuspendResumeData = gsp->sr.radix3.lvl0.addr; sr->sizeOfSuspendResumeData = len; mbox0 = lower_32_bits(gsp->sr.meta.addr); @@ -2069,7 +2654,7 @@ r535_gsp_init(struct nvkm_gsp *gsp) done: if (gsp->sr.meta.data) { - nvkm_gsp_mem_dtor(gsp, &gsp->sr.meta); + nvkm_gsp_mem_dtor(&gsp->sr.meta); nvkm_gsp_radix3_dtor(gsp, &gsp->sr.radix3); nvkm_gsp_sg_free(gsp->subdev.device, &gsp->sr.sgt); return ret; @@ -2143,6 +2728,222 @@ r535_gsp_dtor_fws(struct nvkm_gsp *gsp) gsp->fws.rm = NULL; } +#ifdef CONFIG_DEBUG_FS + +struct r535_gsp_log { + struct nvif_log log; + + /* + * Logging buffers in debugfs. The wrapper objects need to remain + * in memory until the dentry is deleted. + */ + struct dentry *debugfs_logging_dir; + struct debugfs_blob_wrapper blob_init; + struct debugfs_blob_wrapper blob_intr; + struct debugfs_blob_wrapper blob_rm; + struct debugfs_blob_wrapper blob_pmu; +}; + +/** + * r535_debugfs_shutdown - delete GSP-RM logging buffers for one GPU + * @_log: nvif_log struct for this GPU + * + * Called when the driver is shutting down, to clean up the retained GSP-RM + * logging buffers. + */ +static void r535_debugfs_shutdown(struct nvif_log *_log) +{ + struct r535_gsp_log *log = container_of(_log, struct r535_gsp_log, log); + + debugfs_remove(log->debugfs_logging_dir); + + kfree(log->blob_init.data); + kfree(log->blob_intr.data); + kfree(log->blob_rm.data); + kfree(log->blob_pmu.data); + + /* We also need to delete the list object */ + kfree(log); +} + +/** + * is_empty - return true if the logging buffer was never written to + * @b: blob wrapper with ->data field pointing to logging buffer + * + * The first 64-bit field of loginit, and logintr, and logrm is the 'put' + * pointer, and it is initialized to 0. It's a dword-based index into the + * circular buffer, indicating where the next printf write will be made. + * + * If the pointer is still 0 when GSP-RM is shut down, that means that the + * buffer was never written to, so it can be ignored. + * + * This test also works for logpmu, even though it doesn't have a put pointer. + */ +static bool is_empty(const struct debugfs_blob_wrapper *b) +{ + u64 *put = b->data; + + return put ? (*put == 0) : true; +} + +/** + * r535_gsp_copy_log - preserve the logging buffers in a blob + * + * When GSP shuts down, the nvkm_gsp object and all its memory is deleted. + * To preserve the logging buffers, the buffers need to be copied, but only + * if they actually have data. + */ +static int r535_gsp_copy_log(struct dentry *parent, + const char *name, + const struct debugfs_blob_wrapper *s, + struct debugfs_blob_wrapper *t) +{ + struct dentry *dent; + void *p; + + if (is_empty(s)) + return 0; + + /* The original buffers will be deleted */ + p = kmemdup(s->data, s->size, GFP_KERNEL); + if (!p) + return -ENOMEM; + + t->data = p; + t->size = s->size; + + dent = debugfs_create_blob(name, 0444, parent, t); + if (IS_ERR(dent)) { + kfree(p); + memset(t, 0, sizeof(*t)); + return PTR_ERR(dent); + } + + i_size_write(d_inode(dent), t->size); + + return 0; +} + +/** + * r535_gsp_retain_logging - copy logging buffers to new debugfs root + * @gsp: gsp pointer + * + * If keep_gsp_logging is enabled, then we want to preserve the GSP-RM logging + * buffers and their debugfs entries, but all those objects would normally + * deleted if GSP-RM fails to load. + * + * To preserve the logging buffers, we need to: + * + * 1) Allocate new buffers and copy the logs into them, so that the original + * DMA buffers can be released. + * + * 2) Preserve the directories. We don't need to save single dentries because + * we're going to delete the parent when the + * + * If anything fails in this process, then all the dentries need to be + * deleted. We don't need to deallocate the original logging buffers because + * the caller will do that regardless. + */ +static void r535_gsp_retain_logging(struct nvkm_gsp *gsp) +{ + struct device *dev = gsp->subdev.device->dev; + struct r535_gsp_log *log = NULL; + int ret; + + if (!keep_gsp_logging || !gsp->debugfs.parent) { + /* Nothing to do */ + goto exit; + } + + /* Check to make sure at least one buffer has data. */ + if (is_empty(&gsp->blob_init) && is_empty(&gsp->blob_intr) && + is_empty(&gsp->blob_rm) && is_empty(&gsp->blob_rm)) { + nvkm_warn(&gsp->subdev, "all logging buffers are empty\n"); + goto exit; + } + + log = kzalloc(sizeof(*log), GFP_KERNEL); + if (!log) + goto error; + + /* + * Since the nvkm_gsp object is going away, the debugfs_blob_wrapper + * objects are also being deleted, which means the dentries will no + * longer be valid. Delete the existing entries so that we can create + * new ones with the same name. + */ + debugfs_remove(gsp->debugfs.init); + debugfs_remove(gsp->debugfs.intr); + debugfs_remove(gsp->debugfs.rm); + debugfs_remove(gsp->debugfs.pmu); + + ret = r535_gsp_copy_log(gsp->debugfs.parent, "loginit", &gsp->blob_init, &log->blob_init); + if (ret) + goto error; + + ret = r535_gsp_copy_log(gsp->debugfs.parent, "logintr", &gsp->blob_intr, &log->blob_intr); + if (ret) + goto error; + + ret = r535_gsp_copy_log(gsp->debugfs.parent, "logrm", &gsp->blob_rm, &log->blob_rm); + if (ret) + goto error; + + ret = r535_gsp_copy_log(gsp->debugfs.parent, "logpmu", &gsp->blob_pmu, &log->blob_pmu); + if (ret) + goto error; + + /* The nvkm_gsp object is going away, so save the dentry */ + log->debugfs_logging_dir = gsp->debugfs.parent; + + log->log.shutdown = r535_debugfs_shutdown; + list_add(&log->log.entry, &gsp_logs.head); + + nvkm_warn(&gsp->subdev, + "logging buffers migrated to /sys/kernel/debug/nouveau/%s\n", + dev_name(dev)); + + return; + +error: + nvkm_warn(&gsp->subdev, "failed to migrate logging buffers\n"); + +exit: + debugfs_remove(gsp->debugfs.parent); + + if (log) { + kfree(log->blob_init.data); + kfree(log->blob_intr.data); + kfree(log->blob_rm.data); + kfree(log->blob_pmu.data); + kfree(log); + } +} + +#endif + +/** + * r535_gsp_libos_debugfs_fini - cleanup/retain log buffers on shutdown + * @gsp: gsp pointer + * + * If the log buffers are exposed via debugfs, the data for those entries + * needs to be cleaned up when the GSP device shuts down. + */ +static void +r535_gsp_libos_debugfs_fini(struct nvkm_gsp __maybe_unused *gsp) +{ +#ifdef CONFIG_DEBUG_FS + r535_gsp_retain_logging(gsp); + + /* + * Unlike the other buffers, the PMU blob is a kmalloc'd buffer that + * exists only if the debugfs entries were created. + */ + kfree(gsp->blob_pmu.data); + gsp->blob_pmu.data = NULL; +#endif +} + void r535_gsp_dtor(struct nvkm_gsp *gsp) { @@ -2150,7 +2951,7 @@ r535_gsp_dtor(struct nvkm_gsp *gsp) mutex_destroy(&gsp->client_id.mutex); nvkm_gsp_radix3_dtor(gsp, &gsp->radix3); - nvkm_gsp_mem_dtor(gsp, &gsp->sig); + nvkm_gsp_mem_dtor(&gsp->sig); nvkm_firmware_dtor(&gsp->fw); nvkm_falcon_fw_dtor(&gsp->booter.unload); @@ -2161,12 +2962,15 @@ r535_gsp_dtor(struct nvkm_gsp *gsp) r535_gsp_dtor_fws(gsp); - nvkm_gsp_mem_dtor(gsp, &gsp->rmargs); - nvkm_gsp_mem_dtor(gsp, &gsp->wpr_meta); - nvkm_gsp_mem_dtor(gsp, &gsp->shm.mem); - nvkm_gsp_mem_dtor(gsp, &gsp->loginit); - nvkm_gsp_mem_dtor(gsp, &gsp->logintr); - nvkm_gsp_mem_dtor(gsp, &gsp->logrm); + nvkm_gsp_mem_dtor(&gsp->rmargs); + nvkm_gsp_mem_dtor(&gsp->wpr_meta); + nvkm_gsp_mem_dtor(&gsp->shm.mem); + + r535_gsp_libos_debugfs_fini(gsp); + + nvkm_gsp_mem_dtor(&gsp->loginit); + nvkm_gsp_mem_dtor(&gsp->logintr); + nvkm_gsp_mem_dtor(&gsp->logrm); } int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild index 819703913a00..2c551bdc9bc9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/Kbuild @@ -25,7 +25,7 @@ nvkm-y += nvkm/subdev/i2c/busnv50.o nvkm-y += nvkm/subdev/i2c/busgf119.o nvkm-y += nvkm/subdev/i2c/bit.o -nvkm-y += nvkm/subdev/i2c/aux.o +nvkm-y += nvkm/subdev/i2c/auxch.o nvkm-y += nvkm/subdev/i2c/auxg94.o nvkm-y += nvkm/subdev/i2c/auxgf119.o nvkm-y += nvkm/subdev/i2c/auxgm200.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c index dd391809fef7..6c76e5e14b75 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c @@ -24,7 +24,7 @@ #define anx9805_pad(p) container_of((p), struct anx9805_pad, base) #define anx9805_bus(p) container_of((p), struct anx9805_bus, base) #define anx9805_aux(p) container_of((p), struct anx9805_aux, base) -#include "aux.h" +#include "auxch.h" #include "bus.h" struct anx9805_pad { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxch.c index d063d0dc13c5..fafc634acbf6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxch.c @@ -24,7 +24,7 @@ #include <linux/string_helpers.h> -#include "aux.h" +#include "auxch.h" #include "pad.h" static int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxch.h index f920eabf8628..f920eabf8628 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxch.h diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c index 47068f6f9c55..854bb4b5fdb4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c @@ -22,7 +22,7 @@ * Authors: Ben Skeggs <bskeggs@redhat.com> */ #define g94_i2c_aux(p) container_of((p), struct g94_i2c_aux, base) -#include "aux.h" +#include "auxch.h" struct g94_i2c_aux { struct nvkm_i2c_aux base; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgf119.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgf119.c index dab40cd8fe3a..c17d5647cb99 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgf119.c @@ -19,7 +19,7 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include "aux.h" +#include "auxch.h" static const struct nvkm_i2c_aux_func gf119_i2c_aux = { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c index 8bd1d442e465..3c5005e3b330 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c @@ -22,7 +22,7 @@ * Authors: Ben Skeggs <bskeggs@redhat.com> */ #define gm200_i2c_aux(p) container_of((p), struct gm200_i2c_aux, base) -#include "aux.h" +#include "auxch.h" struct gm200_i2c_aux { struct nvkm_i2c_aux base; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c index 731b2f68d3db..7ec17e8435a1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c @@ -22,7 +22,7 @@ * Authors: Ben Skeggs */ #include "priv.h" -#include "aux.h" +#include "auxch.h" #include "bus.h" #include "pad.h" diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padg94.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padg94.c index 5904bc5f2d2a..cc26cd677917 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padg94.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padg94.c @@ -22,7 +22,7 @@ * Authors: Ben Skeggs */ #include "pad.h" -#include "aux.h" +#include "auxch.h" #include "bus.h" void diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c index 3bc4d0310076..1797c6c65979 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgf119.c @@ -22,7 +22,7 @@ * Authors: Ben Skeggs */ #include "pad.h" -#include "aux.h" +#include "auxch.h" #include "bus.h" static const struct nvkm_i2c_pad_func diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgm200.c index 7d417f6a816e..5afc1bf8e798 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/padgm200.c @@ -22,7 +22,7 @@ * Authors: Ben Skeggs */ #include "pad.h" -#include "aux.h" +#include "auxch.h" #include "bus.h" static void diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c index a7f3fc342d87..dd5b5a17ece0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c @@ -222,8 +222,11 @@ nv50_instobj_acquire(struct nvkm_memory *memory) void __iomem *map = NULL; /* Already mapped? */ - if (refcount_inc_not_zero(&iobj->maps)) + if (refcount_inc_not_zero(&iobj->maps)) { + /* read barrier match the wmb on refcount set */ + smp_rmb(); return iobj->map; + } /* Take the lock, and re-check that another thread hasn't * already mapped the object in the meantime. @@ -250,6 +253,8 @@ nv50_instobj_acquire(struct nvkm_memory *memory) iobj->base.memory.ptrs = &nv50_instobj_fast; else iobj->base.memory.ptrs = &nv50_instobj_slow; + /* barrier to ensure the ptrs are written before refcount is set */ + smp_wmb(); refcount_set(&iobj->maps, 1); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c index a6f410ba60bc..d393bc540f86 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c @@ -75,7 +75,7 @@ gp10b_pmu_acr = { .bootstrap_multiple_falcons = gp10b_pmu_acr_bootstrap_multiple_falcons, }; -#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) +#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) MODULE_FIRMWARE("nvidia/gp10b/pmu/desc.bin"); MODULE_FIRMWARE("nvidia/gp10b/pmu/image.bin"); MODULE_FIRMWARE("nvidia/gp10b/pmu/sig.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c index a17a6dd8d3de..803b98df4858 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c @@ -142,7 +142,7 @@ nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temp) return -ENODEV; } - result = min(max(result, (s64)info.min), (s64)info.max); + result = clamp(result, (s64)info.min, (s64)info.max); if (info.link != 0xff) { int ret = nvkm_volt_map(volt, info.link, temp); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk20a.c index 8c2faa964511..ccac88da8864 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk20a.c @@ -45,7 +45,7 @@ static const struct cvb_coef gk20a_cvb_coef[] = { /* 852 */ { 1608418, -21643, -269, 0, 763, -48}, }; -/** +/* * cvb_mv = ((c2 * speedo / s_scale + c1) * speedo / s_scale + c0) */ static inline int @@ -58,7 +58,7 @@ gk20a_volt_get_cvb_voltage(int speedo, int s_scale, const struct cvb_coef *coef) return mv; } -/** +/* * cvb_t_mv = * ((c2 * speedo / s_scale + c1) * speedo / s_scale + c0) + * ((c3 * speedo / s_scale + c4 + c5 * T / t_scale) * T / t_scale) |