From 6e739d924fe9b778fa82396e0e941143f498acb8 Mon Sep 17 00:00:00 2001 From: Alex Waterman Date: Mon, 22 Jan 2018 16:30:53 -0800 Subject: gpu: nvgpu: Userspace POSIX support Add support for compiling nvgpu in a POSIX compliant userspace. This code adds all of the necessary abstraction interfaces (mostly stubbed) to enabled extremely limited and basic functionality in nvgpu. The goal of this code is to facilitate unit testing of the nvgpu common core. By doing this in userspace it is much easier to write tests that rely on very particular states within nvgpu since a user can very precisely control the state of nvgpu. JIRA NVGPU-525 Change-Id: I30e95016df14997d951075777e0585f912dc5960 Signed-off-by: Alex Waterman Reviewed-on: https://git-master.nvidia.com/r/1683914 GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/posix/bitmap.c | 268 +++++++++++++++++++++++ drivers/gpu/nvgpu/common/posix/bug.c | 67 ++++++ drivers/gpu/nvgpu/common/posix/channel.c | 32 +++ drivers/gpu/nvgpu/common/posix/clk_arb.c | 148 +++++++++++++ drivers/gpu/nvgpu/common/posix/cond.c | 55 +++++ drivers/gpu/nvgpu/common/posix/dma.c | 220 +++++++++++++++++++ drivers/gpu/nvgpu/common/posix/error_notifier.c | 40 ++++ drivers/gpu/nvgpu/common/posix/firmware.c | 35 +++ drivers/gpu/nvgpu/common/posix/fuse.c | 54 +++++ drivers/gpu/nvgpu/common/posix/io.c | 82 +++++++ drivers/gpu/nvgpu/common/posix/kmem.c | 134 ++++++++++++ drivers/gpu/nvgpu/common/posix/lock.c | 79 +++++++ drivers/gpu/nvgpu/common/posix/log.c | 95 ++++++++ drivers/gpu/nvgpu/common/posix/nvgpu.c | 137 ++++++++++++ drivers/gpu/nvgpu/common/posix/nvlink.c | 33 +++ drivers/gpu/nvgpu/common/posix/os_posix.h | 32 +++ drivers/gpu/nvgpu/common/posix/posix-comptags.c | 49 +++++ drivers/gpu/nvgpu/common/posix/posix-nvgpu_mem.c | 209 ++++++++++++++++++ drivers/gpu/nvgpu/common/posix/posix-vm.c | 52 +++++ drivers/gpu/nvgpu/common/posix/rwsem.c | 117 ++++++++++ drivers/gpu/nvgpu/common/posix/soc.c | 48 ++++ drivers/gpu/nvgpu/common/posix/stubs.c | 32 +++ drivers/gpu/nvgpu/common/posix/thread.c | 96 ++++++++ drivers/gpu/nvgpu/common/posix/timers.c | 169 ++++++++++++++ drivers/gpu/nvgpu/common/posix/tsg.c | 28 +++ 25 files changed, 2311 insertions(+) create mode 100644 drivers/gpu/nvgpu/common/posix/bitmap.c create mode 100644 drivers/gpu/nvgpu/common/posix/bug.c create mode 100644 drivers/gpu/nvgpu/common/posix/channel.c create mode 100644 drivers/gpu/nvgpu/common/posix/clk_arb.c create mode 100644 drivers/gpu/nvgpu/common/posix/cond.c create mode 100644 drivers/gpu/nvgpu/common/posix/dma.c create mode 100644 drivers/gpu/nvgpu/common/posix/error_notifier.c create mode 100644 drivers/gpu/nvgpu/common/posix/firmware.c create mode 100644 drivers/gpu/nvgpu/common/posix/fuse.c create mode 100644 drivers/gpu/nvgpu/common/posix/io.c create mode 100644 drivers/gpu/nvgpu/common/posix/kmem.c create mode 100644 drivers/gpu/nvgpu/common/posix/lock.c create mode 100644 drivers/gpu/nvgpu/common/posix/log.c create mode 100644 drivers/gpu/nvgpu/common/posix/nvgpu.c create mode 100644 drivers/gpu/nvgpu/common/posix/nvlink.c create mode 100644 drivers/gpu/nvgpu/common/posix/os_posix.h create mode 100644 drivers/gpu/nvgpu/common/posix/posix-comptags.c create mode 100644 drivers/gpu/nvgpu/common/posix/posix-nvgpu_mem.c create mode 100644 drivers/gpu/nvgpu/common/posix/posix-vm.c create mode 100644 drivers/gpu/nvgpu/common/posix/rwsem.c create mode 100644 drivers/gpu/nvgpu/common/posix/soc.c create mode 100644 drivers/gpu/nvgpu/common/posix/stubs.c create mode 100644 drivers/gpu/nvgpu/common/posix/thread.c create mode 100644 drivers/gpu/nvgpu/common/posix/timers.c create mode 100644 drivers/gpu/nvgpu/common/posix/tsg.c (limited to 'drivers/gpu/nvgpu/common/posix') diff --git a/drivers/gpu/nvgpu/common/posix/bitmap.c b/drivers/gpu/nvgpu/common/posix/bitmap.c new file mode 100644 index 00000000..51361777 --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/bitmap.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2018, 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 +#include + +#include +#include + +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) + +unsigned long __nvgpu_posix_fls(unsigned long word) +{ + int num = BITS_PER_LONG - 1; + +#if BITS_PER_LONG == 64 + if (!(word & (~0ul << 32))) { + num -= 32; + word <<= 32; + } +#endif + if (!(word & (~0ul << (BITS_PER_LONG-16)))) { + num -= 16; + word <<= 16; + } + if (!(word & (~0ul << (BITS_PER_LONG-8)))) { + num -= 8; + word <<= 8; + } + if (!(word & (~0ul << (BITS_PER_LONG-4)))) { + num -= 4; + word <<= 4; + } + if (!(word & (~0ul << (BITS_PER_LONG-2)))) { + num -= 2; + word <<= 2; + } + if (!(word & (~0ul << (BITS_PER_LONG-1)))) + num -= 1; + return num; +} + +unsigned long __nvgpu_posix_ffs(unsigned long word) +{ + int num = 0; + +#if BITS_PER_LONG == 64 + if ((word & 0xffffffff) == 0) { + num += 32; + word >>= 32; + } +#endif + if ((word & 0xffff) == 0) { + num += 16; + word >>= 16; + } + if ((word & 0xff) == 0) { + num += 8; + word >>= 8; + } + if ((word & 0xf) == 0) { + num += 4; + word >>= 4; + } + if ((word & 0x3) == 0) { + num += 2; + word >>= 2; + } + if ((word & 0x1) == 0) + num += 1; + + return num; +} + +static unsigned long __find_next_bit(const unsigned long *addr, + unsigned long n, + unsigned long start, + bool invert) +{ + unsigned long idx; + unsigned long w; + unsigned long start_mask; + + /* + * We make a mask we can XOR into the word so that we can invert the + * word without requiring a branch. I.e instead of doing: + * + * w = invert ? ~addr[idx] : addr[idx] + * + * We can do: + * + * w = addr[idx] ^= invert_mask + * + * This saves us a branch every iteration through the loop. Now we can + * always just look for 1s. + */ + unsigned long invert_mask = invert ? ~0UL : 0UL; + + if (start >= n) + return n; + + start_mask = ~0UL << (start & (BITS_PER_LONG - 1)); + + idx = start / BITS_PER_LONG; + w = (addr[idx] ^ invert_mask) & start_mask; + + start = round_up(start, BITS_PER_LONG); + + /* + * Find the first non-zero word taking into account start and + * invert. + */ + while (!w) { + idx++; + start += BITS_PER_LONG; + + w = addr[idx] ^ invert_mask; + } + + return min(n, ffs(w) + idx * BITS_PER_LONG); +} + +unsigned long find_first_bit(const unsigned long *addr, unsigned long size) +{ + return __find_next_bit(addr, size, 0, false); +} + +unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) +{ + return __find_next_bit(addr, size, 0, true); +} + +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + return __find_next_bit(addr, size, offset, false); +} + +static unsigned long find_next_zero_bit(const unsigned long *addr, + unsigned long size, + unsigned long offset) +{ + return __find_next_bit(addr, size, offset, true); +} + +void bitmap_set(unsigned long *map, unsigned int start, int len) +{ + unsigned int end = start + len; + + /* + * Super slow naive implementation. But speed isn't what matters here. + */ + while (start < end) + set_bit(start++, map); +} + +void bitmap_clear(unsigned long *map, unsigned int start, int len) +{ + unsigned int end = start + len; + + while (start < end) + clear_bit(start++, map); +} + +/* + * This is essentially a find-first-fit allocator: this searches a bitmap for + * the first space that is large enough to satisfy the requested size of bits. + * That means that this is not a vary smart allocator. But it is fast relative + * to an allocator that goes looking for an optimal location. + */ +unsigned long bitmap_find_next_zero_area_off(unsigned long *map, + unsigned long size, + unsigned long start, + unsigned int nr, + unsigned long align_mask, + unsigned long align_offset) +{ + unsigned long offs; + + while (start + nr <= size) { + start = find_next_zero_bit(map, size, start); + + start = ALIGN_MASK(start + align_offset, align_mask) - + align_offset; + + /* + * Not enough space left to satisfy the requested area. + */ + if ((start + nr) > size) + return size; + + offs = find_next_bit(map, size, start); + + if ((offs - start) >= nr) + return start; + + start = offs + 1; + } + + return size; +} + +unsigned long bitmap_find_next_zero_area(unsigned long *map, + unsigned long size, + unsigned long start, + unsigned int nr, + unsigned long align_mask) +{ + return bitmap_find_next_zero_area_off(map, size, start, nr, + align_mask, 0); +} + +bool test_bit(int nr, const volatile unsigned long *addr) +{ + return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); +} + +bool test_and_set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + volatile unsigned long *p = addr + BIT_WORD(nr); + + return !!(__sync_fetch_and_or(p, mask) & mask); +} + +bool test_and_clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + return !!(__sync_fetch_and_and(p, ~mask) & mask); +} + +void set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + __atomic_or(p, mask); +} + +void clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + __atomic_and(p, ~mask); +} diff --git a/drivers/gpu/nvgpu/common/posix/bug.c b/drivers/gpu/nvgpu/common/posix/bug.c new file mode 100644 index 00000000..64f4a6f6 --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/bug.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, 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 + +#include + +__attribute__ ((noreturn)) +static void __hang(void) +{ + nvgpu_err(NULL, "Hanging!"); + + while (1) + ; +} + +static void __dump_stack(unsigned int skip_frames) +{ + return; +} + +void dump_stack(void) +{ + __dump_stack(0); +} + +/* + * Ahhh! A bug! + */ +void __bug(const char *fmt, ...) +{ + nvgpu_err(NULL, "BUG detected!"); + + __hang(); +} + +bool __warn(bool cond, const char *fmt, ...) +{ + if (!cond) + goto done; + + nvgpu_warn(NULL, "WARNING detected!"); + + dump_stack(); + +done: + return cond; +} diff --git a/drivers/gpu/nvgpu/common/posix/channel.c b/drivers/gpu/nvgpu/common/posix/channel.c new file mode 100644 index 00000000..05697159 --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/channel.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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 "gk20a/channel_gk20a.h" + +u32 nvgpu_get_gpfifo_entry_size(void) +{ + /* + * There is no struct nvgpu_gpfifo for us to use yet. But when it's + * defined in userspace this is how big it will be. + */ + return 8; +} diff --git a/drivers/gpu/nvgpu/common/posix/clk_arb.c b/drivers/gpu/nvgpu/common/posix/clk_arb.c new file mode 100644 index 00000000..f41383cd --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/clk_arb.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2018, 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 + +/** + * Stub imlementation of the clk_arb code. Yikes. Much of this probably could be + * commonized if one were to think through the implementation but that is + * probably weeks of work at a minimum. + * + * So for POSIX it will be stubbed. + */ + +int nvgpu_clk_arb_init_arbiter(struct gk20a *g) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_get_arbiter_clk_range(struct gk20a *g, u32 api_domain, + u16 *min_mhz, u16 *max_mhz) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_get_arbiter_actual_mhz(struct gk20a *g, + u32 api_domain, u16 *actual_mhz) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_get_arbiter_effective_mhz(struct gk20a *g, + u32 api_domain, u16 *effective_mhz) +{ + return -ENOSYS; +} + + +int nvgpu_clk_arb_get_arbiter_clk_f_points(struct gk20a *g, + u32 api_domain, + u32 *max_points, u16 *fpoints) +{ + return -ENOSYS; +} + +u32 nvgpu_clk_arb_get_arbiter_clk_domains(struct gk20a *g) +{ + return 0; +} + +bool nvgpu_clk_arb_is_valid_domain(struct gk20a *g, u32 api_domain) +{ + return false; +} + +void nvgpu_clk_arb_cleanup_arbiter(struct gk20a *g) +{ +} + +int nvgpu_clk_arb_install_session_fd(struct gk20a *g, + struct nvgpu_clk_session *session) +{ + return -ENOSYS; +} + + +int nvgpu_clk_arb_init_session(struct gk20a *g, + struct nvgpu_clk_session **_session) +{ + return -ENOSYS; +} + +void nvgpu_clk_arb_release_session(struct gk20a *g, + struct nvgpu_clk_session *session) +{ +} + +int nvgpu_clk_arb_commit_request_fd(struct gk20a *g, + struct nvgpu_clk_session *session, + int request_fd) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_set_session_target_mhz(struct nvgpu_clk_session *session, + int fd, u32 api_domain, u16 target_mhz) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_get_session_target_mhz(struct nvgpu_clk_session *session, + u32 api_domain, u16 *target_mhz) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_install_event_fd(struct gk20a *g, + struct nvgpu_clk_session *session, + int *event_fd, u32 alarm_mask) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_install_request_fd(struct gk20a *g, + struct nvgpu_clk_session *session, + int *event_fd) +{ + return -ENOSYS; +} + +void nvgpu_clk_arb_schedule_vf_table_update(struct gk20a *g) +{ +} + +int nvgpu_clk_arb_get_current_pstate(struct gk20a *g) +{ + return -ENOSYS; +} + +void nvgpu_clk_arb_pstate_change_lock(struct gk20a *g, bool lock) +{ +} + +void nvgpu_clk_arb_send_thermal_alarm(struct gk20a *g) +{ +} + +void nvgpu_clk_arb_schedule_alarm(struct gk20a *g, u32 alarm) +{ +} diff --git a/drivers/gpu/nvgpu/common/posix/cond.c b/drivers/gpu/nvgpu/common/posix/cond.c new file mode 100644 index 00000000..ca8a2c4a --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/cond.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, 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 + +#include + +int nvgpu_cond_init(struct nvgpu_cond *cond) +{ + return -ENOSYS; +} + +int nvgpu_cond_signal(struct nvgpu_cond *cond) +{ + return -ENOSYS; +} + +int nvgpu_cond_signal_interruptible(struct nvgpu_cond *cond) +{ + return -ENOSYS; +} + +int nvgpu_cond_broadcast(struct nvgpu_cond *cond) +{ + return -ENOSYS; +} + +int nvgpu_cond_broadcast_interruptible(struct nvgpu_cond *cond) +{ + return -ENOSYS; +} + +void nvgpu_cond_destroy(struct nvgpu_cond *cond) +{ + +} diff --git a/drivers/gpu/nvgpu/common/posix/dma.c b/drivers/gpu/nvgpu/common/posix/dma.c new file mode 100644 index 00000000..23f59501 --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/dma.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2018, 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 + +#include +#include +#include +#include +#include +#include +#include + +/* + * In userspace vidmem vs sysmem is just a difference in what is placed in the + * aperture field. + */ +static int __nvgpu_do_dma_alloc(struct gk20a *g, unsigned long flags, + size_t size, struct nvgpu_mem *mem, + enum nvgpu_aperture ap) +{ + void *memory = malloc(mem->aligned_size); + + if (memory == NULL) + return -ENOMEM; + + mem->cpu_va = memory; + mem->aperture = ap; + mem->size = size; + mem->aligned_size = PAGE_ALIGN(size); + mem->gpu_va = 0ULL; + mem->skip_wmb = true; + mem->vidmem_alloc = NULL; + mem->allocator = NULL; + + return 0; +} + +bool nvgpu_iommuable(struct gk20a *g) +{ + return false; +} + +int nvgpu_dma_alloc(struct gk20a *g, size_t size, struct nvgpu_mem *mem) +{ + return nvgpu_dma_alloc_flags(g, 0, size, mem); +} + +int nvgpu_dma_alloc_flags(struct gk20a *g, unsigned long flags, size_t size, + struct nvgpu_mem *mem) +{ + if (!nvgpu_is_enabled(g, NVGPU_MM_UNIFIED_MEMORY)) { + /* + * First try vidmem. Obviously in userspace there's no such + * thing as vidmem per se but we will mark the aperture as + * vidmem. + */ + int err = nvgpu_dma_alloc_flags_vid(g, 0, size, mem); + + if (!err) + return 0; + /* + * Fall back to sysmem (which may then also fail) in case + * vidmem is exhausted. + */ + } + + return nvgpu_dma_alloc_flags_sys(g, flags, size, mem); + +} + +int nvgpu_dma_alloc_sys(struct gk20a *g, size_t size, struct nvgpu_mem *mem) +{ + return nvgpu_dma_alloc_flags_sys(g, 0, size, mem); +} + +int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags, + size_t size, struct nvgpu_mem *mem) +{ + return __nvgpu_do_dma_alloc(g, flags, size, mem, APERTURE_SYSMEM); +} + +int nvgpu_dma_alloc_vid(struct gk20a *g, size_t size, struct nvgpu_mem *mem) +{ + return nvgpu_dma_alloc_flags_vid(g, 0, size, mem); +} + +int nvgpu_dma_alloc_flags_vid(struct gk20a *g, unsigned long flags, + size_t size, struct nvgpu_mem *mem) +{ + return __nvgpu_do_dma_alloc(g, flags, size, mem, APERTURE_VIDMEM); +} + +int nvgpu_dma_alloc_flags_vid_at(struct gk20a *g, unsigned long flags, + size_t size, struct nvgpu_mem *mem, u64 at) +{ + BUG(); + + return 0; +} + +void nvgpu_dma_free(struct gk20a *g, struct nvgpu_mem *mem) +{ + if (!(mem->mem_flags & NVGPU_MEM_FLAG_SHADOW_COPY)) + free(mem->cpu_va); + + memset(mem, 0, sizeof(*mem)); +} + +int nvgpu_dma_alloc_map(struct vm_gk20a *vm, size_t size, + struct nvgpu_mem *mem) +{ + return nvgpu_dma_alloc_map_flags(vm, 0, size, mem); +} + +int nvgpu_dma_alloc_map_flags(struct vm_gk20a *vm, unsigned long flags, + size_t size, struct nvgpu_mem *mem) +{ + if (!nvgpu_is_enabled(gk20a_from_vm(vm), NVGPU_MM_UNIFIED_MEMORY)) { + int err = nvgpu_dma_alloc_map_flags_vid(vm, + flags | NVGPU_DMA_NO_KERNEL_MAPPING, + size, mem); + + if (!err) + return 0; + /* + * Fall back to sysmem (which may then also fail) in case + * vidmem is exhausted. + */ + } + + return nvgpu_dma_alloc_map_flags_sys(vm, flags, size, mem); +} + +int nvgpu_dma_alloc_map_sys(struct vm_gk20a *vm, size_t size, + struct nvgpu_mem *mem) +{ + return nvgpu_dma_alloc_map_flags_sys(vm, 0, size, mem); +} + +int nvgpu_dma_alloc_map_flags_sys(struct vm_gk20a *vm, unsigned long flags, + size_t size, struct nvgpu_mem *mem) +{ + int err = nvgpu_dma_alloc_flags_sys(vm->mm->g, flags, size, mem); + + if (err) + return err; + + mem->gpu_va = nvgpu_gmmu_map(vm, mem, size, 0, + gk20a_mem_flag_none, false, + mem->aperture); + if (!mem->gpu_va) { + err = -ENOMEM; + goto fail_free; + } + + return 0; + +fail_free: + nvgpu_dma_free(vm->mm->g, mem); + return err; +} + +int nvgpu_dma_alloc_map_vid(struct vm_gk20a *vm, size_t size, + struct nvgpu_mem *mem) +{ + return nvgpu_dma_alloc_map_flags_vid(vm, + NVGPU_DMA_NO_KERNEL_MAPPING, size, mem); +} + +int nvgpu_dma_alloc_map_flags_vid(struct vm_gk20a *vm, unsigned long flags, + size_t size, struct nvgpu_mem *mem) +{ + int err = nvgpu_dma_alloc_flags_vid(vm->mm->g, flags, size, mem); + + if (err) + return err; + + mem->gpu_va = nvgpu_gmmu_map(vm, mem, size, 0, + gk20a_mem_flag_none, false, + mem->aperture); + if (!mem->gpu_va) { + err = -ENOMEM; + goto fail_free; + } + + return 0; + +fail_free: + nvgpu_dma_free(vm->mm->g, mem); + return err; +} + +void nvgpu_dma_unmap_free(struct vm_gk20a *vm, struct nvgpu_mem *mem) +{ + if (mem->gpu_va) + nvgpu_gmmu_unmap(vm, mem, mem->gpu_va); + mem->gpu_va = 0; + + nvgpu_dma_free(vm->mm->g, mem); +} diff --git a/drivers/gpu/nvgpu/common/posix/error_notifier.c b/drivers/gpu/nvgpu/common/posix/error_notifier.c new file mode 100644 index 00000000..50b4f258 --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/error_notifier.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, 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 + +void nvgpu_set_error_notifier_locked(struct channel_gk20a *ch, u32 error) +{ +} + +void nvgpu_set_error_notifier(struct channel_gk20a *ch, u32 error) +{ +} + +void nvgpu_set_error_notifier_if_empty(struct channel_gk20a *ch, u32 error) +{ +} + +bool nvgpu_is_error_notifier_set(struct channel_gk20a *ch, u32 error_notifier) +{ + return false; +} diff --git a/drivers/gpu/nvgpu/common/posix/firmware.c b/drivers/gpu/nvgpu/common/posix/firmware.c new file mode 100644 index 00000000..aedfef9f --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/firmware.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018, 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 + +struct nvgpu_firmware *nvgpu_request_firmware(struct gk20a *g, + const char *fw_name, + int flags) +{ + return NULL; +} + +void nvgpu_release_firmware(struct gk20a *g, struct nvgpu_firmware *fw) +{ + /* Noop. */ +} diff --git a/drivers/gpu/nvgpu/common/posix/fuse.c b/drivers/gpu/nvgpu/common/posix/fuse.c new file mode 100644 index 00000000..09ec36dc --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/fuse.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, 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 + +int nvgpu_tegra_get_gpu_speedo_id(struct gk20a *g) +{ + return 0; +} + +void nvgpu_tegra_fuse_write_bypass(struct gk20a *g, u32 val) +{ +} + +void nvgpu_tegra_fuse_write_access_sw(struct gk20a *g, u32 val) +{ +} + +void nvgpu_tegra_fuse_write_opt_gpu_tpc0_disable(struct gk20a *g, u32 val) +{ +} + +void nvgpu_tegra_fuse_write_opt_gpu_tpc1_disable(struct gk20a *g, u32 val) +{ +} + +int nvgpu_tegra_fuse_read_gcplex_config_fuse(struct gk20a *g, u32 *val) +{ + return -ENODEV; +} + +int nvgpu_tegra_fuse_read_reserved_calib(struct gk20a *g, u32 *val) +{ + return -ENODEV; +} diff --git a/drivers/gpu/nvgpu/common/posix/io.c b/drivers/gpu/nvgpu/common/posix/io.c new file mode 100644 index 00000000..ce018940 --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/io.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, 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 +#include +#include + +/* + * For now none of these make sense to execute in userspace. Eventually we + * may want to use these to verify certain register read/write sequences + * but for now, just hang. + */ + +void nvgpu_writel(struct gk20a *g, u32 r, u32 v) +{ + BUG(); +} + +u32 nvgpu_readl(struct gk20a *g, u32 r) +{ + BUG(); + + return 0; +} + +u32 __nvgpu_readl(struct gk20a *g, u32 r) +{ + BUG(); + + return 0; +} + +void nvgpu_writel_check(struct gk20a *g, u32 r, u32 v) +{ + BUG(); +} + +void nvgpu_bar1_writel(struct gk20a *g, u32 b, u32 v) +{ + BUG(); +} + +u32 nvgpu_bar1_readl(struct gk20a *g, u32 b) +{ + BUG(); + + return 0; +} + +bool nvgpu_io_exists(struct gk20a *g) +{ + return false; +} + +bool nvgpu_io_valid_reg(struct gk20a *g, u32 r) +{ + return false; +} + +void nvgpu_usermode_writel(struct gk20a *g, u32 r, u32 v) +{ + BUG(); +} diff --git a/drivers/gpu/nvgpu/common/posix/kmem.c b/drivers/gpu/nvgpu/common/posix/kmem.c new file mode 100644 index 00000000..3c0b9b66 --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/kmem.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2018, 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 + +#include +#include +#include + +#include + +struct nvgpu_kmem_cache { + size_t alloc_size; +}; + +/* + * kmem cache emulation: basically just do a regular malloc(). This is slower + * but should not affect a user of kmem cache in the slightest bit. + */ +struct nvgpu_kmem_cache *nvgpu_kmem_cache_create(struct gk20a *g, size_t size) +{ + struct nvgpu_kmem_cache *cache = + malloc(sizeof(struct nvgpu_kmem_cache)); + + if (cache != NULL) + return NULL; + + cache->alloc_size = size; + + return cache; +} + +void nvgpu_kmem_cache_destroy(struct nvgpu_kmem_cache *cache) +{ + free(cache); +} + +void *nvgpu_kmem_cache_alloc(struct nvgpu_kmem_cache *cache) +{ + return malloc(cache->alloc_size); +} + +void nvgpu_kmem_cache_free(struct nvgpu_kmem_cache *cache, void *ptr) +{ + free(ptr); +} + +void *__nvgpu_kmalloc(struct gk20a *g, size_t size, unsigned long ip) +{ + return malloc(size); +} + +void *__nvgpu_kzalloc(struct gk20a *g, size_t size, unsigned long ip) +{ + return calloc(1, size); +} + +void *__nvgpu_kcalloc(struct gk20a *g, size_t n, size_t size, unsigned long ip) +{ + /* + * calloc() implicitly zeros mem. So calloc a single member size bytes + * long. + */ + return calloc(n, size); +} + +void __nvgpu_kfree(struct gk20a *g, void *addr) +{ + free(addr); +} + +/* + * The concept of vmalloc() does not exist in userspace. + */ +void *__nvgpu_vmalloc(struct gk20a *g, unsigned long size, unsigned long ip) +{ + return __nvgpu_kmalloc(g, size, ip); +} + +void *__nvgpu_vzalloc(struct gk20a *g, unsigned long size, unsigned long ip) +{ + return __nvgpu_kzalloc(g, size, ip); +} + +void __nvgpu_vfree(struct gk20a *g, void *addr) +{ + __nvgpu_kfree(g, addr); +} + +void *__nvgpu_big_alloc(struct gk20a *g, size_t size, bool clear) +{ + /* + * Since in userspace vmalloc() == kmalloc() == malloc() we can just + * reuse k[zm]alloc() for this. + */ + return clear ? + __nvgpu_kzalloc(g, size, _THIS_IP_) : + __nvgpu_kmalloc(g, size, _THIS_IP_); +} + +void nvgpu_big_free(struct gk20a *g, void *p) +{ + __nvgpu_kfree(g, p); +} + +int nvgpu_kmem_init(struct gk20a *g) +{ + /* Nothing to init at the moment. */ + return 0; +} + +void nvgpu_kmem_fini(struct gk20a *g, int flags) +{ + +} diff --git a/drivers/gpu/nvgpu/common/posix/lock.c b/drivers/gpu/nvgpu/common/posix/lock.c new file mode 100644 index 00000000..bca0f04c --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/lock.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, 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 +#include + +int nvgpu_mutex_init(struct nvgpu_mutex *mutex) +{ + return pthread_mutex_init(&mutex->lock.mutex, NULL); +} + +void nvgpu_mutex_acquire(struct nvgpu_mutex *mutex) +{ + __nvgpu_posix_lock_acquire(&mutex->lock); +} + +void nvgpu_mutex_release(struct nvgpu_mutex *mutex) +{ + __nvgpu_posix_lock_release(&mutex->lock); +} + +int nvgpu_mutex_tryacquire(struct nvgpu_mutex *mutex) +{ + return __nvgpu_posix_lock_try_acquire(&mutex->lock); +} + +void nvgpu_mutex_destroy(struct nvgpu_mutex *mutex) +{ + pthread_mutex_destroy(&mutex->lock.mutex); +} + +void nvgpu_spinlock_init(struct nvgpu_spinlock *spinlock) +{ + pthread_mutex_init(&spinlock->lock.mutex, NULL); +} + +void nvgpu_spinlock_acquire(struct nvgpu_spinlock *spinlock) +{ + __nvgpu_posix_lock_acquire(&spinlock->lock); +} + +void nvgpu_spinlock_release(struct nvgpu_spinlock *spinlock) +{ + __nvgpu_posix_lock_release(&spinlock->lock); +} + +void nvgpu_raw_spinlock_init(struct nvgpu_raw_spinlock *spinlock) +{ + pthread_mutex_init(&spinlock->lock.mutex, NULL); +} + +void nvgpu_raw_spinlock_acquire(struct nvgpu_raw_spinlock *spinlock) +{ + __nvgpu_posix_lock_acquire(&spinlock->lock); +} + +void nvgpu_raw_spinlock_release(struct nvgpu_raw_spinlock *spinlock) +{ + __nvgpu_posix_lock_release(&spinlock->lock); +} diff --git a/drivers/gpu/nvgpu/common/posix/log.c b/drivers/gpu/nvgpu/common/posix/log.c new file mode 100644 index 00000000..6bfb673c --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/log.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, 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 +#include + +#include "gk20a/gk20a.h" + +/* + * Define a length for log buffers. This is the buffer that the 'fmt, ...' part + * of __nvgpu_do_log_print() prints into. + */ +#define LOG_BUFFER_LENGTH 160 + +/* + * Keep this roughly the same as the kernel log format. + */ +#define LOG_FMT "nvgpu: %s %33s:%-4d [%-4s] %s\n" + +u64 nvgpu_dbg_mask = NVGPU_DEFAULT_DBG_MASK; + +static const char *log_types[] = { + "ERR", + "WRN", + "DBG", + "INFO", +}; + +static inline const char *nvgpu_log_name(struct gk20a *g) +{ + return "gpu.USS"; +} + +static void __nvgpu_really_print_log(const char *gpu_name, + const char *func_name, int line, + enum nvgpu_log_type type, const char *log) +{ + const char *name = gpu_name ? gpu_name : ""; + const char *log_type = log_types[type]; + + printf(LOG_FMT, name, func_name, line, log_type, log); +} + +__attribute__((format (printf, 5, 6))) +void __nvgpu_log_msg(struct gk20a *g, const char *func_name, int line, + enum nvgpu_log_type type, const char *fmt, ...) +{ + char log[LOG_BUFFER_LENGTH]; + va_list args; + + va_start(args, fmt); + vsnprintf(log, LOG_BUFFER_LENGTH, fmt, args); + va_end(args); + + __nvgpu_really_print_log(nvgpu_log_name(g), + func_name, line, type, log); +} + +__attribute__((format (printf, 5, 6))) +void __nvgpu_log_dbg(struct gk20a *g, u64 log_mask, + const char *func_name, int line, + const char *fmt, ...) +{ + char log[LOG_BUFFER_LENGTH]; + va_list args; + + if ((log_mask & g->log_mask) == 0) + return; + + va_start(args, fmt); + vsnprintf(log, LOG_BUFFER_LENGTH, fmt, args); + va_end(args); + + __nvgpu_really_print_log(nvgpu_log_name(g), + func_name, line, NVGPU_DEBUG, log); +} diff --git a/drivers/gpu/nvgpu/common/posix/nvgpu.c b/drivers/gpu/nvgpu/common/posix/nvgpu.c new file mode 100644 index 00000000..6f2a5fe9 --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/nvgpu.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2018, 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 +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "os_posix.h" + +#include "gk20a/gk20a.h" + +void nvgpu_wait_for_deferred_interrupts(struct gk20a *g) +{ + /* + * No interrupts in userspace so nothing to wait for. + */ +} + +int nvgpu_current_pid(struct gk20a *g) +{ + /* + * In the kernel this gets us the PID of the calling process for IOCTLs. + * But since we are in userspace this doesn't quite mean the same thing. + * This simply returns the PID of the currently running process. + */ + return (int)getpid(); +} + +int nvgpu_current_tid(struct gk20a *g) +{ + /* + * In POSIX thread ID is not the same as a process ID. In Linux threads + * and processes are represented by the same thing, but userspace can't + * really rely on that. + * + * We can, however, get a pthread_t for a given thread. But this + * pthread_t need not have any relation to the underlying system's + * representation of "threads". + */ + return (int)pthread_self(); +} + +/* + * Somewhat meaningless in userspace... + */ +void nvgpu_kernel_restart(void *cmd) +{ + BUG(); +} + +/* + * We have no runtime PM stuff in userspace so these are really just noops. + */ +void gk20a_busy_noresume(struct gk20a *g) +{ +} + +void gk20a_idle_nosuspend(struct gk20a *g) +{ +} + +int gk20a_busy(struct gk20a *g) +{ + nvgpu_atomic_inc(&g->usage_count); + + return 0; +} + +void gk20a_idle(struct gk20a *g) +{ + nvgpu_atomic_dec(&g->usage_count); +} + +/* + * This function aims to initialize enough stuff to make unit testing worth + * while. There are several interfaces and APIs that rely on the struct gk20a's + * state in order to function: logging, for example, but there are many other + * things, too. + * + * Initialize as much of that as possible here. This is meant to be equivalent + * to the kernel space driver's probe function. + */ +struct gk20a *nvgpu_posix_probe(void) +{ + struct gk20a *g; + struct nvgpu_os_posix *p; + int err; + + p = malloc(sizeof(*p)); + if (p == NULL) + return NULL; + + g = &p->g; + + err = nvgpu_kmem_init(g); + if (err != 0) + goto fail; + + return g; + +fail: + free(p); + + return NULL; +} + +void nvgpu_posix_cleanup(struct gk20a *g) +{ + nvgpu_kmem_fini(g, 0); +} diff --git a/drivers/gpu/nvgpu/common/posix/nvlink.c b/drivers/gpu/nvgpu/common/posix/nvlink.c new file mode 100644 index 00000000..c830d6ed --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/nvlink.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, 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 + +int nvgpu_nvlink_train(struct gk20a *g, u32 link_id, bool from_off) +{ + return -ENOSYS; +} + +int nvgpu_nvlink_enumerate(struct gk20a *g) +{ + return -ENOSYS; +} diff --git a/drivers/gpu/nvgpu/common/posix/os_posix.h b/drivers/gpu/nvgpu/common/posix/os_posix.h new file mode 100644 index 00000000..955186ef --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/os_posix.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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 __NVGPU_OS_POSIX_H__ +#define __NVGPU_OS_POSIX_H__ + +#include "gk20a/gk20a.h" + +struct nvgpu_os_posix { + struct gk20a g; +}; + +#endif diff --git a/drivers/gpu/nvgpu/common/posix/posix-comptags.c b/drivers/gpu/nvgpu/common/posix/posix-comptags.c new file mode 100644 index 00000000..a00246dd --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/posix-comptags.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018, 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 +#include + +#include + +void gk20a_get_comptags(struct nvgpu_os_buffer *buf, + struct gk20a_comptags *comptags) +{ +} + +int gk20a_alloc_or_get_comptags(struct gk20a *g, + struct nvgpu_os_buffer *buf, + struct gk20a_comptag_allocator *allocator, + struct gk20a_comptags *comptags) +{ + return -ENODEV; +} + +bool gk20a_comptags_start_clear(struct nvgpu_os_buffer *buf) +{ + return false; +} + +void gk20a_comptags_finish_clear(struct nvgpu_os_buffer *buf, + bool clear_successful) +{ +} diff --git a/drivers/gpu/nvgpu/common/posix/posix-nvgpu_mem.c b/drivers/gpu/nvgpu/common/posix/posix-nvgpu_mem.c new file mode 100644 index 00000000..f8feb6a2 --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/posix-nvgpu_mem.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2018, 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 +#include +#include +#include +#include + +/* + * DMA memory buffers - obviously we don't really have DMA in userspace but we + * can emulate a lot of the DMA mem functionality for unit testing purposes. + */ + +int nvgpu_mem_begin(struct gk20a *g, struct nvgpu_mem *mem) +{ + return 0; +} + +void nvgpu_mem_end(struct gk20a *g, struct nvgpu_mem *mem) +{ + return; +} + +u32 nvgpu_mem_rd32(struct gk20a *g, struct nvgpu_mem *mem, u32 w) +{ + u32 *mem_ptr = (u32 *)mem->cpu_va; + + return mem_ptr[w]; +} + +u32 nvgpu_mem_rd(struct gk20a *g, struct nvgpu_mem *mem, u32 offset) +{ + if (offset & 0x3) + BUG(); + + return nvgpu_mem_rd32(g, mem, offset >> 2); +} + +void nvgpu_mem_rd_n(struct gk20a *g, struct nvgpu_mem *mem, u32 offset, + void *dest, u32 size) +{ + if (offset & 0x3 || size & 0x3) + BUG(); + + memcpy(dest, ((char *)mem->cpu_va) + offset, size); +} + +void nvgpu_mem_wr32(struct gk20a *g, struct nvgpu_mem *mem, u32 w, u32 data) +{ + u32 *mem_ptr = (u32 *)mem->cpu_va; + + mem_ptr[w] = data; +} + +void nvgpu_mem_wr(struct gk20a *g, struct nvgpu_mem *mem, u32 offset, u32 data) +{ + if (offset & 0x3) + BUG(); + + nvgpu_mem_wr32(g, mem, offset >> 2, data); +} + +void nvgpu_mem_wr_n(struct gk20a *g, struct nvgpu_mem *mem, u32 offset, + void *src, u32 size) +{ + if (offset & 0x3 || size & 0x3) + BUG(); + + memcpy(((char *)mem->cpu_va) + offset, src, size); +} + +void nvgpu_memset(struct gk20a *g, struct nvgpu_mem *mem, u32 offset, + u32 c, u32 size) +{ + memset(((char *)mem->cpu_va) + offset, c, size); +} + +/* + * These functions are somewhat meaningless. + */ +u64 nvgpu_mem_get_addr(struct gk20a *g, struct nvgpu_mem *mem) +{ + return (u64)(uintptr_t)mem->cpu_va; +} + +u64 nvgpu_mem_get_phys_addr(struct gk20a *g, struct nvgpu_mem *mem) +{ + return (u64)(uintptr_t)mem->cpu_va; +} + +static struct nvgpu_sgl *nvgpu_mem_sgl_next(struct nvgpu_sgl *sgl) +{ + return NULL; +} + +static u64 nvgpu_mem_sgl_phys(struct gk20a *g, struct nvgpu_sgl *sgl) +{ + struct nvgpu_mem *mem = (struct nvgpu_mem *)sgl; + + return (u64)(uintptr_t)mem->cpu_va; +} + +static u64 nvgpu_mem_sgl_dma(struct nvgpu_sgl *sgl) +{ + struct nvgpu_mem *mem = (struct nvgpu_mem *)sgl; + + return (u64)(uintptr_t)mem->cpu_va; +} + +static u64 nvgpu_mem_sgl_length(struct nvgpu_sgl *sgl) +{ + struct nvgpu_mem *mem = (struct nvgpu_mem *)sgl; + + return (u64)mem->aligned_size; +} + +static u64 nvgpu_mem_sgl_gpu_addr(struct gk20a *g, struct nvgpu_sgl *sgl, + struct nvgpu_gmmu_attrs *attrs) +{ + struct nvgpu_mem *mem = (struct nvgpu_mem *)sgl; + + return mem->gpu_va; +} + +static bool nvgpu_mem_sgt_iommuable(struct gk20a *g, struct nvgpu_sgt *sgt) +{ + return nvgpu_iommuable(g); +} + +static void nvgpu_mem_sgt_free(struct gk20a *g, struct nvgpu_sgt *sgt) +{ + nvgpu_kfree(g, sgt); +} + +static struct nvgpu_sgt_ops nvgpu_sgt_posix_ops = { + .sgl_next = nvgpu_mem_sgl_next, + .sgl_phys = nvgpu_mem_sgl_phys, + .sgl_dma = nvgpu_mem_sgl_dma, + .sgl_length = nvgpu_mem_sgl_length, + .sgl_gpu_addr = nvgpu_mem_sgl_gpu_addr, + .sgt_iommuable = nvgpu_mem_sgt_iommuable, + .sgt_free = nvgpu_mem_sgt_free, +}; + +struct nvgpu_sgt *nvgpu_sgt_create_from_mem(struct gk20a *g, + struct nvgpu_mem *mem) +{ + struct nvgpu_sgt *sgt = nvgpu_kzalloc(g, sizeof(*sgt)); + + if (sgt == NULL) + return NULL; + + /* + * The userspace implementation is simple: a single 'entry' (which we + * only need the mem struct to describe). Maybe this could be expanded + * to be more interesting some day. + */ + sgt->sgl = (struct nvgpu_sgl *)mem; + sgt->ops = &nvgpu_sgt_posix_ops; + + return sgt; +} + +int nvgpu_mem_create_from_mem(struct gk20a *g, + struct nvgpu_mem *dest, struct nvgpu_mem *src, + int start_page, int nr_pages) +{ + u64 start = start_page * PAGE_SIZE; + u64 size = nr_pages * PAGE_SIZE; + + if (src->aperture != APERTURE_SYSMEM) + return -EINVAL; + + /* Some silly things a caller might do... */ + if (size > src->size) + return -EINVAL; + if ((start + size) > src->size) + return -EINVAL; + + memset(dest, 0, sizeof(*dest)); + + dest->cpu_va = ((char *)src->cpu_va) + start; + dest->mem_flags = src->mem_flags | NVGPU_MEM_FLAG_SHADOW_COPY; + dest->aperture = src->aperture; + dest->skip_wmb = src->skip_wmb; + dest->size = size; + + return 0; +} diff --git a/drivers/gpu/nvgpu/common/posix/posix-vm.c b/drivers/gpu/nvgpu/common/posix/posix-vm.c new file mode 100644 index 00000000..588b956d --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/posix-vm.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018, 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 + +#include +#include + +#include + +u64 nvgpu_os_buf_get_size(struct nvgpu_os_buffer *os_buf) +{ + return os_buf->size; +} + +struct nvgpu_mapped_buf *nvgpu_vm_find_mapping(struct vm_gk20a *vm, + struct nvgpu_os_buffer *os_buf, + u64 map_addr, + u32 flags, + int kind) +{ + BUG(); + + /* + * No map caching for now. + */ + return NULL; +} + +void nvgpu_vm_unmap_system(struct nvgpu_mapped_buf *mapped_buffer) +{ + free(mapped_buffer->os_priv.buf); +} diff --git a/drivers/gpu/nvgpu/common/posix/rwsem.c b/drivers/gpu/nvgpu/common/posix/rwsem.c new file mode 100644 index 00000000..7a696b75 --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/rwsem.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018, 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 +#include +#include + +#include + +void nvgpu_rwsem_init(struct nvgpu_rwsem *rwsem) +{ + memset(rwsem, 0, sizeof(*rwsem)); + + nvgpu_spinlock_init(&rwsem->lock); +} + +/* + * Acquire. + */ +void nvgpu_rwsem_down_read(struct nvgpu_rwsem *rwsem) +{ + while (true) { + nvgpu_spinlock_acquire(&rwsem->lock); + + /* + * If there's a writer try again. + */ + if (rwsem->writers < 0) { + nvgpu_spinlock_release(&rwsem->lock); + nvgpu_msleep(10); + continue; + } + + /* + * Otherwise decrement the read counter and return. + */ + rwsem->readers -= 1; + nvgpu_spinlock_release(&rwsem->lock); + return; + } +} + +/* + * Release. + */ +void nvgpu_rwsem_up_read(struct nvgpu_rwsem *rwsem) +{ + nvgpu_spinlock_acquire(&rwsem->lock); + rwsem->readers += 1; + + /* + * Can't be any writers if there was a reader. Also can't be + * a positive number of readers. The increments are always + * downward so if we have a positive number then there is a + * balancing bug. + */ + BUG_ON(rwsem->writers < 0); + BUG_ON(rwsem->readers > 0); + + nvgpu_spinlock_release(&rwsem->lock); +} + +void nvgpu_rwsem_down_write(struct nvgpu_rwsem *rwsem) +{ + while (true) { + nvgpu_spinlock_acquire(&rwsem->lock); + + /* + * If there's a reader or a writer try again. Note: in this very + * simple implementation it's possible for readers to + * indefinitely starve writers. + */ + if (rwsem->writers < 0 || rwsem->readers < 0) { + nvgpu_spinlock_release(&rwsem->lock); + nvgpu_msleep(10); + continue; + } + + rwsem->writers -= 1; + nvgpu_spinlock_release(&rwsem->lock); + return; + } +} + +void nvgpu_rwsem_up_write(struct nvgpu_rwsem *rwsem) +{ + nvgpu_spinlock_acquire(&rwsem->lock); + rwsem->writers += 1; + + /* + * Writers can't be positive: that would be an unbalanced free. Readers + * must be zero - otherwise this writer should never have had access! + */ + BUG_ON(rwsem->writers > 0); + BUG_ON(rwsem->readers != 0); + + nvgpu_spinlock_release(&rwsem->lock); +} diff --git a/drivers/gpu/nvgpu/common/posix/soc.c b/drivers/gpu/nvgpu/common/posix/soc.c new file mode 100644 index 00000000..0e5c7141 --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/soc.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018, 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 + +bool nvgpu_platform_is_silicon(struct gk20a *g) +{ + return false; +} + +bool nvgpu_platform_is_simulation(struct gk20a *g) +{ + return false; +} + +bool nvgpu_platform_is_fpga(struct gk20a *g) +{ + return false; +} + +bool nvgpu_is_hypervisor_mode(struct gk20a *g) +{ + return false; +} + +bool nvgpu_is_bpmp_running(struct gk20a *g) +{ + return false; +} diff --git a/drivers/gpu/nvgpu/common/posix/stubs.c b/drivers/gpu/nvgpu/common/posix/stubs.c new file mode 100644 index 00000000..d6270692 --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/stubs.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +/** + * Here lie OS stubs that do not have an implementation yet nor has any plans + * for an implementation. + */ + +#include "gk20a/dbg_gpu_gk20a.h" + +void nvgpu_dbg_session_post_event(struct dbg_session_gk20a *dbg_s) +{ +} diff --git a/drivers/gpu/nvgpu/common/posix/thread.c b/drivers/gpu/nvgpu/common/posix/thread.c new file mode 100644 index 00000000..d9476523 --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/thread.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2018, 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 +#include + +#include + +/** + * Use pthreads to mostly emulate the Linux kernel APIs. There are some things + * that are quite different - especially the stop/should_stop notions. In user + * space threads can send signals to one another but of course within the kernel + * that is not as simple. + * + * This could use some nice debugging some day as well. + */ + +/* + * nvgpu thread functions return int. POSIX threads return void *. This little + * wrapper takes the int returning nvgpu thread and instead passes that int back + * through the void * pointer. + */ +static void *__nvgpu_posix_thread_wrapper(void *data) +{ + struct nvgpu_posix_thread_data *nvgpu = data; + + return ERR_PTR(nvgpu->fn(nvgpu->data)); +} + +int nvgpu_thread_create(struct nvgpu_thread *thread, + void *data, + int (*threadfn)(void *data), const char *name) +{ + int ret; + + BUG_ON(thread->running); + + memset(thread, 0, sizeof(*thread)); + + /* + * By subtracting 1 the above memset ensures that we have a zero + * terminated string. + */ + strncpy(thread->tname, name, NVGPU_THREAD_POSIX_MAX_NAMELEN - 1); + + thread->nvgpu.data = data; + thread->nvgpu.fn = threadfn; + + ret = pthread_create(&thread->thread, NULL, + __nvgpu_posix_thread_wrapper, + &thread->nvgpu); + if (ret != 0) + return ret; + +#ifdef _GNU_SOURCE + pthread_setname_np(thread->thread, thread->tname); +#endif + + thread->running = true; + + return 0; +} + +void nvgpu_thread_stop(struct nvgpu_thread *thread) +{ + thread->should_stop = true; +} + +bool nvgpu_thread_should_stop(struct nvgpu_thread *thread) +{ + return thread->should_stop; +} + +bool nvgpu_thread_is_running(struct nvgpu_thread *thread) +{ + return thread->running; +} diff --git a/drivers/gpu/nvgpu/common/posix/timers.c b/drivers/gpu/nvgpu/common/posix/timers.c new file mode 100644 index 00000000..c84b0de5 --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/timers.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2018, 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 + +#include +#include +#include + +static s64 now(void) +{ + return nvgpu_current_time_ms(); +} + +/* + * Returns true if a > b; + */ +static bool time_after(s64 a, s64 b) +{ + return a - b > 0; +} + +int nvgpu_timeout_init(struct gk20a *g, struct nvgpu_timeout *timeout, + u32 duration, unsigned long flags) +{ + if (flags & ~NVGPU_TIMER_FLAG_MASK) + return -EINVAL; + + memset(timeout, 0, sizeof(*timeout)); + + timeout->g = g; + timeout->flags = flags; + + if (flags & NVGPU_TIMER_RETRY_TIMER) + timeout->retries.max = duration; + else + timeout->time = nvgpu_current_time_ms() + (s64)duration; + + return 0; +} + +static int __nvgpu_timeout_expired_msg_cpu(struct nvgpu_timeout *timeout, + void *caller, + const char *fmt, va_list args) +{ + struct gk20a *g = timeout->g; + + if (time_after(now(), timeout->time)) { + if (!(timeout->flags & NVGPU_TIMER_SILENT_TIMEOUT)) { + char buf[128]; + + vsnprintf(buf, sizeof(buf), fmt, args); + + nvgpu_err(g, "Timeout detected @ %p %s", caller, buf); + } + + return -ETIMEDOUT; + } + + return 0; +} + +static int __nvgpu_timeout_expired_msg_retry(struct nvgpu_timeout *timeout, + void *caller, + const char *fmt, va_list args) +{ + struct gk20a *g = timeout->g; + + if (timeout->retries.attempted >= timeout->retries.max) { + if (!(timeout->flags & NVGPU_TIMER_SILENT_TIMEOUT)) { + char buf[128]; + + vsnprintf(buf, sizeof(buf), fmt, args); + + nvgpu_err(g, "No more retries @ %p %s", caller, buf); + } + + return -ETIMEDOUT; + } + + timeout->retries.attempted++; + + return 0; +} + +int __nvgpu_timeout_expired_msg(struct nvgpu_timeout *timeout, + void *caller, const char *fmt, ...) +{ + int ret; + va_list args; + + va_start(args, fmt); + if (timeout->flags & NVGPU_TIMER_RETRY_TIMER) + ret = __nvgpu_timeout_expired_msg_retry(timeout, caller, fmt, + args); + else + ret = __nvgpu_timeout_expired_msg_cpu(timeout, caller, fmt, + args); + va_end(args); + + return ret; +} + +int nvgpu_timeout_peek_expired(struct nvgpu_timeout *timeout) +{ + if (timeout->flags & NVGPU_TIMER_RETRY_TIMER) + return timeout->retries.attempted >= timeout->retries.max; + else + return time_after(now(), timeout->time); +} + +void nvgpu_udelay(unsigned int usecs) +{ + BUG(); +} + +void nvgpu_usleep_range(unsigned int min_us, unsigned int max_us) +{ + BUG(); +} + +void nvgpu_msleep(unsigned int msecs) +{ + BUG(); +} + +static inline s64 __nvgpu_current_time_us(void) +{ + struct timeval now; + s64 time_now; + int ret; + + ret = gettimeofday(&now, NULL); + if (ret != 0) + BUG(); + + time_now = ((s64)now.tv_sec * (s64)1000000) + (s64)now.tv_usec; + + return time_now; +} + +s64 nvgpu_current_time_ms(void) +{ + return __nvgpu_current_time_us() / (s64)1000; +} + +u64 nvgpu_hr_timestamp(void) +{ + return __nvgpu_current_time_us(); +} diff --git a/drivers/gpu/nvgpu/common/posix/tsg.c b/drivers/gpu/nvgpu/common/posix/tsg.c new file mode 100644 index 00000000..8736123d --- /dev/null +++ b/drivers/gpu/nvgpu/common/posix/tsg.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018, 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 "gk20a/tsg_gk20a.h" + +void gk20a_tsg_event_id_post_event(struct tsg_gk20a *tsg, + int __event_id) +{ +} -- cgit v1.2.2