/* * gk20a allocator * * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "gk20a/gk20a.h" #include "gk20a/mm_gk20a.h" u64 nvgpu_alloc_length(struct nvgpu_allocator *a) { if (a->ops->length) return a->ops->length(a); return 0; } u64 nvgpu_alloc_base(struct nvgpu_allocator *a) { if (a->ops->base) return a->ops->base(a); return 0; } u64 nvgpu_alloc_initialized(struct nvgpu_allocator *a) { if (!a->ops || !a->ops->inited) return 0; return a->ops->inited(a); } u64 nvgpu_alloc_end(struct nvgpu_allocator *a) { if (a->ops->end) return a->ops->end(a); return 0; } u64 nvgpu_alloc_space(struct nvgpu_allocator *a) { if (a->ops->space) return a->ops->space(a); return 0; } u64 nvgpu_alloc(struct nvgpu_allocator *a, u64 len) { return a->ops->alloc(a, len); } void nvgpu_free(struct nvgpu_allocator *a, u64 addr) { a->ops->free(a, addr); } u64 nvgpu_alloc_fixed(struct nvgpu_allocator *a, u64 base, u64 len, u32 page_size) { if (a->ops->alloc_fixed) return a->ops->alloc_fixed(a, base, len, page_size); return 0; } void nvgpu_free_fixed(struct nvgpu_allocator *a, u64 base, u64 len) { /* * If this operation is not defined for the allocator then just do * nothing. The alternative would be to fall back on the regular * free but that may be harmful in unexpected ways. */ if (a->ops->free_fixed) a->ops->free_fixed(a, base, len); } int nvgpu_alloc_reserve_carveout(struct nvgpu_allocator *a, struct nvgpu_alloc_carveout *co) { if (a->ops->reserve_carveout) return a->ops->reserve_carveout(a, co); return -ENODEV; } void nvgpu_alloc_release_carveout(struct nvgpu_allocator *a, struct nvgpu_alloc_carveout *co) { if (a->ops->release_carveout) a->ops->release_carveout(a, co); } void nvgpu_alloc_destroy(struct nvgpu_allocator *a) { a->ops->fini(a); nvgpu_mutex_destroy(&a->lock); memset(a, 0, sizeof(*a)); } #ifdef __KERNEL__ void nvgpu_alloc_print_stats(struct nvgpu_allocator *__a, struct seq_file *s, int lock) { __a->ops->print_stats(__a, s, lock); } #endif /* * Handle the common init stuff for a nvgpu_allocator. */ int __nvgpu_alloc_common_init(struct nvgpu_allocator *a, struct gk20a *g, const char *name, void *priv, bool dbg, const struct nvgpu_allocator_ops *ops) { int err; if (!ops) return -EINVAL; /* * This is the bare minimum operations required for a sensible * allocator. */ if (!ops->alloc || !ops->free || !ops->fini) return -EINVAL; err = nvgpu_mutex_init(&a->lock); if (err) return err; a->g = g; a->ops = ops; a->priv = priv; a->debug = dbg; strlcpy(a->name, name, sizeof(a->name)); return 0; }