Ben Skeggs
2024-Jun-13 16:59 UTC
[PATCH 00/21] drm/nouveau: insert auxiliary device between nvkm and drm
This series was originally part of an RFC demonstrating NVKM and the DRM driver split into separate kernel modules, but it became apparent whilst working on this series that there's some benefit to making these changes regardless of a module split, so I'm sending them out separately. The bulk of the series moves the remaining bus-specific handling (PCI/ platform driver registation, power management, ACPI, etc) out of the DRM driver and into NVKM. As NVKM finishes probe() for a PCI or Tegra device, it will now register a device on the auxiliary bus, which the DRM driver will probe() against instead of devices from the PCI and platform buses directly. The result of this is a cleaner integration of support for Tegra GPUs in a codebase that originally assumed a PCI device everywhere. As the DRM driver mostly just operates on objects allocated from NVKM, support for Tegra wasn't *too* bad to integrate, but with NVKM handling some pieces, and the DRM driver handling others, the driver init paths were somewhat convoluted. With the bus-level device handling now entirely living within NVKM, the DRM driver's init paths for PCI and Tegra GPUs has been unified, which cleans up the remaining messy bits there. One unanticipated benefit that comes from utilising the auxiliary bus is that, on Optimus systems, it's no longer necessary to fully reinitialise the entire GPU (including time-consuming steps such as booting firmware, or restoring page tables to VRAM) in order to respond to simple queries of the underlying PCI device (ie. running lspci). Now, NVKM will only wake the PCI device itself when asked by the kernel, and because the remainder of GPU (re)initialisation is tied to clients' object trees, *and* the DRM device is still asleep, no other steps need to be taken, greatly reducing resume latency. A link to a tree containing the patches is below. [1] https://gitlab.freedesktop.org/bskeggs/nouveau/-/tree/00.02-auxdev Ben Skeggs (21): drm/nouveau: fix a couple of KBuild comments drm/nouveau/nvkm: delay calling subdev ctor()'s until device oneinit() drm/nouveau/nvkm: add nvkm_client_event() drm/nouveau/nvif: add nvif_event_stat drm/nouveau/nvif: add nvif_driver_func for nvkm->drm callbacks drm/nouveau/nvkm: add init()/exit() drm/nouveau/nvkm: cleanup in nvkm_device_{pci,tegra}_new() on failure drm/nouveau/nvkm: move vgaarb code from drm drm/nouveau/nvkm: move switcheroo init from drm drm/nouveau/nvif: add runpm supported flag to device impl drm/nouveau/nvkm: move switcheroo from drm drm/nouveau/nvkm: prepare pci/tegra probe()/remove() functions drm/nouveau/nvkm: move pci probe() defer from drm drm/nouveau/nvkm: move pci probe() fb handoff from drm drm/nouveau/nvkm: move pci probe() enable/disable handling from drm drm/nouveau/nvkm: move pci probe() runpm quirk from drm drm/nouveau/nvkm: move pci pm ops from drm drm/nouveau/nvkm: add device to auxiliary bus for each nvkm_device drm/nouveau: wrap pm_runtime_* calls with nouveau_runpm drm/nouveau: probe() against nvkm-provided auxiliary devices drm/nouveau/nvkm: s/nouveau/nvkm/ over code moved from drm drivers/gpu/drm/nouveau/Kbuild | 11 +- drivers/gpu/drm/nouveau/Kconfig | 1 + drivers/gpu/drm/nouveau/dispnv04/crtc.c | 4 +- drivers/gpu/drm/nouveau/dispnv04/disp.h | 2 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 40 +- drivers/gpu/drm/nouveau/dispnv50/head.c | 2 +- .../gpu/drm/nouveau/include/nvif/driverif.h | 18 + drivers/gpu/drm/nouveau/include/nvif/event.h | 7 +- .../drm/nouveau/include/nvkm/core/client.h | 4 +- .../drm/nouveau/include/nvkm/core/device.h | 12 + .../drm/nouveau/include/nvkm/core/module.h | 10 + .../gpu/drm/nouveau/include/nvkm/core/pci.h | 8 +- .../gpu/drm/nouveau/include/nvkm/core/tegra.h | 5 +- drivers/gpu/drm/nouveau/nouveau_acpi.c | 352 --------------- drivers/gpu/drm/nouveau/nouveau_acpi.h | 10 - drivers/gpu/drm/nouveau/nouveau_chan.c | 2 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 16 +- drivers/gpu/drm/nouveau/nouveau_connector.h | 1 + drivers/gpu/drm/nouveau/nouveau_debugfs.c | 24 +- drivers/gpu/drm/nouveau/nouveau_display.c | 19 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 347 ++++----------- drivers/gpu/drm/nouveau/nouveau_drv.h | 24 +- drivers/gpu/drm/nouveau/nouveau_fence.c | 2 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 30 +- drivers/gpu/drm/nouveau/nouveau_platform.c | 91 ---- drivers/gpu/drm/nouveau/nouveau_runpm.h | 89 ++++ drivers/gpu/drm/nouveau/nouveau_svm.c | 2 +- drivers/gpu/drm/nouveau/nouveau_vga.c | 98 +---- drivers/gpu/drm/nouveau/nouveau_vga.h | 3 +- drivers/gpu/drm/nouveau/nvif/event.c | 9 + drivers/gpu/drm/nouveau/nvkm/Kbuild | 3 + drivers/gpu/drm/nouveau/nvkm/core/Kbuild | 2 +- drivers/gpu/drm/nouveau/nvkm/core/client.c | 17 +- drivers/gpu/drm/nouveau/nvkm/core/driver.c | 14 +- drivers/gpu/drm/nouveau/nvkm/core/uevent.c | 2 +- drivers/gpu/drm/nouveau/nvkm/device/acpi.c | 416 +++++++++++++++++- drivers/gpu/drm/nouveau/nvkm/device/acpi.h | 19 + drivers/gpu/drm/nouveau/nvkm/device/base.c | 151 +++++-- drivers/gpu/drm/nouveau/nvkm/device/pci.c | 258 +++++++++-- drivers/gpu/drm/nouveau/nvkm/device/priv.h | 3 +- drivers/gpu/drm/nouveau/nvkm/device/tegra.c | 87 +++- drivers/gpu/drm/nouveau/nvkm/device/user.c | 2 + .../gpu/drm/nouveau/nvkm/engine/disp/uconn.c | 6 +- .../{nouveau_platform.h => nvkm/module.c} | 45 +- .../gpu/drm/nouveau/nvkm/subdev/pci/base.c | 30 ++ 45 files changed, 1246 insertions(+), 1052 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/include/nvkm/core/module.h delete mode 100644 drivers/gpu/drm/nouveau/nouveau_platform.c create mode 100644 drivers/gpu/drm/nouveau/nouveau_runpm.h rename drivers/gpu/drm/nouveau/{nouveau_platform.h => nvkm/module.c} (60%) -- 2.44.0
Ben Skeggs
2024-Jun-13 16:59 UTC
[PATCH 01/21] drm/nouveau: fix a couple of KBuild comments
The NVIF/NVKM comments were backwards. Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/Kbuild | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/nouveau/Kbuild b/drivers/gpu/drm/nouveau/Kbuild index f99b7b227947..61eeef83847a 100644 --- a/drivers/gpu/drm/nouveau/Kbuild +++ b/drivers/gpu/drm/nouveau/Kbuild @@ -7,14 +7,12 @@ ccflags-y += -I $(NOUVEAU_PATH)/$(src)/nvkm ccflags-y += -I $(NOUVEAU_PATH)/$(src) # NVKM - HW resource manager -#- code also used by various userspace tools/tests -include $(src)/nvif/Kbuild -nouveau-y := $(nvif-y) +include $(src)/nvkm/Kbuild +nouveau-y := $(nvkm-y) # NVIF - NVKM interface library (NVKM user interface also defined here) -#- code also used by various userspace tools/tests -include $(src)/nvkm/Kbuild -nouveau-y += $(nvkm-y) +include $(src)/nvif/Kbuild +nouveau-y += $(nvif-y) # DRM - general ifdef CONFIG_X86 -- 2.44.0
Ben Skeggs
2024-Jun-13 16:59 UTC
[PATCH 02/21] drm/nouveau/nvkm: delay calling subdev ctor()'s until device oneinit()
A later patch in the series converts nvkm_device_{pci_tegra}_new into PCI/platform device probe functions, as a step towards moving all the PCI/Tegra-specific handling into NVKM. nouveau.ko has two module options (nouveau.config/nouveau.debug) that affect the behaviour of NVKM, however, and the probe() functions will not have access to these, which would break a user's configuration if they depend on any of the options to workaround a problem, etc. To avoid this, we delay calling constructors for each subdev (which could depend on module parameters) until allocation of the first nvif_device, which will allow the DRM driver a chance to override device.{cfg,dbg}opt before they're needed. Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/nouveau_drm.c | 3 + drivers/gpu/drm/nouveau/nvkm/device/base.c | 112 ++++++++++++-------- drivers/gpu/drm/nouveau/nvkm/device/pci.c | 2 +- drivers/gpu/drm/nouveau/nvkm/device/priv.h | 3 +- drivers/gpu/drm/nouveau/nvkm/device/tegra.c | 2 +- 5 files changed, 71 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 965331e65fda..18990d21dc48 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -644,6 +644,9 @@ nouveau_drm_device_new(const struct drm_driver *drm_driver, struct device *paren drm->nvkm = device; + device->cfgopt = nouveau_config; + device->dbgopt = nouveau_debug; + nvif_parent_ctor(&nouveau_parent, &drm->parent); ret = nvkm_driver_ctor(device, &driver, &impl, &priv); diff --git a/drivers/gpu/drm/nouveau/nvkm/device/base.c b/drivers/gpu/drm/nouveau/nvkm/device/base.c index 20609571793e..1b76c2a60799 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/base.c @@ -2908,6 +2908,62 @@ nvkm_device_preinit(struct nvkm_device *device) return ret; } +static int +nvkm_device_oneinit(struct nvkm_device *device) +{ + struct nvkm_subdev *subdev, *subtmp; + int ret, j; + +#define NVKM_LAYOUT_ONCE(type,data,ptr) \ + 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); \ + if (ret) { \ + nvkm_subdev_del(&subdev); \ + device->ptr = NULL; \ + if (ret != -ENODEV) { \ + nvdev_error(device, "%s ctor failed: %d\n", \ + nvkm_subdev_type[(type)], ret); \ + goto done; \ + } \ + } else { \ + subdev->pself = (void **)&device->ptr; \ + } \ + } +#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)) { \ + ret = device->chip->ptr.ctor(device, (type), (j), &device->ptr[j]); \ + subdev = nvkm_device_subdev(device, (type), (j)); \ + if (ret) { \ + nvkm_subdev_del(&subdev); \ + device->ptr[j] = NULL; \ + if (ret != -ENODEV) { \ + nvdev_error(device, "%s%d ctor failed: %d\n", \ + nvkm_subdev_type[(type)], (j), ret); \ + goto done; \ + } \ + } else { \ + subdev->pself = (void **)&device->ptr[j]; \ + } \ + } \ + } +#include <core/layout.h> +#undef NVKM_LAYOUT_INST +#undef NVKM_LAYOUT_ONCE + + ret = nvkm_intr_install(device); +done: + if (ret) { + list_for_each_entry_safe_reverse(subdev, subtmp, &device->subdev, head) + nvkm_subdev_del(&subdev); + } + + return ret; +} + int nvkm_device_init(struct nvkm_device *device) { @@ -2915,6 +2971,12 @@ nvkm_device_init(struct nvkm_device *device) int ret; s64 time; + if (list_empty(&device->subdev)) { + ret = nvkm_device_oneinit(device); + if (ret) + return ret; + } + ret = nvkm_device_preinit(device); if (ret) return ret; @@ -3012,13 +3074,11 @@ int 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, - struct nvkm_device *device) + const char *name, struct nvkm_device *device) { - struct nvkm_subdev *subdev; u64 mmio_base, mmio_size; u32 boot0, boot1, strap; - int ret = -EEXIST, j; + int ret = -EEXIST; unsigned chipset; device->func = func; @@ -3026,8 +3086,6 @@ nvkm_device_ctor(const struct nvkm_device_func *func, device->dev = dev; device->type = type; device->handle = handle; - device->cfgopt = cfg; - device->dbgopt = dbg; device->name = name; device->debug = nvkm_dbgopt(device->dbgopt, "device"); INIT_LIST_HEAD(&device->subdev); @@ -3265,47 +3323,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, mutex_init(&device->mutex); nvkm_intr_ctor(device); -#define NVKM_LAYOUT_ONCE(type,data,ptr) \ - 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); \ - if (ret) { \ - nvkm_subdev_del(&subdev); \ - device->ptr = NULL; \ - if (ret != -ENODEV) { \ - nvdev_error(device, "%s ctor failed: %d\n", \ - nvkm_subdev_type[(type)], ret); \ - goto done; \ - } \ - } else { \ - subdev->pself = (void **)&device->ptr; \ - } \ - } -#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)) { \ - ret = device->chip->ptr.ctor(device, (type), (j), &device->ptr[j]); \ - subdev = nvkm_device_subdev(device, (type), (j)); \ - if (ret) { \ - nvkm_subdev_del(&subdev); \ - device->ptr[j] = NULL; \ - if (ret != -ENODEV) { \ - nvdev_error(device, "%s%d ctor failed: %d\n", \ - nvkm_subdev_type[(type)], (j), ret); \ - goto done; \ - } \ - } else { \ - subdev->pself = (void **)&device->ptr[j]; \ - } \ - } \ - } -#include <core/layout.h> -#undef NVKM_LAYOUT_INST -#undef NVKM_LAYOUT_ONCE - - ret = nvkm_intr_install(device); + ret = 0; done: if (ret && device->pri) { iounmap(device->pri); diff --git a/drivers/gpu/drm/nouveau/nvkm/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/device/pci.c index 3ff6436007fa..8bfedd79d7a5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/pci.c @@ -1679,7 +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, &pdev->device); + &pdev->device); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/device/priv.h b/drivers/gpu/drm/nouveau/nvkm/device/priv.h index e42b18820a95..176cb1dfb2fe 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/device/priv.h @@ -54,8 +54,7 @@ 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, - struct nvkm_device *); + const char *name, struct nvkm_device *); int nvkm_device_init(struct nvkm_device *); int nvkm_device_fini(struct nvkm_device *, bool suspend); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/device/tegra.c index d1c294f00665..bb514ccdfff4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/tegra.c @@ -310,7 +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, &tdev->device); + &tdev->device); if (ret) goto powerdown; -- 2.44.0
A later patch in this series moves the nvif_event callback function, but all the callers directly dereference object->client->event(). Add a helper function so this only has to be changed in one place. Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/include/nvkm/core/client.h | 1 + drivers/gpu/drm/nouveau/nvkm/core/client.c | 6 ++++++ drivers/gpu/drm/nouveau/nvkm/core/uevent.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c | 6 +++--- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h index 2da9dfbf0d56..5c9a54d4bd64 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h @@ -19,6 +19,7 @@ struct nvkm_client { int nvkm_client_new(const char *name, struct nvkm_device *, int (*event)(u64, void *, u32), const struct nvif_client_impl **, struct nvif_client_priv **); +int nvkm_client_event(struct nvkm_client *client, u64 token, void *repv, u32 repc); /* logging for client-facing objects */ #define nvif_printk(o,l,p,f,a...) do { \ diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c index 6471edda8a96..beb966d65daf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/client.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c @@ -31,6 +31,12 @@ #include <nvif/event.h> #include <nvif/unpack.h> +int +nvkm_client_event(struct nvkm_client *client, u64 token, void *repv, u32 repc) +{ + return client->event(token, repv, repc); +} + static int nvkm_client_new_device(struct nvif_client_priv *client, const struct nvif_device_impl **pimpl, struct nvif_device_priv **ppriv) diff --git a/drivers/gpu/drm/nouveau/nvkm/core/uevent.c b/drivers/gpu/drm/nouveau/nvkm/core/uevent.c index 365e41134f3d..fccf6477d3d1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/uevent.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/uevent.c @@ -111,7 +111,7 @@ nvkm_uevent_ntfy(struct nvkm_event_ntfy *ntfy, u32 bits) if (uevent->func) return uevent->func(uevent->parent, uevent->object.object, bits); - return client->event(uevent->object.object, NULL, 0); + return nvkm_client_event(client, uevent->object.object, NULL, 0); } int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c index 9c7b83c99b80..4284e7b924fc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c @@ -50,7 +50,7 @@ nvkm_uconn_uevent_gsp(struct nvkm_object *object, u64 token, u32 bits) if (bits & NVKM_DPYID_IRQ) args.v0.types |= NVIF_CONN_EVENT_V0_IRQ; - return object->client->event(token, &args, sizeof(args.v0)); + return nvkm_client_event(object->client, token, &args, sizeof(args.v0)); } static int @@ -67,7 +67,7 @@ nvkm_uconn_uevent_aux(struct nvkm_object *object, u64 token, u32 bits) if (bits & NVKM_I2C_IRQ) args.v0.types |= NVIF_CONN_EVENT_V0_IRQ; - return object->client->event(token, &args, sizeof(args.v0)); + return nvkm_client_event(object->client, token, &args, sizeof(args.v0)); } static int @@ -82,7 +82,7 @@ nvkm_uconn_uevent_gpio(struct nvkm_object *object, u64 token, u32 bits) if (bits & NVKM_GPIO_LO) args.v0.types |= NVIF_CONN_EVENT_V0_UNPLUG; - return object->client->event(token, &args, sizeof(args.v0)); + return nvkm_client_event(object->client, token, &args, sizeof(args.v0)); } static bool -- 2.44.0
Return an enum rather than an int from nvif_event callbacks. Also moves the NVIF_EVENT_* definitions to driverif.h, with the rest of the DRM<->NVKM interfaces. Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 4 ++-- drivers/gpu/drm/nouveau/dispnv04/disp.h | 2 +- drivers/gpu/drm/nouveau/dispnv50/head.c | 2 +- drivers/gpu/drm/nouveau/include/nvif/driverif.h | 5 +++++ drivers/gpu/drm/nouveau/include/nvif/event.h | 5 ++--- drivers/gpu/drm/nouveau/nouveau_chan.c | 2 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 4 ++-- drivers/gpu/drm/nouveau/nouveau_fence.c | 2 +- drivers/gpu/drm/nouveau/nouveau_svm.c | 2 +- 9 files changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 225716d47c56..d7575ece9214 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1072,7 +1072,7 @@ nv04_finish_page_flip(struct nouveau_channel *chan, return 0; } -int +enum nvif_event_stat nv04_flip_complete(struct nvif_event *event, void *argv, u32 argc) { struct nv04_display *disp = container_of(event, typeof(*disp), flip); @@ -1272,7 +1272,7 @@ static const struct drm_plane_funcs nv04_primary_plane_funcs = { DRM_PLANE_NON_ATOMIC_FUNCS, }; -static int +static enum nvif_event_stat nv04_crtc_vblank_handler(struct nvif_event *event, void *repv, u32 repc) { struct nouveau_crtc *nv_crtc = container_of(event, struct nouveau_crtc, vblank); diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h index 8eba76ab880e..88df31b6ac6b 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.h +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h @@ -182,5 +182,5 @@ nouveau_bios_run_init_table(struct drm_device *dev, u16 table, ); } -int nv04_flip_complete(struct nvif_event *, void *, u32); +enum nvif_event_stat nv04_flip_complete(struct nvif_event *, void *, u32); #endif diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c index 4ad117b01d69..fd7791540f6f 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c @@ -549,7 +549,7 @@ nvd9_head_func = { .late_register = nv50_head_late_register, }; -static int +static enum nvif_event_stat nv50_head_vblank_handler(struct nvif_event *event, void *repv, u32 repc) { struct nouveau_crtc *nv_crtc = container_of(event, struct nouveau_crtc, vblank); diff --git a/drivers/gpu/drm/nouveau/include/nvif/driverif.h b/drivers/gpu/drm/nouveau/include/nvif/driverif.h index 40f58a94c09a..0476dd6621b5 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/driverif.h +++ b/drivers/gpu/drm/nouveau/include/nvif/driverif.h @@ -23,6 +23,11 @@ struct nvif_cgrp_priv; struct nvif_chan_priv; struct nvif_engobj_priv; +enum nvif_event_stat { + NVIF_EVENT_KEEP, + NVIF_EVENT_DROP, +}; + struct nvif_event_impl { void (*del)(struct nvif_event_priv *); int (*allow)(struct nvif_event_priv *); diff --git a/drivers/gpu/drm/nouveau/include/nvif/event.h b/drivers/gpu/drm/nouveau/include/nvif/event.h index 42c2d0b5f66b..6c52de0e17d0 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/event.h +++ b/drivers/gpu/drm/nouveau/include/nvif/event.h @@ -2,11 +2,10 @@ #ifndef __NVIF_EVENT_H__ #define __NVIF_EVENT_H__ #include <nvif/object.h> +#include <nvif/driverif.h> struct nvif_event; -#define NVIF_EVENT_KEEP 0 -#define NVIF_EVENT_DROP 1 -typedef int (*nvif_event_func)(struct nvif_event *, void *repv, u32 repc); +typedef enum nvif_event_stat (*nvif_event_func)(struct nvif_event *, void *repv, u32 repc); struct nvif_event { const struct nvif_event_impl *impl; diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 3a17e30d6c49..6a2b7e21afbf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -47,7 +47,7 @@ nouveau_channel_kill(struct nouveau_channel *chan) nouveau_fence_context_kill(chan->fence, -ENODEV); } -static int +static enum nvif_event_stat nouveau_channel_killed(struct nvif_event *event, void *repv, u32 repc) { struct nouveau_channel *chan = container_of(event, typeof(*chan), kill); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 7d9cba7bcb8f..e3071ea845e6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1199,7 +1199,7 @@ nouveau_connector_hpd(struct nouveau_connector *nv_connector, u64 bits) spin_unlock_irqrestore(&drm->hpd_lock, flags); } -static int +static enum nvif_event_stat nouveau_connector_irq(struct nvif_event *event, void *repv, u32 repc) { struct nouveau_connector *nv_connector = container_of(event, typeof(*nv_connector), irq); @@ -1208,7 +1208,7 @@ nouveau_connector_irq(struct nvif_event *event, void *repv, u32 repc) return NVIF_EVENT_KEEP; } -static int +static enum nvif_event_stat nouveau_connector_hotplug(struct nvif_event *event, void *repv, u32 repc) { struct nouveau_connector *nv_connector = container_of(event, typeof(*nv_connector), hpd); diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 9443cbaa8cff..2b6b60ec10fa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -168,7 +168,7 @@ nouveau_fence_uevent_work(struct work_struct *work) spin_unlock_irqrestore(&fctx->lock, flags); } -static int +static enum nvif_event_stat nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 repc) { struct nouveau_fence_chan *fctx = container_of(event, typeof(*fctx), event); diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c index 5b94f6e3a39d..b8a3c3d2d3aa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_svm.c +++ b/drivers/gpu/drm/nouveau/nouveau_svm.c @@ -870,7 +870,7 @@ nouveau_svm_fault(struct work_struct *work) nouveau_svm_fault_replay(svm); } -static int +static enum nvif_event_stat nouveau_svm_event(struct nvif_event *event, void *argv, u32 argc) { struct nouveau_svm_fault_buffer *buffer = container_of(event, typeof(*buffer), notify); -- 2.44.0
Ben Skeggs
2024-Jun-13 16:59 UTC
[PATCH 05/21] drm/nouveau/nvif: add nvif_driver_func for nvkm->drm callbacks
A later patch in this series will move the code that binds to a PCI/ Tegra device into NVKM, and requires a couple of callbacks to handle switcheroo, etc. nvif_event is generally used for NVKM->DRM callbacks, but these will need to be registered before nvif_event is ready. This patch replaces the event() function pointer that was passed to nvkm_driver_ctor() during init with a nvif_driver_func struct, that contains the existing event() callback. Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/include/nvif/driverif.h | 4 ++++ drivers/gpu/drm/nouveau/include/nvif/event.h | 2 ++ drivers/gpu/drm/nouveau/include/nvkm/core/client.h | 3 +-- drivers/gpu/drm/nouveau/include/nvkm/core/device.h | 2 ++ drivers/gpu/drm/nouveau/nouveau_drm.c | 7 +++++++ drivers/gpu/drm/nouveau/nouveau_drv.h | 1 + drivers/gpu/drm/nouveau/nvif/event.c | 9 +++++++++ drivers/gpu/drm/nouveau/nvkm/core/client.c | 13 +++++++++---- drivers/gpu/drm/nouveau/nvkm/core/driver.c | 14 +------------- 9 files changed, 36 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvif/driverif.h b/drivers/gpu/drm/nouveau/include/nvif/driverif.h index 0476dd6621b5..638c72c1b580 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/driverif.h +++ b/drivers/gpu/drm/nouveau/include/nvif/driverif.h @@ -34,6 +34,10 @@ struct nvif_event_impl { int (*block)(struct nvif_event_priv *); }; +struct nvif_driver_func { + enum nvif_event_stat (*event)(u64 token, void *repv, u32 repc); +}; + struct nvif_driver { const char *name; int (*suspend)(struct nvif_client_priv *); diff --git a/drivers/gpu/drm/nouveau/include/nvif/event.h b/drivers/gpu/drm/nouveau/include/nvif/event.h index 6c52de0e17d0..ce14e478b1fe 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/event.h +++ b/drivers/gpu/drm/nouveau/include/nvif/event.h @@ -5,6 +5,8 @@ #include <nvif/driverif.h> struct nvif_event; +enum nvif_event_stat nvif_event(u64 token, void *repv, u32 repc); + typedef enum nvif_event_stat (*nvif_event_func)(struct nvif_event *, void *repv, u32 repc); struct nvif_event { diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h index 5c9a54d4bd64..4e5d56056b81 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h @@ -14,10 +14,9 @@ struct nvkm_client { spinlock_t obj_lock; void *data; - int (*event)(u64 token, void *argv, u32 argc); }; -int nvkm_client_new(const char *name, struct nvkm_device *, int (*event)(u64, void *, u32), +int nvkm_client_new(const char *name, struct nvkm_device *, const struct nvif_client_impl **, struct nvif_client_priv **); int nvkm_client_event(struct nvkm_client *client, u64 token, void *repv, u32 repc); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index fff0d7dd0e1b..c9965934b0d5 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -71,6 +71,8 @@ struct nvkm_device { bool armed; bool legacy_done; } intr; + + const struct nvif_driver_func *driver; }; struct nvkm_subdev *nvkm_device_subdev(struct nvkm_device *, int type, int inst); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 18990d21dc48..09947790f677 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -614,6 +614,11 @@ nouveau_drm_device_init(struct nouveau_drm *drm) return ret; } +static const struct nvif_driver_func +nouveau_driver = { + .event = nvif_event, +}; + static void nouveau_drm_device_del(struct nouveau_drm *drm) { @@ -643,9 +648,11 @@ nouveau_drm_device_new(const struct drm_driver *drm_driver, struct device *paren return ERR_PTR(-ENOMEM); drm->nvkm = device; + drm->driver = nouveau_driver; device->cfgopt = nouveau_config; device->dbgopt = nouveau_debug; + device->driver = &drm->driver; nvif_parent_ctor(&nouveau_parent, &drm->parent); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 832651fe9f42..52589d5eab63 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -202,6 +202,7 @@ u_memcpya(uint64_t user, unsigned int nmemb, unsigned int size) struct nouveau_drm { struct nvkm_device *nvkm; + struct nvif_driver_func driver; struct nvif_parent parent; struct nvif_client client; struct nvif_device device; diff --git a/drivers/gpu/drm/nouveau/nvif/event.c b/drivers/gpu/drm/nouveau/nvif/event.c index 2974ec8e13af..816e3d1bedb4 100644 --- a/drivers/gpu/drm/nouveau/nvif/event.c +++ b/drivers/gpu/drm/nouveau/nvif/event.c @@ -23,6 +23,15 @@ #include <nvif/driverif.h> #include <nvif/printf.h> +enum nvif_event_stat +nvif_event(u64 token, void *repv, u32 repc) +{ + struct nvif_object *object = (void *)(unsigned long)token; + struct nvif_event *event = container_of(object, typeof(*event), object); + + return event->func(event, repv, repc); +} + int nvif_event_block(struct nvif_event *event) { diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c index beb966d65daf..b767d77ad205 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/client.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c @@ -23,6 +23,7 @@ */ #include <core/client.h> #include <core/device.h> +#include <core/event.h> #include <core/option.h> #include <device/user.h> @@ -34,7 +35,12 @@ int nvkm_client_event(struct nvkm_client *client, u64 token, void *repv, u32 repc) { - return client->event(token, repv, repc); + enum nvif_event_stat stat = client->device->driver->event(token, repv, repc); + + if (stat == NVIF_EVENT_KEEP) + return NVKM_EVENT_KEEP; + + return NVKM_EVENT_DROP; } static int @@ -59,7 +65,7 @@ nvkm_client_new_client(struct nvif_client_priv *parent, struct nvkm_client *client; int ret; - ret = nvkm_client_new("client", parent->device, parent->event, pimpl, &client); + ret = nvkm_client_new("client", parent->device, pimpl, &client); if (ret) return ret; @@ -96,7 +102,7 @@ nvkm_client = { }; int -nvkm_client_new(const char *name, struct nvkm_device *device, int (*event)(u64, void *, u32), +nvkm_client_new(const char *name, struct nvkm_device *device, const struct nvif_client_impl **pimpl, struct nvif_client_priv **ppriv) { struct nvkm_oclass oclass = {}; @@ -112,7 +118,6 @@ nvkm_client_new(const char *name, struct nvkm_device *device, int (*event)(u64, client->device = device; client->debug = NV_DBG_ERROR; spin_lock_init(&client->obj_lock); - client->event = event; *pimpl = &nvkm_client_impl; *ppriv = client; diff --git a/drivers/gpu/drm/nouveau/nvkm/core/driver.c b/drivers/gpu/drm/nouveau/nvkm/core/driver.c index 86ada3c888ec..dcc5dc7f246e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/driver.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/driver.c @@ -56,18 +56,6 @@ nvkm_driver_suspend(struct nvif_client_priv *client) return nvkm_object_fini(&client->object, true); } -static int -nvkm_driver_event(u64 token, void *repv, u32 repc) -{ - struct nvif_object *object = (void *)(unsigned long)token; - struct nvif_event *event = container_of(object, typeof(*event), object); - - if (event->func(event, repv, repc) == NVIF_EVENT_KEEP) - return NVKM_EVENT_KEEP; - - return NVKM_EVENT_DROP; -} - static const struct nvif_driver nvkm_driver = { .name = "nvkm", @@ -83,7 +71,7 @@ nvkm_driver_ctor(struct nvkm_device *device, const struct nvif_driver **pdrv, { int ret; - ret = nvkm_client_new("driver", device, nvkm_driver_event, pimpl, ppriv); + ret = nvkm_client_new("driver", device, pimpl, ppriv); if (ret) return ret; -- 2.44.0
Add stub init()/exit() functions that subsequent patches will use as they move the pci/platform-specific code out of the DRM driver. Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- .../drm/nouveau/include/nvkm/core/module.h | 8 +++++ drivers/gpu/drm/nouveau/nouveau_drm.c | 9 +++++ drivers/gpu/drm/nouveau/nvkm/Kbuild | 3 ++ drivers/gpu/drm/nouveau/nvkm/core/Kbuild | 2 +- drivers/gpu/drm/nouveau/nvkm/module.c | 33 +++++++++++++++++++ 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/nouveau/include/nvkm/core/module.h create mode 100644 drivers/gpu/drm/nouveau/nvkm/module.c diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/module.h b/drivers/gpu/drm/nouveau/include/nvkm/core/module.h new file mode 100644 index 000000000000..5cf80e4deb90 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/module.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_MODULE_H__ +#define __NVKM_MODULE_H__ +#include <linux/module.h> + +int __init nvkm_init(void); +void __exit nvkm_exit(void); +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 09947790f677..0bf39b05926f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -39,6 +39,7 @@ #include <core/driver.h> #include <core/gpuobj.h> +#include <core/module.h> #include <core/option.h> #include <core/pci.h> #include <core/tegra.h> @@ -1375,6 +1376,8 @@ nouveau_platform_device_create(const struct nvkm_device_tegra_func *func, static int __init nouveau_drm_init(void) { + int ret; + driver_pci = driver_stub; driver_platform = driver_stub; @@ -1388,6 +1391,10 @@ nouveau_drm_init(void) if (!nouveau_modeset) return 0; + ret = nvkm_init(); + if (ret) + return ret; + #ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER platform_driver_register(&nouveau_platform_driver); #endif @@ -1419,6 +1426,8 @@ nouveau_drm_exit(void) #endif if (IS_ENABLED(CONFIG_DRM_NOUVEAU_SVM)) mmu_notifier_synchronize(); + + nvkm_exit(); } module_init(nouveau_drm_init); diff --git a/drivers/gpu/drm/nouveau/nvkm/Kbuild b/drivers/gpu/drm/nouveau/nvkm/Kbuild index f68c19586b53..9e1a6ab937e1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/Kbuild @@ -1,4 +1,7 @@ # SPDX-License-Identifier: MIT + +nvkm-y := nvkm/module.o + include $(src)/nvkm/core/Kbuild include $(src)/nvkm/nvfw/Kbuild include $(src)/nvkm/device/Kbuild diff --git a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild index 50ff041ecdf0..70cec7bbb018 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild @@ -1,5 +1,5 @@ # SPDX-License-Identifier: MIT -nvkm-y := nvkm/core/client.o +nvkm-y += nvkm/core/client.o nvkm-y += nvkm/core/driver.o nvkm-y += nvkm/core/engine.o nvkm-y += nvkm/core/enum.o diff --git a/drivers/gpu/drm/nouveau/nvkm/module.c b/drivers/gpu/drm/nouveau/nvkm/module.c new file mode 100644 index 000000000000..66d28465514b --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/module.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved. + * + * 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 AUTHORS OR COPYRIGHT HOLDERS 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. + */ +#include <core/module.h> + +void __exit +nvkm_exit(void) +{ +} + +int __init +nvkm_init(void) +{ + return 0; +} -- 2.44.0
Ben Skeggs
2024-Jun-13 16:59 UTC
[PATCH 07/21] drm/nouveau/nvkm: cleanup in nvkm_device_{pci, tegra}_new() on failure
These previously depended on the caller calling nvkm_device_del() to cleanup if nvkm_device_*_new() fails. That's a little odd for starters, but only the Tegra path cleaned up, and the PCI path would have leaked the memory, FWs etc that had been allocated as NVKM ran each subdev's ctor(). A later patch turns these into pci/platform driver probe() functions, so they need to learn how to clean up after themselves regardless. Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/nouveau_drm.c | 2 +- drivers/gpu/drm/nouveau/nvkm/device/pci.c | 26 ++++++++++++++------- drivers/gpu/drm/nouveau/nvkm/device/tegra.c | 11 +++++---- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 0bf39b05926f..6c1cfc38d8fa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -1351,7 +1351,7 @@ nouveau_platform_device_create(const struct nvkm_device_tegra_func *func, err = nvkm_device_tegra_new(func, pdev, nouveau_config, nouveau_debug, pdevice); if (err) - goto err_free; + return ERR_PTR(err); drm = nouveau_drm_device_new(&driver_platform, &pdev->dev, *pdevice); if (IS_ERR(drm)) { diff --git a/drivers/gpu/drm/nouveau/nvkm/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/device/pci.c index 8bfedd79d7a5..e48f3219f047 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/pci.c @@ -1633,12 +1633,9 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, const struct nvkm_device_pci_vendor *pciv; const char *name = NULL; struct nvkm_device_pci *pdev; + struct nvkm_device *device; int ret, bits; - ret = pci_enable_device(pci_dev); - if (ret) - return ret; - switch (pci_dev->vendor) { case 0x10de: pcid = nvkm_device_pci_10de; break; default: @@ -1664,12 +1661,16 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, pcid++; } - if (!(pdev = kzalloc(sizeof(*pdev), GFP_KERNEL))) { - pci_disable_device(pci_dev); + if (!(pdev = kzalloc(sizeof(*pdev), GFP_KERNEL))) return -ENOMEM; - } - *pdevice = &pdev->device; pdev->pdev = pci_dev; + device = &pdev->device; + + ret = pci_enable_device(pci_dev); + if (ret) { + kfree(pdev); + return ret; + } ret = nvkm_device_ctor(&nvkm_device_pci_func, quirk, &pci_dev->dev, pci_is_pcie(pci_dev) ? NVKM_DEVICE_PCIE : @@ -1682,7 +1683,7 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, &pdev->device); if (ret) - return ret; + goto done; /* Set DMA mask based on capabilities reported by the MMU subdev. */ if (pdev->device.mmu && !pdev->device.pci->agp.bridge) @@ -1696,5 +1697,12 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, pdev->device.mmu->dma_bits = 32; } +done: + if (ret) { + nvkm_device_del(&device); + return ret; + } + + *pdevice = &pdev->device; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/device/tegra.c index bb514ccdfff4..9c3673c74b19 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/tegra.c @@ -240,6 +240,7 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, struct nvkm_device **pdevice) { struct nvkm_device_tegra *tdev; + struct nvkm_device *device; unsigned long rate; int ret; @@ -248,6 +249,7 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, tdev->func = func; tdev->pdev = pdev; + device = &tdev->device; if (func->require_vdd) { tdev->vdd = devm_regulator_get(&pdev->dev, "vdd"); @@ -311,15 +313,14 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev, NVKM_DEVICE_TEGRA, pdev->id, NULL, &tdev->device); - if (ret) - goto powerdown; + if (ret) { + nvkm_device_del(&device); + return ret; + } *pdevice = &tdev->device; - return 0; -powerdown: - nvkm_device_tegra_power_down(tdev); remove: nvkm_device_tegra_remove_iommu(tdev); free: -- 2.44.0
Ben Skeggs
2024-Jun-13 17:00 UTC
[PATCH 08/21] drm/nouveau/nvkm: move vgaarb code from drm
Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/nouveau_vga.c | 27 ---------------- .../gpu/drm/nouveau/nvkm/subdev/pci/base.c | 32 +++++++++++++++++++ 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index 83496af605a1..53b332708061 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: MIT -#include <linux/vgaarb.h> #include <linux/vga_switcheroo.h> #include <drm/drm_fb_helper.h> @@ -8,28 +7,6 @@ #include "nouveau_acpi.h" #include "nouveau_vga.h" -static unsigned int -nouveau_vga_set_decode(struct pci_dev *pdev, bool state) -{ - struct nouveau_drm *drm = pci_get_drvdata(pdev); - struct nvif_device *device = &drm->device; - - if (device->impl->family == NVIF_DEVICE_CURIE && - device->impl->chipset >= 0x4c) - nvif_wr32(device, 0x088060, state); - else - if (device->impl->chipset >= 0x40) - nvif_wr32(device, 0x088054, state); - else - nvif_wr32(device, 0x001854, state); - - if (state) - return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | - VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; - else - return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; -} - static void nouveau_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) @@ -94,8 +71,6 @@ nouveau_vga_init(struct nouveau_drm *drm) return; pdev = to_pci_dev(dev->dev); - vga_client_register(pdev, nouveau_vga_set_decode); - /* don't register Thunderbolt eGPU with vga_switcheroo */ if (pci_is_thunderbolt_attached(pdev)) return; @@ -118,8 +93,6 @@ nouveau_vga_fini(struct nouveau_drm *drm) return; pdev = to_pci_dev(dev->dev); - vga_client_unregister(pdev); - if (pci_is_thunderbolt_attached(pdev)) return; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c index 5a0de45d36ce..e4737b89cb63 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c @@ -27,6 +27,8 @@ #include <core/option.h> #include <core/pci.h> +#include <linux/vgaarb.h> + void nvkm_pci_msi_rearm(struct nvkm_device *device) { @@ -62,6 +64,29 @@ nvkm_pci_mask(struct nvkm_pci *pci, u16 addr, u32 mask, u32 value) return data; } +#include "nouveau_drv.h" + +static unsigned int +nvkm_pci_vga_set_decode(struct pci_dev *pdev, bool state) +{ + struct nvkm_device *device = ((struct nouveau_drm *)pci_get_drvdata(pdev))->nvkm; + + if (device->card_type == NV_40 && + device->chipset >= 0x4c) + nvkm_wr32(device, 0x088060, state); + else + if (device->chipset >= 0x40) + nvkm_wr32(device, 0x088054, state); + else + nvkm_wr32(device, 0x001854, state); + + if (state) + return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | + VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; + else + return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; +} + void nvkm_pci_rom_shadow(struct nvkm_pci *pci, bool shadow) { @@ -76,11 +101,16 @@ nvkm_pci_rom_shadow(struct nvkm_pci *pci, bool shadow) static int nvkm_pci_fini(struct nvkm_subdev *subdev, bool suspend) { + struct nvkm_device_pci *pdev = subdev->device->func->pci(subdev->device); struct nvkm_pci *pci = nvkm_pci(subdev); + if (!subdev->use.enabled) + return 0; + if (pci->agp.bridge) nvkm_agp_fini(pci); + vga_client_unregister(pdev->pdev); return 0; } @@ -111,6 +141,7 @@ nvkm_pci_oneinit(struct nvkm_subdev *subdev) static int nvkm_pci_init(struct nvkm_subdev *subdev) { + struct nvkm_device_pci *pdev = subdev->device->func->pci(subdev->device); struct nvkm_pci *pci = nvkm_pci(subdev); int ret; @@ -131,6 +162,7 @@ nvkm_pci_init(struct nvkm_subdev *subdev) if (pci->msi) pci->func->msi_rearm(pci); + vga_client_register(pdev->pdev, nvkm_pci_vga_set_decode); return 0; } -- 2.44.0
Ben Skeggs
2024-Jun-13 17:00 UTC
[PATCH 09/21] drm/nouveau/nvkm: move switcheroo init from drm
Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 344 --------------------- drivers/gpu/drm/nouveau/nouveau_acpi.h | 7 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 2 - drivers/gpu/drm/nouveau/nvkm/device/acpi.c | 339 +++++++++++++++++++- drivers/gpu/drm/nouveau/nvkm/device/acpi.h | 19 ++ drivers/gpu/drm/nouveau/nvkm/module.c | 3 + 6 files changed, 362 insertions(+), 352 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 8f0c69aad248..b9c43fe552c0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -2,55 +2,12 @@ #include <linux/pci.h> #include <linux/acpi.h> #include <linux/slab.h> -#include <linux/mxm-wmi.h> -#include <linux/vga_switcheroo.h> #include <drm/drm_edid.h> #include <acpi/video.h> #include "nouveau_drv.h" #include "nouveau_acpi.h" -#define NOUVEAU_DSM_LED 0x02 -#define NOUVEAU_DSM_LED_STATE 0x00 -#define NOUVEAU_DSM_LED_OFF 0x10 -#define NOUVEAU_DSM_LED_STAMINA 0x11 -#define NOUVEAU_DSM_LED_SPEED 0x12 - -#define NOUVEAU_DSM_POWER 0x03 -#define NOUVEAU_DSM_POWER_STATE 0x00 -#define NOUVEAU_DSM_POWER_SPEED 0x01 -#define NOUVEAU_DSM_POWER_STAMINA 0x02 - -#define NOUVEAU_DSM_OPTIMUS_CAPS 0x1A -#define NOUVEAU_DSM_OPTIMUS_FLAGS 0x1B - -#define NOUVEAU_DSM_OPTIMUS_POWERDOWN_PS3 (3 << 24) -#define NOUVEAU_DSM_OPTIMUS_NO_POWERDOWN_PS3 (2 << 24) -#define NOUVEAU_DSM_OPTIMUS_FLAGS_CHANGED (1) - -#define NOUVEAU_DSM_OPTIMUS_SET_POWERDOWN (NOUVEAU_DSM_OPTIMUS_POWERDOWN_PS3 | NOUVEAU_DSM_OPTIMUS_FLAGS_CHANGED) - -/* result of the optimus caps function */ -#define OPTIMUS_ENABLED (1 << 0) -#define OPTIMUS_STATUS_MASK (3 << 3) -#define OPTIMUS_STATUS_OFF (0 << 3) -#define OPTIMUS_STATUS_ON_ENABLED (1 << 3) -#define OPTIMUS_STATUS_PWR_STABLE (3 << 3) -#define OPTIMUS_DISPLAY_HOTPLUG (1 << 6) -#define OPTIMUS_CAPS_MASK (7 << 24) -#define OPTIMUS_DYNAMIC_PWR_CAP (1 << 24) - -#define OPTIMUS_AUDIO_CAPS_MASK (3 << 27) -#define OPTIMUS_HDA_CODEC_MASK (2 << 27) /* hda bios control */ - -static struct nouveau_dsm_priv { - bool dsm_detected; - bool optimus_detected; - bool optimus_flags_detected; - bool optimus_skip_dsm; - acpi_handle dhandle; -} nouveau_dsm_priv; - bool nouveau_is_optimus(void) { return nouveau_dsm_priv.optimus_detected; } @@ -59,307 +16,6 @@ bool nouveau_is_v1_dsm(void) { return nouveau_dsm_priv.dsm_detected; } -#ifdef CONFIG_VGA_SWITCHEROO -static const guid_t nouveau_dsm_muid - GUID_INIT(0x9D95A0A0, 0x0060, 0x4D48, - 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4); - -static const guid_t nouveau_op_dsm_muid - GUID_INIT(0xA486D8F8, 0x0BDA, 0x471B, - 0xA7, 0x2B, 0x60, 0x42, 0xA6, 0xB5, 0xBE, 0xE0); - -static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result) -{ - int i; - union acpi_object *obj; - char args_buff[4]; - union acpi_object argv4 = { - .buffer.type = ACPI_TYPE_BUFFER, - .buffer.length = 4, - .buffer.pointer = args_buff - }; - - /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */ - for (i = 0; i < 4; i++) - args_buff[i] = (arg >> i * 8) & 0xFF; - - *result = 0; - obj = acpi_evaluate_dsm_typed(handle, &nouveau_op_dsm_muid, 0x00000100, - func, &argv4, ACPI_TYPE_BUFFER); - if (!obj) { - acpi_handle_info(handle, "failed to evaluate _DSM\n"); - return AE_ERROR; - } else { - if (obj->buffer.length == 4) { - *result |= obj->buffer.pointer[0]; - *result |= (obj->buffer.pointer[1] << 8); - *result |= (obj->buffer.pointer[2] << 16); - *result |= (obj->buffer.pointer[3] << 24); - } - ACPI_FREE(obj); - } - - return 0; -} - -/* - * On some platforms, _DSM(nouveau_op_dsm_muid, func0) has special - * requirements on the fourth parameter, so a private implementation - * instead of using acpi_check_dsm(). - */ -static int nouveau_dsm_get_optimus_functions(acpi_handle handle) -{ - int result; - - /* - * Function 0 returns a Buffer containing available functions. - * The args parameter is ignored for function 0, so just put 0 in it - */ - if (nouveau_optimus_dsm(handle, 0, 0, &result)) - return 0; - - /* - * ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. - * If the n-th bit is enabled, function n is supported - */ - if (result & 1 && result & (1 << NOUVEAU_DSM_OPTIMUS_CAPS)) - return result; - return 0; -} - -static int nouveau_dsm(acpi_handle handle, int func, int arg) -{ - int ret = 0; - union acpi_object *obj; - union acpi_object argv4 = { - .integer.type = ACPI_TYPE_INTEGER, - .integer.value = arg, - }; - - obj = acpi_evaluate_dsm_typed(handle, &nouveau_dsm_muid, 0x00000102, - func, &argv4, ACPI_TYPE_INTEGER); - if (!obj) { - acpi_handle_info(handle, "failed to evaluate _DSM\n"); - return AE_ERROR; - } else { - if (obj->integer.value == 0x80000002) - ret = -ENODEV; - ACPI_FREE(obj); - } - - return ret; -} - -static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) -{ - mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); - mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); - return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id); -} - -static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state) -{ - int arg; - if (state == VGA_SWITCHEROO_ON) - arg = NOUVEAU_DSM_POWER_SPEED; - else - arg = NOUVEAU_DSM_POWER_STAMINA; - nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg); - return 0; -} - -static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id) -{ - if (!nouveau_dsm_priv.dsm_detected) - return 0; - if (id == VGA_SWITCHEROO_IGD) - return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA); - else - return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_SPEED); -} - -static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id, - enum vga_switcheroo_state state) -{ - if (id == VGA_SWITCHEROO_IGD) - return 0; - - /* Optimus laptops have the card already disabled in - * nouveau_switcheroo_set_state */ - if (!nouveau_dsm_priv.dsm_detected) - return 0; - - return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state); -} - -static enum vga_switcheroo_client_id nouveau_dsm_get_client_id(struct pci_dev *pdev) -{ - /* easy option one - intel vendor ID means Integrated */ - if (pdev->vendor == PCI_VENDOR_ID_INTEL) - return VGA_SWITCHEROO_IGD; - - /* is this device on Bus 0? - this may need improving */ - if (pdev->bus->number == 0) - return VGA_SWITCHEROO_IGD; - - return VGA_SWITCHEROO_DIS; -} - -static const struct vga_switcheroo_handler nouveau_dsm_handler = { - .switchto = nouveau_dsm_switchto, - .power_state = nouveau_dsm_power_state, - .get_client_id = nouveau_dsm_get_client_id, -}; - -static void nouveau_dsm_pci_probe(struct pci_dev *pdev, acpi_handle *dhandle_out, - bool *has_mux, bool *has_opt, - bool *has_opt_flags, bool *has_pr3) -{ - acpi_handle dhandle; - bool supports_mux; - int optimus_funcs; - struct pci_dev *parent_pdev; - - if (pdev->vendor != PCI_VENDOR_ID_NVIDIA) - return; - - *has_pr3 = false; - parent_pdev = pci_upstream_bridge(pdev); - if (parent_pdev) { - if (parent_pdev->bridge_d3) - *has_pr3 = pci_pr3_present(parent_pdev); - else - pci_d3cold_disable(pdev); - } - - dhandle = ACPI_HANDLE(&pdev->dev); - if (!dhandle) - return; - - if (!acpi_has_method(dhandle, "_DSM")) - return; - - supports_mux = acpi_check_dsm(dhandle, &nouveau_dsm_muid, 0x00000102, - 1 << NOUVEAU_DSM_POWER); - optimus_funcs = nouveau_dsm_get_optimus_functions(dhandle); - - /* Does not look like a Nvidia device. */ - if (!supports_mux && !optimus_funcs) - return; - - *dhandle_out = dhandle; - *has_mux = supports_mux; - *has_opt = !!optimus_funcs; - *has_opt_flags = optimus_funcs & (1 << NOUVEAU_DSM_OPTIMUS_FLAGS); - - if (optimus_funcs) { - uint32_t result; - nouveau_optimus_dsm(dhandle, NOUVEAU_DSM_OPTIMUS_CAPS, 0, - &result); - dev_info(&pdev->dev, "optimus capabilities: %s, status %s%s\n", - (result & OPTIMUS_ENABLED) ? "enabled" : "disabled", - (result & OPTIMUS_DYNAMIC_PWR_CAP) ? "dynamic power, " : "", - (result & OPTIMUS_HDA_CODEC_MASK) ? "hda bios codec supported" : ""); - } -} - -static bool nouveau_dsm_detect(void) -{ - char acpi_method_name[255] = { 0 }; - struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; - struct pci_dev *pdev = NULL; - acpi_handle dhandle = NULL; - bool has_mux = false; - bool has_optimus = false; - bool has_optimus_flags = false; - bool has_power_resources = false; - int vga_count = 0; - bool guid_valid; - bool ret = false; - - /* lookup the MXM GUID */ - guid_valid = mxm_wmi_supported(); - - if (guid_valid) - printk("MXM: GUID detected in BIOS\n"); - - /* now do DSM detection */ - while ((pdev = pci_get_base_class(PCI_BASE_CLASS_DISPLAY, pdev))) { - if ((pdev->class != PCI_CLASS_DISPLAY_VGA << 8) && - (pdev->class != PCI_CLASS_DISPLAY_3D << 8)) - continue; - - vga_count++; - - nouveau_dsm_pci_probe(pdev, &dhandle, &has_mux, &has_optimus, - &has_optimus_flags, &has_power_resources); - } - - /* find the optimus DSM or the old v1 DSM */ - if (has_optimus) { - nouveau_dsm_priv.dhandle = dhandle; - acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, - &buffer); - pr_info("VGA switcheroo: detected Optimus DSM method %s handle\n", - acpi_method_name); - if (has_power_resources) - pr_info("nouveau: detected PR support, will not use DSM\n"); - nouveau_dsm_priv.optimus_detected = true; - nouveau_dsm_priv.optimus_flags_detected = has_optimus_flags; - nouveau_dsm_priv.optimus_skip_dsm = has_power_resources; - ret = true; - } else if (vga_count == 2 && has_mux && guid_valid) { - nouveau_dsm_priv.dhandle = dhandle; - acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, - &buffer); - pr_info("VGA switcheroo: detected DSM switching method %s handle\n", - acpi_method_name); - nouveau_dsm_priv.dsm_detected = true; - ret = true; - } - - - return ret; -} - -void nouveau_register_dsm_handler(void) -{ - bool r; - - r = nouveau_dsm_detect(); - if (!r) - return; - - vga_switcheroo_register_handler(&nouveau_dsm_handler, 0); -} - -/* Must be called for Optimus models before the card can be turned off */ -void nouveau_switcheroo_optimus_dsm(void) -{ - u32 result = 0; - if (!nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.optimus_skip_dsm) - return; - - if (nouveau_dsm_priv.optimus_flags_detected) - nouveau_optimus_dsm(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_OPTIMUS_FLAGS, - 0x3, &result); - - nouveau_optimus_dsm(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_OPTIMUS_CAPS, - NOUVEAU_DSM_OPTIMUS_SET_POWERDOWN, &result); - -} - -void nouveau_unregister_dsm_handler(void) -{ - if (nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.dsm_detected) - vga_switcheroo_unregister_handler(); -} -#else -void nouveau_register_dsm_handler(void) {} -void nouveau_unregister_dsm_handler(void) {} -void nouveau_switcheroo_optimus_dsm(void) {} -#endif - void * nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.h b/drivers/gpu/drm/nouveau/nouveau_acpi.h index e39dd8b94b8b..a7fac1f7a73d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.h +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.h @@ -7,17 +7,14 @@ #if defined(CONFIG_ACPI) && defined(CONFIG_X86) bool nouveau_is_optimus(void); bool nouveau_is_v1_dsm(void); -void nouveau_register_dsm_handler(void); -void nouveau_unregister_dsm_handler(void); -void nouveau_switcheroo_optimus_dsm(void); +#include <device/acpi.h> +static inline void nouveau_switcheroo_optimus_dsm(void) { nvkm_acpi_switcheroo_set_powerdown(); } void *nouveau_acpi_edid(struct drm_device *, struct drm_connector *); bool nouveau_acpi_video_backlight_use_native(void); void nouveau_acpi_video_register_backlight(void); #else static inline bool nouveau_is_optimus(void) { return false; }; static inline bool nouveau_is_v1_dsm(void) { return false; }; -static inline void nouveau_register_dsm_handler(void) {} -static inline void nouveau_unregister_dsm_handler(void) {} static inline void nouveau_switcheroo_optimus_dsm(void) {} static inline void *nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return NULL; } static inline bool nouveau_acpi_video_backlight_use_native(void) { return true; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 6c1cfc38d8fa..0ac17da04819 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -1399,7 +1399,6 @@ nouveau_drm_init(void) platform_driver_register(&nouveau_platform_driver); #endif - nouveau_register_dsm_handler(); nouveau_backlight_ctor(); #ifdef CONFIG_PCI @@ -1419,7 +1418,6 @@ nouveau_drm_exit(void) pci_unregister_driver(&nouveau_drm_pci_driver); #endif nouveau_backlight_dtor(); - nouveau_unregister_dsm_handler(); #ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER platform_driver_unregister(&nouveau_platform_driver); diff --git a/drivers/gpu/drm/nouveau/nvkm/device/acpi.c b/drivers/gpu/drm/nouveau/nvkm/device/acpi.c index c948a0dc9e62..2bead7e879a5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/acpi.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/acpi.c @@ -26,6 +26,343 @@ #include <core/device.h> #include <subdev/clk.h> +#include <linux/mxm-wmi.h> +#include <linux/vga_switcheroo.h> + +#ifdef CONFIG_VGA_SWITCHEROO +struct nouveau_dsm_priv nouveau_dsm_priv = {}; + +static const guid_t nouveau_op_dsm_muid + GUID_INIT(0xA486D8F8, 0x0BDA, 0x471B, + 0xA7, 0x2B, 0x60, 0x42, 0xA6, 0xB5, 0xBE, 0xE0); + +#define NOUVEAU_DSM_OPTIMUS_CAPS 0x1A +#define NOUVEAU_DSM_OPTIMUS_FLAGS 0x1B + +#define NOUVEAU_DSM_OPTIMUS_POWERDOWN_PS3 (3 << 24) +#define NOUVEAU_DSM_OPTIMUS_NO_POWERDOWN_PS3 (2 << 24) +#define NOUVEAU_DSM_OPTIMUS_FLAGS_CHANGED (1) + +#define NOUVEAU_DSM_OPTIMUS_SET_POWERDOWN (NOUVEAU_DSM_OPTIMUS_POWERDOWN_PS3 | NOUVEAU_DSM_OPTIMUS_FLAGS_CHANGED) + +/* result of the optimus caps function */ +#define OPTIMUS_ENABLED (1 << 0) +#define OPTIMUS_STATUS_MASK (3 << 3) +#define OPTIMUS_STATUS_OFF (0 << 3) +#define OPTIMUS_STATUS_ON_ENABLED (1 << 3) +#define OPTIMUS_STATUS_PWR_STABLE (3 << 3) +#define OPTIMUS_DISPLAY_HOTPLUG (1 << 6) +#define OPTIMUS_CAPS_MASK (7 << 24) +#define OPTIMUS_DYNAMIC_PWR_CAP (1 << 24) + +#define OPTIMUS_AUDIO_CAPS_MASK (3 << 27) +#define OPTIMUS_HDA_CODEC_MASK (2 << 27) /* hda bios control */ + +static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result) +{ + int i; + union acpi_object *obj; + char args_buff[4]; + union acpi_object argv4 = { + .buffer.type = ACPI_TYPE_BUFFER, + .buffer.length = 4, + .buffer.pointer = args_buff + }; + + /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */ + for (i = 0; i < 4; i++) + args_buff[i] = (arg >> i * 8) & 0xFF; + + *result = 0; + obj = acpi_evaluate_dsm_typed(handle, &nouveau_op_dsm_muid, 0x00000100, + func, &argv4, ACPI_TYPE_BUFFER); + if (!obj) { + acpi_handle_info(handle, "failed to evaluate _DSM\n"); + return AE_ERROR; + } else { + if (obj->buffer.length == 4) { + *result |= obj->buffer.pointer[0]; + *result |= (obj->buffer.pointer[1] << 8); + *result |= (obj->buffer.pointer[2] << 16); + *result |= (obj->buffer.pointer[3] << 24); + } + ACPI_FREE(obj); + } + + return 0; +} + +/* Must be called for Optimus models before the card can be turned off */ +void nvkm_acpi_switcheroo_set_powerdown(void) +{ + u32 result = 0; + if (!nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.optimus_skip_dsm) + return; + + if (nouveau_dsm_priv.optimus_flags_detected) + nouveau_optimus_dsm(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_OPTIMUS_FLAGS, + 0x3, &result); + + nouveau_optimus_dsm(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_OPTIMUS_CAPS, + NOUVEAU_DSM_OPTIMUS_SET_POWERDOWN, &result); + +} + +/* + * On some platforms, _DSM(nouveau_op_dsm_muid, func0) has special + * requirements on the fourth parameter, so a private implementation + * instead of using acpi_check_dsm(). + */ +static int nouveau_dsm_get_optimus_functions(acpi_handle handle) +{ + int result; + + /* + * Function 0 returns a Buffer containing available functions. + * The args parameter is ignored for function 0, so just put 0 in it + */ + if (nouveau_optimus_dsm(handle, 0, 0, &result)) + return 0; + + /* + * ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. + * If the n-th bit is enabled, function n is supported + */ + if (result & 1 && result & (1 << NOUVEAU_DSM_OPTIMUS_CAPS)) + return result; + return 0; +} + +static const guid_t nouveau_dsm_muid + GUID_INIT(0x9D95A0A0, 0x0060, 0x4D48, + 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4); + +#define NOUVEAU_DSM_LED 0x02 +#define NOUVEAU_DSM_LED_STATE 0x00 +#define NOUVEAU_DSM_LED_OFF 0x10 +#define NOUVEAU_DSM_LED_STAMINA 0x11 +#define NOUVEAU_DSM_LED_SPEED 0x12 + +#define NOUVEAU_DSM_POWER 0x03 +#define NOUVEAU_DSM_POWER_STATE 0x00 +#define NOUVEAU_DSM_POWER_SPEED 0x01 +#define NOUVEAU_DSM_POWER_STAMINA 0x02 + +static int nouveau_dsm(acpi_handle handle, int func, int arg) +{ + int ret = 0; + union acpi_object *obj; + union acpi_object argv4 = { + .integer.type = ACPI_TYPE_INTEGER, + .integer.value = arg, + }; + + obj = acpi_evaluate_dsm_typed(handle, &nouveau_dsm_muid, 0x00000102, + func, &argv4, ACPI_TYPE_INTEGER); + if (!obj) { + acpi_handle_info(handle, "failed to evaluate _DSM\n"); + return AE_ERROR; + } else { + if (obj->integer.value == 0x80000002) + ret = -ENODEV; + ACPI_FREE(obj); + } + + return ret; +} + +static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) +{ + mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); + mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); + return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id); +} + +static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state) +{ + int arg; + if (state == VGA_SWITCHEROO_ON) + arg = NOUVEAU_DSM_POWER_SPEED; + else + arg = NOUVEAU_DSM_POWER_STAMINA; + nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg); + return 0; +} + +static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id) +{ + if (!nouveau_dsm_priv.dsm_detected) + return 0; + if (id == VGA_SWITCHEROO_IGD) + return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA); + else + return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_SPEED); +} + +static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id, + enum vga_switcheroo_state state) +{ + if (id == VGA_SWITCHEROO_IGD) + return 0; + + /* Optimus laptops have the card already disabled in + * nouveau_switcheroo_set_state */ + if (!nouveau_dsm_priv.dsm_detected) + return 0; + + return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state); +} + +static enum vga_switcheroo_client_id nouveau_dsm_get_client_id(struct pci_dev *pdev) +{ + /* easy option one - intel vendor ID means Integrated */ + if (pdev->vendor == PCI_VENDOR_ID_INTEL) + return VGA_SWITCHEROO_IGD; + + /* is this device on Bus 0? - this may need improving */ + if (pdev->bus->number == 0) + return VGA_SWITCHEROO_IGD; + + return VGA_SWITCHEROO_DIS; +} + +static const struct vga_switcheroo_handler nouveau_dsm_handler = { + .switchto = nouveau_dsm_switchto, + .power_state = nouveau_dsm_power_state, + .get_client_id = nouveau_dsm_get_client_id, +}; + +static void nouveau_dsm_pci_probe(struct pci_dev *pdev, acpi_handle *dhandle_out, + bool *has_mux, bool *has_opt, + bool *has_opt_flags, bool *has_pr3) +{ + acpi_handle dhandle; + bool supports_mux; + int optimus_funcs; + struct pci_dev *parent_pdev; + + if (pdev->vendor != PCI_VENDOR_ID_NVIDIA) + return; + + *has_pr3 = false; + parent_pdev = pci_upstream_bridge(pdev); + if (parent_pdev) { + if (parent_pdev->bridge_d3) + *has_pr3 = pci_pr3_present(parent_pdev); + else + pci_d3cold_disable(pdev); + } + + dhandle = ACPI_HANDLE(&pdev->dev); + if (!dhandle) + return; + + if (!acpi_has_method(dhandle, "_DSM")) + return; + + supports_mux = acpi_check_dsm(dhandle, &nouveau_dsm_muid, 0x00000102, + 1 << NOUVEAU_DSM_POWER); + optimus_funcs = nouveau_dsm_get_optimus_functions(dhandle); + + /* Does not look like a Nvidia device. */ + if (!supports_mux && !optimus_funcs) + return; + + *dhandle_out = dhandle; + *has_mux = supports_mux; + *has_opt = !!optimus_funcs; + *has_opt_flags = optimus_funcs & (1 << NOUVEAU_DSM_OPTIMUS_FLAGS); + + if (optimus_funcs) { + uint32_t result; + nouveau_optimus_dsm(dhandle, NOUVEAU_DSM_OPTIMUS_CAPS, 0, + &result); + dev_info(&pdev->dev, "optimus capabilities: %s, status %s%s\n", + (result & OPTIMUS_ENABLED) ? "enabled" : "disabled", + (result & OPTIMUS_DYNAMIC_PWR_CAP) ? "dynamic power, " : "", + (result & OPTIMUS_HDA_CODEC_MASK) ? "hda bios codec supported" : ""); + } +} + +static bool nouveau_dsm_detect(void) +{ + char acpi_method_name[255] = { 0 }; + struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; + struct pci_dev *pdev = NULL; + acpi_handle dhandle = NULL; + bool has_mux = false; + bool has_optimus = false; + bool has_optimus_flags = false; + bool has_power_resources = false; + int vga_count = 0; + bool guid_valid; + bool ret = false; + + /* lookup the MXM GUID */ + guid_valid = mxm_wmi_supported(); + + if (guid_valid) + printk("MXM: GUID detected in BIOS\n"); + + /* now do DSM detection */ + while ((pdev = pci_get_base_class(PCI_BASE_CLASS_DISPLAY, pdev))) { + if ((pdev->class != PCI_CLASS_DISPLAY_VGA << 8) && + (pdev->class != PCI_CLASS_DISPLAY_3D << 8)) + continue; + + vga_count++; + + nouveau_dsm_pci_probe(pdev, &dhandle, &has_mux, &has_optimus, + &has_optimus_flags, &has_power_resources); + } + + /* find the optimus DSM or the old v1 DSM */ + if (has_optimus) { + nouveau_dsm_priv.dhandle = dhandle; + acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, + &buffer); + pr_info("VGA switcheroo: detected Optimus DSM method %s handle\n", + acpi_method_name); + if (has_power_resources) + pr_info("nouveau: detected PR support, will not use DSM\n"); + nouveau_dsm_priv.optimus_detected = true; + nouveau_dsm_priv.optimus_flags_detected = has_optimus_flags; + nouveau_dsm_priv.optimus_skip_dsm = has_power_resources; + ret = true; + } else if (vga_count == 2 && has_mux && guid_valid) { + nouveau_dsm_priv.dhandle = dhandle; + acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, + &buffer); + pr_info("VGA switcheroo: detected DSM switching method %s handle\n", + acpi_method_name); + nouveau_dsm_priv.dsm_detected = true; + ret = true; + } + + + return ret; +} + +void +nvkm_acpi_switcheroo_fini(void) +{ + if (nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.dsm_detected) + vga_switcheroo_unregister_handler(); +} + +void +nvkm_acpi_switcheroo_init(void) +{ + bool r; + + r = nouveau_dsm_detect(); + if (!r) + return; + + vga_switcheroo_register_handler(&nouveau_dsm_handler, 0); +} +#endif + #ifdef CONFIG_ACPI static int nvkm_acpi_ntfy(struct notifier_block *nb, unsigned long val, void *data) @@ -38,7 +375,7 @@ nvkm_acpi_ntfy(struct notifier_block *nb, unsigned long val, void *data) return NOTIFY_DONE; } -#endif +#endif /* CONFIG_ACPI */ void nvkm_acpi_fini(struct nvkm_device *device) diff --git a/drivers/gpu/drm/nouveau/nvkm/device/acpi.h b/drivers/gpu/drm/nouveau/nvkm/device/acpi.h index 1d3c5cf7c3b4..34854d10026d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/acpi.h +++ b/drivers/gpu/drm/nouveau/nvkm/device/acpi.h @@ -6,4 +6,23 @@ struct nvkm_device; void nvkm_acpi_init(struct nvkm_device *); void nvkm_acpi_fini(struct nvkm_device *); + +#ifdef CONFIG_VGA_SWITCHEROO +extern struct nouveau_dsm_priv { + bool dsm_detected; + bool optimus_detected; + bool optimus_flags_detected; + bool optimus_skip_dsm; + acpi_handle dhandle; +} nouveau_dsm_priv; + +void nvkm_acpi_switcheroo_init(void); +void nvkm_acpi_switcheroo_fini(void); +void nvkm_acpi_switcheroo_set_powerdown(void); +#else +static inline void nvkm_acpi_switcheroo_init(void) {}; +static inline void nvkm_acpi_switcheroo_fini(void) {}; +static inline void nvkm_acpi_switcheroo_set_powerdown(void) {}; +#endif + #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/module.c b/drivers/gpu/drm/nouveau/nvkm/module.c index 66d28465514b..cf71c68af89a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/module.c +++ b/drivers/gpu/drm/nouveau/nvkm/module.c @@ -20,14 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ #include <core/module.h> +#include <device/acpi.h> void __exit nvkm_exit(void) { + nvkm_acpi_switcheroo_fini(); } int __init nvkm_init(void) { + nvkm_acpi_switcheroo_init(); return 0; } -- 2.44.0
Ben Skeggs
2024-Jun-13 17:00 UTC
[PATCH 10/21] drm/nouveau/nvif: add runpm supported flag to device impl
The DRM driver uses "nouveau_is_optimus() || nouveau_is_v1_dsm()", which have been moved to NVKM, to determine support for runtime pm. Replace with a feature flag returned when allocating an nvif_device. Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/include/nvif/driverif.h | 2 ++ .../gpu/drm/nouveau/include/nvkm/core/device.h | 6 ++++++ .../gpu/drm/nouveau/include/nvkm/core/module.h | 2 ++ drivers/gpu/drm/nouveau/nouveau_drm.c | 17 ++++++++++------- drivers/gpu/drm/nouveau/nouveau_drv.h | 2 +- drivers/gpu/drm/nouveau/nouveau_vga.c | 4 ++-- drivers/gpu/drm/nouveau/nvkm/device/pci.c | 12 ++++++++++++ drivers/gpu/drm/nouveau/nvkm/device/user.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/module.c | 2 ++ 9 files changed, 39 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvif/driverif.h b/drivers/gpu/drm/nouveau/include/nvif/driverif.h index 638c72c1b580..e1d3ccc2128c 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/driverif.h +++ b/drivers/gpu/drm/nouveau/include/nvif/driverif.h @@ -538,6 +538,8 @@ struct nvif_device_impl { u64 ram_size; u64 ram_user; + bool runpm; + u64 (*time)(struct nvif_device_priv *); struct { diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index c9965934b0d5..3c11d3068ced 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -55,6 +55,12 @@ struct nvkm_device { struct notifier_block nb; } acpi; + enum { + NVKM_DEVICE_RUNPM_NONE = 0, + NVKM_DEVICE_RUNPM_V1, + NVKM_DEVICE_RUNPM_OPTIMUS, + } runpm; + #define NVKM_LAYOUT_ONCE(type,data,ptr) data *ptr; #define NVKM_LAYOUT_INST(type,data,ptr,cnt) data *ptr[cnt]; #include <core/layout.h> diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/module.h b/drivers/gpu/drm/nouveau/include/nvkm/core/module.h index 5cf80e4deb90..fc42ace93a1c 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/module.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/module.h @@ -5,4 +5,6 @@ int __init nvkm_init(void); void __exit nvkm_exit(void); + +extern int nvkm_runpm; #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 0ac17da04819..52c4c3f58799 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -486,7 +486,7 @@ nouveau_drm_device_fini(struct nouveau_drm *drm) struct drm_device *dev = drm->dev; struct nouveau_cli *cli, *temp_cli; - if (nouveau_pmops_runtime()) { + if (nouveau_pmops_runtime(dev->dev)) { pm_runtime_get_sync(dev->dev); pm_runtime_forbid(dev->dev); } @@ -584,7 +584,7 @@ nouveau_drm_device_init(struct nouveau_drm *drm) nouveau_dmem_init(drm); nouveau_led_init(dev); - if (nouveau_pmops_runtime()) { + if (nouveau_pmops_runtime(dev->dev)) { pm_runtime_use_autosuspend(dev->dev); pm_runtime_set_autosuspend_delay(dev->dev, 5000); pm_runtime_set_active(dev->dev); @@ -1031,10 +1031,13 @@ nouveau_pmops_thaw(struct device *dev) } bool -nouveau_pmops_runtime(void) +nouveau_pmops_runtime(struct device *dev) { + struct nouveau_drm *drm = nouveau_drm(dev_get_drvdata(dev)); + if (nouveau_runtime_pm == -1) - return nouveau_is_optimus() || nouveau_is_v1_dsm(); + return drm->device.impl->runpm; + return nouveau_runtime_pm == 1; } @@ -1045,7 +1048,7 @@ nouveau_pmops_runtime_suspend(struct device *dev) struct nouveau_drm *drm = pci_get_drvdata(pdev); int ret; - if (!nouveau_pmops_runtime()) { + if (!nouveau_pmops_runtime(dev)) { pm_runtime_forbid(dev); return -EBUSY; } @@ -1067,7 +1070,7 @@ nouveau_pmops_runtime_resume(struct device *dev) struct nouveau_drm *drm = pci_get_drvdata(pdev); int ret; - if (!nouveau_pmops_runtime()) { + if (!nouveau_pmops_runtime(dev)) { pm_runtime_forbid(dev); return -EBUSY; } @@ -1098,7 +1101,7 @@ nouveau_pmops_runtime_resume(struct device *dev) static int nouveau_pmops_runtime_idle(struct device *dev) { - if (!nouveau_pmops_runtime()) { + if (!nouveau_pmops_runtime(dev)) { pm_runtime_forbid(dev); return -EBUSY; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 52589d5eab63..c2014a29891c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -324,7 +324,7 @@ nouveau_drm_use_coherent_gpu_mapping(struct nouveau_drm *drm) int nouveau_pmops_suspend(struct device *); int nouveau_pmops_resume(struct device *); -bool nouveau_pmops_runtime(void); +bool nouveau_pmops_runtime(struct device *); #include <nvkm/core/tegra.h> diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index 53b332708061..1f5ccec025d7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -63,7 +63,7 @@ void nouveau_vga_init(struct nouveau_drm *drm) { struct drm_device *dev = drm->dev; - bool runtime = nouveau_pmops_runtime(); + bool runtime = nouveau_pmops_runtime(dev->dev); struct pci_dev *pdev; /* only relevant for PCI devices */ @@ -85,7 +85,7 @@ void nouveau_vga_fini(struct nouveau_drm *drm) { struct drm_device *dev = drm->dev; - bool runtime = nouveau_pmops_runtime(); + bool runtime = nouveau_pmops_runtime(dev->dev); struct pci_dev *pdev; /* only relevant for PCI devices */ diff --git a/drivers/gpu/drm/nouveau/nvkm/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/device/pci.c index e48f3219f047..16e059866168 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/pci.c @@ -22,6 +22,8 @@ * Authors: Ben Skeggs <bskeggs at redhat.com> */ #include <core/pci.h> +#include <core/module.h> +#include "acpi.h" #include "priv.h" struct nvkm_device_pci_device { @@ -1704,5 +1706,15 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, } *pdevice = &pdev->device; + + if (nvkm_runpm) { + if (!nouveau_dsm_priv.optimus_detected) { + if (nouveau_dsm_priv.dsm_detected) + device->runpm = NVKM_DEVICE_RUNPM_V1; + } else { + device->runpm = NVKM_DEVICE_RUNPM_OPTIMUS; + } + } + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/device/user.c b/drivers/gpu/drm/nouveau/nvkm/device/user.c index 4ffcd7c6e0b9..a510d24019f6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/user.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/user.c @@ -393,6 +393,8 @@ nvkm_udevice_new(struct nvkm_device *device, if (device->imem && udev->impl.ram_size > 0) udev->impl.ram_user = udev->impl.ram_user - device->imem->reserved; + udev->impl.runpm = (device->runpm != NVKM_DEVICE_RUNPM_NONE); + if (device->vfn) { udev->impl.usermode.oclass = device->vfn->user.base.oclass; udev->impl.usermode.new = nvkm_udevice_usermode_new; diff --git a/drivers/gpu/drm/nouveau/nvkm/module.c b/drivers/gpu/drm/nouveau/nvkm/module.c index cf71c68af89a..7a56ef8c3b6b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/module.c +++ b/drivers/gpu/drm/nouveau/nvkm/module.c @@ -22,6 +22,8 @@ #include <core/module.h> #include <device/acpi.h> +int nvkm_runpm = -1; + void __exit nvkm_exit(void) { -- 2.44.0
The DRM driver needs to do things in response to vga_switcheroo_client callbacks, so this move isn't a direct copy+paste. 3 new callbacks are added to nvif_driver_func, which are basically the same as the switcheroo callbacks, except NVKM handles all the PCI/ACPI parts, and calls into the DRM driver for the rest. Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- .../gpu/drm/nouveau/include/nvif/driverif.h | 7 ++ .../gpu/drm/nouveau/include/nvkm/core/pci.h | 2 + drivers/gpu/drm/nouveau/nouveau_acpi.c | 8 -- drivers/gpu/drm/nouveau/nouveau_acpi.h | 4 - drivers/gpu/drm/nouveau/nouveau_drm.c | 5 +- drivers/gpu/drm/nouveau/nouveau_drv.h | 2 - drivers/gpu/drm/nouveau/nouveau_vga.c | 71 +++------------- drivers/gpu/drm/nouveau/nouveau_vga.h | 3 +- drivers/gpu/drm/nouveau/nvkm/device/acpi.c | 83 ++++++++++++++++++- 9 files changed, 104 insertions(+), 81 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvif/driverif.h b/drivers/gpu/drm/nouveau/include/nvif/driverif.h index e1d3ccc2128c..49db239f1156 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/driverif.h +++ b/drivers/gpu/drm/nouveau/include/nvif/driverif.h @@ -2,6 +2,7 @@ #ifndef __NVIF_DRIVERIF_H__ #define __NVIF_DRIVERIF_H__ #include <drm/display/drm_dp.h> +#include <linux/vga_switcheroo.h> struct nvif_event_priv; struct nvif_client_priv; @@ -36,6 +37,12 @@ struct nvif_event_impl { struct nvif_driver_func { enum nvif_event_stat (*event)(u64 token, void *repv, u32 repc); + + struct nvif_driver_func_switcheroo { + bool (*can_switch)(const struct nvif_driver_func *); + void (*set_state)(const struct nvif_driver_func *, enum vga_switcheroo_state); + void (*reprobe)(const struct nvif_driver_func *); + } switcheroo; }; struct nvif_driver { diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h b/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h index 7444c4d59e09..a1e9ee6da44e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h @@ -7,6 +7,8 @@ struct nvkm_device_pci { struct nvkm_device device; struct pci_dev *pdev; bool suspend; + + struct dev_pm_domain vga_pm_domain; }; int nvkm_device_pci_new(struct pci_dev *, const char *cfg, const char *dbg, diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index b9c43fe552c0..da3120258527 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -8,14 +8,6 @@ #include "nouveau_drv.h" #include "nouveau_acpi.h" -bool nouveau_is_optimus(void) { - return nouveau_dsm_priv.optimus_detected; -} - -bool nouveau_is_v1_dsm(void) { - return nouveau_dsm_priv.dsm_detected; -} - void * nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.h b/drivers/gpu/drm/nouveau/nouveau_acpi.h index a7fac1f7a73d..be1b218cb921 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.h +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.h @@ -5,16 +5,12 @@ #define ROM_BIOS_PAGE 4096 #if defined(CONFIG_ACPI) && defined(CONFIG_X86) -bool nouveau_is_optimus(void); -bool nouveau_is_v1_dsm(void); #include <device/acpi.h> static inline void nouveau_switcheroo_optimus_dsm(void) { nvkm_acpi_switcheroo_set_powerdown(); } void *nouveau_acpi_edid(struct drm_device *, struct drm_connector *); bool nouveau_acpi_video_backlight_use_native(void); void nouveau_acpi_video_register_backlight(void); #else -static inline bool nouveau_is_optimus(void) { return false; }; -static inline bool nouveau_is_v1_dsm(void) { return false; }; static inline void nouveau_switcheroo_optimus_dsm(void) {} static inline void *nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return NULL; } static inline bool nouveau_acpi_video_backlight_use_native(void) { return true; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 52c4c3f58799..580849b78231 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -505,7 +505,6 @@ nouveau_drm_device_fini(struct nouveau_drm *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, @@ -556,8 +555,6 @@ nouveau_drm_device_init(struct nouveau_drm *drm) if (drm->device.impl->chipset == 0xc1) nvif_mask(&drm->device, 0x00088080, 0x00000800, 0x00000000); - nouveau_vga_init(drm); - ret = nouveau_ttm_init(drm); if (ret) goto fail_ttm; @@ -608,7 +605,6 @@ nouveau_drm_device_init(struct nouveau_drm *drm) fail_bios: nouveau_ttm_fini(drm); fail_ttm: - nouveau_vga_fini(drm); nouveau_cli_fini(&drm->cli); fail_wq: destroy_workqueue(drm->sched_wq); @@ -650,6 +646,7 @@ nouveau_drm_device_new(const struct drm_driver *drm_driver, struct device *paren drm->nvkm = device; drm->driver = nouveau_driver; + drm->driver.switcheroo = nouveau_switcheroo; device->cfgopt = nouveau_config; device->dbgopt = nouveau_debug; diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index c2014a29891c..b44f0d408ccc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -295,8 +295,6 @@ struct nouveau_drm { /* led management */ struct nouveau_led *led; - struct dev_pm_domain vga_pm_domain; - struct nouveau_svm *svm; struct nouveau_dmem *dmem; diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index 1f5ccec025d7..cb5cd4b93fdf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -8,41 +8,35 @@ #include "nouveau_vga.h" static void -nouveau_switcheroo_set_state(struct pci_dev *pdev, - enum vga_switcheroo_state state) +nouveau_switcheroo_set_state(const struct nvif_driver_func *driver, enum vga_switcheroo_state state) { - 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; + struct drm_device *dev = container_of(driver, struct nouveau_drm, driver)->dev; if (state == VGA_SWITCHEROO_ON) { pr_err("VGA switcheroo: switched nouveau on\n"); dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; - nouveau_pmops_resume(&pdev->dev); + nouveau_pmops_resume(dev->dev); dev->switch_power_state = DRM_SWITCH_POWER_ON; } else { pr_err("VGA switcheroo: switched nouveau off\n"); dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; - nouveau_switcheroo_optimus_dsm(); - nouveau_pmops_suspend(&pdev->dev); + nouveau_pmops_suspend(dev->dev); dev->switch_power_state = DRM_SWITCH_POWER_OFF; } } static void -nouveau_switcheroo_reprobe(struct pci_dev *pdev) +nouveau_switcheroo_reprobe(const struct nvif_driver_func *driver) { - struct nouveau_drm *drm = pci_get_drvdata(pdev); + struct nouveau_drm *drm = container_of(driver, struct nouveau_drm, driver); drm_fb_helper_output_poll_changed(drm->dev); } static bool -nouveau_switcheroo_can_switch(struct pci_dev *pdev) +nouveau_switcheroo_can_switch(const struct nvif_driver_func *driver) { - struct nouveau_drm *drm = pci_get_drvdata(pdev); + struct nouveau_drm *drm = container_of(driver, struct nouveau_drm, driver); /* * FIXME: open_count is protected by drm_global_mutex but that would lead to @@ -52,56 +46,13 @@ nouveau_switcheroo_can_switch(struct pci_dev *pdev) return atomic_read(&drm->dev->open_count) == 0; } -static const struct vga_switcheroo_client_ops -nouveau_switcheroo_ops = { - .set_gpu_state = nouveau_switcheroo_set_state, +const struct nvif_driver_func_switcheroo +nouveau_switcheroo = { + .set_state = nouveau_switcheroo_set_state, .reprobe = nouveau_switcheroo_reprobe, .can_switch = nouveau_switcheroo_can_switch, }; -void -nouveau_vga_init(struct nouveau_drm *drm) -{ - struct drm_device *dev = drm->dev; - bool runtime = nouveau_pmops_runtime(dev->dev); - struct pci_dev *pdev; - - /* only relevant for PCI devices */ - if (!dev_is_pci(dev->dev)) - return; - pdev = to_pci_dev(dev->dev); - - /* don't register Thunderbolt eGPU with vga_switcheroo */ - if (pci_is_thunderbolt_attached(pdev)) - return; - - vga_switcheroo_register_client(pdev, &nouveau_switcheroo_ops, runtime); - - if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus()) - vga_switcheroo_init_domain_pm_ops(drm->dev->dev, &drm->vga_pm_domain); -} - -void -nouveau_vga_fini(struct nouveau_drm *drm) -{ - struct drm_device *dev = drm->dev; - bool runtime = nouveau_pmops_runtime(dev->dev); - struct pci_dev *pdev; - - /* only relevant for PCI devices */ - if (!dev_is_pci(dev->dev)) - return; - pdev = to_pci_dev(dev->dev); - - if (pci_is_thunderbolt_attached(pdev)) - return; - - vga_switcheroo_unregister_client(pdev); - 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) { diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.h b/drivers/gpu/drm/nouveau/nouveau_vga.h index 951a83f984dd..119b39cfbbcc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.h +++ b/drivers/gpu/drm/nouveau/nouveau_vga.h @@ -2,8 +2,7 @@ #ifndef __NOUVEAU_VGA_H__ #define __NOUVEAU_VGA_H__ -void nouveau_vga_init(struct nouveau_drm *); -void nouveau_vga_fini(struct nouveau_drm *); +extern const struct nvif_driver_func_switcheroo nouveau_switcheroo; void nouveau_vga_lastclose(struct drm_device *dev); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/device/acpi.c b/drivers/gpu/drm/nouveau/nvkm/device/acpi.c index 2bead7e879a5..cbaad3ea10eb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/acpi.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/acpi.c @@ -23,9 +23,11 @@ */ #include "acpi.h" -#include <core/device.h> +#include <core/pci.h> #include <subdev/clk.h> +#include <nvif/driverif.h> + #include <linux/mxm-wmi.h> #include <linux/vga_switcheroo.h> @@ -189,6 +191,48 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero return 0; } +#include "nouveau_drv.h" +#include "nouveau_acpi.h" + +static void +nvkm_acpi_switcheroo_reprobe(struct pci_dev *pdev) +{ + struct nvkm_device *device = ((struct nouveau_drm *)pci_get_drvdata(pdev))->nvkm; + + device->driver->switcheroo.reprobe(device->driver); +} + +static void +nvkm_acpi_switcheroo_set_state(struct pci_dev *pdev, + enum vga_switcheroo_state state) +{ + struct nvkm_device *device = ((struct nouveau_drm *)pci_get_drvdata(pdev))->nvkm; + + if (state == VGA_SWITCHEROO_OFF) { + if (nouveau_dsm_priv.dsm_detected || nouveau_dsm_priv.optimus_detected) + return; + + nvkm_acpi_switcheroo_set_powerdown(); + } + + device->driver->switcheroo.set_state(device->driver, state); +} + +static bool +nvkm_acpi_switcheroo_can_switch(struct pci_dev *pdev) +{ + struct nvkm_device *device = ((struct nouveau_drm *)pci_get_drvdata(pdev))->nvkm; + + return device->driver->switcheroo.can_switch(device->driver); +} + +static const struct vga_switcheroo_client_ops +nvkm_acpi_switcheroo_ops = { + .can_switch = nvkm_acpi_switcheroo_can_switch, + .set_gpu_state = nvkm_acpi_switcheroo_set_state, + .reprobe = nvkm_acpi_switcheroo_reprobe, +}; + static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id) { if (!nouveau_dsm_priv.dsm_detected) @@ -380,16 +424,53 @@ nvkm_acpi_ntfy(struct notifier_block *nb, unsigned long val, void *data) void nvkm_acpi_fini(struct nvkm_device *device) { + struct nvkm_device_pci *pdev; + + if (!device->func->pci) + return; + + pdev = device->func->pci(device); + (void)pdev; + #ifdef CONFIG_ACPI unregister_acpi_notifier(&device->acpi.nb); #endif + +#ifdef CONFIG_VGA_SWITCHEROO + if (pci_is_thunderbolt_attached(pdev->pdev)) + return; + + vga_switcheroo_unregister_client(pdev->pdev); + if (device->runpm == NVKM_DEVICE_RUNPM_V1) + vga_switcheroo_fini_domain_pm_ops(device->dev); +#endif } void nvkm_acpi_init(struct nvkm_device *device) { + struct nvkm_device_pci *pdev; + + if (!device->func->pci) + return; + + pdev = device->func->pci(device); + (void)pdev; + #ifdef CONFIG_ACPI device->acpi.nb.notifier_call = nvkm_acpi_ntfy; register_acpi_notifier(&device->acpi.nb); #endif + +#ifdef CONFIG_VGA_SWITCHEROO + /* don't register Thunderbolt eGPU with vga_switcheroo */ + if (pci_is_thunderbolt_attached(pdev->pdev)) + return; + + vga_switcheroo_register_client(pdev->pdev, &nvkm_acpi_switcheroo_ops, + device->runpm != NVKM_DEVICE_RUNPM_NONE); + + if (device->runpm == NVKM_DEVICE_RUNPM_V1) + vga_switcheroo_init_domain_pm_ops(device->dev, &pdev->vga_pm_domain); +#endif } -- 2.44.0
Ben Skeggs
2024-Jun-13 17:00 UTC
[PATCH 12/21] drm/nouveau/nvkm: prepare pci/tegra probe()/remove() functions
Rename, and modify the signatures of nvkm_device_{pci,tegra}_new() to be consistent with pci/platform driver probe() functions. The DRM driver is still calling the functions as it did before, just via the new pci/platform driver structs in NVKM that will eventually be used for driver registration. Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- .../gpu/drm/nouveau/include/nvkm/core/pci.h | 3 +- .../gpu/drm/nouveau/include/nvkm/core/tegra.h | 5 +-- drivers/gpu/drm/nouveau/nouveau_drm.c | 13 ++++--- drivers/gpu/drm/nouveau/nouveau_platform.c | 2 + drivers/gpu/drm/nouveau/nvkm/device/pci.c | 24 ++++++++++-- drivers/gpu/drm/nouveau/nvkm/device/tegra.c | 37 ++++++++++++------- 6 files changed, 55 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h b/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h index a1e9ee6da44e..b9e10dad6ee9 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h @@ -11,6 +11,5 @@ struct nvkm_device_pci { struct dev_pm_domain vga_pm_domain; }; -int nvkm_device_pci_new(struct pci_dev *, const char *cfg, const char *dbg, - struct nvkm_device **); +extern struct pci_driver nvkm_device_pci_driver; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h index 22f74fc88cd7..e641f387fa3e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h @@ -48,8 +48,5 @@ struct nvkm_device_tegra_func { bool require_vdd; }; -int nvkm_device_tegra_new(const struct nvkm_device_tegra_func *, - struct platform_device *, - const char *cfg, const char *dbg, - struct nvkm_device **); +extern struct platform_driver nvkm_device_tegra; #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 580849b78231..632635c16b88 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -801,10 +801,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, nouveau_debug, &device); + ret = nvkm_device_pci_driver.probe(pdev, NULL); if (ret) return ret; + device = pci_get_drvdata(pdev); + /* Remove conflicting drivers (vesafb, efifb etc). */ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &driver_pci); if (ret) @@ -849,13 +851,10 @@ static int nouveau_drm_probe(struct pci_dev *pdev, void nouveau_drm_device_remove(struct nouveau_drm *drm) { - struct nvkm_device *device = drm->nvkm; - drm_dev_unplug(drm->dev); nouveau_drm_device_fini(drm); nouveau_drm_device_del(drm); - nvkm_device_del(&device); } static void @@ -868,6 +867,8 @@ nouveau_drm_remove(struct pci_dev *pdev) pdev->pm_cap = drm->old_pm_cap; nouveau_drm_device_remove(drm); pci_disable_device(pdev); + + nvkm_device_pci_driver.remove(pdev); } static int @@ -1349,10 +1350,12 @@ nouveau_platform_device_create(const struct nvkm_device_tegra_func *func, struct nouveau_drm *drm; int err; - err = nvkm_device_tegra_new(func, pdev, nouveau_config, nouveau_debug, pdevice); + err = nvkm_device_tegra.probe(pdev); if (err) return ERR_PTR(err); + *pdevice = platform_get_drvdata(pdev); + drm = nouveau_drm_device_new(&driver_platform, &pdev->dev, *pdevice); if (IS_ERR(drm)) { err = PTR_ERR(drm); diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c index 3194b110eff8..23beac1f96f1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_platform.c +++ b/drivers/gpu/drm/nouveau/nouveau_platform.c @@ -42,6 +42,8 @@ static void nouveau_platform_remove(struct platform_device *pdev) struct nouveau_drm *drm = platform_get_drvdata(pdev); nouveau_drm_device_remove(drm); + + nvkm_device_tegra.remove_new(pdev); } #if IS_ENABLED(CONFIG_OF) diff --git a/drivers/gpu/drm/nouveau/nvkm/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/device/pci.c index 16e059866168..be6433eab814 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/pci.c @@ -1626,9 +1626,19 @@ nvkm_device_pci_func = { .cpu_coherent = !IS_ENABLED(CONFIG_ARM), }; -int -nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, - struct nvkm_device **pdevice) +#include "nouveau_drv.h" + +static void +nvkm_device_pci_remove(struct pci_dev *dev) +{ + struct drm_device *drm_dev = pci_get_drvdata(dev); + struct nvkm_device *device = nouveau_drm(drm_dev)->nvkm; + + nvkm_device_del(&device); +} + +static int +nvkm_device_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) { const struct nvkm_device_quirk *quirk = NULL; const struct nvkm_device_pci_device *pcid; @@ -1705,7 +1715,7 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, return ret; } - *pdevice = &pdev->device; + pci_set_drvdata(pci_dev, &pdev->device); if (nvkm_runpm) { if (!nouveau_dsm_priv.optimus_detected) { @@ -1718,3 +1728,9 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, return 0; } + +struct pci_driver +nvkm_device_pci_driver = { + .probe = nvkm_device_pci_probe, + .remove = nvkm_device_pci_remove, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/device/tegra.c index 9c3673c74b19..f0c1258170f4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/tegra.c @@ -233,12 +233,20 @@ nvkm_device_tegra_func = { .cpu_coherent = false, }; -int -nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, - struct platform_device *pdev, - const char *cfg, const char *dbg, - struct nvkm_device **pdevice) +#include "nouveau_drv.h" + +static void +nvkm_device_tegra_remove(struct platform_device *pdev) +{ + struct nvkm_device *device = ((struct nouveau_drm *)platform_get_drvdata(pdev))->nvkm; + + nvkm_device_del(&device); +} + +static int +nvkm_device_tegra_probe(struct platform_device *pdev) { + const struct nvkm_device_tegra_func *func = of_device_get_match_data(&pdev->dev); struct nvkm_device_tegra *tdev; struct nvkm_device *device; unsigned long rate; @@ -318,7 +326,7 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, return ret; } - *pdevice = &tdev->device; + platform_set_drvdata(pdev, &tdev->device); return 0; remove: @@ -327,13 +335,14 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, kfree(tdev); return ret; } + +struct platform_driver +nvkm_device_tegra = { + .probe = nvkm_device_tegra_probe, + .remove_new = nvkm_device_tegra_remove, +}; #else -int -nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, - struct platform_device *pdev, - const char *cfg, const char *dbg, - struct nvkm_device **pdevice) -{ - return -ENOSYS; -} +struct platform_driver +nvkm_device_tegra = { +}; #endif -- 2.44.0
Ben Skeggs
2024-Jun-13 17:00 UTC
[PATCH 13/21] drm/nouveau/nvkm: move pci probe() defer from drm
Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/nouveau_drm.c | 3 --- drivers/gpu/drm/nouveau/nvkm/device/pci.c | 5 +++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 632635c16b88..3f1f93fa7029 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -795,9 +795,6 @@ static int nouveau_drm_probe(struct pci_dev *pdev, struct nouveau_drm *drm; int ret; - if (vga_switcheroo_client_probe_defer(pdev)) - return -EPROBE_DEFER; - /* We need to check that the chipset is supported before booting * fbdev off the hardware, as there's no way to put it back. */ diff --git a/drivers/gpu/drm/nouveau/nvkm/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/device/pci.c index be6433eab814..21ca094df54f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/pci.c @@ -26,6 +26,8 @@ #include "acpi.h" #include "priv.h" +#include <linux/vga_switcheroo.h> + struct nvkm_device_pci_device { u16 device; const char *name; @@ -1648,6 +1650,9 @@ nvkm_device_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) struct nvkm_device *device; int ret, bits; + if (vga_switcheroo_client_probe_defer(pci_dev)) + return -EPROBE_DEFER; + switch (pci_dev->vendor) { case 0x10de: pcid = nvkm_device_pci_10de; break; default: -- 2.44.0
Ben Skeggs
2024-Jun-13 17:00 UTC
[PATCH 14/21] drm/nouveau/nvkm: move pci probe() fb handoff from drm
Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/include/nvkm/core/device.h | 1 + drivers/gpu/drm/nouveau/nouveau_drm.c | 5 ----- drivers/gpu/drm/nouveau/nvkm/device/base.c | 6 ++++++ drivers/gpu/drm/nouveau/nvkm/device/pci.c | 11 +++++++++++ 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index 3c11d3068ced..d8596fe0adea 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -89,6 +89,7 @@ struct nvkm_device_func { struct nvkm_device_tegra *(*tegra)(struct nvkm_device *); void *(*dtor)(struct nvkm_device *); int (*preinit)(struct nvkm_device *); + int (*oneinit)(struct nvkm_device *); int (*init)(struct nvkm_device *); void (*fini)(struct nvkm_device *, bool suspend); int (*irq)(struct nvkm_device *); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 3f1f93fa7029..be31e8ea4fee 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -804,11 +804,6 @@ static int nouveau_drm_probe(struct pci_dev *pdev, device = pci_get_drvdata(pdev); - /* Remove conflicting drivers (vesafb, efifb etc). */ - ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &driver_pci); - if (ret) - return ret; - pci_set_master(pdev); if (nouveau_atomic) diff --git a/drivers/gpu/drm/nouveau/nvkm/device/base.c b/drivers/gpu/drm/nouveau/nvkm/device/base.c index 1b76c2a60799..4f8298bf71ee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/base.c @@ -2954,6 +2954,12 @@ nvkm_device_oneinit(struct nvkm_device *device) #undef NVKM_LAYOUT_INST #undef NVKM_LAYOUT_ONCE + if (device->func->oneinit) { + ret = device->func->oneinit(device); + if (ret) + goto done; + } + ret = nvkm_intr_install(device); done: if (ret) { diff --git a/drivers/gpu/drm/nouveau/nvkm/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/device/pci.c index 21ca094df54f..7d0ddc968246 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/pci.c @@ -26,6 +26,7 @@ #include "acpi.h" #include "priv.h" +#include <linux/aperture.h> #include <linux/vga_switcheroo.h> struct nvkm_device_pci_device { @@ -1608,6 +1609,15 @@ nvkm_device_pci_preinit(struct nvkm_device *device) return 0; } +static int +nvkm_device_pci_oneinit(struct nvkm_device *device) +{ + struct nvkm_device_pci *pdev = nvkm_device_pci(device); + + /* Remove conflicting drivers (vesafb, efifb etc). */ + return aperture_remove_conflicting_pci_devices(pdev->pdev, "nvkm"); +} + static void * nvkm_device_pci_dtor(struct nvkm_device *device) { @@ -1621,6 +1631,7 @@ nvkm_device_pci_func = { .pci = nvkm_device_pci, .dtor = nvkm_device_pci_dtor, .preinit = nvkm_device_pci_preinit, + .oneinit = nvkm_device_pci_oneinit, .fini = nvkm_device_pci_fini, .irq = nvkm_device_pci_irq, .resource_addr = nvkm_device_pci_resource_addr, -- 2.44.0
Ben Skeggs
2024-Jun-13 17:00 UTC
[PATCH 15/21] drm/nouveau/nvkm: move pci probe() enable/disable handling from drm
Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- .../gpu/drm/nouveau/include/nvkm/core/pci.h | 1 - drivers/gpu/drm/nouveau/nouveau_drm.c | 11 +------- drivers/gpu/drm/nouveau/nvkm/device/pci.c | 28 ++----------------- 3 files changed, 3 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h b/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h index b9e10dad6ee9..0797225ab038 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h @@ -6,7 +6,6 @@ struct nvkm_device_pci { struct nvkm_device device; struct pci_dev *pdev; - bool suspend; struct dev_pm_domain vga_pm_domain; }; diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index be31e8ea4fee..4bcfc2291c4d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -804,8 +804,6 @@ static int nouveau_drm_probe(struct pci_dev *pdev, device = pci_get_drvdata(pdev); - pci_set_master(pdev); - if (nouveau_atomic) driver_pci.driver_features |= DRIVER_ATOMIC; @@ -815,13 +813,9 @@ static int nouveau_drm_probe(struct pci_dev *pdev, goto fail_nvkm; } - ret = pci_enable_device(pdev); - if (ret) - goto fail_drm; - ret = nouveau_drm_device_init(drm); if (ret) - goto fail_pci; + goto fail_drm; if (drm->device.impl->ram_size <= 32 * 1024 * 1024) drm_fbdev_ttm_setup(drm->dev, 8); @@ -831,8 +825,6 @@ static int nouveau_drm_probe(struct pci_dev *pdev, quirk_broken_nv_runpm(pdev); return 0; -fail_pci: - pci_disable_device(pdev); fail_drm: nouveau_drm_device_del(drm); fail_nvkm: @@ -858,7 +850,6 @@ nouveau_drm_remove(struct pci_dev *pdev) if (drm->old_pm_cap) pdev->pm_cap = drm->old_pm_cap; nouveau_drm_device_remove(drm); - pci_disable_device(pdev); nvkm_device_pci_driver.remove(pdev); } diff --git a/drivers/gpu/drm/nouveau/nvkm/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/device/pci.c index 7d0ddc968246..d9b8e3bc4169 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/pci.c @@ -1585,30 +1585,6 @@ nvkm_device_pci_irq(struct nvkm_device *device) return nvkm_device_pci(device)->pdev->irq; } -static void -nvkm_device_pci_fini(struct nvkm_device *device, bool suspend) -{ - struct nvkm_device_pci *pdev = nvkm_device_pci(device); - if (suspend) { - pci_disable_device(pdev->pdev); - pdev->suspend = true; - } -} - -static int -nvkm_device_pci_preinit(struct nvkm_device *device) -{ - struct nvkm_device_pci *pdev = nvkm_device_pci(device); - if (pdev->suspend) { - int ret = pci_enable_device(pdev->pdev); - if (ret) - return ret; - pci_set_master(pdev->pdev); - pdev->suspend = false; - } - return 0; -} - static int nvkm_device_pci_oneinit(struct nvkm_device *device) { @@ -1630,9 +1606,7 @@ static const struct nvkm_device_func nvkm_device_pci_func = { .pci = nvkm_device_pci, .dtor = nvkm_device_pci_dtor, - .preinit = nvkm_device_pci_preinit, .oneinit = nvkm_device_pci_oneinit, - .fini = nvkm_device_pci_fini, .irq = nvkm_device_pci_irq, .resource_addr = nvkm_device_pci_resource_addr, .resource_size = nvkm_device_pci_resource_size, @@ -1700,6 +1674,8 @@ nvkm_device_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) return ret; } + pci_set_master(pci_dev); + ret = nvkm_device_ctor(&nvkm_device_pci_func, quirk, &pci_dev->dev, pci_is_pcie(pci_dev) ? NVKM_DEVICE_PCIE : pci_find_capability(pci_dev, PCI_CAP_ID_AGP) ? -- 2.44.0
Ben Skeggs
2024-Jun-13 17:00 UTC
[PATCH 16/21] drm/nouveau/nvkm: move pci probe() runpm quirk from drm
Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- .../gpu/drm/nouveau/include/nvkm/core/pci.h | 2 + drivers/gpu/drm/nouveau/nouveau_drm.c | 61 ------------------ drivers/gpu/drm/nouveau/nouveau_drv.h | 2 - drivers/gpu/drm/nouveau/nvkm/device/pci.c | 62 +++++++++++++++++++ 4 files changed, 64 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h b/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h index 0797225ab038..95deea8c65ff 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/pci.h @@ -7,6 +7,8 @@ struct nvkm_device_pci { struct nvkm_device device; struct pci_dev *pdev; + u8 old_pm_cap; + struct dev_pm_domain vga_pm_domain; }; diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 4bcfc2291c4d..76eddf172bb5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -731,63 +731,6 @@ nouveau_drm_device_new(const struct drm_driver *drm_driver, struct device *paren return ret ? ERR_PTR(ret) : drm; } -/* - * On some Intel PCIe bridge controllers doing a - * D0 -> D3hot -> D3cold -> D0 sequence causes Nvidia GPUs to not reappear. - * Skipping the intermediate D3hot step seems to make it work again. This is - * probably caused by not meeting the expectation the involved AML code has - * when the GPU is put into D3hot state before invoking it. - * - * This leads to various manifestations of this issue: - * - AML code execution to power on the GPU hits an infinite loop (as the - * code waits on device memory to change). - * - kernel crashes, as all PCI reads return -1, which most code isn't able - * to handle well enough. - * - * In all cases dmesg will contain at least one line like this: - * 'nouveau 0000:01:00.0: Refused to change power state, currently in D3' - * followed by a lot of nouveau timeouts. - * - * In the \_SB.PCI0.PEG0.PG00._OFF code deeper down writes bit 0x80 to the not - * documented PCI config space register 0x248 of the Intel PCIe bridge - * controller (0x1901) in order to change the state of the PCIe link between - * the PCIe port and the GPU. There are alternative code paths using other - * registers, which seem to work fine (executed pre Windows 8): - * - 0xbc bit 0x20 (publicly available documentation claims 'reserved') - * - 0xb0 bit 0x10 (link disable) - * Changing the conditions inside the firmware by poking into the relevant - * addresses does resolve the issue, but it seemed to be ACPI private memory - * and not any device accessible memory at all, so there is no portable way of - * changing the conditions. - * On a XPS 9560 that means bits [0,3] on \CPEX need to be cleared. - * - * The only systems where this behavior can be seen are hybrid graphics laptops - * with a secondary Nvidia Maxwell, Pascal or Turing GPU. It's unclear whether - * this issue only occurs in combination with listed Intel PCIe bridge - * controllers and the mentioned GPUs or other devices as well. - * - * documentation on the PCIe bridge controller can be found in the - * "7th Generation Intel? Processor Families for H Platforms Datasheet Volume 2" - * Section "12 PCI Express* Controller (x16) Registers" - */ - -static void quirk_broken_nv_runpm(struct pci_dev *pdev) -{ - struct nouveau_drm *drm = pci_get_drvdata(pdev); - struct pci_dev *bridge = pci_upstream_bridge(pdev); - - if (!bridge || bridge->vendor != PCI_VENDOR_ID_INTEL) - return; - - switch (bridge->device) { - case 0x1901: - drm->old_pm_cap = pdev->pm_cap; - pdev->pm_cap = 0; - NV_INFO(drm, "Disabling PCI power management to avoid bug\n"); - break; - } -} - static int nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent) { @@ -822,7 +765,6 @@ static int nouveau_drm_probe(struct pci_dev *pdev, else drm_fbdev_ttm_setup(drm->dev, 32); - quirk_broken_nv_runpm(pdev); return 0; fail_drm: @@ -846,9 +788,6 @@ nouveau_drm_remove(struct pci_dev *pdev) { 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(drm); nvkm_device_pci_driver.remove(pdev); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index b44f0d408ccc..9ca0f6ab4359 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -218,8 +218,6 @@ struct nouveau_drm { */ struct mutex clients_lock; - u8 old_pm_cap; - struct { struct agp_bridge_data *bridge; u32 base; diff --git a/drivers/gpu/drm/nouveau/nvkm/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/device/pci.c index d9b8e3bc4169..d454d56a7909 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/pci.c @@ -1598,6 +1598,11 @@ static void * nvkm_device_pci_dtor(struct nvkm_device *device) { struct nvkm_device_pci *pdev = nvkm_device_pci(device); + + /* revert our workaround */ + if (pdev->old_pm_cap) + pdev->pdev->pm_cap = pdev->old_pm_cap; + pci_disable_device(pdev->pdev); return pdev; } @@ -1624,6 +1629,62 @@ nvkm_device_pci_remove(struct pci_dev *dev) nvkm_device_del(&device); } +/* + * On some Intel PCIe bridge controllers doing a + * D0 -> D3hot -> D3cold -> D0 sequence causes Nvidia GPUs to not reappear. + * Skipping the intermediate D3hot step seems to make it work again. This is + * probably caused by not meeting the expectation the involved AML code has + * when the GPU is put into D3hot state before invoking it. + * + * This leads to various manifestations of this issue: + * - AML code execution to power on the GPU hits an infinite loop (as the + * code waits on device memory to change). + * - kernel crashes, as all PCI reads return -1, which most code isn't able + * to handle well enough. + * + * In all cases dmesg will contain at least one line like this: + * 'nouveau 0000:01:00.0: Refused to change power state, currently in D3' + * followed by a lot of nouveau timeouts. + * + * In the \_SB.PCI0.PEG0.PG00._OFF code deeper down writes bit 0x80 to the not + * documented PCI config space register 0x248 of the Intel PCIe bridge + * controller (0x1901) in order to change the state of the PCIe link between + * the PCIe port and the GPU. There are alternative code paths using other + * registers, which seem to work fine (executed pre Windows 8): + * - 0xbc bit 0x20 (publicly available documentation claims 'reserved') + * - 0xb0 bit 0x10 (link disable) + * Changing the conditions inside the firmware by poking into the relevant + * addresses does resolve the issue, but it seemed to be ACPI private memory + * and not any device accessible memory at all, so there is no portable way of + * changing the conditions. + * On a XPS 9560 that means bits [0,3] on \CPEX need to be cleared. + * + * The only systems where this behavior can be seen are hybrid graphics laptops + * with a secondary Nvidia Maxwell, Pascal or Turing GPU. It's unclear whether + * this issue only occurs in combination with listed Intel PCIe bridge + * controllers and the mentioned GPUs or other devices as well. + * + * documentation on the PCIe bridge controller can be found in the + * "7th Generation Intel? Processor Families for H Platforms Datasheet Volume 2" + * Section "12 PCI Express* Controller (x16) Registers" + */ + +static void quirk_broken_nv_runpm(struct nvkm_device_pci *pdev) +{ + struct pci_dev *bridge = pci_upstream_bridge(pdev->pdev); + + if (!bridge || bridge->vendor != PCI_VENDOR_ID_INTEL) + return; + + switch (bridge->device) { + case 0x1901: + pdev->old_pm_cap = pdev->pdev->pm_cap; + pdev->pdev->pm_cap = 0; + nvdev_info(&pdev->device, "Disabling PCI power management to avoid bug\n"); + break; + } +} + static int nvkm_device_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) { @@ -1701,6 +1762,7 @@ nvkm_device_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) pdev->device.mmu->dma_bits = 32; } + quirk_broken_nv_runpm(pdev); done: if (ret) { nvkm_device_del(&device); -- 2.44.0
Moves the PCI-specific portions of nouveau_pmops to NVKM, leaving the DRM pieces where they are. The NVKM functions are called through the the nvkm_device_pci_driver struct from DRM for now, but will be fully separated once the DRM driver is implemented on an auxiliary device. Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/nouveau_acpi.h | 3 - drivers/gpu/drm/nouveau/nouveau_drm.c | 24 ++----- drivers/gpu/drm/nouveau/nvkm/device/pci.c | 76 +++++++++++++++++++++++ 3 files changed, 80 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.h b/drivers/gpu/drm/nouveau/nouveau_acpi.h index be1b218cb921..b4c7ae78cedc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.h +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.h @@ -5,13 +5,10 @@ #define ROM_BIOS_PAGE 4096 #if defined(CONFIG_ACPI) && defined(CONFIG_X86) -#include <device/acpi.h> -static inline void nouveau_switcheroo_optimus_dsm(void) { nvkm_acpi_switcheroo_set_powerdown(); } void *nouveau_acpi_edid(struct drm_device *, struct drm_connector *); bool nouveau_acpi_video_backlight_use_native(void); void nouveau_acpi_video_register_backlight(void); #else -static inline void nouveau_switcheroo_optimus_dsm(void) {} static inline void *nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return NULL; } static inline bool nouveau_acpi_video_backlight_use_native(void) { return true; } static inline void nouveau_acpi_video_register_backlight(void) {} diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 76eddf172bb5..aa54aee23814 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -901,11 +901,7 @@ nouveau_pmops_suspend(struct device *dev) if (ret) return ret; - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - udelay(200); - return 0; + return nvkm_device_pci_driver.driver.pm->suspend(dev); } int @@ -919,12 +915,9 @@ nouveau_pmops_resume(struct device *dev) drm->dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF) return 0; - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - ret = pci_enable_device(pdev); + ret = nvkm_device_pci_driver.driver.pm->resume(dev); if (ret) return ret; - pci_set_master(pdev); ret = nouveau_do_resume(drm, false); @@ -973,12 +966,8 @@ nouveau_pmops_runtime_suspend(struct device *dev) return -EBUSY; } - nouveau_switcheroo_optimus_dsm(); 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); + ret = nvkm_device_pci_driver.driver.pm->runtime_suspend(dev); drm->dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; return ret; } @@ -995,12 +984,9 @@ nouveau_pmops_runtime_resume(struct device *dev) return -EBUSY; } - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - ret = pci_enable_device(pdev); + ret = nvkm_device_pci_driver.driver.pm->runtime_resume(dev); if (ret) return ret; - pci_set_master(pdev); ret = nouveau_do_resume(drm, true); if (ret) { @@ -1008,8 +994,6 @@ nouveau_pmops_runtime_resume(struct device *dev) return ret; } - /* do magic */ - nvif_mask(&drm->device, 0x088488, (1 << 25), (1 << 25)); drm->dev->switch_power_state = DRM_SWITCH_POWER_ON; /* Monitors may have been connected / disconnected during suspend */ diff --git a/drivers/gpu/drm/nouveau/nvkm/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/device/pci.c index d454d56a7909..a66cb9d474d5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/pci.c @@ -1620,6 +1620,81 @@ nvkm_device_pci_func = { #include "nouveau_drv.h" +static int +nvkm_device_pci_pm_runtime_resume(struct device *dev) +{ + struct nvkm_device *device = ((struct nouveau_drm *)dev_get_drvdata(dev))->nvkm; + struct pci_dev *pdev = nvkm_device_pci(device)->pdev; + int ret; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + ret = pci_enable_device(pdev); + if (ret) + return ret; + + pci_set_master(pdev); + + /* do magic */ + nvkm_mask(device, 0x088488, (1 << 25), (1 << 25)); + return 0; +} + +static int +nvkm_device_pci_pm_runtime_suspend(struct device *dev) +{ + struct nvkm_device *device = ((struct nouveau_drm *)dev_get_drvdata(dev))->nvkm; + struct pci_dev *pdev = nvkm_device_pci(device)->pdev; + + nvkm_acpi_switcheroo_set_powerdown(); + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_ignore_hotplug(pdev); + pci_set_power_state(pdev, PCI_D3cold); + return 0; +} + +static int +nvkm_device_pci_pm_resume(struct device *dev) +{ + struct nvkm_device *device = ((struct nouveau_drm *)dev_get_drvdata(dev))->nvkm; + struct pci_dev *pdev = nvkm_device_pci(device)->pdev; + int ret; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + ret = pci_enable_device(pdev); + if (ret) + return ret; + + pci_set_master(pdev); + return 0; +} + +static int +nvkm_device_pci_pm_suspend(struct device *dev) +{ + struct nvkm_device *device = ((struct nouveau_drm *)dev_get_drvdata(dev))->nvkm; + struct pci_dev *pdev = nvkm_device_pci(device)->pdev; + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + udelay(200); + return 0; +} + +static const struct dev_pm_ops +nvkm_device_pci_pm = { + .suspend = nvkm_device_pci_pm_suspend, + .resume = nvkm_device_pci_pm_resume, + .runtime_suspend = nvkm_device_pci_pm_runtime_suspend, + .runtime_resume = nvkm_device_pci_pm_runtime_resume, +}; + static void nvkm_device_pci_remove(struct pci_dev *dev) { @@ -1787,4 +1862,5 @@ struct pci_driver nvkm_device_pci_driver = { .probe = nvkm_device_pci_probe, .remove = nvkm_device_pci_remove, + .driver.pm = &nvkm_device_pci_pm, }; -- 2.44.0
Ben Skeggs
2024-Jun-13 17:00 UTC
[PATCH 18/21] drm/nouveau/nvkm: add device to auxiliary bus for each nvkm_device
This commit registers a device on the aux bus after core NVKM init has finished, which will be used by a later commit to have the DRM driver probe() against an aux device instead of a PCI or platform device (in the case of Tegra). Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/Kconfig | 1 + .../drm/nouveau/include/nvkm/core/device.h | 3 ++ drivers/gpu/drm/nouveau/nvkm/device/base.c | 33 +++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index 4c10b400658c..6d0d46a0e66f 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -7,6 +7,7 @@ config DRM_NOUVEAU depends on DRM_DISPLAY_HELPER depends on PCI depends on MMU + select AUXILIARY_BUS select IOMMU_API select FW_LOADER select DRM_KMS_HELPER diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index d8596fe0adea..855d1b20820d 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -5,6 +5,8 @@ #include <core/intr.h> enum nvkm_subdev_type; +#include <linux/auxiliary_bus.h> + enum nvkm_device_type { NVKM_DEVICE_PCI, NVKM_DEVICE_AGP, @@ -78,6 +80,7 @@ struct nvkm_device { bool legacy_done; } intr; + struct auxiliary_device auxdev; const struct nvif_driver_func *driver; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/device/base.c b/drivers/gpu/drm/nouveau/nvkm/device/base.c index 4f8298bf71ee..fbb6e20bc1f2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/base.c @@ -3029,6 +3029,9 @@ nvkm_device_del(struct nvkm_device **pdevice) struct nvkm_device *device = *pdevice; struct nvkm_subdev *subdev, *subtmp; if (device) { + auxiliary_device_delete(&device->auxdev); + auxiliary_device_uninit(&device->auxdev); + nvkm_intr_dtor(device); list_for_each_entry_safe_reverse(subdev, subtmp, &device->subdev, head) @@ -3076,6 +3079,16 @@ nvkm_device_endianness(struct nvkm_device *device) return true; } +static DEFINE_IDA(nvkm_device_id); + +static void +nvkm_device_release(struct device *dev) +{ + struct nvkm_device *device = container_of(dev, typeof(*device), auxdev.dev); + + ida_free(&nvkm_device_id, device->auxdev.id); +} + int nvkm_device_ctor(const struct nvkm_device_func *func, const struct nvkm_device_quirk *quirk, @@ -3335,5 +3348,25 @@ nvkm_device_ctor(const struct nvkm_device_func *func, iounmap(device->pri); device->pri = NULL; } + + if (ret == 0) { + ret = ida_alloc(&nvkm_device_id, GFP_KERNEL); + if (ret < 0) + return ret; + + device->auxdev.dev.parent = device->dev; + device->auxdev.dev.release = nvkm_device_release; + device->auxdev.name = "device"; + device->auxdev.id = ret; + + ret = auxiliary_device_init(&device->auxdev); + if (ret) + return ret; + + ret = auxiliary_device_add(&device->auxdev); + if (ret) + auxiliary_device_uninit(&device->auxdev); + } + return ret; } -- 2.44.0
Ben Skeggs
2024-Jun-13 17:00 UTC
[PATCH 19/21] drm/nouveau: wrap pm_runtime_* calls with nouveau_runpm
This wraps direct calls to pm_runtime functions to cleanup some common usage patterns, and keep the logic in one place.>From the next commit, the pm_runtime calls will need to operate againstthe DRM driver's auxiliary device instead of directly on the underlying PCI device. This commit will help make that switch cleaner. Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 31 ++++--- drivers/gpu/drm/nouveau/nouveau_connector.c | 12 ++- drivers/gpu/drm/nouveau/nouveau_connector.h | 1 + drivers/gpu/drm/nouveau/nouveau_debugfs.c | 24 +++--- drivers/gpu/drm/nouveau/nouveau_display.c | 19 ++--- drivers/gpu/drm/nouveau/nouveau_drm.c | 45 ++++------- drivers/gpu/drm/nouveau/nouveau_gem.c | 30 +++---- drivers/gpu/drm/nouveau/nouveau_runpm.h | 89 +++++++++++++++++++++ 8 files changed, 156 insertions(+), 95 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nouveau_runpm.h diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 64f3a1b00173..c0fc5233ebd4 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -952,17 +952,16 @@ static int nv50_mstc_detect(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx, bool force) { + struct nouveau_drm *drm = nouveau_drm(connector->dev); struct nv50_mstc *mstc = nv50_mstc(connector); int ret; if (drm_connector_is_unregistered(connector)) return connector_status_disconnected; - ret = pm_runtime_get_sync(connector->dev->dev); - if (ret < 0 && ret != -EACCES) { - pm_runtime_put_autosuspend(connector->dev->dev); + ret = nouveau_runpm_get(drm); + if (ret) return connector_status_disconnected; - } ret = drm_dp_mst_detect_port(connector, ctx, mstc->port->mgr, mstc->port); @@ -970,8 +969,7 @@ nv50_mstc_detect(struct drm_connector *connector, goto out; out: - pm_runtime_mark_last_busy(connector->dev->dev); - pm_runtime_put_autosuspend(connector->dev->dev); + nouveau_runpm_put(drm); return ret; } @@ -1950,7 +1948,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) asyh->clr.mask, asyh->set.mask); if (old_crtc_state->active && !new_crtc_state->active) { - pm_runtime_put_noidle(dev->dev); + nouveau_runpm_put_noidle(drm); drm_crtc_vblank_off(crtc); } @@ -2040,7 +2038,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) if (new_crtc_state->active) { if (!old_crtc_state->active) { drm_crtc_vblank_on(crtc); - pm_runtime_get_noresume(dev->dev); + nouveau_runpm_get_noresume(drm); } if (new_crtc_state->event) drm_crtc_vblank_get(crtc); @@ -2159,8 +2157,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_state_put(state); /* Drop the RPM ref we got from nv50_disp_atomic_commit() */ - pm_runtime_mark_last_busy(dev->dev); - pm_runtime_put_autosuspend(dev->dev); + nouveau_runpm_put(drm); } static void @@ -2175,15 +2172,14 @@ static int nv50_disp_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, bool nonblock) { + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_plane_state *new_plane_state; struct drm_plane *plane; int ret, i; - ret = pm_runtime_get_sync(dev->dev); - if (ret < 0 && ret != -EACCES) { - pm_runtime_put_autosuspend(dev->dev); + ret = nouveau_runpm_get(drm); + if (ret) return ret; - } ret = drm_atomic_helper_setup_commit(state, nonblock); if (ret) @@ -2219,7 +2215,7 @@ nv50_disp_atomic_commit(struct drm_device *dev, * Grab another RPM ref for the commit tail, which will release the * ref when it's finished */ - pm_runtime_get_noresume(dev->dev); + nouveau_runpm_get_noresume(drm); if (nonblock) queue_work(system_unbound_wq, &state->commit_work); @@ -2230,7 +2226,7 @@ nv50_disp_atomic_commit(struct drm_device *dev, if (ret) drm_atomic_helper_unprepare_planes(dev, state); done: - pm_runtime_put_autosuspend(dev->dev); + nouveau_runpm_put(drm); return ret; } @@ -2439,6 +2435,7 @@ static inline void nv50_display_read_hw_or_state(struct drm_device *dev, struct nv50_disp *disp, struct nouveau_encoder *outp) { + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_crtc *crtc; struct drm_connector_list_iter conn_iter; struct drm_connector *conn; @@ -2501,7 +2498,7 @@ nv50_display_read_hw_or_state(struct drm_device *dev, struct nv50_disp *disp, armh->state.connector_mask = drm_connector_mask(conn); armh->state.active = true; armh->state.enable = true; - pm_runtime_get_noresume(dev->dev); + nouveau_runpm_get_noresume(drm); outp->crtc = crtc; outp->ctrl = NVVAL(NV507D, SOR_SET_CONTROL, PROTOCOL, proto) | BIT(crtc->index); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index e3071ea845e6..c5386166b15d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -26,7 +26,6 @@ #include <acpi/button.h> -#include <linux/pm_runtime.h> #include <linux/vga_switcheroo.h> #include <drm/drm_atomic_helper.h> @@ -579,11 +578,11 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) * if possible. */ if (drm_kms_helper_is_poll_worker()) { - pm_runtime_get_noresume(dev->dev); + nouveau_runpm_get_noresume(drm); } else { - ret = pm_runtime_get_sync(dev->dev); - if (ret < 0 && ret != -EACCES) { - pm_runtime_put_autosuspend(dev->dev); + ret = nouveau_runpm_get(drm); + if (ret) { + nouveau_runpm_put(drm); nouveau_connector_set_edid(nv_connector, NULL); return conn_status; } @@ -674,8 +673,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) if (!nv_connector->edid) drm_dp_cec_unset_edid(&nv_connector->aux); - pm_runtime_mark_last_busy(dev->dev); - pm_runtime_put_autosuspend(dev->dev); + nouveau_runpm_put(drm); return conn_status; } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index 0608cabed058..d2035855861d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -40,6 +40,7 @@ #include "nouveau_crtc.h" #include "nouveau_encoder.h" +#include "nouveau_runpm.h" struct nvkm_i2c_port; struct dcb_output; diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c index aff6ee476f65..4c0e122ba724 100644 --- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c @@ -31,6 +31,7 @@ #include <linux/debugfs.h> #include "nouveau_debugfs.h" #include "nouveau_drv.h" +#include "nouveau_runpm.h" static int nouveau_debugfs_vbios_image(struct seq_file *m, void *data) @@ -51,18 +52,14 @@ nouveau_debugfs_strap_peek(struct seq_file *m, void *data) struct nouveau_drm *drm = nouveau_drm(node->minor->dev); int ret; - ret = pm_runtime_get_sync(drm->dev->dev); - if (ret < 0 && ret != -EACCES) { - pm_runtime_put_autosuspend(drm->dev->dev); + ret = nouveau_runpm_get(drm); + if (ret) return ret; - } seq_printf(m, "0x%08x\n", nvif_rd32(&drm->device, 0x101000)); - pm_runtime_mark_last_busy(drm->dev->dev); - pm_runtime_put_autosuspend(drm->dev->dev); - + nouveau_runpm_put(drm); return 0; } @@ -135,8 +132,9 @@ nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) { struct seq_file *m = file->private_data; - struct drm_device *drm = m->private; - struct nouveau_debugfs *debugfs = nouveau_debugfs(drm); + struct drm_device *dev = m->private; + struct nouveau_debugfs *debugfs = nouveau_debugfs(dev); + struct nouveau_drm *drm = nouveau_drm(dev); struct nvif_control_pstate_user args = { .pwrsrc = -EINVAL }; char buf[32] = {}, *tmp, *cur = buf; long value, ret; @@ -174,14 +172,12 @@ nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf, args.ustate = value; } - ret = pm_runtime_get_sync(drm->dev); - if (ret < 0 && ret != -EACCES) { - pm_runtime_put_autosuspend(drm->dev); + ret = nouveau_runpm_get(drm); + if (ret) return ret; - } ret = debugfs->impl->pstate.user(debugfs->priv, &args); - pm_runtime_put_autosuspend(drm->dev); + nouveau_runpm_put(drm); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index e892f5f5ea16..57d31a17ad68 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -466,7 +466,7 @@ nouveau_display_hpd_work(struct work_struct *work) int changed = 0; struct drm_connector *first_changed_connector = NULL; - pm_runtime_get_sync(dev->dev); + nouveau_runpm_try_get(drm); spin_lock_irq(&drm->hpd_lock); pending = drm->hpd_pending; @@ -474,8 +474,10 @@ nouveau_display_hpd_work(struct work_struct *work) spin_unlock_irq(&drm->hpd_lock); /* Nothing to do, exit early without updating the last busy counter */ - if (!pending) - goto noop; + if (!pending) { + nouveau_runpm_put_noop(drm); + return; + } mutex_lock(&dev->mode_config.mutex); drm_connector_list_iter_begin(dev, &conn_iter); @@ -532,9 +534,7 @@ nouveau_display_hpd_work(struct work_struct *work) if (first_changed_connector) drm_connector_put(first_changed_connector); - pm_runtime_mark_last_busy(drm->dev->dev); -noop: - pm_runtime_put_autosuspend(dev->dev); + nouveau_runpm_put(drm); } #ifdef CONFIG_ACPI @@ -545,24 +545,25 @@ nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val, { struct nouveau_drm *drm = container_of(nb, typeof(*drm), acpi_nb); struct acpi_bus_event *info = data; + struct device *dev = drm->dev->dev; int ret; if (!strcmp(info->device_class, ACPI_VIDEO_CLASS)) { if (info->type == ACPI_VIDEO_NOTIFY_PROBE) { - ret = pm_runtime_get(drm->dev->dev); + ret = pm_runtime_get(dev); if (ret == 1 || ret == -EACCES) { /* If the GPU is already awake, or in a state * where we can't wake it up, it can handle * it's own hotplug events. */ - pm_runtime_put_autosuspend(drm->dev->dev); + pm_runtime_put_autosuspend(dev); } else if (ret == 0 || ret == -EINPROGRESS) { /* We've started resuming the GPU already, so * it will handle scheduling a full reprobe * itself */ NV_DEBUG(drm, "ACPI requested connector reprobe\n"); - pm_runtime_put_noidle(drm->dev->dev); + pm_runtime_put_noidle(dev); } else { NV_WARN(drm, "Dropped ACPI reprobe event due to RPM error: %d\n", ret); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index aa54aee23814..2a9faf0fc277 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -25,7 +25,6 @@ #include <linux/delay.h> #include <linux/module.h> #include <linux/pci.h> -#include <linux/pm_runtime.h> #include <linux/vga_switcheroo.h> #include <linux/mmu_notifier.h> #include <linux/dynamic_debug.h> @@ -72,6 +71,7 @@ #include "nouveau_exec.h" #include "nouveau_uvmm.h" #include "nouveau_sched.h" +#include "nouveau_runpm.h" DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0, "DRM_UT_CORE", @@ -486,10 +486,8 @@ nouveau_drm_device_fini(struct nouveau_drm *drm) struct drm_device *dev = drm->dev; struct nouveau_cli *cli, *temp_cli; - if (nouveau_pmops_runtime(dev->dev)) { - pm_runtime_get_sync(dev->dev); - pm_runtime_forbid(dev->dev); - } + if (nouveau_pmops_runtime(dev->dev)) + nouveau_runpm_disable(drm); nouveau_led_fini(dev); nouveau_dmem_fini(drm); @@ -581,14 +579,8 @@ nouveau_drm_device_init(struct nouveau_drm *drm) nouveau_dmem_init(drm); nouveau_led_init(dev); - if (nouveau_pmops_runtime(dev->dev)) { - pm_runtime_use_autosuspend(dev->dev); - pm_runtime_set_autosuspend_delay(dev->dev, 5000); - pm_runtime_set_active(dev->dev); - pm_runtime_allow(dev->dev); - pm_runtime_mark_last_busy(dev->dev); - pm_runtime_put(dev->dev); - } + if (nouveau_pmops_runtime(dev->dev)) + nouveau_runpm_enable(drm); ret = drm_dev_register(drm->dev, 0); if (ret) { @@ -1025,11 +1017,9 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) int ret; /* need to bring up power immediately if opening device */ - ret = pm_runtime_get_sync(dev->dev); - if (ret < 0 && ret != -EACCES) { - pm_runtime_put_autosuspend(dev->dev); + ret = nouveau_runpm_get(drm); + if (ret) return ret; - } get_task_comm(tmpname, current); rcu_read_lock(); @@ -1058,8 +1048,7 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) kfree(cli); } - pm_runtime_mark_last_busy(dev->dev); - pm_runtime_put_autosuspend(dev->dev); + nouveau_runpm_put(drm); return ret; } @@ -1079,7 +1068,7 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) if (!drm_dev_enter(dev, &dev_index)) return; - pm_runtime_get_sync(dev->dev); + nouveau_runpm_try_get(drm); mutex_lock(&cli->mutex); if (cli->abi16) @@ -1092,8 +1081,9 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) nouveau_cli_fini(cli); kfree(cli); - pm_runtime_mark_last_busy(dev->dev); - pm_runtime_put_autosuspend(dev->dev); + + nouveau_runpm_put(drm); + drm_dev_exit(dev_index); } @@ -1122,14 +1112,12 @@ long nouveau_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct drm_file *filp = file->private_data; - struct drm_device *dev = filp->minor->dev; + struct nouveau_drm *drm = nouveau_drm(filp->minor->dev); long ret; - ret = pm_runtime_get_sync(dev->dev); - if (ret < 0 && ret != -EACCES) { - pm_runtime_put_autosuspend(dev->dev); + ret = nouveau_runpm_get(drm); + if (ret) return ret; - } switch (_IOC_NR(cmd) - DRM_COMMAND_BASE) { case DRM_NOUVEAU_NVIF: @@ -1140,8 +1128,7 @@ nouveau_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } - pm_runtime_mark_last_busy(dev->dev); - pm_runtime_put_autosuspend(dev->dev); + nouveau_runpm_put(drm); return ret; } diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index ede2bf30ebc2..e650cb52e267 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -30,6 +30,7 @@ #include "nouveau_dma.h" #include "nouveau_fence.h" #include "nouveau_abi16.h" +#include "nouveau_runpm.h" #include "nouveau_ttm.h" #include "nouveau_gem.h" @@ -78,22 +79,18 @@ nouveau_gem_object_del(struct drm_gem_object *gem) { struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); - struct device *dev = drm->dev->dev; int ret; - ret = pm_runtime_get_sync(dev); - if (WARN_ON(ret < 0 && ret != -EACCES)) { - pm_runtime_put_autosuspend(dev); + ret = nouveau_runpm_get(drm); + if (WARN_ON(ret)) return; - } if (gem->import_attach) drm_prime_gem_destroy(gem, nvbo->bo.sg); ttm_bo_put(&nvbo->bo); - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); + nouveau_runpm_put(drm); } int @@ -102,7 +99,6 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); - struct device *dev = drm->dev->dev; struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(cli); struct nouveau_vmm *vmm = nouveau_cli_vmm(cli); struct nouveau_vma *vma; @@ -119,19 +115,17 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) if (ret) return ret; - ret = pm_runtime_get_sync(dev); - if (ret < 0 && ret != -EACCES) { - pm_runtime_put_autosuspend(dev); + ret = nouveau_runpm_get(drm); + if (ret) goto out; - } /* only create a VMA on binding */ if (!nouveau_cli_uvmm(cli)) ret = nouveau_vma_new(nvbo, vmm, &vma); else ret = 0; - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); + + nouveau_runpm_put(drm); out: ttm_bo_unreserve(&nvbo->bo); return ret; @@ -188,7 +182,6 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); - struct device *dev = drm->dev->dev; struct nouveau_vmm *vmm = nouveau_cli_vmm(cli); struct nouveau_vma *vma; int ret; @@ -206,12 +199,11 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) vma = nouveau_vma_find(nvbo, vmm); if (vma) { if (--vma->refs == 0) { - ret = pm_runtime_get_sync(dev); - if (!WARN_ON(ret < 0 && ret != -EACCES)) { + ret = nouveau_runpm_get(drm); + if (!WARN_ON(ret)) { nouveau_gem_object_unmap(nvbo, vma); - pm_runtime_mark_last_busy(dev); + nouveau_runpm_put(drm); } - pm_runtime_put_autosuspend(dev); } } ttm_bo_unreserve(&nvbo->bo); diff --git a/drivers/gpu/drm/nouveau/nouveau_runpm.h b/drivers/gpu/drm/nouveau/nouveau_runpm.h new file mode 100644 index 000000000000..92d6c518bdad --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_runpm.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NOUVEAU_RUNPM_H__ +#define __NOUVEAU_RUNPM_H__ +#include <linux/pm_runtime.h> + +static inline struct device * +nouveau_runpm_dev(struct nouveau_drm *drm) +{ + return drm->dev->dev; +} + +static inline void +nouveau_runpm_put_noidle(struct nouveau_drm *drm) +{ + struct device *dev = nouveau_runpm_dev(drm); + + pm_runtime_put_noidle(dev); +} + +static inline void +nouveau_runpm_put_noop(struct nouveau_drm *drm) +{ + struct device *dev = nouveau_runpm_dev(drm); + + pm_runtime_put_autosuspend(dev); +} + +static inline void +nouveau_runpm_put(struct nouveau_drm *drm) +{ + struct device *dev = nouveau_runpm_dev(drm); + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); +} + +static inline int +nouveau_runpm_try_get(struct nouveau_drm *drm) +{ + struct device *dev = nouveau_runpm_dev(drm); + + return pm_runtime_get_sync(dev); +} + +static inline __must_check int +nouveau_runpm_get(struct nouveau_drm *drm) +{ + struct device *dev = nouveau_runpm_dev(drm); + int ret; + + ret = pm_runtime_get_sync(dev); + if (ret < 0 && ret != -EACCES) { + pm_runtime_put_autosuspend(dev); + return ret; + } + + return 0; +} + +static inline void +nouveau_runpm_get_noresume(struct nouveau_drm *drm) +{ + struct device *dev = nouveau_runpm_dev(drm); + + pm_runtime_get_noresume(dev); +} + +static inline void +nouveau_runpm_disable(struct nouveau_drm *drm) +{ + struct device *dev = nouveau_runpm_dev(drm); + + pm_runtime_get_sync(dev); + pm_runtime_forbid(dev); +} + +static inline void +nouveau_runpm_enable(struct nouveau_drm *drm) +{ + struct device *dev = nouveau_runpm_dev(drm); + + pm_runtime_use_autosuspend(dev); + pm_runtime_set_autosuspend_delay(dev, 5000); + pm_runtime_set_active(dev); + pm_runtime_allow(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put(dev); +} +#endif -- 2.44.0
Ben Skeggs
2024-Jun-13 17:00 UTC
[PATCH 20/21] drm/nouveau: probe() against nvkm-provided auxiliary devices
Previously, the DRM driver was the entry-point for the pci/platform bus probe() functions, and calls into NVKM to create an nvkm_device from pci/platform devices, then continues on with DRM init. Most of the code handling PCI/Tegra-specific functions has now been moved to NVKM (though prior to this commit, still *called* from DRM) and NVKM registers devices named "nvkm.device.<n>" on the auxiliary bus for each PCI or Tegra GPU in the system. The final step is to move pci/platform driver registration to NVKM, and have the DRM driver register as an auxiliary driver, from where it can gain access to the nvkm_device and proceed as it did before. Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/Kbuild | 1 - drivers/gpu/drm/nouveau/dispnv50/disp.c | 9 +- drivers/gpu/drm/nouveau/nouveau_display.c | 2 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 178 ++++-------------- drivers/gpu/drm/nouveau/nouveau_drv.h | 17 +- drivers/gpu/drm/nouveau/nouveau_platform.c | 93 --------- drivers/gpu/drm/nouveau/nouveau_platform.h | 27 --- drivers/gpu/drm/nouveau/nouveau_runpm.h | 2 +- drivers/gpu/drm/nouveau/nvkm/device/acpi.c | 9 +- drivers/gpu/drm/nouveau/nvkm/device/pci.c | 42 ++++- drivers/gpu/drm/nouveau/nvkm/device/tegra.c | 43 ++++- drivers/gpu/drm/nouveau/nvkm/module.c | 24 +++ .../gpu/drm/nouveau/nvkm/subdev/pci/base.c | 4 +- 13 files changed, 155 insertions(+), 296 deletions(-) delete mode 100644 drivers/gpu/drm/nouveau/nouveau_platform.c delete mode 100644 drivers/gpu/drm/nouveau/nouveau_platform.h diff --git a/drivers/gpu/drm/nouveau/Kbuild b/drivers/gpu/drm/nouveau/Kbuild index 61eeef83847a..cc471ab6a7ec 100644 --- a/drivers/gpu/drm/nouveau/Kbuild +++ b/drivers/gpu/drm/nouveau/Kbuild @@ -23,7 +23,6 @@ nouveau-y += nouveau_drm.o nouveau-y += nouveau_hwmon.o nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o nouveau-$(CONFIG_LEDS_CLASS) += nouveau_led.o -nouveau-$(CONFIG_NOUVEAU_PLATFORM_DRIVER) += nouveau_platform.o nouveau-y += nouveau_vga.o # DRM - memory management diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index c0fc5233ebd4..60affaedb933 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -353,7 +353,8 @@ static int nv50_audio_component_get_eld(struct device *kdev, int port, int dev_id, bool *enabled, unsigned char *buf, int max_bytes) { - struct nouveau_drm *drm = dev_get_drvdata(kdev); + struct nvkm_device *device = dev_get_drvdata(kdev); + struct nouveau_drm *drm = container_of(device->driver, typeof(*drm), driver); struct drm_encoder *encoder; struct nouveau_encoder *nv_encoder; struct nouveau_crtc *nv_crtc; @@ -398,7 +399,8 @@ static int nv50_audio_component_bind(struct device *kdev, struct device *hda_kdev, void *data) { - struct nouveau_drm *drm = dev_get_drvdata(kdev); + struct nvkm_device *device = dev_get_drvdata(kdev); + struct nouveau_drm *drm = container_of(device->driver, typeof(*drm), driver); struct drm_audio_component *acomp = data; if (WARN_ON(!device_link_add(hda_kdev, kdev, DL_FLAG_STATELESS))) @@ -416,7 +418,8 @@ static void nv50_audio_component_unbind(struct device *kdev, struct device *hda_kdev, void *data) { - struct nouveau_drm *drm = dev_get_drvdata(kdev); + struct nvkm_device *device = dev_get_drvdata(kdev); + struct nouveau_drm *drm = container_of(device->driver, typeof(*drm), driver); struct drm_audio_component *acomp = data; drm_modeset_lock_all(drm->dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 57d31a17ad68..5ec320fdfaf8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -545,7 +545,7 @@ nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val, { struct nouveau_drm *drm = container_of(nb, typeof(*drm), acpi_nb); struct acpi_bus_event *info = data; - struct device *dev = drm->dev->dev; + struct device *dev = &drm->auxdev->dev; int ret; if (!strcmp(info->device_class, ACPI_VIDEO_CLASS)) { diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 2a9faf0fc277..7e77e950eba2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -40,8 +40,6 @@ #include <core/gpuobj.h> #include <core/module.h> #include <core/option.h> -#include <core/pci.h> -#include <core/tegra.h> #include <nvif/driver.h> #include <nvif/fifo.h> @@ -65,7 +63,6 @@ #include "nouveau_fence.h" #include "nouveau_debugfs.h" #include "nouveau_connector.h" -#include "nouveau_platform.h" #include "nouveau_svm.h" #include "nouveau_dmem.h" #include "nouveau_exec.h" @@ -111,8 +108,6 @@ static int nouveau_runtime_pm = -1; module_param_named(runpm, nouveau_runtime_pm, int, 0400); static struct drm_driver driver_stub; -static struct drm_driver driver_pci; -static struct drm_driver driver_platform; static inline bool nouveau_cli_work_ready(struct dma_fence *fence) @@ -530,6 +525,7 @@ nouveau_drm_device_fini(struct nouveau_drm *drm) static int nouveau_drm_device_init(struct nouveau_drm *drm) { + struct nvkm_device *device = container_of(drm->auxdev, typeof(*device), auxdev); struct drm_device *dev = drm->dev; int ret; @@ -623,7 +619,7 @@ nouveau_drm_device_del(struct nouveau_drm *drm) } static struct nouveau_drm * -nouveau_drm_device_new(const struct drm_driver *drm_driver, struct device *parent, +nouveau_drm_device_new(const struct drm_driver *drm_driver, struct auxiliary_device *parent, struct nvkm_device *device) { const struct nvif_driver *driver; @@ -636,7 +632,7 @@ nouveau_drm_device_new(const struct drm_driver *drm_driver, struct device *paren if (!drm) return ERR_PTR(-ENOMEM); - drm->nvkm = device; + drm->auxdev = parent; drm->driver = nouveau_driver; drm->driver.switcheroo = nouveau_switcheroo; @@ -705,14 +701,14 @@ nouveau_drm_device_new(const struct drm_driver *drm_driver, struct device *paren goto done; } - drm->dev = drm_dev_alloc(drm_driver, parent); + drm->dev = drm_dev_alloc(drm_driver, parent->dev.parent); if (IS_ERR(drm->dev)) { ret = PTR_ERR(drm->dev); goto done; } drm->dev->dev_private = drm; - dev_set_drvdata(parent, drm); + auxiliary_set_drvdata(parent, drm); done: if (ret) { @@ -723,68 +719,51 @@ nouveau_drm_device_new(const struct drm_driver *drm_driver, struct device *paren return ret ? ERR_PTR(ret) : drm; } -static int nouveau_drm_probe(struct pci_dev *pdev, - const struct pci_device_id *pent) +static int +nouveau_drm_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id) { - struct nvkm_device *device; + struct nvkm_device *device = container_of(auxdev, typeof(*device), auxdev); struct nouveau_drm *drm; int ret; - /* 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_driver.probe(pdev, NULL); - if (ret) - return ret; - - device = pci_get_drvdata(pdev); - - if (nouveau_atomic) - driver_pci.driver_features |= DRIVER_ATOMIC; - - drm = nouveau_drm_device_new(&driver_pci, &pdev->dev, device); + drm = nouveau_drm_device_new(&driver_stub, auxdev, device); if (IS_ERR(drm)) { ret = PTR_ERR(drm); - goto fail_nvkm; + return ret; } ret = nouveau_drm_device_init(drm); if (ret) goto fail_drm; - if (drm->device.impl->ram_size <= 32 * 1024 * 1024) - drm_fbdev_ttm_setup(drm->dev, 8); - else - drm_fbdev_ttm_setup(drm->dev, 32); + if (drm->device.impl->disp.oclass) { + if (drm->device.impl->ram_size <= 32 * 1024 * 1024) + drm_fbdev_ttm_setup(drm->dev, 8); + else + drm_fbdev_ttm_setup(drm->dev, 32); + + if (nouveau_atomic) + drm->dev->driver_features |= DRIVER_ATOMIC; + } return 0; fail_drm: nouveau_drm_device_del(drm); -fail_nvkm: - nvkm_device_del(&device); return ret; } -void -nouveau_drm_device_remove(struct nouveau_drm *drm) +static void +nouveau_drm_remove(struct auxiliary_device *auxdev) { + struct nouveau_drm *drm = auxiliary_get_drvdata(auxdev); + drm_dev_unplug(drm->dev); nouveau_drm_device_fini(drm); nouveau_drm_device_del(drm); } -static void -nouveau_drm_remove(struct pci_dev *pdev) -{ - struct nouveau_drm *drm = pci_get_drvdata(pdev); - - nouveau_drm_device_remove(drm); - - nvkm_device_pci_driver.remove(pdev); -} - static int nouveau_do_suspend(struct nouveau_drm *drm, bool runtime) { @@ -881,36 +860,25 @@ nouveau_do_resume(struct nouveau_drm *drm, bool runtime) int nouveau_pmops_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct nouveau_drm *drm = pci_get_drvdata(pdev); - int ret; + struct nouveau_drm *drm = dev_get_drvdata(dev); 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, false); - if (ret) - return ret; - - return nvkm_device_pci_driver.driver.pm->suspend(dev); + return nouveau_do_suspend(drm, false); } int nouveau_pmops_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct nouveau_drm *drm = pci_get_drvdata(pdev); + struct nouveau_drm *drm = dev_get_drvdata(dev); int ret; if (drm->dev->switch_power_state == DRM_SWITCH_POWER_OFF || drm->dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF) return 0; - ret = nvkm_device_pci_driver.driver.pm->resume(dev); - if (ret) - return ret; - ret = nouveau_do_resume(drm, false); /* Monitors may have been connected / disconnected during suspend */ @@ -949,8 +917,7 @@ nouveau_pmops_runtime(struct device *dev) static int nouveau_pmops_runtime_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct nouveau_drm *drm = pci_get_drvdata(pdev); + struct nouveau_drm *drm = dev_get_drvdata(dev); int ret; if (!nouveau_pmops_runtime(dev)) { @@ -959,7 +926,6 @@ nouveau_pmops_runtime_suspend(struct device *dev) } ret = nouveau_do_suspend(drm, true); - ret = nvkm_device_pci_driver.driver.pm->runtime_suspend(dev); drm->dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; return ret; } @@ -967,8 +933,7 @@ nouveau_pmops_runtime_suspend(struct device *dev) static int nouveau_pmops_runtime_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct nouveau_drm *drm = pci_get_drvdata(pdev); + struct nouveau_drm *drm = dev_get_drvdata(dev); int ret; if (!nouveau_pmops_runtime(dev)) { @@ -976,10 +941,6 @@ nouveau_pmops_runtime_resume(struct device *dev) return -EBUSY; } - ret = nvkm_device_pci_driver.driver.pm->runtime_resume(dev); - if (ret) - return ret; - ret = nouveau_do_resume(drm, true); if (ret) { NV_ERROR(drm, "resume failed with: %d\n", ret); @@ -1183,21 +1144,6 @@ driver_stub = { .patchlevel = DRIVER_PATCHLEVEL, }; -static struct pci_device_id -nouveau_drm_pci_table[] = { - { - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), - .class = PCI_BASE_CLASS_DISPLAY << 16, - .class_mask = 0xff << 16, - }, - { - PCI_DEVICE(PCI_VENDOR_ID_NVIDIA_SGS, PCI_ANY_ID), - .class = PCI_BASE_CLASS_DISPLAY << 16, - .class_mask = 0xff << 16, - }, - {} -}; - static void nouveau_display_options(void) { DRM_DEBUG_DRIVER("Loading Nouveau with parameters:\n"); @@ -1226,57 +1172,26 @@ static const struct dev_pm_ops nouveau_pm_ops = { .runtime_idle = nouveau_pmops_runtime_idle, }; -static struct pci_driver -nouveau_drm_pci_driver = { +static const struct auxiliary_device_id +nouveau_drm_id_table[] = { + { .name = "nouveau.device" }, + {} +}; + +static struct auxiliary_driver +nouveau_auxdrv = { .name = "nouveau", - .id_table = nouveau_drm_pci_table, + .id_table = nouveau_drm_id_table, .probe = nouveau_drm_probe, .remove = nouveau_drm_remove, .driver.pm = &nouveau_pm_ops, }; -struct drm_device * -nouveau_platform_device_create(const struct nvkm_device_tegra_func *func, - struct platform_device *pdev, - struct nvkm_device **pdevice) -{ - struct nouveau_drm *drm; - int err; - - err = nvkm_device_tegra.probe(pdev); - if (err) - return ERR_PTR(err); - - *pdevice = platform_get_drvdata(pdev); - - drm = nouveau_drm_device_new(&driver_platform, &pdev->dev, *pdevice); - if (IS_ERR(drm)) { - err = PTR_ERR(drm); - goto err_free; - } - - err = nouveau_drm_device_init(drm); - if (err) - goto err_put; - - return drm->dev; - -err_put: - nouveau_drm_device_del(drm); -err_free: - nvkm_device_del(pdevice); - - return ERR_PTR(err); -} - static int __init nouveau_drm_init(void) { int ret; - driver_pci = driver_stub; - driver_platform = driver_stub; - nouveau_display_options(); if (nouveau_modeset == -1) { @@ -1291,17 +1206,9 @@ nouveau_drm_init(void) if (ret) return ret; -#ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER - platform_driver_register(&nouveau_platform_driver); -#endif - nouveau_backlight_ctor(); -#ifdef CONFIG_PCI - return pci_register_driver(&nouveau_drm_pci_driver); -#else - return 0; -#endif + return auxiliary_driver_register(&nouveau_auxdrv); } static void __exit @@ -1310,14 +1217,10 @@ nouveau_drm_exit(void) if (!nouveau_modeset) return; -#ifdef CONFIG_PCI - pci_unregister_driver(&nouveau_drm_pci_driver); -#endif + auxiliary_driver_unregister(&nouveau_auxdrv); + nouveau_backlight_dtor(); -#ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER - platform_driver_unregister(&nouveau_platform_driver); -#endif if (IS_ENABLED(CONFIG_DRM_NOUVEAU_SVM)) mmu_notifier_synchronize(); @@ -1327,7 +1230,6 @@ nouveau_drm_exit(void) module_init(nouveau_drm_init); module_exit(nouveau_drm_exit); -MODULE_DEVICE_TABLE(pci, nouveau_drm_pci_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 9ca0f6ab4359..ee1116bf7824 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -61,7 +61,6 @@ #include "uapi/drm/nouveau_drm.h" struct nouveau_channel; -struct platform_device; #include "nouveau_fence.h" #include "nouveau_bios.h" @@ -201,7 +200,8 @@ u_memcpya(uint64_t user, unsigned int nmemb, unsigned int size) #include <nvif/parent.h> struct nouveau_drm { - struct nvkm_device *nvkm; + struct auxiliary_device *auxdev; + struct nvif_driver_func driver; struct nvif_parent parent; struct nvif_client client; @@ -322,20 +322,13 @@ int nouveau_pmops_suspend(struct device *); int nouveau_pmops_resume(struct device *); bool nouveau_pmops_runtime(struct device *); -#include <nvkm/core/tegra.h> - -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 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_PRINTK_(l,drm,f,a...) do { \ - dev_##l((drm)->nvkm->dev, "drm: "f, ##a); \ +#define NV_PRINTK_(l,drm,f,a...) do { \ + dev_##l(&(drm)->auxdev->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) @@ -371,7 +364,7 @@ extern int nouveau_modeset; static inline struct nvkm_device * nvxx_device(struct nouveau_drm *drm) { - return drm->nvkm; + return container_of(drm->auxdev, struct nvkm_device, auxdev); } #define nvxx_bios(a) nvxx_device(a)->bios diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c deleted file mode 100644 index 23beac1f96f1..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_platform.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. - * - * 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ -#include "nouveau_platform.h" - -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); - - drm = nouveau_platform_device_create(func, pdev, &device); - if (IS_ERR(drm)) - return PTR_ERR(drm); - - return 0; -} - -static void nouveau_platform_remove(struct platform_device *pdev) -{ - struct nouveau_drm *drm = platform_get_drvdata(pdev); - - nouveau_drm_device_remove(drm); - - nvkm_device_tegra.remove_new(pdev); -} - -#if IS_ENABLED(CONFIG_OF) -static const struct nvkm_device_tegra_func gk20a_platform_data = { - .iommu_bit = 34, - .require_vdd = true, -}; - -static const struct nvkm_device_tegra_func gm20b_platform_data = { - .iommu_bit = 34, - .require_vdd = true, - .require_ref_clk = true, -}; - -static const struct nvkm_device_tegra_func gp10b_platform_data = { - .iommu_bit = 36, - /* power provided by generic PM domains */ - .require_vdd = false, -}; - -static const struct of_device_id nouveau_platform_match[] = { - { - .compatible = "nvidia,gk20a", - .data = &gk20a_platform_data, - }, - { - .compatible = "nvidia,gm20b", - .data = &gm20b_platform_data, - }, - { - .compatible = "nvidia,gp10b", - .data = &gp10b_platform_data, - }, - { } -}; - -MODULE_DEVICE_TABLE(of, nouveau_platform_match); -#endif - -struct platform_driver nouveau_platform_driver = { - .driver = { - .name = "nouveau", - .of_match_table = of_match_ptr(nouveau_platform_match), - }, - .probe = nouveau_platform_probe, - .remove_new = nouveau_platform_remove, -}; diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.h b/drivers/gpu/drm/nouveau/nouveau_platform.h deleted file mode 100644 index a90d72767b8b..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_platform.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. - * - * 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ -#ifndef __NOUVEAU_PLATFORM_H__ -#define __NOUVEAU_PLATFORM_H__ -#include "nouveau_drv.h" - -extern struct platform_driver nouveau_platform_driver; -#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_runpm.h b/drivers/gpu/drm/nouveau/nouveau_runpm.h index 92d6c518bdad..0de62022db58 100644 --- a/drivers/gpu/drm/nouveau/nouveau_runpm.h +++ b/drivers/gpu/drm/nouveau/nouveau_runpm.h @@ -6,7 +6,7 @@ static inline struct device * nouveau_runpm_dev(struct nouveau_drm *drm) { - return drm->dev->dev; + return &drm->auxdev->dev; } static inline void diff --git a/drivers/gpu/drm/nouveau/nvkm/device/acpi.c b/drivers/gpu/drm/nouveau/nvkm/device/acpi.c index cbaad3ea10eb..c4cbdf172499 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/acpi.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/acpi.c @@ -191,13 +191,10 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero return 0; } -#include "nouveau_drv.h" -#include "nouveau_acpi.h" - static void nvkm_acpi_switcheroo_reprobe(struct pci_dev *pdev) { - struct nvkm_device *device = ((struct nouveau_drm *)pci_get_drvdata(pdev))->nvkm; + struct nvkm_device *device = pci_get_drvdata(pdev); device->driver->switcheroo.reprobe(device->driver); } @@ -206,7 +203,7 @@ static void nvkm_acpi_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) { - struct nvkm_device *device = ((struct nouveau_drm *)pci_get_drvdata(pdev))->nvkm; + struct nvkm_device *device = pci_get_drvdata(pdev); if (state == VGA_SWITCHEROO_OFF) { if (nouveau_dsm_priv.dsm_detected || nouveau_dsm_priv.optimus_detected) @@ -221,7 +218,7 @@ nvkm_acpi_switcheroo_set_state(struct pci_dev *pdev, static bool nvkm_acpi_switcheroo_can_switch(struct pci_dev *pdev) { - struct nvkm_device *device = ((struct nouveau_drm *)pci_get_drvdata(pdev))->nvkm; + struct nvkm_device *device = pci_get_drvdata(pdev); return device->driver->switcheroo.can_switch(device->driver); } diff --git a/drivers/gpu/drm/nouveau/nvkm/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/device/pci.c index a66cb9d474d5..735bf0a9931d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/pci.c @@ -1618,12 +1618,10 @@ nvkm_device_pci_func = { .cpu_coherent = !IS_ENABLED(CONFIG_ARM), }; -#include "nouveau_drv.h" - static int nvkm_device_pci_pm_runtime_resume(struct device *dev) { - struct nvkm_device *device = ((struct nouveau_drm *)dev_get_drvdata(dev))->nvkm; + struct nvkm_device *device = dev_get_drvdata(dev); struct pci_dev *pdev = nvkm_device_pci(device)->pdev; int ret; @@ -1644,7 +1642,7 @@ nvkm_device_pci_pm_runtime_resume(struct device *dev) static int nvkm_device_pci_pm_runtime_suspend(struct device *dev) { - struct nvkm_device *device = ((struct nouveau_drm *)dev_get_drvdata(dev))->nvkm; + struct nvkm_device *device = dev_get_drvdata(dev); struct pci_dev *pdev = nvkm_device_pci(device)->pdev; nvkm_acpi_switcheroo_set_powerdown(); @@ -1659,7 +1657,7 @@ nvkm_device_pci_pm_runtime_suspend(struct device *dev) static int nvkm_device_pci_pm_resume(struct device *dev) { - struct nvkm_device *device = ((struct nouveau_drm *)dev_get_drvdata(dev))->nvkm; + struct nvkm_device *device = dev_get_drvdata(dev); struct pci_dev *pdev = nvkm_device_pci(device)->pdev; int ret; @@ -1677,7 +1675,7 @@ nvkm_device_pci_pm_resume(struct device *dev) static int nvkm_device_pci_pm_suspend(struct device *dev) { - struct nvkm_device *device = ((struct nouveau_drm *)dev_get_drvdata(dev))->nvkm; + struct nvkm_device *device = dev_get_drvdata(dev); struct pci_dev *pdev = nvkm_device_pci(device)->pdev; pci_save_state(pdev); @@ -1698,8 +1696,12 @@ nvkm_device_pci_pm = { static void nvkm_device_pci_remove(struct pci_dev *dev) { - struct drm_device *drm_dev = pci_get_drvdata(dev); - struct nvkm_device *device = nouveau_drm(drm_dev)->nvkm; + struct nvkm_device *device = pci_get_drvdata(dev); + + if (device->runpm) { + pm_runtime_get_sync(device->dev); + pm_runtime_forbid(device->dev); + } nvkm_device_del(&device); } @@ -1855,12 +1857,36 @@ nvkm_device_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) } } + if (device->runpm) { + pm_runtime_allow(device->dev); + pm_runtime_put(device->dev); + } + return 0; } +static struct pci_device_id +nvkm_device_pci_id_table[] = { + { + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), + .class = PCI_BASE_CLASS_DISPLAY << 16, + .class_mask = 0xff << 16, + }, + { + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA_SGS, PCI_ANY_ID), + .class = PCI_BASE_CLASS_DISPLAY << 16, + .class_mask = 0xff << 16, + }, + {} +}; + struct pci_driver nvkm_device_pci_driver = { + .name = "nvkm", + .id_table = nvkm_device_pci_id_table, .probe = nvkm_device_pci_probe, .remove = nvkm_device_pci_remove, .driver.pm = &nvkm_device_pci_pm, }; + +MODULE_DEVICE_TABLE(pci, nvkm_device_pci_id_table); diff --git a/drivers/gpu/drm/nouveau/nvkm/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/device/tegra.c index f0c1258170f4..743a781586c0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/tegra.c @@ -233,12 +233,10 @@ nvkm_device_tegra_func = { .cpu_coherent = false, }; -#include "nouveau_drv.h" - static void nvkm_device_tegra_remove(struct platform_device *pdev) { - struct nvkm_device *device = ((struct nouveau_drm *)platform_get_drvdata(pdev))->nvkm; + struct nvkm_device *device = platform_get_drvdata(dev); nvkm_device_del(&device); } @@ -336,11 +334,50 @@ nvkm_device_tegra_probe(struct platform_device *pdev) return ret; } +static const struct nvkm_device_tegra_func gk20a_platform_data = { + .iommu_bit = 34, + .require_vdd = true, +}; + +static const struct nvkm_device_tegra_func gm20b_platform_data = { + .iommu_bit = 34, + .require_vdd = true, + .require_ref_clk = true, +}; + +static const struct nvkm_device_tegra_func gp10b_platform_data = { + .iommu_bit = 36, + /* power provided by generic PM domains */ + .require_vdd = false, +}; + +static const struct of_device_id nouveau_platform_match[] = { + { + .compatible = "nvidia,gk20a", + .data = &gk20a_platform_data, + }, + { + .compatible = "nvidia,gm20b", + .data = &gm20b_platform_data, + }, + { + .compatible = "nvidia,gp10b", + .data = &gp10b_platform_data, + }, + { } +}; + struct platform_driver nvkm_device_tegra = { + .driver = { + .name = "nvkm", + .of_match_table = of_match_ptr(nouveau_platform_match), + }, .probe = nvkm_device_tegra_probe, .remove_new = nvkm_device_tegra_remove, }; + +MODULE_DEVICE_TABLE(of, nouveau_platform_match); #else struct platform_driver nvkm_device_tegra = { diff --git a/drivers/gpu/drm/nouveau/nvkm/module.c b/drivers/gpu/drm/nouveau/nvkm/module.c index 7a56ef8c3b6b..c14dd7fa15c2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/module.c +++ b/drivers/gpu/drm/nouveau/nvkm/module.c @@ -20,6 +20,8 @@ * DEALINGS IN THE SOFTWARE. */ #include <core/module.h> +#include <core/pci.h> +#include <core/tegra.h> #include <device/acpi.h> int nvkm_runpm = -1; @@ -27,12 +29,34 @@ int nvkm_runpm = -1; void __exit nvkm_exit(void) { +#ifdef CONFIG_PCI nvkm_acpi_switcheroo_fini(); + pci_unregister_driver(&nvkm_device_pci_driver); +#endif + +#ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER + platform_driver_unregister(&nvkm_device_tegra); +#endif } int __init nvkm_init(void) { + int ret; + +#ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER + ret = platform_driver_register(&nvkm_device_tegra); + if (ret) + return ret; +#endif + +#ifdef CONFIG_PCI nvkm_acpi_switcheroo_init(); + + ret = pci_register_driver(&nvkm_device_pci_driver); + if (ret) + return ret; +#endif + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c index e4737b89cb63..919e07d85f2e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c @@ -64,12 +64,10 @@ nvkm_pci_mask(struct nvkm_pci *pci, u16 addr, u32 mask, u32 value) return data; } -#include "nouveau_drv.h" - static unsigned int nvkm_pci_vga_set_decode(struct pci_dev *pdev, bool state) { - struct nvkm_device *device = ((struct nouveau_drm *)pci_get_drvdata(pdev))->nvkm; + struct nvkm_device *device = pci_get_drvdata(pdev); if (device->card_type == NV_40 && device->chipset >= 0x4c) -- 2.44.0
Ben Skeggs
2024-Jun-13 17:00 UTC
[PATCH 21/21] drm/nouveau/nvkm: s/nouveau/nvkm/ over code moved from drm
The move and renames were kept separate for cleaner diffs. Signed-off-by: Ben Skeggs <bskeggs at nvidia.com> --- drivers/gpu/drm/nouveau/nvkm/device/acpi.c | 113 ++++++++++---------- drivers/gpu/drm/nouveau/nvkm/device/acpi.h | 4 +- drivers/gpu/drm/nouveau/nvkm/device/pci.c | 8 +- drivers/gpu/drm/nouveau/nvkm/device/tegra.c | 6 +- 4 files changed, 64 insertions(+), 67 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/device/acpi.c b/drivers/gpu/drm/nouveau/nvkm/device/acpi.c index c4cbdf172499..ff8a3027c1bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/acpi.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/acpi.c @@ -32,9 +32,9 @@ #include <linux/vga_switcheroo.h> #ifdef CONFIG_VGA_SWITCHEROO -struct nouveau_dsm_priv nouveau_dsm_priv = {}; +struct nvkm_dsm_priv nvkm_dsm_priv = {}; -static const guid_t nouveau_op_dsm_muid +static const guid_t nvkm_op_dsm_muid GUID_INIT(0xA486D8F8, 0x0BDA, 0x471B, 0xA7, 0x2B, 0x60, 0x42, 0xA6, 0xB5, 0xBE, 0xE0); @@ -60,7 +60,7 @@ static const guid_t nouveau_op_dsm_muid #define OPTIMUS_AUDIO_CAPS_MASK (3 << 27) #define OPTIMUS_HDA_CODEC_MASK (2 << 27) /* hda bios control */ -static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result) +static int nvkm_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result) { int i; union acpi_object *obj; @@ -76,7 +76,7 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t * args_buff[i] = (arg >> i * 8) & 0xFF; *result = 0; - obj = acpi_evaluate_dsm_typed(handle, &nouveau_op_dsm_muid, 0x00000100, + obj = acpi_evaluate_dsm_typed(handle, &nvkm_op_dsm_muid, 0x00000100, func, &argv4, ACPI_TYPE_BUFFER); if (!obj) { acpi_handle_info(handle, "failed to evaluate _DSM\n"); @@ -98,24 +98,24 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t * void nvkm_acpi_switcheroo_set_powerdown(void) { u32 result = 0; - if (!nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.optimus_skip_dsm) + if (!nvkm_dsm_priv.optimus_detected || nvkm_dsm_priv.optimus_skip_dsm) return; - if (nouveau_dsm_priv.optimus_flags_detected) - nouveau_optimus_dsm(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_OPTIMUS_FLAGS, - 0x3, &result); + if (nvkm_dsm_priv.optimus_flags_detected) + nvkm_optimus_dsm(nvkm_dsm_priv.dhandle, NOUVEAU_DSM_OPTIMUS_FLAGS, + 0x3, &result); - nouveau_optimus_dsm(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_OPTIMUS_CAPS, - NOUVEAU_DSM_OPTIMUS_SET_POWERDOWN, &result); + nvkm_optimus_dsm(nvkm_dsm_priv.dhandle, NOUVEAU_DSM_OPTIMUS_CAPS, + NOUVEAU_DSM_OPTIMUS_SET_POWERDOWN, &result); } /* - * On some platforms, _DSM(nouveau_op_dsm_muid, func0) has special + * On some platforms, _DSM(nvkm_op_dsm_muid, func0) has special * requirements on the fourth parameter, so a private implementation * instead of using acpi_check_dsm(). */ -static int nouveau_dsm_get_optimus_functions(acpi_handle handle) +static int nvkm_dsm_get_optimus_functions(acpi_handle handle) { int result; @@ -123,7 +123,7 @@ static int nouveau_dsm_get_optimus_functions(acpi_handle handle) * Function 0 returns a Buffer containing available functions. * The args parameter is ignored for function 0, so just put 0 in it */ - if (nouveau_optimus_dsm(handle, 0, 0, &result)) + if (nvkm_optimus_dsm(handle, 0, 0, &result)) return 0; /* @@ -135,7 +135,7 @@ static int nouveau_dsm_get_optimus_functions(acpi_handle handle) return 0; } -static const guid_t nouveau_dsm_muid +static const guid_t nvkm_dsm_muid GUID_INIT(0x9D95A0A0, 0x0060, 0x4D48, 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4); @@ -150,7 +150,7 @@ static const guid_t nouveau_dsm_muid #define NOUVEAU_DSM_POWER_SPEED 0x01 #define NOUVEAU_DSM_POWER_STAMINA 0x02 -static int nouveau_dsm(acpi_handle handle, int func, int arg) +static int nvkm_dsm(acpi_handle handle, int func, int arg) { int ret = 0; union acpi_object *obj; @@ -159,7 +159,7 @@ static int nouveau_dsm(acpi_handle handle, int func, int arg) .integer.value = arg, }; - obj = acpi_evaluate_dsm_typed(handle, &nouveau_dsm_muid, 0x00000102, + obj = acpi_evaluate_dsm_typed(handle, &nvkm_dsm_muid, 0x00000102, func, &argv4, ACPI_TYPE_INTEGER); if (!obj) { acpi_handle_info(handle, "failed to evaluate _DSM\n"); @@ -173,21 +173,21 @@ static int nouveau_dsm(acpi_handle handle, int func, int arg) return ret; } -static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) +static int nvkm_dsm_switch_mux(acpi_handle handle, int mux_id) { mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); - return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id); + return nvkm_dsm(handle, NOUVEAU_DSM_LED, mux_id); } -static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state) +static int nvkm_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state) { int arg; if (state == VGA_SWITCHEROO_ON) arg = NOUVEAU_DSM_POWER_SPEED; else arg = NOUVEAU_DSM_POWER_STAMINA; - nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg); + nvkm_dsm(handle, NOUVEAU_DSM_POWER, arg); return 0; } @@ -206,7 +206,7 @@ nvkm_acpi_switcheroo_set_state(struct pci_dev *pdev, struct nvkm_device *device = pci_get_drvdata(pdev); if (state == VGA_SWITCHEROO_OFF) { - if (nouveau_dsm_priv.dsm_detected || nouveau_dsm_priv.optimus_detected) + if (nvkm_dsm_priv.dsm_detected || nvkm_dsm_priv.optimus_detected) return; nvkm_acpi_switcheroo_set_powerdown(); @@ -230,31 +230,31 @@ nvkm_acpi_switcheroo_ops = { .reprobe = nvkm_acpi_switcheroo_reprobe, }; -static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id) +static int nvkm_dsm_switchto(enum vga_switcheroo_client_id id) { - if (!nouveau_dsm_priv.dsm_detected) + if (!nvkm_dsm_priv.dsm_detected) return 0; if (id == VGA_SWITCHEROO_IGD) - return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA); + return nvkm_dsm_switch_mux(nvkm_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA); else - return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_SPEED); + return nvkm_dsm_switch_mux(nvkm_dsm_priv.dhandle, NOUVEAU_DSM_LED_SPEED); } -static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id, +static int nvkm_dsm_power_state(enum vga_switcheroo_client_id id, enum vga_switcheroo_state state) { if (id == VGA_SWITCHEROO_IGD) return 0; /* Optimus laptops have the card already disabled in - * nouveau_switcheroo_set_state */ - if (!nouveau_dsm_priv.dsm_detected) + * nvkm_switcheroo_set_state */ + if (!nvkm_dsm_priv.dsm_detected) return 0; - return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state); + return nvkm_dsm_set_discrete_state(nvkm_dsm_priv.dhandle, state); } -static enum vga_switcheroo_client_id nouveau_dsm_get_client_id(struct pci_dev *pdev) +static enum vga_switcheroo_client_id nvkm_dsm_get_client_id(struct pci_dev *pdev) { /* easy option one - intel vendor ID means Integrated */ if (pdev->vendor == PCI_VENDOR_ID_INTEL) @@ -267,15 +267,15 @@ static enum vga_switcheroo_client_id nouveau_dsm_get_client_id(struct pci_dev *p return VGA_SWITCHEROO_DIS; } -static const struct vga_switcheroo_handler nouveau_dsm_handler = { - .switchto = nouveau_dsm_switchto, - .power_state = nouveau_dsm_power_state, - .get_client_id = nouveau_dsm_get_client_id, +static const struct vga_switcheroo_handler nvkm_dsm_handler = { + .switchto = nvkm_dsm_switchto, + .power_state = nvkm_dsm_power_state, + .get_client_id = nvkm_dsm_get_client_id, }; -static void nouveau_dsm_pci_probe(struct pci_dev *pdev, acpi_handle *dhandle_out, - bool *has_mux, bool *has_opt, - bool *has_opt_flags, bool *has_pr3) +static void nvkm_dsm_pci_probe(struct pci_dev *pdev, acpi_handle *dhandle_out, + bool *has_mux, bool *has_opt, + bool *has_opt_flags, bool *has_pr3) { acpi_handle dhandle; bool supports_mux; @@ -301,9 +301,9 @@ static void nouveau_dsm_pci_probe(struct pci_dev *pdev, acpi_handle *dhandle_out if (!acpi_has_method(dhandle, "_DSM")) return; - supports_mux = acpi_check_dsm(dhandle, &nouveau_dsm_muid, 0x00000102, + supports_mux = acpi_check_dsm(dhandle, &nvkm_dsm_muid, 0x00000102, 1 << NOUVEAU_DSM_POWER); - optimus_funcs = nouveau_dsm_get_optimus_functions(dhandle); + optimus_funcs = nvkm_dsm_get_optimus_functions(dhandle); /* Does not look like a Nvidia device. */ if (!supports_mux && !optimus_funcs) @@ -316,8 +316,7 @@ static void nouveau_dsm_pci_probe(struct pci_dev *pdev, acpi_handle *dhandle_out if (optimus_funcs) { uint32_t result; - nouveau_optimus_dsm(dhandle, NOUVEAU_DSM_OPTIMUS_CAPS, 0, - &result); + nvkm_optimus_dsm(dhandle, NOUVEAU_DSM_OPTIMUS_CAPS, 0, &result); dev_info(&pdev->dev, "optimus capabilities: %s, status %s%s\n", (result & OPTIMUS_ENABLED) ? "enabled" : "disabled", (result & OPTIMUS_DYNAMIC_PWR_CAP) ? "dynamic power, " : "", @@ -325,7 +324,7 @@ static void nouveau_dsm_pci_probe(struct pci_dev *pdev, acpi_handle *dhandle_out } } -static bool nouveau_dsm_detect(void) +static bool nvkm_dsm_detect(void) { char acpi_method_name[255] = { 0 }; struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; @@ -353,30 +352,28 @@ static bool nouveau_dsm_detect(void) vga_count++; - nouveau_dsm_pci_probe(pdev, &dhandle, &has_mux, &has_optimus, - &has_optimus_flags, &has_power_resources); + nvkm_dsm_pci_probe(pdev, &dhandle, &has_mux, &has_optimus, + &has_optimus_flags, &has_power_resources); } /* find the optimus DSM or the old v1 DSM */ if (has_optimus) { - nouveau_dsm_priv.dhandle = dhandle; - acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, - &buffer); + nvkm_dsm_priv.dhandle = dhandle; + acpi_get_name(nvkm_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer); pr_info("VGA switcheroo: detected Optimus DSM method %s handle\n", acpi_method_name); if (has_power_resources) - pr_info("nouveau: detected PR support, will not use DSM\n"); - nouveau_dsm_priv.optimus_detected = true; - nouveau_dsm_priv.optimus_flags_detected = has_optimus_flags; - nouveau_dsm_priv.optimus_skip_dsm = has_power_resources; + pr_info("nvkm: detected PR support, will not use DSM\n"); + nvkm_dsm_priv.optimus_detected = true; + nvkm_dsm_priv.optimus_flags_detected = has_optimus_flags; + nvkm_dsm_priv.optimus_skip_dsm = has_power_resources; ret = true; } else if (vga_count == 2 && has_mux && guid_valid) { - nouveau_dsm_priv.dhandle = dhandle; - acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, - &buffer); + nvkm_dsm_priv.dhandle = dhandle; + acpi_get_name(nvkm_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer); pr_info("VGA switcheroo: detected DSM switching method %s handle\n", acpi_method_name); - nouveau_dsm_priv.dsm_detected = true; + nvkm_dsm_priv.dsm_detected = true; ret = true; } @@ -387,7 +384,7 @@ static bool nouveau_dsm_detect(void) void nvkm_acpi_switcheroo_fini(void) { - if (nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.dsm_detected) + if (nvkm_dsm_priv.optimus_detected || nvkm_dsm_priv.dsm_detected) vga_switcheroo_unregister_handler(); } @@ -396,11 +393,11 @@ nvkm_acpi_switcheroo_init(void) { bool r; - r = nouveau_dsm_detect(); + r = nvkm_dsm_detect(); if (!r) return; - vga_switcheroo_register_handler(&nouveau_dsm_handler, 0); + vga_switcheroo_register_handler(&nvkm_dsm_handler, 0); } #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/device/acpi.h b/drivers/gpu/drm/nouveau/nvkm/device/acpi.h index 34854d10026d..2dd8a3029b55 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/acpi.h +++ b/drivers/gpu/drm/nouveau/nvkm/device/acpi.h @@ -8,13 +8,13 @@ void nvkm_acpi_init(struct nvkm_device *); void nvkm_acpi_fini(struct nvkm_device *); #ifdef CONFIG_VGA_SWITCHEROO -extern struct nouveau_dsm_priv { +extern struct nvkm_dsm_priv { bool dsm_detected; bool optimus_detected; bool optimus_flags_detected; bool optimus_skip_dsm; acpi_handle dhandle; -} nouveau_dsm_priv; +} nvkm_dsm_priv; void nvkm_acpi_switcheroo_init(void); void nvkm_acpi_switcheroo_fini(void); diff --git a/drivers/gpu/drm/nouveau/nvkm/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/device/pci.c index 735bf0a9931d..8eb3a66f53d6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/pci.c @@ -1720,8 +1720,8 @@ nvkm_device_pci_remove(struct pci_dev *dev) * to handle well enough. * * In all cases dmesg will contain at least one line like this: - * 'nouveau 0000:01:00.0: Refused to change power state, currently in D3' - * followed by a lot of nouveau timeouts. + * 'nvkm 0000:01:00.0: Refused to change power state, currently in D3' + * followed by a lot of nvkm timeouts. * * In the \_SB.PCI0.PEG0.PG00._OFF code deeper down writes bit 0x80 to the not * documented PCI config space register 0x248 of the Intel PCIe bridge @@ -1849,8 +1849,8 @@ nvkm_device_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) pci_set_drvdata(pci_dev, &pdev->device); if (nvkm_runpm) { - if (!nouveau_dsm_priv.optimus_detected) { - if (nouveau_dsm_priv.dsm_detected) + if (!nvkm_dsm_priv.optimus_detected) { + if (nvkm_dsm_priv.dsm_detected) device->runpm = NVKM_DEVICE_RUNPM_V1; } else { device->runpm = NVKM_DEVICE_RUNPM_OPTIMUS; diff --git a/drivers/gpu/drm/nouveau/nvkm/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/device/tegra.c index 743a781586c0..75ce47f25e19 100644 --- a/drivers/gpu/drm/nouveau/nvkm/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/device/tegra.c @@ -351,7 +351,7 @@ static const struct nvkm_device_tegra_func gp10b_platform_data = { .require_vdd = false, }; -static const struct of_device_id nouveau_platform_match[] = { +static const struct of_device_id nvkm_platform_match[] = { { .compatible = "nvidia,gk20a", .data = &gk20a_platform_data, @@ -371,13 +371,13 @@ struct platform_driver nvkm_device_tegra = { .driver = { .name = "nvkm", - .of_match_table = of_match_ptr(nouveau_platform_match), + .of_match_table = of_match_ptr(nvkm_platform_match), }, .probe = nvkm_device_tegra_probe, .remove_new = nvkm_device_tegra_remove, }; -MODULE_DEVICE_TABLE(of, nouveau_platform_match); +MODULE_DEVICE_TABLE(of, nvkm_platform_match); #else struct platform_driver nvkm_device_tegra = { -- 2.44.0