This was the first step of the secure boot refactoring - as Ben asked for some fixes, I now submit it as its own series to make it easier to review (and also because rebasing secure boot on top of this takes time and I don't want to do it until this is validated!). This series attempts to factorize the duplicate falcon-related code into a single library, using the existing nvkm_falcon structure as a basis. Note that this currently makes struct nvkm_falcon used for two different purposes: this fact is acknowledged, and temporary. It just makes it easier to review this first step. Using the library, falcons are now acquired by a given subdev using nvkm_falcon_get(), and released with nvkm_falcon_put(). This allows different engines to share a falcon (as devinit, secboot and pmu will need to do), but forces us to think about falcon ownership and handling them to the next engine properly. Right now the most obvious ownership issue is between secboot and pmu. I have code coming after the secboot refactor that takes care of this ; but in the meantime I hope we can go with the empty gm20b PMU driver in this series. This series also updates gr, secboot and gk20a's PMU implementation to use the falcon library as an example. Converting other engines is trivial and should make our use of falcons generally safer. Changes since v1: * renamed falcon/falcon_v1.c to shorter falcon/v1.c * add and use nvkm_gr_fini() to reserve GR falcons accurately * pad IMEM to 0x40 words otherwise some FW will not work properly * make IMEM/DMEM writing functions more robust * move falcons instances into their owning subdev * rework gk20a's PMU implementation and add dummy gm20b PMU driver Alexandre Courbot (15): core: constify nv*_printk macros mc: add nvkm_mc_enabled() function core: add falcon library functions pmu: instanciate the falcon in PMU device pmu: add nvkm_pmu_ctor() function pmu/gk20a: use nvkm_pmu_ctor() pmu/gk20a: simplify code a bit pmu/gk20a: use falcon library functions gm20b: add dummy PMU device secboot: fix functions definitions secboot: use falcon library gr: add fini() hook gr/gf100: split gf100_gr_init_ctxctl() gr/gf100: instantiate and reserve GR falcons secboot: remove nvkm_secboot_start() drm/nouveau/include/nvkm/core/client.h | 4 +- drm/nouveau/include/nvkm/core/device.h | 3 +- drm/nouveau/include/nvkm/core/subdev.h | 2 +- drm/nouveau/include/nvkm/engine/falcon.h | 65 +++++- drm/nouveau/include/nvkm/subdev/mc.h | 1 +- drm/nouveau/include/nvkm/subdev/pmu.h | 3 +- drm/nouveau/include/nvkm/subdev/secboot.h | 9 +- drm/nouveau/nvkm/Kbuild | 1 +- drm/nouveau/nvkm/engine/device/base.c | 2 +- drm/nouveau/nvkm/engine/gr/base.c | 10 +- drm/nouveau/nvkm/engine/gr/gf100.c | 300 ++++++++++++----------- drm/nouveau/nvkm/engine/gr/gf100.h | 3 +- drm/nouveau/nvkm/engine/gr/priv.h | 1 +- drm/nouveau/nvkm/falcon/Kbuild | 2 +- drm/nouveau/nvkm/falcon/base.c | 194 +++++++++++++++- drm/nouveau/nvkm/falcon/v1.c | 235 ++++++++++++++++++- drm/nouveau/nvkm/subdev/mc/base.c | 10 +- drm/nouveau/nvkm/subdev/pmu/Kbuild | 1 +- drm/nouveau/nvkm/subdev/pmu/base.c | 21 +- drm/nouveau/nvkm/subdev/pmu/gk20a.c | 96 +++---- drm/nouveau/nvkm/subdev/pmu/gm20b.c | 34 +++- drm/nouveau/nvkm/subdev/pmu/priv.h | 2 +- drm/nouveau/nvkm/subdev/secboot/base.c | 163 +------------ drm/nouveau/nvkm/subdev/secboot/gm200.c | 152 +++--------- drm/nouveau/nvkm/subdev/secboot/gm20b.c | 1 +- drm/nouveau/nvkm/subdev/secboot/priv.h | 7 +- 26 files changed, 851 insertions(+), 471 deletions(-) create mode 100644 drm/nouveau/nvkm/falcon/Kbuild create mode 100644 drm/nouveau/nvkm/falcon/base.c create mode 100644 drm/nouveau/nvkm/falcon/v1.c create mode 100644 drm/nouveau/nvkm/subdev/pmu/gm20b.c -- git-series 0.8.10
Alexandre Courbot
2016-Dec-13 08:11 UTC
[Nouveau] [PATCH v2 1/15] core: constify nv*_printk macros
Constify the local variables declared in these macros so we can pass const pointers to them. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/include/nvkm/core/client.h | 4 ++-- drm/nouveau/include/nvkm/core/device.h | 2 +- drm/nouveau/include/nvkm/core/subdev.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drm/nouveau/include/nvkm/core/client.h b/drm/nouveau/include/nvkm/core/client.h index eaf5905a87a3..99083349c3d4 100644 --- a/drm/nouveau/include/nvkm/core/client.h +++ b/drm/nouveau/include/nvkm/core/client.h @@ -37,8 +37,8 @@ int nvkm_client_notify_put(struct nvkm_client *, int index); /* logging for client-facing objects */ #define nvif_printk(o,l,p,f,a...) do { \ - struct nvkm_object *_object = (o); \ - struct nvkm_client *_client = _object->client; \ + const struct nvkm_object *_object = (o); \ + const struct nvkm_client *_client = _object->client; \ if (_client->debug >= NV_DBG_##l) \ printk(KERN_##p "nouveau: %s:%08x:%08x: "f, _client->name, \ _object->handle, _object->oclass, ##a); \ diff --git a/drm/nouveau/include/nvkm/core/device.h b/drm/nouveau/include/nvkm/core/device.h index 6bc712f32c8b..d426b86e2712 100644 --- a/drm/nouveau/include/nvkm/core/device.h +++ b/drm/nouveau/include/nvkm/core/device.h @@ -262,7 +262,7 @@ extern const struct nvkm_sclass nvkm_udevice_sclass; /* device logging */ #define nvdev_printk_(d,l,p,f,a...) do { \ - struct nvkm_device *_device = (d); \ + const struct nvkm_device *_device = (d); \ if (_device->debug >= (l)) \ dev_##p(_device->dev, f, ##a); \ } while(0) diff --git a/drm/nouveau/include/nvkm/core/subdev.h b/drm/nouveau/include/nvkm/core/subdev.h index 57adefa8b08e..ca9ed3d68f44 100644 --- a/drm/nouveau/include/nvkm/core/subdev.h +++ b/drm/nouveau/include/nvkm/core/subdev.h @@ -32,7 +32,7 @@ void nvkm_subdev_intr(struct nvkm_subdev *); /* subdev logging */ #define nvkm_printk_(s,l,p,f,a...) do { \ - struct nvkm_subdev *_subdev = (s); \ + const struct nvkm_subdev *_subdev = (s); \ if (_subdev->debug >= (l)) { \ dev_##p(_subdev->device->dev, "%s: "f, \ nvkm_subdev_name[_subdev->index], ##a); \ -- git-series 0.8.10
Alexandre Courbot
2016-Dec-13 08:11 UTC
[Nouveau] [PATCH v2 2/15] mc: add nvkm_mc_enabled() function
Add a function that allows us to query whether a given subdev is currently enabled or not. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/include/nvkm/subdev/mc.h | 1 + drm/nouveau/nvkm/subdev/mc/base.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 0 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/mc.h b/drm/nouveau/include/nvkm/subdev/mc.h index 27d25b18d85c..e68ba636741b 100644 --- a/drm/nouveau/include/nvkm/subdev/mc.h +++ b/drm/nouveau/include/nvkm/subdev/mc.h @@ -9,6 +9,7 @@ struct nvkm_mc { void nvkm_mc_enable(struct nvkm_device *, enum nvkm_devidx); void nvkm_mc_disable(struct nvkm_device *, enum nvkm_devidx); +bool nvkm_mc_enabled(struct nvkm_device *, enum nvkm_devidx); void nvkm_mc_reset(struct nvkm_device *, enum nvkm_devidx); void nvkm_mc_intr(struct nvkm_device *, bool *handled); void nvkm_mc_intr_unarm(struct nvkm_device *); diff --git a/drm/nouveau/nvkm/subdev/mc/base.c b/drm/nouveau/nvkm/subdev/mc/base.c index 6b25e25f9eba..09f669ac6630 100644 --- a/drm/nouveau/nvkm/subdev/mc/base.c +++ b/drm/nouveau/nvkm/subdev/mc/base.c @@ -161,6 +161,16 @@ nvkm_mc_enable(struct nvkm_device *device, enum nvkm_devidx devidx) } } +bool +nvkm_mc_enabled(struct nvkm_device *device, enum nvkm_devidx devidx) +{ + u64 pmc_enable = nvkm_mc_reset_mask(device, false, devidx); + + return (pmc_enable != 0) && + ((nvkm_rd32(device, 0x000200) & pmc_enable) == pmc_enable); +} + + static int nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend) { -- git-series 0.8.10
Alexandre Courbot
2016-Dec-13 08:11 UTC
[Nouveau] [PATCH v2 3/15] core: add falcon library functions
Falcon processors are used in various places of GPU chips. Although there exist different versions of the falcon, and some variants exist, the base set of actions performed on them is the same, which results in lots of duplicated code. This patch consolidates the current nvkm_falcon structure and extends it with the following features: * Ability for an engine to obtain and later release a given falcon, * Abstractions for basic operations (IMEM/DMEM access, start, etc) * Abstractions for secure operations if a falcon is secure Abstractions make it easy to e.g. start a falcon, without having to care about its details. For instance, falcons in secure mode need to be started by writing to a different register. Right now the abstractions variants only cover secure vs. non-secure falcon, but more will come as e.g. SEC2 support is added. This is still a WIP as other functions previously done by engine/falcon.c need to be reimplemented. However this first step allows to keep things simple and to discuss basic design. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/include/nvkm/core/device.h | 1 +- drm/nouveau/include/nvkm/engine/falcon.h | 65 +++++++- drm/nouveau/nvkm/Kbuild | 1 +- drm/nouveau/nvkm/engine/device/base.c | 1 +- drm/nouveau/nvkm/falcon/Kbuild | 2 +- drm/nouveau/nvkm/falcon/base.c | 194 ++++++++++++++++++++- drm/nouveau/nvkm/falcon/v1.c | 235 ++++++++++++++++++++++++- 7 files changed, 499 insertions(+), 0 deletions(-) create mode 100644 drm/nouveau/nvkm/falcon/Kbuild create mode 100644 drm/nouveau/nvkm/falcon/base.c create mode 100644 drm/nouveau/nvkm/falcon/v1.c diff --git a/drm/nouveau/include/nvkm/core/device.h b/drm/nouveau/include/nvkm/core/device.h index d426b86e2712..7742c8e0f68c 100644 --- a/drm/nouveau/include/nvkm/core/device.h +++ b/drm/nouveau/include/nvkm/core/device.h @@ -85,6 +85,7 @@ struct nvkm_device { struct list_head head; struct mutex mutex; + struct mutex falcon_mutex; int refcount; void __iomem *pri; diff --git a/drm/nouveau/include/nvkm/engine/falcon.h b/drm/nouveau/include/nvkm/engine/falcon.h index e6baf039c269..dc5a9d7c22b0 100644 --- a/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drm/nouveau/include/nvkm/engine/falcon.h @@ -4,13 +4,25 @@ #include <core/engine.h> struct nvkm_fifo_chan; +enum nvkm_falcon_dmaidx { + FALCON_DMAIDX_UCODE = 0, + FALCON_DMAIDX_VIRT = 1, + FALCON_DMAIDX_PHYS_VID = 2, + FALCON_DMAIDX_PHYS_SYS_COH = 3, + FALCON_DMAIDX_PHYS_SYS_NCOH = 4, +}; + struct nvkm_falcon { const struct nvkm_falcon_func *func; + struct nvkm_subdev *owner; + const struct nvkm_subdev *user; + const char *name; struct nvkm_engine engine; u32 addr; u8 version; u8 secret; + bool debug; struct nvkm_memory *core; bool external; @@ -19,12 +31,14 @@ struct nvkm_falcon { u32 limit; u32 *data; u32 size; + u8 ports; } code; struct { u32 limit; u32 *data; u32 size; + u8 ports; } data; }; @@ -42,6 +56,57 @@ struct nvkm_falcon_func { } data; void (*init)(struct nvkm_falcon *); void (*intr)(struct nvkm_falcon *, struct nvkm_fifo_chan *); + void (*load_imem)(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool); + void (*load_dmem)(struct nvkm_falcon *, void *, u32, u32, u8); + void (*read_dmem)(struct nvkm_falcon *, u32, u32, u8, void *); + void (*bind_context)(struct nvkm_falcon *, struct nvkm_gpuobj *); + int (*wait_for_halt)(struct nvkm_falcon *, u32); + void (*set_start_addr)(struct nvkm_falcon *, u32 start_addr); + void (*start)(struct nvkm_falcon *); + int (*enable)(struct nvkm_falcon *falcon); + void (*disable)(struct nvkm_falcon *falcon); + struct nvkm_sclass sclass[]; }; + +extern const struct nvkm_falcon_func nvkm_falcon_v1_func; + +void +nvkm_falcon_ctor(struct nvkm_subdev *, const struct nvkm_falcon_func *, + const char *, u32, struct nvkm_falcon *); +int nvkm_falcon_get(struct nvkm_falcon *, const struct nvkm_subdev *); +void nvkm_falcon_put(struct nvkm_falcon *); + +static inline u32 +nvkm_falcon_rd32(struct nvkm_falcon *falcon, u32 addr) +{ + return nvkm_rd32(falcon->owner->device, falcon->addr + addr); +} + +static inline void +nvkm_falcon_wr32(struct nvkm_falcon *falcon, u32 addr, u32 data) +{ + nvkm_wr32(falcon->owner->device, falcon->addr + addr, data); +} + +static inline u32 +nvkm_falcon_mask(struct nvkm_falcon *falcon, u32 addr, u32 mask, u32 val) +{ + struct nvkm_device *device = falcon->owner->device; + + return nvkm_mask(device, falcon->addr + addr, mask, val); +} + +void nvkm_falcon_load_imem(struct nvkm_falcon *, void *, u32, u32, u16, u8, + bool); +void nvkm_falcon_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8); +void nvkm_falcon_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *); +void nvkm_falcon_bind_context(struct nvkm_falcon *, struct nvkm_gpuobj *); +void nvkm_falcon_set_start_addr(struct nvkm_falcon *, u32); +void nvkm_falcon_start(struct nvkm_falcon *); +int nvkm_falcon_wait_for_halt(struct nvkm_falcon *, u32); +int nvkm_falcon_enable(struct nvkm_falcon *); +void nvkm_falcon_disable(struct nvkm_falcon *); +int nvkm_falcon_reset(struct nvkm_falcon *); + #endif diff --git a/drm/nouveau/nvkm/Kbuild b/drm/nouveau/nvkm/Kbuild index 2832147b676c..e664378f6eda 100644 --- a/drm/nouveau/nvkm/Kbuild +++ b/drm/nouveau/nvkm/Kbuild @@ -1,3 +1,4 @@ include $(src)/nvkm/core/Kbuild +include $(src)/nvkm/falcon/Kbuild include $(src)/nvkm/subdev/Kbuild include $(src)/nvkm/engine/Kbuild diff --git a/drm/nouveau/nvkm/engine/device/base.c b/drm/nouveau/nvkm/engine/device/base.c index cceda959b47c..e3ddd3fc3b17 100644 --- a/drm/nouveau/nvkm/engine/device/base.c +++ b/drm/nouveau/nvkm/engine/device/base.c @@ -2745,6 +2745,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, } mutex_init(&device->mutex); + mutex_init(&device->falcon_mutex); for (i = 0; i < NVKM_SUBDEV_NR; i++) { #define _(s,m) case s: \ diff --git a/drm/nouveau/nvkm/falcon/Kbuild b/drm/nouveau/nvkm/falcon/Kbuild new file mode 100644 index 000000000000..584863db9bfc --- /dev/null +++ b/drm/nouveau/nvkm/falcon/Kbuild @@ -0,0 +1,2 @@ +nvkm-y += nvkm/falcon/base.o +nvkm-y += nvkm/falcon/v1.o diff --git a/drm/nouveau/nvkm/falcon/base.c b/drm/nouveau/nvkm/falcon/base.c new file mode 100644 index 000000000000..9323115541be --- /dev/null +++ b/drm/nouveau/nvkm/falcon/base.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2016, 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 <engine/falcon.h> +#include <subdev/mc.h> + +void +nvkm_falcon_ctor(struct nvkm_subdev *subdev, + const struct nvkm_falcon_func *func, const char *name, + u32 addr, struct nvkm_falcon *falcon) +{ + u32 reg; + + falcon->owner = subdev; + falcon->func = func; + falcon->name = name; + falcon->addr = addr; + + /* Set self as user and get falcon characteristics */ + nvkm_falcon_get(falcon, subdev); + + reg = nvkm_falcon_rd32(falcon, 0x12c); + falcon->version = reg & 0xf; + falcon->secret = (reg >> 4) & 0x3; + falcon->code.ports = (reg >> 8) & 0xf; + falcon->data.ports = (reg >> 12) & 0xf; + + reg = nvkm_falcon_rd32(falcon, 0x108); + falcon->code.limit = (reg & 0x1ff) << 8; + falcon->data.limit = (reg & 0x3fe00) >> 1; + + reg = nvkm_falcon_rd32(falcon, 0xc08); + falcon->debug = (reg >> 20) & 0x1; + + nvkm_falcon_put(falcon); +} + +int +nvkm_falcon_get(struct nvkm_falcon *falcon, const struct nvkm_subdev *subdev) +{ + struct nvkm_device *device = falcon->owner->device;; + + mutex_lock(&device->falcon_mutex); + + if (falcon->user) { + nvkm_error(subdev, "%s falcon already acquired by %s!\n", + falcon->name, nvkm_subdev_name[falcon->user->index]); + mutex_unlock(&device->falcon_mutex); + return -EBUSY; + } + + falcon->user = subdev; + + mutex_unlock(&device->falcon_mutex); + + nvkm_debug(subdev, "acquired %s falcon\n", falcon->name); + + return 0; +} + +void +nvkm_falcon_put(struct nvkm_falcon *falcon) +{ + struct nvkm_device *device = falcon->owner->device; + const struct nvkm_subdev *user = falcon->user; + const char *name = falcon->name; + + mutex_lock(&device->falcon_mutex); + + WARN(!user, "trying to release non-acquired %s falcon", name); + + if (user) + nvkm_debug(user, "released %s falcon\n", name); + + falcon->user = NULL; + + mutex_unlock(&device->falcon_mutex); +} + +void +nvkm_falcon_load_imem(struct nvkm_falcon *falcon, void *data, u32 start, + u32 size, u16 tag, u8 port, bool secure) +{ + if (secure && !falcon->secret) { + nvkm_warn(falcon->user, + "writing with secure tag on a non-secure falcon!\n"); + return; + } + + falcon->func->load_imem(falcon, data, start, size, tag, port, + secure); +} + +void +nvkm_falcon_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start, + u32 size, u8 port) +{ + falcon->func->load_dmem(falcon, data, start, size, port); +} + +void +nvkm_falcon_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, u8 port, + void *data) +{ + falcon->func->read_dmem(falcon, start, size, port, data); +} + +void +nvkm_falcon_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *inst) +{ + if (!falcon->func->bind_context) { + nvkm_error(falcon->user, + "Context binding not supported on this falcon!\n"); + return; + } + + falcon->func->bind_context(falcon, inst); +} + +void +nvkm_falcon_set_start_addr(struct nvkm_falcon *falcon, u32 start_addr) +{ + falcon->func->set_start_addr(falcon, start_addr); +} + +void +nvkm_falcon_start(struct nvkm_falcon *falcon) +{ + falcon->func->start(falcon); +} + +int +nvkm_falcon_enable(struct nvkm_falcon *falcon) +{ + struct nvkm_device *device = falcon->owner->device; + enum nvkm_devidx id = falcon->owner->index; + int ret; + + nvkm_mc_enable(device, id); + ret = falcon->func->enable(falcon); + if (ret) { + nvkm_mc_disable(device, id); + return ret; + } + + return 0; +} + +void +nvkm_falcon_disable(struct nvkm_falcon *falcon) +{ + struct nvkm_device *device = falcon->owner->device; + enum nvkm_devidx id = falcon->owner->index; + + /* already disabled, return or wait_idle will timeout */ + if (!nvkm_mc_enabled(device, id)) + return; + + falcon->func->disable(falcon); + + nvkm_mc_disable(device, id); +} + +int +nvkm_falcon_reset(struct nvkm_falcon *falcon) +{ + nvkm_falcon_disable(falcon); + return nvkm_falcon_enable(falcon); +} + +int +nvkm_falcon_wait_for_halt(struct nvkm_falcon *falcon, u32 ms) +{ + return falcon->func->wait_for_halt(falcon, ms); +} diff --git a/drm/nouveau/nvkm/falcon/v1.c b/drm/nouveau/nvkm/falcon/v1.c new file mode 100644 index 000000000000..2e571402cf99 --- /dev/null +++ b/drm/nouveau/nvkm/falcon/v1.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2016, 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 <engine/falcon.h> +#include <core/gpuobj.h> +#include <core/memory.h> +#include <subdev/timer.h> + +static void +nvkm_falcon_v1_load_imem(struct nvkm_falcon *falcon, void *data, u32 start, + u32 size, u16 tag, u8 port, bool secure) +{ + u8 rem = size % 4; + u32 reg; + int i; + + size -= rem; + + reg = start | BIT(24) | (secure ? BIT(28) : 0); + nvkm_falcon_wr32(falcon, 0x180 + (port * 16), reg); + for (i = 0; i < size / 4; i++) { + /* write new tag every 256B */ + if ((i & 0x3f) == 0) + nvkm_falcon_wr32(falcon, 0x188, tag++); + nvkm_falcon_wr32(falcon, 0x184, ((u32 *)data)[i]); + } + + /* + * If size is not a multiple of 4, mask the last work to ensure garbage + * does not get written + */ + if (rem) { + u32 extra = ((u32 *)data)[i]; + + /* write new tag every 256B */ + if ((i & 0x3f) == 0) + nvkm_falcon_wr32(falcon, 0x188, tag++); + nvkm_falcon_wr32(falcon, 0x184, extra & (BIT(rem * 8) - 1)); + ++i; + } + + /* code must be padded to 0x40 words */ + for (; i & 0x3f; i++) + nvkm_falcon_wr32(falcon, 0x184, 0); +} + +static void +nvkm_falcon_v1_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start, + u32 size, u8 port) +{ + u8 rem = size % 4; + int i; + + size -= rem; + + nvkm_falcon_wr32(falcon, 0x1c0 + (port * 16), start | (0x1 << 24)); + for (i = 0; i < size / 4; i++) + nvkm_falcon_wr32(falcon, 0x1c4, ((u32 *)data)[i]); + + /* + * If size is not a multiple of 4, mask the last work to ensure garbage + * does not get read + */ + if (rem) { + u32 extra = ((u32 *)data)[i]; + + nvkm_falcon_wr32(falcon, 0x1c4, extra & (BIT(rem * 8) - 1)); + } +} + +static void +nvkm_falcon_v1_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, + u8 port, void *data) +{ + u8 rem = size % 4; + int i; + + size -= rem; + + nvkm_falcon_wr32(falcon, 0x1c0 + (port * 16), start | (0x1 << 25)); + for (i = 0; i < size / 4; i++) + ((u32 *)data)[i] = nvkm_falcon_rd32(falcon, 0x1c4); + + /* + * If size is not a multiple of 4, mask the last work to ensure garbage + * does not get read + */ + if (rem) { + u32 extra = nvkm_falcon_rd32(falcon, 0x1c4); + + for (i = size; i < size + rem; i++) { + ((u8 *)data)[i] = (u8)(extra & 0xff); + extra >>= 8; + } + } +} + +static void +nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *ctx) +{ + u32 inst_loc; + + /* disable instance block binding */ + if (ctx == NULL) { + nvkm_falcon_wr32(falcon, 0x10c, 0x0); + return; + } + + nvkm_falcon_wr32(falcon, 0x10c, 0x1); + + /* setup apertures - virtual */ + nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_UCODE, 0x4); + nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_VIRT, 0x0); + /* setup apertures - physical */ + nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_PHYS_VID, 0x4); + nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_PHYS_SYS_COH, 0x5); + nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_PHYS_SYS_NCOH, 0x6); + + /* Set context */ + if (nvkm_memory_target(ctx->memory) == NVKM_MEM_TARGET_VRAM) + inst_loc = 0x0; /* FB */ + else + inst_loc = 0x3; /* Non-coherent sysmem */ + + /* Enable context */ + nvkm_falcon_mask(falcon, 0x048, 0x1, 0x1); + nvkm_falcon_wr32(falcon, 0x480, + ((ctx->addr >> 12) & 0xfffffff) | + (inst_loc << 28) | (1 << 30)); +} + +static void +nvkm_falcon_v1_set_start_addr(struct nvkm_falcon *falcon, u32 start_addr) +{ + nvkm_falcon_wr32(falcon, 0x104, start_addr); +} + +static void +nvkm_falcon_v1_start(struct nvkm_falcon *falcon) +{ + u32 reg = nvkm_falcon_rd32(falcon, 0x100); + + if (reg & BIT(6)) + nvkm_falcon_wr32(falcon, 0x130, 0x2); + else + nvkm_falcon_wr32(falcon, 0x100, 0x2); +} + +static int +nvkm_falcon_v1_wait_for_halt(struct nvkm_falcon *falcon, u32 ms) +{ + struct nvkm_device *device = falcon->owner->device; + int ret; + + ret = nvkm_wait_msec(device, ms, falcon->addr + 0x100, 0x10, 0x10); + if (ret < 0) + return ret; + + return 0; +} + +static int +falcon_v1_wait_idle(struct nvkm_falcon *falcon) +{ + struct nvkm_device *device = falcon->owner->device; + int ret; + + ret = nvkm_wait_msec(device, 10, falcon->addr + 0x04c, 0xffff, 0x0); + if (ret < 0) + return ret; + + return 0; +} + +static int +nvkm_falcon_v1_enable(struct nvkm_falcon *falcon) +{ + struct nvkm_device *device = falcon->owner->device; + int ret; + + ret = nvkm_wait_msec(device, 10, falcon->addr + 0x10c, 0x6, 0x0); + if (ret < 0) { + nvkm_error(falcon->user, "Falcon mem scrubbing timeout\n"); + return ret; + } + + ret = falcon_v1_wait_idle(falcon); + if (ret) + return ret; + + /* enable IRQs */ + nvkm_falcon_wr32(falcon, 0x010, 0xff); + + return 0; +} + +static void +nvkm_falcon_v1_disable(struct nvkm_falcon *falcon) +{ + /* disable IRQs and wait for any previous code to complete */ + nvkm_falcon_wr32(falcon, 0x014, 0xff); + falcon_v1_wait_idle(falcon); +} + +const struct nvkm_falcon_func +nvkm_falcon_v1_func = { + .load_imem = nvkm_falcon_v1_load_imem, + .load_dmem = nvkm_falcon_v1_load_dmem, + .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_context = nvkm_falcon_v1_bind_context, + .start = nvkm_falcon_v1_start, + .wait_for_halt = nvkm_falcon_v1_wait_for_halt, + .enable = nvkm_falcon_v1_enable, + .disable = nvkm_falcon_v1_disable, + .set_start_addr = nvkm_falcon_v1_set_start_addr, +}; -- git-series 0.8.10
Alexandre Courbot
2016-Dec-13 08:11 UTC
[Nouveau] [PATCH v2 4/15] pmu: instanciate the falcon in PMU device
Have an instance of nvkm_falcon in the PMU structure, ready to be used by other subdevs (i.e. secboot). Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/include/nvkm/subdev/pmu.h | 2 ++ drm/nouveau/nvkm/subdev/pmu/base.c | 4 ++++ 2 files changed, 6 insertions(+), 0 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/pmu.h b/drm/nouveau/include/nvkm/subdev/pmu.h index f37538eb1fe5..342f9a2f32ef 100644 --- a/drm/nouveau/include/nvkm/subdev/pmu.h +++ b/drm/nouveau/include/nvkm/subdev/pmu.h @@ -1,10 +1,12 @@ #ifndef __NVKM_PMU_H__ #define __NVKM_PMU_H__ #include <core/subdev.h> +#include <engine/falcon.h> struct nvkm_pmu { const struct nvkm_pmu_func *func; struct nvkm_subdev subdev; + struct nvkm_falcon falcon; struct { u32 base; diff --git a/drm/nouveau/nvkm/subdev/pmu/base.c b/drm/nouveau/nvkm/subdev/pmu/base.c index e611ce80f8ef..1e645eec1951 100644 --- a/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drm/nouveau/nvkm/subdev/pmu/base.c @@ -139,5 +139,9 @@ nvkm_pmu_new_(const struct nvkm_pmu_func *func, struct nvkm_device *device, pmu->func = func; INIT_WORK(&pmu->recv.work, nvkm_pmu_recv); init_waitqueue_head(&pmu->recv.wait); + + nvkm_falcon_ctor(&pmu->subdev, &nvkm_falcon_v1_func, "PMU", 0x10a000, + &pmu->falcon); + return 0; } -- git-series 0.8.10
Alexandre Courbot
2016-Dec-13 08:11 UTC
[Nouveau] [PATCH v2 5/15] pmu: add nvkm_pmu_ctor() function
Add a PMU constructor so implementations that extend the nvkm_pmu structure can have all base members properly initialized. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/nvkm/subdev/pmu/base.c | 21 +++++++++++++++------ drm/nouveau/nvkm/subdev/pmu/priv.h | 2 ++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/drm/nouveau/nvkm/subdev/pmu/base.c b/drm/nouveau/nvkm/subdev/pmu/base.c index 1e645eec1951..6db1ee45e610 100644 --- a/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drm/nouveau/nvkm/subdev/pmu/base.c @@ -128,13 +128,10 @@ nvkm_pmu = { .intr = nvkm_pmu_intr, }; -int -nvkm_pmu_new_(const struct nvkm_pmu_func *func, struct nvkm_device *device, - int index, struct nvkm_pmu **ppmu) +void +nvkm_pmu_ctor(const struct nvkm_pmu_func *func, struct nvkm_device *device, + int index, struct nvkm_pmu *pmu) { - struct nvkm_pmu *pmu; - if (!(pmu = *ppmu = kzalloc(sizeof(*pmu), GFP_KERNEL))) - return -ENOMEM; nvkm_subdev_ctor(&nvkm_pmu, device, index, &pmu->subdev); pmu->func = func; INIT_WORK(&pmu->recv.work, nvkm_pmu_recv); @@ -143,5 +140,17 @@ nvkm_pmu_new_(const struct nvkm_pmu_func *func, struct nvkm_device *device, nvkm_falcon_ctor(&pmu->subdev, &nvkm_falcon_v1_func, "PMU", 0x10a000, &pmu->falcon); +} + +int +nvkm_pmu_new_(const struct nvkm_pmu_func *func, struct nvkm_device *device, + int index, struct nvkm_pmu **ppmu) +{ + struct nvkm_pmu *pmu; + if (!(pmu = *ppmu = kzalloc(sizeof(*pmu), GFP_KERNEL))) + return -ENOMEM; + + nvkm_pmu_ctor(func, device, index, *ppmu); + return 0; } diff --git a/drm/nouveau/nvkm/subdev/pmu/priv.h b/drm/nouveau/nvkm/subdev/pmu/priv.h index 2e2179a4ad17..1eda37b787f7 100644 --- a/drm/nouveau/nvkm/subdev/pmu/priv.h +++ b/drm/nouveau/nvkm/subdev/pmu/priv.h @@ -4,6 +4,8 @@ #include <subdev/pmu.h> #include <subdev/pmu/fuc/os.h> +void nvkm_pmu_ctor(const struct nvkm_pmu_func *, struct nvkm_device *, + int index, struct nvkm_pmu *); int nvkm_pmu_new_(const struct nvkm_pmu_func *, struct nvkm_device *, int index, struct nvkm_pmu **); -- git-series 0.8.10
Alexandre Courbot
2016-Dec-13 08:11 UTC
[Nouveau] [PATCH v2 6/15] pmu/gk20a: use nvkm_pmu_ctor()
Use the PMU constructor so that all base members (in particular the falcon instance) are initialized properly. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/nvkm/subdev/pmu/gk20a.c | 35 ++++++++++++------------------ 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/drm/nouveau/nvkm/subdev/pmu/gk20a.c b/drm/nouveau/nvkm/subdev/pmu/gk20a.c index f996d90c9f0d..e897bbde44f2 100644 --- a/drm/nouveau/nvkm/subdev/pmu/gk20a.c +++ b/drm/nouveau/nvkm/subdev/pmu/gk20a.c @@ -19,7 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#define gk20a_pmu(p) container_of((p), struct gk20a_pmu, base.subdev) +#define gk20a_pmu(p) container_of((p), struct gk20a_pmu, base) #include "priv.h" #include <subdev/clk.h> @@ -166,32 +166,25 @@ resched: nvkm_timer_alarm(tmr, 100000000, alarm); } -static int -gk20a_pmu_fini(struct nvkm_subdev *subdev, bool suspend) -{ - struct gk20a_pmu *pmu = gk20a_pmu(subdev); - nvkm_timer_alarm_cancel(subdev->device->timer, &pmu->alarm); - return 0; -} - -static void * -gk20a_pmu_dtor(struct nvkm_subdev *subdev) +static void +gk20a_pmu_fini(struct nvkm_pmu *pmu) { - return gk20a_pmu(subdev); + struct gk20a_pmu *gpmu = gk20a_pmu(pmu); + nvkm_timer_alarm_cancel(pmu->subdev.device->timer, &gpmu->alarm); } static int -gk20a_pmu_init(struct nvkm_subdev *subdev) +gk20a_pmu_init(struct nvkm_pmu *pmu) { - struct gk20a_pmu *pmu = gk20a_pmu(subdev); - struct nvkm_device *device = pmu->base.subdev.device; + struct gk20a_pmu *gpmu = gk20a_pmu(pmu); + struct nvkm_device *device = pmu->subdev.device; /* init pwr perf counter */ nvkm_wr32(device, 0x10a504 + (BUSY_SLOT * 0x10), 0x00200001); nvkm_wr32(device, 0x10a50c + (BUSY_SLOT * 0x10), 0x00000002); nvkm_wr32(device, 0x10a50c + (CLK_SLOT * 0x10), 0x00000003); - nvkm_timer_alarm(device->timer, 2000000000, &pmu->alarm); + nvkm_timer_alarm(device->timer, 2000000000, &gpmu->alarm); return 0; } @@ -202,26 +195,26 @@ gk20a_dvfs_data= { .p_smooth = 1, }; -static const struct nvkm_subdev_func +static const struct nvkm_pmu_func gk20a_pmu = { .init = gk20a_pmu_init, .fini = gk20a_pmu_fini, - .dtor = gk20a_pmu_dtor, + .reset = gt215_pmu_reset, }; int gk20a_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { - static const struct nvkm_pmu_func func = {}; struct gk20a_pmu *pmu; if (!(pmu = kzalloc(sizeof(*pmu), GFP_KERNEL))) return -ENOMEM; - pmu->base.func = &func; *ppmu = &pmu->base; - nvkm_subdev_ctor(&gk20a_pmu, device, index, &pmu->base.subdev); + nvkm_pmu_ctor(&gk20a_pmu, device, index, &pmu->base); + pmu->data = &gk20a_dvfs_data; nvkm_alarm_init(&pmu->alarm, gk20a_pmu_dvfs_work); + return 0; } -- git-series 0.8.10
Alexandre Courbot
2016-Dec-13 08:11 UTC
[Nouveau] [PATCH v2 7/15] pmu/gk20a: simplify code a bit
Some functions always succeed - change their return type to void and remove the error-handling code in their caller. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/nvkm/subdev/pmu/gk20a.c | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/drm/nouveau/nvkm/subdev/pmu/gk20a.c b/drm/nouveau/nvkm/subdev/pmu/gk20a.c index e897bbde44f2..4a0f80983564 100644 --- a/drm/nouveau/nvkm/subdev/pmu/gk20a.c +++ b/drm/nouveau/nvkm/subdev/pmu/gk20a.c @@ -43,9 +43,8 @@ struct gk20a_pmu { }; struct gk20a_pmu_dvfs_dev_status { - unsigned long total; - unsigned long busy; - int cur_state; + u32 total; + u32 busy; }; static int @@ -56,13 +55,12 @@ gk20a_pmu_dvfs_target(struct gk20a_pmu *pmu, int *state) return nvkm_clk_astate(clk, *state, 0, false); } -static int +static void gk20a_pmu_dvfs_get_cur_state(struct gk20a_pmu *pmu, int *state) { struct nvkm_clk *clk = pmu->base.subdev.device->clk; *state = clk->pstate; - return 0; } static int @@ -90,20 +88,16 @@ gk20a_pmu_dvfs_get_target_state(struct gk20a_pmu *pmu, *state = level; - if (level == cur_level) - return 0; - else - return 1; + return (level != cur_level); } -static int +static void gk20a_pmu_dvfs_get_dev_status(struct gk20a_pmu *pmu, struct gk20a_pmu_dvfs_dev_status *status) { struct nvkm_device *device = pmu->base.subdev.device; status->busy = nvkm_rd32(device, 0x10a508 + (BUSY_SLOT * 0x10)); status->total= nvkm_rd32(device, 0x10a508 + (CLK_SLOT * 0x10)); - return 0; } static void @@ -127,7 +121,7 @@ gk20a_pmu_dvfs_work(struct nvkm_alarm *alarm) struct nvkm_timer *tmr = device->timer; struct nvkm_volt *volt = device->volt; u32 utilization = 0; - int state, ret; + int state; /* * The PMU is initialized before CLK and VOLT, so we have to make sure the @@ -136,11 +130,7 @@ gk20a_pmu_dvfs_work(struct nvkm_alarm *alarm) if (!clk || !volt) goto resched; - ret = gk20a_pmu_dvfs_get_dev_status(pmu, &status); - if (ret) { - nvkm_warn(subdev, "failed to get device status\n"); - goto resched; - } + gk20a_pmu_dvfs_get_dev_status(pmu, &status); if (status.total) utilization = div_u64((u64)status.busy * 100, status.total); @@ -150,11 +140,7 @@ gk20a_pmu_dvfs_work(struct nvkm_alarm *alarm) nvkm_trace(subdev, "utilization = %d %%, avg_load = %d %%\n", utilization, data->avg_load); - ret = gk20a_pmu_dvfs_get_cur_state(pmu, &state); - if (ret) { - nvkm_warn(subdev, "failed to get current state\n"); - goto resched; - } + gk20a_pmu_dvfs_get_cur_state(pmu, &state); if (gk20a_pmu_dvfs_get_target_state(pmu, &state, data->avg_load)) { nvkm_trace(subdev, "set new state to %d\n", state); -- git-series 0.8.10
Alexandre Courbot
2016-Dec-13 08:11 UTC
[Nouveau] [PATCH v2 8/15] pmu/gk20a: use falcon library functions
Use the falcon library functions where relevant. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/nvkm/subdev/pmu/gk20a.c | 33 +++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/drm/nouveau/nvkm/subdev/pmu/gk20a.c b/drm/nouveau/nvkm/subdev/pmu/gk20a.c index 4a0f80983564..b5b880d85770 100644 --- a/drm/nouveau/nvkm/subdev/pmu/gk20a.c +++ b/drm/nouveau/nvkm/subdev/pmu/gk20a.c @@ -95,17 +95,19 @@ static void gk20a_pmu_dvfs_get_dev_status(struct gk20a_pmu *pmu, struct gk20a_pmu_dvfs_dev_status *status) { - struct nvkm_device *device = pmu->base.subdev.device; - status->busy = nvkm_rd32(device, 0x10a508 + (BUSY_SLOT * 0x10)); - status->total= nvkm_rd32(device, 0x10a508 + (CLK_SLOT * 0x10)); + struct nvkm_falcon *falcon = &pmu->base.falcon; + + status->busy = nvkm_falcon_rd32(falcon, 0x508 + (BUSY_SLOT * 0x10)); + status->total= nvkm_falcon_rd32(falcon, 0x508 + (CLK_SLOT * 0x10)); } static void gk20a_pmu_dvfs_reset_dev_status(struct gk20a_pmu *pmu) { - struct nvkm_device *device = pmu->base.subdev.device; - nvkm_wr32(device, 0x10a508 + (BUSY_SLOT * 0x10), 0x80000000); - nvkm_wr32(device, 0x10a508 + (CLK_SLOT * 0x10), 0x80000000); + struct nvkm_falcon *falcon = &pmu->base.falcon; + + nvkm_falcon_wr32(falcon, 0x508 + (BUSY_SLOT * 0x10), 0x80000000); + nvkm_falcon_wr32(falcon, 0x508 + (CLK_SLOT * 0x10), 0x80000000); } static void @@ -157,18 +159,31 @@ gk20a_pmu_fini(struct nvkm_pmu *pmu) { struct gk20a_pmu *gpmu = gk20a_pmu(pmu); nvkm_timer_alarm_cancel(pmu->subdev.device->timer, &gpmu->alarm); + + /* release falcon if we have acquired it, i.e. if init() has been run */ + if (pmu->falcon.user == &pmu->subdev) + nvkm_falcon_put(&pmu->falcon); } static int gk20a_pmu_init(struct nvkm_pmu *pmu) { struct gk20a_pmu *gpmu = gk20a_pmu(pmu); + struct nvkm_falcon *falcon = &pmu->falcon; + struct nvkm_subdev *subdev = &pmu->subdev; struct nvkm_device *device = pmu->subdev.device; + int ret; + + ret = nvkm_falcon_get(falcon, subdev); + if (ret) { + nvkm_error(subdev, "cannot acquire %s falcon!\n", falcon->name); + return ret; + } /* init pwr perf counter */ - nvkm_wr32(device, 0x10a504 + (BUSY_SLOT * 0x10), 0x00200001); - nvkm_wr32(device, 0x10a50c + (BUSY_SLOT * 0x10), 0x00000002); - nvkm_wr32(device, 0x10a50c + (CLK_SLOT * 0x10), 0x00000003); + nvkm_falcon_wr32(falcon, 0x504 + (BUSY_SLOT * 0x10), 0x00200001); + nvkm_falcon_wr32(falcon, 0x50c + (BUSY_SLOT * 0x10), 0x00000002); + nvkm_falcon_wr32(falcon, 0x50c + (CLK_SLOT * 0x10), 0x00000003); nvkm_timer_alarm(device->timer, 2000000000, &gpmu->alarm); return 0; -- git-series 0.8.10
Alexandre Courbot
2016-Dec-13 08:11 UTC
[Nouveau] [PATCH v2 9/15] gm20b: add dummy PMU device
Add a dummy PMU device so the PMU falcon is instanciated and can be used by secure boot. We could reuse gk20a's implementation here, but it would fight with secboot over PMU falcon's ownership and secboot will reset the PMU, preventing it from operating afterwards. Proper handout between secboot and pmu is coming along with the actual gm20b PMU implementation, so use this as a temporary solution. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/include/nvkm/subdev/pmu.h | 1 +- drm/nouveau/nvkm/engine/device/base.c | 1 +- drm/nouveau/nvkm/subdev/pmu/Kbuild | 1 +- drm/nouveau/nvkm/subdev/pmu/gm20b.c | 34 ++++++++++++++++++++++++++++- 4 files changed, 37 insertions(+), 0 deletions(-) create mode 100644 drm/nouveau/nvkm/subdev/pmu/gm20b.c diff --git a/drm/nouveau/include/nvkm/subdev/pmu.h b/drm/nouveau/include/nvkm/subdev/pmu.h index 342f9a2f32ef..55da79d0efee 100644 --- a/drm/nouveau/include/nvkm/subdev/pmu.h +++ b/drm/nouveau/include/nvkm/subdev/pmu.h @@ -37,6 +37,7 @@ int gk110_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); int gk208_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); int gk20a_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); int gm107_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); +int gm20b_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); int gp100_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); int gp102_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); diff --git a/drm/nouveau/nvkm/engine/device/base.c b/drm/nouveau/nvkm/engine/device/base.c index e3ddd3fc3b17..49e894203157 100644 --- a/drm/nouveau/nvkm/engine/device/base.c +++ b/drm/nouveau/nvkm/engine/device/base.c @@ -2138,6 +2138,7 @@ nv12b_chipset = { .ltc = gm200_ltc_new, .mc = gk20a_mc_new, .mmu = gf100_mmu_new, + .pmu = gm20b_pmu_new, .secboot = gm20b_secboot_new, .timer = gk20a_timer_new, .top = gk104_top_new, diff --git a/drm/nouveau/nvkm/subdev/pmu/Kbuild b/drm/nouveau/nvkm/subdev/pmu/Kbuild index 51fb4bf94a44..ca57c1e491b0 100644 --- a/drm/nouveau/nvkm/subdev/pmu/Kbuild +++ b/drm/nouveau/nvkm/subdev/pmu/Kbuild @@ -8,5 +8,6 @@ nvkm-y += nvkm/subdev/pmu/gk110.o nvkm-y += nvkm/subdev/pmu/gk208.o nvkm-y += nvkm/subdev/pmu/gk20a.o nvkm-y += nvkm/subdev/pmu/gm107.o +nvkm-y += nvkm/subdev/pmu/gm20b.o nvkm-y += nvkm/subdev/pmu/gp100.o nvkm-y += nvkm/subdev/pmu/gp102.o diff --git a/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drm/nouveau/nvkm/subdev/pmu/gm20b.c new file mode 100644 index 000000000000..0b8a1cc4a0ee --- /dev/null +++ b/drm/nouveau/nvkm/subdev/pmu/gm20b.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, 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 "priv.h" + +static const struct nvkm_pmu_func +gm20b_pmu = { + .reset = gt215_pmu_reset, +}; + +int +gm20b_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) +{ + return nvkm_pmu_new_(&gm20b_pmu, device, index, ppmu); +} -- git-series 0.8.10
Alexandre Courbot
2016-Dec-13 08:11 UTC
[Nouveau] [PATCH v2 10/15] secboot: fix functions definitions
These functions should use the nvkm_secboot_falcon enum. Fix this. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/include/nvkm/subdev/secboot.h | 6 +++--- drm/nouveau/nvkm/subdev/secboot/base.c | 4 ++-- drm/nouveau/nvkm/subdev/secboot/priv.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/secboot.h b/drm/nouveau/include/nvkm/subdev/secboot.h index b04c38c07761..781586b8cc34 100644 --- a/drm/nouveau/include/nvkm/subdev/secboot.h +++ b/drm/nouveau/include/nvkm/subdev/secboot.h @@ -26,7 +26,7 @@ #include <core/subdev.h> enum nvkm_secboot_falcon { - NVKM_SECBOOT_FALCON_PMU = 0, + NVKM_SECBOOT_FALCON_PMU = 0, NVKM_SECBOOT_FALCON_RESERVED = 1, NVKM_SECBOOT_FALCON_FECS = 2, NVKM_SECBOOT_FALCON_GPCCS = 3, @@ -49,8 +49,8 @@ struct nvkm_secboot { #define nvkm_secboot(p) container_of((p), struct nvkm_secboot, subdev) bool nvkm_secboot_is_managed(struct nvkm_secboot *, enum nvkm_secboot_falcon); -int nvkm_secboot_reset(struct nvkm_secboot *, u32 falcon); -int nvkm_secboot_start(struct nvkm_secboot *, u32 falcon); +int nvkm_secboot_reset(struct nvkm_secboot *, enum nvkm_secboot_falcon); +int nvkm_secboot_start(struct nvkm_secboot *, enum nvkm_secboot_falcon); int gm200_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); int gm20b_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); diff --git a/drm/nouveau/nvkm/subdev/secboot/base.c b/drm/nouveau/nvkm/subdev/secboot/base.c index 314be2192b7d..6ee140ee4415 100644 --- a/drm/nouveau/nvkm/subdev/secboot/base.c +++ b/drm/nouveau/nvkm/subdev/secboot/base.c @@ -160,7 +160,7 @@ nvkm_secboot_falcon_run(struct nvkm_secboot *sb) * nvkm_secboot_reset() - reset specified falcon */ int -nvkm_secboot_reset(struct nvkm_secboot *sb, u32 falcon) +nvkm_secboot_reset(struct nvkm_secboot *sb, enum nvkm_secboot_falcon falcon) { /* Unmanaged falcon? */ if (!(BIT(falcon) & sb->func->managed_falcons)) { @@ -175,7 +175,7 @@ nvkm_secboot_reset(struct nvkm_secboot *sb, u32 falcon) * nvkm_secboot_start() - start specified falcon */ int -nvkm_secboot_start(struct nvkm_secboot *sb, u32 falcon) +nvkm_secboot_start(struct nvkm_secboot *sb, enum nvkm_secboot_falcon falcon) { /* Unmanaged falcon? */ if (!(BIT(falcon) & sb->func->managed_falcons)) { diff --git a/drm/nouveau/nvkm/subdev/secboot/priv.h b/drm/nouveau/nvkm/subdev/secboot/priv.h index a9a8a0e1017e..2ad6d622e7e5 100644 --- a/drm/nouveau/nvkm/subdev/secboot/priv.h +++ b/drm/nouveau/nvkm/subdev/secboot/priv.h @@ -226,8 +226,8 @@ struct gm200_secboot_func { int gm200_secboot_init(struct nvkm_secboot *); void *gm200_secboot_dtor(struct nvkm_secboot *); -int gm200_secboot_reset(struct nvkm_secboot *, u32); -int gm200_secboot_start(struct nvkm_secboot *, u32); +int gm200_secboot_reset(struct nvkm_secboot *, enum nvkm_secboot_falcon); +int gm200_secboot_start(struct nvkm_secboot *, enum nvkm_secboot_falcon); int gm20x_secboot_prepare_blobs(struct gm200_secboot *); -- git-series 0.8.10
Alexandre Courbot
2016-Dec-13 08:11 UTC
[Nouveau] [PATCH v2 11/15] secboot: use falcon library
Use the falcon library functions in secure boot. This removes a lot of code and makes the secure boot flow easier to understand as no register is directly accessed. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/include/nvkm/subdev/secboot.h | 4 +- drm/nouveau/nvkm/subdev/secboot/base.c | 146 +---------------------- drm/nouveau/nvkm/subdev/secboot/gm200.c | 125 ++++++-------------- drm/nouveau/nvkm/subdev/secboot/priv.h | 2 +- 4 files changed, 51 insertions(+), 226 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/secboot.h b/drm/nouveau/include/nvkm/subdev/secboot.h index 781586b8cc34..2a2f651ccceb 100644 --- a/drm/nouveau/include/nvkm/subdev/secboot.h +++ b/drm/nouveau/include/nvkm/subdev/secboot.h @@ -42,9 +42,7 @@ enum nvkm_secboot_falcon { struct nvkm_secboot { const struct nvkm_secboot_func *func; struct nvkm_subdev subdev; - - enum nvkm_devidx devidx; - u32 base; + struct nvkm_falcon *boot_falcon; }; #define nvkm_secboot(p) container_of((p), struct nvkm_secboot, subdev) diff --git a/drm/nouveau/nvkm/subdev/secboot/base.c b/drm/nouveau/nvkm/subdev/secboot/base.c index 6ee140ee4415..633dee87ac98 100644 --- a/drm/nouveau/nvkm/subdev/secboot/base.c +++ b/drm/nouveau/nvkm/subdev/secboot/base.c @@ -23,6 +23,7 @@ #include <subdev/mc.h> #include <subdev/timer.h> +#include <subdev/pmu.h> static const char * managed_falcons_names[] = { @@ -32,130 +33,6 @@ managed_falcons_names[] = { [NVKM_SECBOOT_FALCON_GPCCS] = "GPCCS", [NVKM_SECBOOT_FALCON_END] = "<invalid>", }; - -/* - * Helper falcon functions - */ - -static int -falcon_clear_halt_interrupt(struct nvkm_device *device, u32 base) -{ - int ret; - - /* clear halt interrupt */ - nvkm_mask(device, base + 0x004, 0x10, 0x10); - /* wait until halt interrupt is cleared */ - ret = nvkm_wait_msec(device, 10, base + 0x008, 0x10, 0x0); - if (ret < 0) - return ret; - - return 0; -} - -static int -falcon_wait_idle(struct nvkm_device *device, u32 base) -{ - int ret; - - ret = nvkm_wait_msec(device, 10, base + 0x04c, 0xffff, 0x0); - if (ret < 0) - return ret; - - return 0; -} - -static int -nvkm_secboot_falcon_enable(struct nvkm_secboot *sb) -{ - struct nvkm_device *device = sb->subdev.device; - int ret; - - /* enable engine */ - nvkm_mc_enable(device, sb->devidx); - ret = nvkm_wait_msec(device, 10, sb->base + 0x10c, 0x6, 0x0); - if (ret < 0) { - nvkm_error(&sb->subdev, "Falcon mem scrubbing timeout\n"); - nvkm_mc_disable(device, sb->devidx); - return ret; - } - - ret = falcon_wait_idle(device, sb->base); - if (ret) - return ret; - - /* enable IRQs */ - nvkm_wr32(device, sb->base + 0x010, 0xff); - nvkm_mc_intr_mask(device, sb->devidx, true); - - return 0; -} - -static int -nvkm_secboot_falcon_disable(struct nvkm_secboot *sb) -{ - struct nvkm_device *device = sb->subdev.device; - - /* disable IRQs and wait for any previous code to complete */ - nvkm_mc_intr_mask(device, sb->devidx, false); - nvkm_wr32(device, sb->base + 0x014, 0xff); - - falcon_wait_idle(device, sb->base); - - /* disable engine */ - nvkm_mc_disable(device, sb->devidx); - - return 0; -} - -int -nvkm_secboot_falcon_reset(struct nvkm_secboot *sb) -{ - int ret; - - ret = nvkm_secboot_falcon_disable(sb); - if (ret) - return ret; - - ret = nvkm_secboot_falcon_enable(sb); - if (ret) - return ret; - - return 0; -} - -/** - * nvkm_secboot_falcon_run - run the falcon that will perform secure boot - * - * This function is to be called after all chip-specific preparations have - * been completed. It will start the falcon to perform secure boot, wait for - * it to halt, and report if an error occurred. - */ -int -nvkm_secboot_falcon_run(struct nvkm_secboot *sb) -{ - struct nvkm_device *device = sb->subdev.device; - int ret; - - /* Start falcon */ - nvkm_wr32(device, sb->base + 0x100, 0x2); - - /* Wait for falcon halt */ - ret = nvkm_wait_msec(device, 100, sb->base + 0x100, 0x10, 0x10); - if (ret < 0) - return ret; - - /* If mailbox register contains an error code, then ACR has failed */ - ret = nvkm_rd32(device, sb->base + 0x040); - if (ret) { - nvkm_error(&sb->subdev, "ACR boot failed, ret 0x%08x", ret); - falcon_clear_halt_interrupt(device, sb->base); - return -EINVAL; - } - - return 0; -} - - /** * nvkm_secboot_reset() - reset specified falcon */ @@ -205,6 +82,16 @@ nvkm_secboot_oneinit(struct nvkm_subdev *subdev) struct nvkm_secboot *sb = nvkm_secboot(subdev); int ret = 0; + switch (sb->func->boot_falcon) { + case NVKM_SECBOOT_FALCON_PMU: + sb->boot_falcon = &subdev->device->pmu->falcon; + break; + default: + nvkm_error(subdev, "Unmanaged boot falcon %s!\n", + managed_falcons_names[sb->func->boot_falcon]); + return -EINVAL; + } + /* Call chip-specific init function */ if (sb->func->init) ret = sb->func->init(sb); @@ -258,17 +145,6 @@ nvkm_secboot_ctor(const struct nvkm_secboot_func *func, nvkm_subdev_ctor(&nvkm_secboot, device, index, &sb->subdev); sb->func = func; - /* setup the performing falcon's base address and masks */ - switch (func->boot_falcon) { - case NVKM_SECBOOT_FALCON_PMU: - sb->devidx = NVKM_SUBDEV_PMU; - sb->base = 0x10a000; - break; - default: - nvkm_error(&sb->subdev, "invalid secure boot falcon\n"); - return -EINVAL; - }; - nvkm_debug(&sb->subdev, "securely managed falcons:\n"); for_each_set_bit(fid, &sb->func->managed_falcons, NVKM_SECBOOT_FALCON_END) diff --git a/drm/nouveau/nvkm/subdev/secboot/gm200.c b/drm/nouveau/nvkm/subdev/secboot/gm200.c index ec48e4ace37a..667582a92d77 100644 --- a/drm/nouveau/nvkm/subdev/secboot/gm200.c +++ b/drm/nouveau/nvkm/subdev/secboot/gm200.c @@ -86,14 +86,7 @@ #include <core/gpuobj.h> #include <core/firmware.h> #include <subdev/fb.h> - -enum { - FALCON_DMAIDX_UCODE = 0, - FALCON_DMAIDX_VIRT = 1, - FALCON_DMAIDX_PHYS_VID = 2, - FALCON_DMAIDX_PHYS_SYS_COH = 3, - FALCON_DMAIDX_PHYS_SYS_NCOH = 4, -}; +#include <engine/falcon.h> /** * struct fw_bin_header - header of firmware files @@ -887,7 +880,7 @@ gm200_secboot_hsf_patch_signature(struct gm200_secboot *gsb, void *acr_image) u32 sig_size; /* Falcon in debug or production mode? */ - if ((nvkm_rd32(sb->subdev.device, sb->base + 0xc08) >> 20) & 0x1) { + if (sb->boot_falcon->debug) { sig = acr_image + fw_hdr->sig_dbg_offset; sig_size = fw_hdr->sig_dbg_size; } else { @@ -1101,96 +1094,33 @@ gm200_secboot_blobs_ready(struct gm200_secboot *gsb) * gm200_secboot_load_hs_bl() - load HS bootloader into DMEM and IMEM */ static void -gm200_secboot_load_hs_bl(struct gm200_secboot *gsb, void *data, u32 data_size) +gm200_secboot_load_hs_bl(struct gm200_secboot *gsb, struct nvkm_falcon *falcon, + void *data, u32 data_size) { - struct nvkm_device *device = gsb->base.subdev.device; struct fw_bin_header *hdr = gsb->hsbl_blob; struct fw_bl_desc *hsbl_desc = gsb->hsbl_blob + hdr->header_offset; void *blob_data = gsb->hsbl_blob + hdr->data_offset; void *hsbl_code = blob_data + hsbl_desc->code_off; void *hsbl_data = blob_data + hsbl_desc->data_off; u32 code_size = ALIGN(hsbl_desc->code_size, 256); - const u32 base = gsb->base.base; - u32 blk; u32 tag; - int i; /* * Copy HS bootloader data */ - nvkm_wr32(device, base + 0x1c0, (0x00000000 | (0x1 << 24))); - for (i = 0; i < hsbl_desc->data_size / 4; i++) - nvkm_wr32(device, base + 0x1c4, ((u32 *)hsbl_data)[i]); + nvkm_falcon_load_dmem(falcon, hsbl_data, 0x0, hsbl_desc->data_size, 0); /* * Copy HS bootloader interface structure where the HS descriptor * expects it to be */ - nvkm_wr32(device, base + 0x1c0, - (hsbl_desc->dmem_load_off | (0x1 << 24))); - for (i = 0; i < data_size / 4; i++) - nvkm_wr32(device, base + 0x1c4, ((u32 *)data)[i]); + nvkm_falcon_load_dmem(falcon, data, hsbl_desc->dmem_load_off, data_size, + 0); /* Copy HS bootloader code to end of IMEM */ - blk = (nvkm_rd32(device, base + 0x108) & 0x1ff) - (code_size >> 8); tag = hsbl_desc->start_tag; - nvkm_wr32(device, base + 0x180, ((blk & 0xff) << 8) | (0x1 << 24)); - for (i = 0; i < code_size / 4; i++) { - /* write new tag every 256B */ - if ((i & 0x3f) == 0) { - nvkm_wr32(device, base + 0x188, tag & 0xffff); - tag++; - } - nvkm_wr32(device, base + 0x184, ((u32 *)hsbl_code)[i]); - } - nvkm_wr32(device, base + 0x188, 0); -} - -/** - * gm200_secboot_setup_falcon() - set up the secure falcon for secure boot - */ -static int -gm200_secboot_setup_falcon(struct gm200_secboot *gsb) -{ - struct nvkm_device *device = gsb->base.subdev.device; - struct fw_bin_header *hdr = gsb->hsbl_blob; - struct fw_bl_desc *hsbl_desc = gsb->hsbl_blob + hdr->header_offset; - /* virtual start address for boot vector */ - u32 virt_addr = hsbl_desc->start_tag << 8; - const u32 base = gsb->base.base; - const u32 reg_base = base + 0xe00; - u32 inst_loc; - int ret; - - ret = nvkm_secboot_falcon_reset(&gsb->base); - if (ret) - return ret; - - /* setup apertures - virtual */ - nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_UCODE), 0x4); - nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_VIRT), 0x0); - /* setup apertures - physical */ - nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_PHYS_VID), 0x4); - nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_PHYS_SYS_COH), - 0x4 | 0x1); - nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_PHYS_SYS_NCOH), - 0x4 | 0x2); - - /* Set context */ - if (nvkm_memory_target(gsb->inst->memory) == NVKM_MEM_TARGET_VRAM) - inst_loc = 0x0; /* FB */ - else - inst_loc = 0x3; /* Non-coherent sysmem */ - - nvkm_mask(device, base + 0x048, 0x1, 0x1); - nvkm_wr32(device, base + 0x480, - ((gsb->inst->addr >> 12) & 0xfffffff) | - (inst_loc << 28) | (1 << 30)); - - /* Set boot vector to code's starting virtual address */ - nvkm_wr32(device, base + 0x104, virt_addr); - - return 0; + nvkm_falcon_load_imem(falcon, hsbl_code, falcon->code.limit - code_size, + code_size, tag, 0, false); } /** @@ -1200,16 +1130,27 @@ static int gm200_secboot_run_hs_blob(struct gm200_secboot *gsb, struct nvkm_gpuobj *blob, struct gm200_flcn_bl_desc *desc) { - struct nvkm_vma vma; - u64 vma_addr; + struct nvkm_subdev *subdev = &gsb->base.subdev; + struct fw_bin_header *hdr = gsb->hsbl_blob; + struct fw_bl_desc *hsbl_desc = gsb->hsbl_blob + hdr->header_offset; + struct nvkm_falcon *falcon = gsb->base.boot_falcon; + const u32 virt_addr = hsbl_desc->start_tag << 8; const u32 bl_desc_size = gsb->func->bl_desc_size; u8 bl_desc[bl_desc_size]; + struct nvkm_vma vma; + u64 vma_addr; int ret; + ret = nvkm_falcon_get(falcon, subdev); + if (ret) + return ret; + /* Map the HS firmware so the HS bootloader can see it */ ret = nvkm_gpuobj_map(blob, gsb->vm, NV_MEM_ACCESS_RW, &vma); - if (ret) + if (ret) { + nvkm_falcon_put(falcon); return ret; + } /* Add the mapping address to the DMA bases */ vma_addr = flcn64_to_u64(desc->code_dma_base) + vma.offset; @@ -1222,19 +1163,30 @@ gm200_secboot_run_hs_blob(struct gm200_secboot *gsb, struct nvkm_gpuobj *blob, /* Fixup the BL header */ gsb->func->fixup_bl_desc(desc, &bl_desc); - /* Reset the falcon and make it ready to run the HS bootloader */ - ret = gm200_secboot_setup_falcon(gsb); + /* Reset and set the falcon up */ + ret = nvkm_falcon_reset(falcon); if (ret) goto done; + nvkm_falcon_bind_context(falcon, gsb->inst); /* Load the HS bootloader into the falcon's IMEM/DMEM */ - gm200_secboot_load_hs_bl(gsb, &bl_desc, bl_desc_size); + gm200_secboot_load_hs_bl(gsb, falcon, &bl_desc, bl_desc_size); /* Start the HS bootloader */ - ret = nvkm_secboot_falcon_run(&gsb->base); + nvkm_falcon_set_start_addr(falcon, virt_addr); + nvkm_falcon_start(falcon); + ret = nvkm_falcon_wait_for_halt(falcon, 100); if (ret) goto done; + /* If mailbox register contains an error code, then ACR has failed */ + ret = nvkm_falcon_rd32(falcon, 0x040); + if (ret) { + nvkm_error(subdev, "ACR boot failed, ret 0x%08x", ret); + ret = -EINVAL; + goto done; + } + done: /* Restore the original DMA addresses */ vma_addr = flcn64_to_u64(desc->code_dma_base) - vma.offset; @@ -1246,6 +1198,7 @@ done: /* We don't need the ACR firmware anymore */ nvkm_gpuobj_unmap(&vma); + nvkm_falcon_put(falcon); return ret; } diff --git a/drm/nouveau/nvkm/subdev/secboot/priv.h b/drm/nouveau/nvkm/subdev/secboot/priv.h index 2ad6d622e7e5..4b090d23c289 100644 --- a/drm/nouveau/nvkm/subdev/secboot/priv.h +++ b/drm/nouveau/nvkm/subdev/secboot/priv.h @@ -41,8 +41,6 @@ struct nvkm_secboot_func { int nvkm_secboot_ctor(const struct nvkm_secboot_func *, struct nvkm_device *, int index, struct nvkm_secboot *); -int nvkm_secboot_falcon_reset(struct nvkm_secboot *); -int nvkm_secboot_falcon_run(struct nvkm_secboot *); struct flcn_u64 { u32 lo; -- git-series 0.8.10
Add a fini() hook to the GR engine. This will be used by gf100+ to properly release the FECS and GPCCS falcons. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/nvkm/engine/gr/base.c | 10 ++++++++++ drm/nouveau/nvkm/engine/gr/priv.h | 1 + 2 files changed, 11 insertions(+), 0 deletions(-) diff --git a/drm/nouveau/nvkm/engine/gr/base.c b/drm/nouveau/nvkm/engine/gr/base.c index 467065d1b4e6..a8282edc2b58 100644 --- a/drm/nouveau/nvkm/engine/gr/base.c +++ b/drm/nouveau/nvkm/engine/gr/base.c @@ -106,6 +106,15 @@ nvkm_gr_init(struct nvkm_engine *engine) return gr->func->init(gr); } +static int +nvkm_gr_fini(struct nvkm_engine *engine, bool suspend) +{ + struct nvkm_gr *gr = nvkm_gr(engine); + if (gr->func->fini) + return gr->func->fini(gr, suspend); + return 0; +} + static void * nvkm_gr_dtor(struct nvkm_engine *engine) { @@ -120,6 +129,7 @@ nvkm_gr = { .dtor = nvkm_gr_dtor, .oneinit = nvkm_gr_oneinit, .init = nvkm_gr_init, + .fini = nvkm_gr_fini, .intr = nvkm_gr_intr, .tile = nvkm_gr_tile, .fifo.cclass = nvkm_gr_cclass_new, diff --git a/drm/nouveau/nvkm/engine/gr/priv.h b/drm/nouveau/nvkm/engine/gr/priv.h index d8adcdf6985a..0d6d940a744f 100644 --- a/drm/nouveau/nvkm/engine/gr/priv.h +++ b/drm/nouveau/nvkm/engine/gr/priv.h @@ -15,6 +15,7 @@ struct nvkm_gr_func { void *(*dtor)(struct nvkm_gr *); int (*oneinit)(struct nvkm_gr *); int (*init)(struct nvkm_gr *); + int (*fini)(struct nvkm_gr *, bool); void (*intr)(struct nvkm_gr *); void (*tile)(struct nvkm_gr *, int region, struct nvkm_fb_tile *); int (*tlb_flush)(struct nvkm_gr *); -- git-series 0.8.10
Alexandre Courbot
2016-Dec-13 08:11 UTC
[Nouveau] [PATCH v2 13/15] gr/gf100: split gf100_gr_init_ctxctl()
gf100_gr_init_ctxctl() is basically two different functions (one for use of internal firmware, the other for use of external firmware), but its current layout makes it look more complex than it is. Split it to better reflect that fact. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/nvkm/engine/gr/gf100.c | 212 ++++++++++++++++-------------- 1 file changed, 115 insertions(+), 97 deletions(-) diff --git a/drm/nouveau/nvkm/engine/gr/gf100.c b/drm/nouveau/nvkm/engine/gr/gf100.c index f65a5b0a1a4d..7cf1492d3922 100644 --- a/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1455,134 +1455,139 @@ gf100_gr_init_csdata(struct gf100_gr *gr, nvkm_wr32(device, falcon + 0x01c4, star + 4); } -int -gf100_gr_init_ctxctl(struct gf100_gr *gr) +/* Initialize context from an external (secure or not) firmware */ +static int +gf100_gr_init_ctxctl_ext(struct gf100_gr *gr) { - const struct gf100_grctx_func *grctx = gr->func->grctx; struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; struct nvkm_secboot *sb = device->secboot; - int i; int ret = 0; - if (gr->firmware) { - /* load fuc microcode */ - nvkm_mc_unk260(device, 0); - - /* securely-managed falcons must be reset using secure boot */ - if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) - ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_FECS); - else - gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c, - &gr->fuc409d); - if (ret) - return ret; + /* load fuc microcode */ + nvkm_mc_unk260(device, 0); - if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) - ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_GPCCS); - else - gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac, - &gr->fuc41ad); - if (ret) - return ret; + /* securely-managed falcons must be reset using secure boot */ + if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) + ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_FECS); + else + gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c, &gr->fuc409d); + if (ret) + return ret; - nvkm_mc_unk260(device, 1); - - /* start both of them running */ - nvkm_wr32(device, 0x409840, 0xffffffff); - nvkm_wr32(device, 0x41a10c, 0x00000000); - nvkm_wr32(device, 0x40910c, 0x00000000); - - if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) - nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_GPCCS); - else - nvkm_wr32(device, 0x41a100, 0x00000002); - if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) - nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_FECS); - else - nvkm_wr32(device, 0x409100, 0x00000002); - if (nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x409800) & 0x00000001) - break; - ) < 0) - return -EBUSY; + if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) + ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_GPCCS); + else + gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac, &gr->fuc41ad); + if (ret) + return ret; - nvkm_wr32(device, 0x409840, 0xffffffff); - nvkm_wr32(device, 0x409500, 0x7fffffff); - nvkm_wr32(device, 0x409504, 0x00000021); + nvkm_mc_unk260(device, 1); + + /* start both of them running */ + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x41a10c, 0x00000000); + nvkm_wr32(device, 0x40910c, 0x00000000); - nvkm_wr32(device, 0x409840, 0xffffffff); - nvkm_wr32(device, 0x409500, 0x00000000); - nvkm_wr32(device, 0x409504, 0x00000010); + if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) + nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_GPCCS); + else + nvkm_wr32(device, 0x41a100, 0x00000002); + if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) + nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_FECS); + else + nvkm_wr32(device, 0x409100, 0x00000002); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800) & 0x00000001) + break; + ) < 0) + return -EBUSY; + + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409500, 0x7fffffff); + nvkm_wr32(device, 0x409504, 0x00000021); + + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409500, 0x00000000); + nvkm_wr32(device, 0x409504, 0x00000010); + if (nvkm_msec(device, 2000, + if ((gr->size = nvkm_rd32(device, 0x409800))) + break; + ) < 0) + return -EBUSY; + + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409500, 0x00000000); + nvkm_wr32(device, 0x409504, 0x00000016); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800)) + break; + ) < 0) + return -EBUSY; + + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409500, 0x00000000); + nvkm_wr32(device, 0x409504, 0x00000025); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800)) + break; + ) < 0) + return -EBUSY; + + if (device->chipset >= 0xe0) { + nvkm_wr32(device, 0x409800, 0x00000000); + nvkm_wr32(device, 0x409500, 0x00000001); + nvkm_wr32(device, 0x409504, 0x00000030); if (nvkm_msec(device, 2000, - if ((gr->size = nvkm_rd32(device, 0x409800))) + if (nvkm_rd32(device, 0x409800)) break; ) < 0) return -EBUSY; - nvkm_wr32(device, 0x409840, 0xffffffff); - nvkm_wr32(device, 0x409500, 0x00000000); - nvkm_wr32(device, 0x409504, 0x00000016); + nvkm_wr32(device, 0x409810, 0xb00095c8); + nvkm_wr32(device, 0x409800, 0x00000000); + nvkm_wr32(device, 0x409500, 0x00000001); + nvkm_wr32(device, 0x409504, 0x00000031); if (nvkm_msec(device, 2000, if (nvkm_rd32(device, 0x409800)) break; ) < 0) return -EBUSY; - nvkm_wr32(device, 0x409840, 0xffffffff); - nvkm_wr32(device, 0x409500, 0x00000000); - nvkm_wr32(device, 0x409504, 0x00000025); + nvkm_wr32(device, 0x409810, 0x00080420); + nvkm_wr32(device, 0x409800, 0x00000000); + nvkm_wr32(device, 0x409500, 0x00000001); + nvkm_wr32(device, 0x409504, 0x00000032); if (nvkm_msec(device, 2000, if (nvkm_rd32(device, 0x409800)) break; ) < 0) return -EBUSY; - if (device->chipset >= 0xe0) { - nvkm_wr32(device, 0x409800, 0x00000000); - nvkm_wr32(device, 0x409500, 0x00000001); - nvkm_wr32(device, 0x409504, 0x00000030); - if (nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x409800)) - break; - ) < 0) - return -EBUSY; - - nvkm_wr32(device, 0x409810, 0xb00095c8); - nvkm_wr32(device, 0x409800, 0x00000000); - nvkm_wr32(device, 0x409500, 0x00000001); - nvkm_wr32(device, 0x409504, 0x00000031); - if (nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x409800)) - break; - ) < 0) - return -EBUSY; - - nvkm_wr32(device, 0x409810, 0x00080420); - nvkm_wr32(device, 0x409800, 0x00000000); - nvkm_wr32(device, 0x409500, 0x00000001); - nvkm_wr32(device, 0x409504, 0x00000032); - if (nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x409800)) - break; - ) < 0) - return -EBUSY; + nvkm_wr32(device, 0x409614, 0x00000070); + nvkm_wr32(device, 0x409614, 0x00000770); + nvkm_wr32(device, 0x40802c, 0x00000001); + } - nvkm_wr32(device, 0x409614, 0x00000070); - nvkm_wr32(device, 0x409614, 0x00000770); - nvkm_wr32(device, 0x40802c, 0x00000001); + if (gr->data == NULL) { + int ret = gf100_grctx_generate(gr); + if (ret) { + nvkm_error(subdev, "failed to construct context\n"); + return ret; } + } - if (gr->data == NULL) { - int ret = gf100_grctx_generate(gr); - if (ret) { - nvkm_error(subdev, "failed to construct context\n"); - return ret; - } - } + return 0; +} + +static int +gf100_gr_init_ctxctl_int(struct gf100_gr *gr) +{ + const struct gf100_grctx_func *grctx = gr->func->grctx; + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int i; - return 0; - } else if (!gr->func->fecs.ucode) { return -ENOSYS; } @@ -1642,6 +1647,19 @@ gf100_gr_init_ctxctl(struct gf100_gr *gr) return 0; } +int +gf100_gr_init_ctxctl(struct gf100_gr *gr) +{ + int ret; + + if (gr->firmware) + ret = gf100_gr_init_ctxctl_ext(gr); + else + ret = gf100_gr_init_ctxctl_int(gr); + + return ret; +} + static int gf100_gr_oneinit(struct nvkm_gr *base) { -- git-series 0.8.10
Alexandre Courbot
2016-Dec-13 08:11 UTC
[Nouveau] [PATCH v2 14/15] gr/gf100: instantiate and reserve GR falcons
Create instances for the FECS and GPCCS falcons and use the init() and fini() hooks to reserve them for as long as GR controls them. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/nvkm/engine/gr/gf100.c | 110 ++++++++++++++++-------------- drm/nouveau/nvkm/engine/gr/gf100.h | 3 +- 2 files changed, 63 insertions(+), 50 deletions(-) diff --git a/drm/nouveau/nvkm/engine/gr/gf100.c b/drm/nouveau/nvkm/engine/gr/gf100.c index 7cf1492d3922..4330e8417a25 100644 --- a/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1391,26 +1391,11 @@ gf100_gr_intr(struct nvkm_gr *base) } static void -gf100_gr_init_fw(struct gf100_gr *gr, u32 fuc_base, +gf100_gr_init_fw(struct nvkm_falcon *falcon, struct gf100_gr_fuc *code, struct gf100_gr_fuc *data) { - struct nvkm_device *device = gr->base.engine.subdev.device; - int i; - - nvkm_wr32(device, fuc_base + 0x01c0, 0x01000000); - for (i = 0; i < data->size / 4; i++) - nvkm_wr32(device, fuc_base + 0x01c4, data->data[i]); - - nvkm_wr32(device, fuc_base + 0x0180, 0x01000000); - for (i = 0; i < code->size / 4; i++) { - if ((i & 0x3f) == 0) - nvkm_wr32(device, fuc_base + 0x0188, i >> 6); - nvkm_wr32(device, fuc_base + 0x0184, code->data[i]); - } - - /* code must be padded to 0x40 words */ - for (; i & 0x3f; i++) - nvkm_wr32(device, fuc_base + 0x0184, 0); + nvkm_falcon_load_dmem(falcon, data->data, 0x0, data->size, 0); + nvkm_falcon_load_imem(falcon, code->data, 0x0, code->size, 0, 0, false); } static void @@ -1471,14 +1456,14 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr) if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_FECS); else - gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c, &gr->fuc409d); + gf100_gr_init_fw(&gr->fecs, &gr->fuc409c, &gr->fuc409d); if (ret) return ret; if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_GPCCS); else - gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac, &gr->fuc41ad); + gf100_gr_init_fw(&gr->gpccs, &gr->fuc41ac, &gr->fuc41ad); if (ret) return ret; @@ -1489,14 +1474,9 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr) nvkm_wr32(device, 0x41a10c, 0x00000000); nvkm_wr32(device, 0x40910c, 0x00000000); - if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) - nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_GPCCS); - else - nvkm_wr32(device, 0x41a100, 0x00000002); - if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) - nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_FECS); - else - nvkm_wr32(device, 0x409100, 0x00000002); + nvkm_falcon_start(&gr->gpccs); + nvkm_falcon_start(&gr->fecs); + if (nvkm_msec(device, 2000, if (nvkm_rd32(device, 0x409800) & 0x00000001) break; @@ -1586,7 +1566,6 @@ gf100_gr_init_ctxctl_int(struct gf100_gr *gr) const struct gf100_grctx_func *grctx = gr->func->grctx; struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; - int i; if (!gr->func->fecs.ucode) { return -ENOSYS; @@ -1594,28 +1573,16 @@ gf100_gr_init_ctxctl_int(struct gf100_gr *gr) /* load HUB microcode */ nvkm_mc_unk260(device, 0); - nvkm_wr32(device, 0x4091c0, 0x01000000); - for (i = 0; i < gr->func->fecs.ucode->data.size / 4; i++) - nvkm_wr32(device, 0x4091c4, gr->func->fecs.ucode->data.data[i]); - - nvkm_wr32(device, 0x409180, 0x01000000); - for (i = 0; i < gr->func->fecs.ucode->code.size / 4; i++) { - if ((i & 0x3f) == 0) - nvkm_wr32(device, 0x409188, i >> 6); - nvkm_wr32(device, 0x409184, gr->func->fecs.ucode->code.data[i]); - } + nvkm_falcon_load_dmem(&gr->fecs, gr->func->fecs.ucode->data.data, 0x0, + gr->func->fecs.ucode->data.size, 0); + nvkm_falcon_load_imem(&gr->fecs, gr->func->fecs.ucode->code.data, 0x0, + gr->func->fecs.ucode->code.size, 0, 0, false); /* load GPC microcode */ - nvkm_wr32(device, 0x41a1c0, 0x01000000); - for (i = 0; i < gr->func->gpccs.ucode->data.size / 4; i++) - nvkm_wr32(device, 0x41a1c4, gr->func->gpccs.ucode->data.data[i]); - - nvkm_wr32(device, 0x41a180, 0x01000000); - for (i = 0; i < gr->func->gpccs.ucode->code.size / 4; i++) { - if ((i & 0x3f) == 0) - nvkm_wr32(device, 0x41a188, i >> 6); - nvkm_wr32(device, 0x41a184, gr->func->gpccs.ucode->code.data[i]); - } + nvkm_falcon_load_dmem(&gr->gpccs, gr->func->gpccs.ucode->data.data, 0x0, + gr->func->gpccs.ucode->data.size, 0); + nvkm_falcon_load_imem(&gr->gpccs, gr->func->gpccs.ucode->code.data, 0x0, + gr->func->gpccs.ucode->code.size, 0, 0, false); nvkm_mc_unk260(device, 1); /* load register lists */ @@ -1729,8 +1696,44 @@ static int gf100_gr_init_(struct nvkm_gr *base) { struct gf100_gr *gr = gf100_gr(base); + struct nvkm_subdev *subdev = &base->engine.subdev; + u32 ret; + nvkm_pmu_pgob(gr->base.engine.subdev.device->pmu, false); - return gr->func->init(gr); + + ret = nvkm_falcon_get(&gr->fecs, subdev); + if (ret) + return ret; + ret = nvkm_falcon_get(&gr->gpccs, subdev); + if (ret) + goto gpccs_failed; + + ret = gr->func->init(gr); + if (ret) + goto init_failed; + + return 0; + +init_failed: + nvkm_falcon_put(&gr->gpccs); +gpccs_failed: + nvkm_falcon_put(&gr->fecs); + + return ret; +} + +static int +gf100_gr_fini_(struct nvkm_gr *base, bool suspend) +{ + struct gf100_gr *gr = gf100_gr(base); + + /* We only own the falcons if init has been performed at this stage */ + if (gr->gpccs.user == &base->engine.subdev) { + nvkm_falcon_put(&gr->gpccs); + nvkm_falcon_put(&gr->fecs); + } + + return 0; } void @@ -1773,6 +1776,7 @@ gf100_gr_ = { .dtor = gf100_gr_dtor, .oneinit = gf100_gr_oneinit, .init = gf100_gr_init_, + .fini = gf100_gr_fini_, .intr = gf100_gr_intr, .units = gf100_gr_units, .chan_new = gf100_gr_chan_new, @@ -1846,6 +1850,7 @@ int gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device, int index, struct gf100_gr *gr) { + struct nvkm_subdev *subdev = &gr->base.engine.subdev; int ret; gr->func = func; @@ -1858,6 +1863,11 @@ gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device, if (ret) return ret; + nvkm_falcon_ctor(subdev, &nvkm_falcon_v1_func, "FECS", 0x409000, + &gr->fecs); + nvkm_falcon_ctor(subdev, &nvkm_falcon_v1_func, "GPCCS", 0x41a000, + &gr->gpccs); + return 0; } diff --git a/drm/nouveau/nvkm/engine/gr/gf100.h b/drm/nouveau/nvkm/engine/gr/gf100.h index 268b8d60ff73..cc90f924def4 100644 --- a/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drm/nouveau/nvkm/engine/gr/gf100.h @@ -29,6 +29,7 @@ #include <core/gpuobj.h> #include <subdev/ltc.h> #include <subdev/mmu.h> +#include <engine/falcon.h> #define GPC_MAX 32 #define TPC_MAX_PER_GPC 8 @@ -75,6 +76,8 @@ struct gf100_gr { const struct gf100_gr_func *func; struct nvkm_gr base; + struct nvkm_falcon fecs; + struct nvkm_falcon gpccs; struct gf100_gr_fuc fuc409c; struct gf100_gr_fuc fuc409d; struct gf100_gr_fuc fuc41ac; -- git-series 0.8.10
Alexandre Courbot
2016-Dec-13 08:11 UTC
[Nouveau] [PATCH v2 15/15] secboot: remove nvkm_secboot_start()
Since GR has moved to using the falcon library to start the falcons, this function is not needed anymore. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/include/nvkm/subdev/secboot.h | 1 +- drm/nouveau/nvkm/subdev/secboot/base.c | 15 +------------- drm/nouveau/nvkm/subdev/secboot/gm200.c | 27 +------------------------ drm/nouveau/nvkm/subdev/secboot/gm20b.c | 1 +- drm/nouveau/nvkm/subdev/secboot/priv.h | 1 +- 5 files changed, 0 insertions(+), 45 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/secboot.h b/drm/nouveau/include/nvkm/subdev/secboot.h index 2a2f651ccceb..be04c34f25e3 100644 --- a/drm/nouveau/include/nvkm/subdev/secboot.h +++ b/drm/nouveau/include/nvkm/subdev/secboot.h @@ -48,7 +48,6 @@ struct nvkm_secboot { bool nvkm_secboot_is_managed(struct nvkm_secboot *, enum nvkm_secboot_falcon); int nvkm_secboot_reset(struct nvkm_secboot *, enum nvkm_secboot_falcon); -int nvkm_secboot_start(struct nvkm_secboot *, enum nvkm_secboot_falcon); int gm200_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); int gm20b_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); diff --git a/drm/nouveau/nvkm/subdev/secboot/base.c b/drm/nouveau/nvkm/subdev/secboot/base.c index 633dee87ac98..2d921ece85e7 100644 --- a/drm/nouveau/nvkm/subdev/secboot/base.c +++ b/drm/nouveau/nvkm/subdev/secboot/base.c @@ -49,21 +49,6 @@ nvkm_secboot_reset(struct nvkm_secboot *sb, enum nvkm_secboot_falcon falcon) } /** - * nvkm_secboot_start() - start specified falcon - */ -int -nvkm_secboot_start(struct nvkm_secboot *sb, enum nvkm_secboot_falcon falcon) -{ - /* Unmanaged falcon? */ - if (!(BIT(falcon) & sb->func->managed_falcons)) { - nvkm_error(&sb->subdev, "cannot start unmanaged falcon!\n"); - return -EINVAL; - } - - return sb->func->start(sb, falcon); -} - -/** * nvkm_secboot_is_managed() - check whether a given falcon is securely-managed */ bool diff --git a/drm/nouveau/nvkm/subdev/secboot/gm200.c b/drm/nouveau/nvkm/subdev/secboot/gm200.c index 667582a92d77..aa435bb84dd1 100644 --- a/drm/nouveau/nvkm/subdev/secboot/gm200.c +++ b/drm/nouveau/nvkm/subdev/secboot/gm200.c @@ -1253,32 +1253,6 @@ end: } int -gm200_secboot_start(struct nvkm_secboot *sb, enum nvkm_secboot_falcon falcon) -{ - struct gm200_secboot *gsb = gm200_secboot(sb); - int base; - - switch (falcon) { - case NVKM_SECBOOT_FALCON_FECS: - base = 0x409000; - break; - case NVKM_SECBOOT_FALCON_GPCCS: - base = 0x41a000; - break; - default: - nvkm_error(&sb->subdev, "cannot start unhandled falcon!\n"); - return -EINVAL; - } - - nvkm_wr32(sb->subdev.device, base + 0x130, 0x00000002); - gsb->falcon_state[falcon] = RUNNING; - - return 0; -} - - - -int gm200_secboot_init(struct nvkm_secboot *sb) { struct gm200_secboot *gsb = gm200_secboot(sb); @@ -1361,7 +1335,6 @@ gm200_secboot = { .init = gm200_secboot_init, .fini = gm200_secboot_fini, .reset = gm200_secboot_reset, - .start = gm200_secboot_start, .managed_falcons = BIT(NVKM_SECBOOT_FALCON_FECS) | BIT(NVKM_SECBOOT_FALCON_GPCCS), .boot_falcon = NVKM_SECBOOT_FALCON_PMU, diff --git a/drm/nouveau/nvkm/subdev/secboot/gm20b.c b/drm/nouveau/nvkm/subdev/secboot/gm20b.c index d5395ebfe8d3..50f503b5d1ce 100644 --- a/drm/nouveau/nvkm/subdev/secboot/gm20b.c +++ b/drm/nouveau/nvkm/subdev/secboot/gm20b.c @@ -191,7 +191,6 @@ gm20b_secboot = { .dtor = gm200_secboot_dtor, .init = gm20b_secboot_init, .reset = gm200_secboot_reset, - .start = gm200_secboot_start, .managed_falcons = BIT(NVKM_SECBOOT_FALCON_FECS), .boot_falcon = NVKM_SECBOOT_FALCON_PMU, }; diff --git a/drm/nouveau/nvkm/subdev/secboot/priv.h b/drm/nouveau/nvkm/subdev/secboot/priv.h index 4b090d23c289..d23c94c8e597 100644 --- a/drm/nouveau/nvkm/subdev/secboot/priv.h +++ b/drm/nouveau/nvkm/subdev/secboot/priv.h @@ -31,7 +31,6 @@ struct nvkm_secboot_func { int (*fini)(struct nvkm_secboot *, bool suspend); void *(*dtor)(struct nvkm_secboot *); int (*reset)(struct nvkm_secboot *, enum nvkm_secboot_falcon); - int (*start)(struct nvkm_secboot *, enum nvkm_secboot_falcon); /* ID of the falcon that will perform secure boot */ enum nvkm_secboot_falcon boot_falcon; -- git-series 0.8.10