diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2015-08-20 14:54:17 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2015-08-28 12:40:34 +1000 |
commit | 7974dd1bdb43aaf5b45a915c6b439d11733450fc (patch) | |
tree | 716712130efe76478612a719fba409554cbff59b /drivers/gpu/drm/nouveau/nvkm | |
parent | 168c2e213d3a9b605856d3676d9e93733c8b37d3 (diff) | |
download | blackbird-op-linux-7974dd1bdb43aaf5b45a915c6b439d11733450fc.tar.gz blackbird-op-linux-7974dd1bdb43aaf5b45a915c6b439d11733450fc.zip |
drm/nouveau/device: separate construction of pci/tegra devices
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/device/Kbuild | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 104 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c | 100 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c | 66 |
5 files changed, 249 insertions, 32 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/device/Kbuild index 47c8fe8f9e3e..91110cd2562e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/Kbuild @@ -1,6 +1,8 @@ nvkm-y += nvkm/engine/device/acpi.o nvkm-y += nvkm/engine/device/base.o nvkm-y += nvkm/engine/device/ctrl.o +nvkm-y += nvkm/engine/device/pci.o +nvkm-y += nvkm/engine/device/tegra.o nvkm-y += nvkm/engine/device/user.o nvkm-y += nvkm/engine/device/nv04.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index b7892e6f080b..c7d8e2902c6c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -32,19 +32,25 @@ static DEFINE_MUTEX(nv_devices_mutex); static LIST_HEAD(nv_devices); -struct nvkm_device * -nvkm_device_find(u64 name) +static struct nvkm_device * +nvkm_device_find_locked(u64 handle) { - struct nvkm_device *device, *match = NULL; - mutex_lock(&nv_devices_mutex); + struct nvkm_device *device; list_for_each_entry(device, &nv_devices, head) { - if (device->handle == name) { - match = device; - break; - } + if (device->handle == handle) + return device; } + return NULL; +} + +struct nvkm_device * +nvkm_device_find(u64 handle) +{ + struct nvkm_device *device; + mutex_lock(&nv_devices_mutex); + device = nvkm_device_find_locked(handle); mutex_unlock(&nv_devices_mutex); - return match; + return device; } int @@ -62,6 +68,7 @@ nvkm_device_list(u64 *name, int size) } #include <core/parent.h> +#include <core/client.h> struct nvkm_device * nv_device(void *obj) @@ -70,7 +77,8 @@ nv_device(void *obj) if (device->engine == NULL) { while (device && device->parent) { - if (nv_mclass(device) == 0x0080) { + if (!nv_iclass(device, NV_SUBDEV_CLASS) && + device->parent == &nvkm_client(device)->namedb.parent.object) { struct { struct nvkm_parent base; struct nvkm_device *device; @@ -125,6 +133,9 @@ nvkm_device_fini(struct nvkm_device *device, bool suspend) } ret = nvkm_acpi_fini(device, suspend); + + if (device->func->fini) + device->func->fini(device, suspend); fail: for (; ret && i < NVDEV_SUBDEV_NR; i++) { if ((subdev = device->subdev[i])) { @@ -141,11 +152,39 @@ fail: } int +nvkm_device_preinit(struct nvkm_device *device) +{ + int ret; + s64 time; + + nvdev_trace(device, "preinit running...\n"); + time = ktime_to_us(ktime_get()); + + if (device->func->preinit) { + ret = device->func->preinit(device); + if (ret) + goto fail; + } + + time = ktime_to_us(ktime_get()) - time; + nvdev_trace(device, "preinit completed in %lldus\n", time); + return 0; + +fail: + nvdev_error(device, "preinit failed with %d\n", ret); + return ret; +} + +int nvkm_device_init(struct nvkm_device *device) { struct nvkm_object *subdev; int ret, i = 0, c; + ret = nvkm_device_preinit(device); + if (ret) + return ret; + ret = nvkm_acpi_init(device); if (ret) goto fail; @@ -287,12 +326,6 @@ nv_device_get_irq(struct nvkm_device *device, bool stall) } } -static struct nvkm_oclass -nvkm_device_oclass = { - .ofuncs = &(struct nvkm_ofuncs) { - }, -}; - void nvkm_device_del(struct nvkm_device **pdevice) { @@ -308,20 +341,28 @@ nvkm_device_del(struct nvkm_device **pdevice) if (device->pri) iounmap(device->pri); list_del(&device->head); + + if (device->func->dtor) + *pdevice = device->func->dtor(device); mutex_unlock(&nv_devices_mutex); - nvkm_engine_destroy(&device->engine); + kfree(*pdevice); *pdevice = NULL; } } +static const struct nvkm_engine_func +nvkm_device_func = { +}; + int -nvkm_device_new(void *dev, enum nv_bus_type type, u64 name, - const char *sname, const char *cfg, const char *dbg, - bool detect, bool mmio, u64 subdev_mask, - struct nvkm_device **pdevice) +nvkm_device_ctor(const struct nvkm_device_func *func, + const struct nvkm_device_quirk *quirk, + void *dev, enum nv_bus_type type, u64 handle, + const char *name, const char *cfg, const char *dbg, + bool detect, bool mmio, u64 subdev_mask, + struct nvkm_device *device) { - struct nvkm_device *device; u64 mmio_base, mmio_size; u32 boot0, strap; void __iomem *map; @@ -329,17 +370,17 @@ nvkm_device_new(void *dev, enum nv_bus_type type, u64 name, int i; mutex_lock(&nv_devices_mutex); - list_for_each_entry(device, &nv_devices, head) { - if (device->handle == name) - goto done; - } + if (nvkm_device_find_locked(handle)) + goto done; - ret = nvkm_engine_create(NULL, NULL, &nvkm_device_oclass, true, - "DEVICE", "device", &device); - *pdevice = device; + ret = nvkm_engine_ctor(&nvkm_device_func, device, 0, 0, + true, &device->engine); + device->engine.subdev.object.parent = NULL; + device->func = func; if (ret) goto done; + device->quirk = quirk; switch (type) { case NVKM_BUS_PCI: device->pdev = dev; @@ -350,12 +391,11 @@ nvkm_device_new(void *dev, enum nv_bus_type type, u64 name, device->dev = &device->platformdev->dev; break; } - device->handle = name; + device->handle = handle; device->cfgopt = cfg; device->dbgopt = dbg; - device->name = sname; + device->name = name; - nv_subdev(device)->debug = nvkm_dbgopt(device->dbgopt, "DEVICE"); list_add_tail(&device->head, &nv_devices); ret = nvkm_event_init(&nvkm_device_event_func, 1, 1, &device->event); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c new file mode 100644 index 000000000000..1a1d1e584a7f --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c @@ -0,0 +1,100 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include <core/pci.h> +#include "priv.h" + +static struct nvkm_device_pci * +nvkm_device_pci(struct nvkm_device *device) +{ + return container_of(device, struct nvkm_device_pci, device); +} + +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 void * +nvkm_device_pci_dtor(struct nvkm_device *device) +{ + struct nvkm_device_pci *pdev = nvkm_device_pci(device); + pci_disable_device(pdev->pdev); + return pdev; +} + +static const struct nvkm_device_func +nvkm_device_pci_func = { + .pci = nvkm_device_pci, + .dtor = nvkm_device_pci_dtor, + .preinit = nvkm_device_pci_preinit, + .fini = nvkm_device_pci_fini, +}; + +int +nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, + bool detect, bool mmio, u64 subdev_mask, + struct nvkm_device **pdevice) +{ + struct nvkm_device_pci *pdev; + int ret; + + ret = pci_enable_device(pci_dev); + if (ret) + return ret; + + if (!(pdev = kzalloc(sizeof(*pdev), GFP_KERNEL))) { + pci_disable_device(pci_dev); + return -ENOMEM; + } + *pdevice = &pdev->device; + pdev->pdev = pci_dev; + + return nvkm_device_ctor(&nvkm_device_pci_func, NULL, + pci_dev, NVKM_BUS_PCI, + (u64)pci_domain_nr(pci_dev->bus) << 32 | + pci_dev->bus->number << 16 | + PCI_SLOT(pci_dev->devfn) << 8 | + PCI_FUNC(pci_dev->devfn), NULL, + cfg, dbg, detect, mmio, subdev_mask, + &pdev->device); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h index 8d3590e7bd87..df9c1550301f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h @@ -2,6 +2,15 @@ #define __NVKM_DEVICE_PRIV_H__ #include <core/device.h> +int nvkm_device_ctor(const struct nvkm_device_func *, + const struct nvkm_device_quirk *, + void *, enum nv_bus_type type, u64 handle, + const char *name, const char *cfg, const char *dbg, + bool detect, bool mmio, u64 subdev_mask, + struct nvkm_device *); +int nvkm_device_init(struct nvkm_device *); +int nvkm_device_fini(struct nvkm_device *, bool suspend); + extern struct nvkm_oclass nvkm_control_oclass[]; int nv04_identify(struct nvkm_device *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c new file mode 100644 index 000000000000..0a5e5b88fee2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c @@ -0,0 +1,66 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include <core/tegra.h> +#ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER +#include "priv.h" + +static struct nvkm_device_tegra * +nvkm_device_tegra(struct nvkm_device *obj) +{ + return container_of(obj, struct nvkm_device_tegra, device); +} + +static const struct nvkm_device_func +nvkm_device_tegra_func = { + .tegra = nvkm_device_tegra, +}; + +int +nvkm_device_tegra_new(struct platform_device *pdev, + const char *cfg, const char *dbg, + bool detect, bool mmio, u64 subdev_mask, + struct nvkm_device **pdevice) +{ + struct nvkm_device_tegra *tdev; + + if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL))) + return -ENOMEM; + *pdevice = &tdev->device; + tdev->pdev = pdev; + + return nvkm_device_ctor(&nvkm_device_tegra_func, NULL, pdev, + NVKM_BUS_PLATFORM, pdev->id, NULL, + cfg, dbg, detect, mmio, subdev_mask, + &tdev->device); +} +#else +int +nvkm_device_tegra_new(struct platform_device *pdev, + const char *cfg, const char *dbg, + bool detect, bool mmio, u64 subdev_mask, + struct nvkm_device **pdevice) +{ + return -ENOSYS; +} +#endif |