diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2015-08-20 14:54:05 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2015-08-28 12:37:26 +1000 |
commit | cf43fc0391a257fb17414d8b41746b9e16093578 (patch) | |
tree | 389b7f77db26a321fe0368262aa8888edcb55a5c /lib | |
parent | a1d7077da37dfe2c3f89d1445f5b78e63de5666c (diff) | |
download | nouveau-cf43fc0391a257fb17414d8b41746b9e16093578.tar.gz |
lib: various tweaks
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile | 8 | ||||
-rw-r--r-- | lib/bit.c | 28 | ||||
-rw-r--r-- | lib/drm.c | 21 | ||||
-rw-r--r-- | lib/include/nvif/list.h | 3 | ||||
-rw-r--r-- | lib/include/nvif/os.h | 105 | ||||
-rw-r--r-- | lib/main.c | 89 | ||||
-rw-r--r-- | lib/null.c | 2 | ||||
-rw-r--r-- | lib/work.c | 107 |
8 files changed, 232 insertions, 131 deletions
diff --git a/lib/Makefile b/lib/Makefile index 82706f872..ca3be266d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,4 +1,4 @@ -LIBNVIF_CC := $(CFLAGS) -I$(drm) -fPIC +LIBNVIF_CC := $(CFLAGS) -I$(drm) -fPIC -Wframe-larger-than=1024 LIBNVIF_LD := $(LDFLAGS) -shared -lpciaccess -lpthread -ldrm src := $(drm) @@ -26,10 +26,12 @@ fucs := $(drm)/nvkm/engine/ce/fuc/gt215.fuc3.h \ $(drm)/nvkm/engine/sec/fuc/g98.fuc0s.h drms := $(addprefix $(lib)/, $(nvif-y)) \ $(addprefix $(lib)/, $(nvkm-y)) -srcs := $(lib)/drm.o \ +srcs := $(lib)/bit.o \ + $(lib)/drm.o \ $(lib)/intr.o \ $(lib)/main.o \ - $(lib)/null.o + $(lib)/null.o \ + $(lib)/work.o outp := $(lib)/libnvif.so deps-fuc := $(fucs:$(drm)/%.h=$(lib)/%.d) diff --git a/lib/bit.c b/lib/bit.c new file mode 100644 index 000000000..520aecd6f --- /dev/null +++ b/lib/bit.c @@ -0,0 +1,28 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "priv.h" + +const struct i2c_algorithm +i2c_bit_algo = { +}; @@ -170,8 +170,8 @@ drm_client_init(const char *name, u64 device, const char *cfg, int ret, minor; char path[128]; - if (ret = -ENOMEM, !(drm = *ppriv = malloc(sizeof(*drm)))) - goto fail; + if (!(drm = *ppriv = calloc(1, sizeof(*drm)))) + return -ENOMEM; for (minor = DRM_RENDER_MIN; minor <= DRM_RENDER_MAX; minor++) { snprintf(path, sizeof(path), "/dev/dri/renderD%d", minor); @@ -181,27 +181,24 @@ drm_client_init(const char *name, u64 device, const char *cfg, continue; if (!strcmp(ver->name, "nouveau")) break; - free(ver); + drmFreeVersion(ver); } - if (ret = -ENODEV, minor > DRM_RENDER_MAX) - goto fail; + if (minor > DRM_RENDER_MAX) + return -ENODEV; drm->version = (ver->version_major << 24) | (ver->version_minor << 8) | ver->version_patchlevel; - free(ver); - if (ret = -ENOSYS, drm->version < 0x01000200) - goto fail; + drmFreeVersion(ver); + if (drm->version < 0x01000200) + return -ENOSYS; if ((ret = pthread_create(&drm->event, NULL, drm_client_event, drm))) - goto fail; + return ret; drm->done = true; return 0; -fail: - drm_client_fini(drm); - return ret; } const struct nvif_driver diff --git a/lib/include/nvif/list.h b/lib/include/nvif/list.h index f273376ec..2bed23c29 100644 --- a/lib/include/nvif/list.h +++ b/lib/include/nvif/list.h @@ -252,7 +252,8 @@ list_empty(struct list_head *head) */ #ifndef container_of #define container_of(ptr, type, member) ({ \ - (type *)((char *)(ptr) - (char *) &((type *)0)->member); \ + typeof(((type *)0)->member) *__mptr = (ptr); \ + (type *)((char *)(__mptr) - (char *) &((type *)0)->member); \ }) #endif diff --git a/lib/include/nvif/os.h b/lib/include/nvif/os.h index 71a369ec2..bd958403c 100644 --- a/lib/include/nvif/os.h +++ b/lib/include/nvif/os.h @@ -34,22 +34,22 @@ #include <limits.h> #include <ctype.h> -typedef uint64_t u64; +__extension__ typedef unsigned long long u64; typedef uint32_t u32; typedef uint16_t u16; typedef uint8_t u8; -typedef int64_t s64; +__extension__ typedef long long s64; typedef int32_t s32; typedef int16_t s16; typedef int8_t s8; #ifndef _ASM_GENERIC_INT_LL64_H -typedef uint64_t __u64; +__extension__ typedef unsigned long long __u64; typedef uint32_t __u32; typedef uint16_t __u16; typedef uint8_t __u8; -typedef int64_t __s64; +__extension__ typedef long long __s64; typedef int32_t __s32; typedef int16_t __s16; typedef int8_t __s8; @@ -266,28 +266,28 @@ typedef struct atomic { /****************************************************************************** * ktime *****************************************************************************/ -#include <sys/time.h> +#include <time.h> -typedef struct timeval ktime_t; +typedef struct timespec ktime_t; static inline ktime_t ktime_get(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - return tv; + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts; } static inline s64 -ktime_to_us(ktime_t kt) +ktime_to_ns(ktime_t kt) { - return kt.tv_sec * 1000000 + kt.tv_usec; + return (s64)kt.tv_sec * 1000000000 + kt.tv_nsec; } static inline s64 -ktime_to_ns(ktime_t kt) +ktime_to_us(ktime_t kt) { - return ktime_to_us(kt) * 1000; + return ktime_to_ns(kt) / 1000; } /****************************************************************************** @@ -424,17 +424,19 @@ get_num_physpages(void) static inline void nvos_backtrace(void) { - void *buffer[512]; + void **buffer; char **sinfo; int ninfo, i; - ninfo = backtrace(buffer, sizeof(buffer)); + buffer = malloc(sizeof(*buffer) * 512); + ninfo = backtrace(buffer, 512); sinfo = backtrace_symbols(buffer, ninfo); if (sinfo) { for (i = 0; i < ninfo; i++) printf("%s\n", sinfo[i]); free(sinfo); } + free(buffer); } #define BUG() do { \ @@ -497,7 +499,9 @@ typedef struct spinlock_t { #define DEFINE_SPINLOCK(a) spinlock_t a = { .lock = PTHREAD_MUTEX_INITIALIZER } -#define spin_lock_init(a) pthread_mutex_init(&(a)->lock, NULL) +#define spin_lock_init(a) do { \ + (a)->lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; \ +} while(0) #define spin_lock(a) pthread_mutex_lock(&(a)->lock) #define spin_unlock(a) pthread_mutex_unlock(&(a)->lock) #define spin_lock_irqsave(a,b) do { (b) = 1; spin_lock((a)); } while (0) @@ -939,7 +943,7 @@ request_firmware(const struct firmware **pfw, const char *name, return 0; } free(fw); - return errno; + return -EINVAL; } static inline void @@ -952,60 +956,20 @@ release_firmware(const struct firmware *fw) /****************************************************************************** * workqueues *****************************************************************************/ -struct work_struct; - -typedef void (*work_func_t)(struct work_struct *); - struct work_struct { - work_func_t func; - pthread_mutex_t mutex; - pthread_t thread; - bool pending; + union { + void (*func)(struct work_struct *); + void (*exec)(void *); + }; + struct nvos_work *nvos; }; -static inline void -INIT_WORK(struct work_struct *work, work_func_t func) -{ - pthread_mutex_init(&work->mutex, NULL); - work->func = func; - work->pending = false; -} +#define INIT_WORK(a,b) ((a)->func = (b), (a)->nvos = NULL) +#define schedule_work(a) BUG_ON(!nvos_work_init((a)->exec, (a), &(a)->nvos)) +#define flush_work(a) nvos_work_fini(&(a)->nvos) -static inline void * -os_work(void *arg) -{ - struct work_struct *work = arg; - work_func_t func; - do { - pthread_mutex_lock(&work->mutex); - if (work->pending) { - work->pending = false; - func = work->func; - } else { - func = NULL; - } - pthread_mutex_unlock(&work->mutex); - if (func) - func(work); - } while (func); - return NULL; -} - -static inline void -schedule_work(struct work_struct *work) -{ - pthread_mutex_lock(&work->mutex); - if (!work->pending) { - work->pending = true; - assert(!pthread_create(&work->thread, NULL, os_work, work)); - } - pthread_mutex_unlock(&work->mutex); -} - -static inline void -flush_work(struct work_struct *work) -{ -} +bool nvos_work_init(void (*)(void *), void *, struct nvos_work **); +void nvos_work_fini(struct nvos_work **); /****************************************************************************** * waitqueues @@ -1140,10 +1104,6 @@ i2c_transfer(struct i2c_adapter *a, struct i2c_msg *m, int num) * i2c bit-bang *****************************************************************************/ -static struct i2c_algorithm -i2c_bit_algo = { -}; - struct i2c_algo_bit_data { int udelay; unsigned long timeout; @@ -1159,10 +1119,11 @@ struct i2c_algo_bit_data { static inline int i2c_bit_add_bus(struct i2c_adapter *a) { - (void)i2c_bit_algo; return 0; } +extern const struct i2c_algorithm i2c_bit_algo; + /****************************************************************************** * delay *****************************************************************************/ diff --git a/lib/main.c b/lib/main.c index ac03c9684..6201c3ca3 100644 --- a/lib/main.c +++ b/lib/main.c @@ -47,6 +47,7 @@ static int os_client_nr = 0; /****************************************************************************** * horrific stuff to implement linux's ioremap interface on top of pciaccess *****************************************************************************/ +static DEFINE_MUTEX(os_ioremap_mutex); static struct os_ioremap_info { struct pci_device *pdev; int refs; @@ -56,54 +57,54 @@ static struct os_ioremap_info { } os_ioremap[32]; void __iomem * -nvos_ioremap(u64 addr, u64 size) +nvos_ioremap_bar(struct pci_device *pdev, int bar, u64 addr) { - struct pci_device *pdev = NULL; - struct os_ioremap_info *info; - struct os_device *odev; - u64 m_page = addr & 0xfff; - u64 m_addr = addr & ~0xfff; - u64 m_size = (size + 0xfff) & ~0xfff; + u64 base = pdev->regions[bar].base_addr; + u64 size = pdev->regions[bar].size; + u64 offset = addr - base; + void __iomem *ptr = NULL; int i; - list_for_each_entry(odev, &os_device_list, head) { - for (i = 0; i < 6; i++) { - pdev = odev->base.pdev->pdev; - if (m_addr >= pdev->regions[i].base_addr && - m_addr + m_size <= pdev->regions[i].base_addr + - pdev->regions[i].size) - break; - pdev = NULL; + mutex_lock(&os_ioremap_mutex); + for (i = 0; !ptr && i < ARRAY_SIZE(os_ioremap); i++) { + if (os_ioremap[i].refs && os_ioremap[i].addr == base) { + os_ioremap[i].refs++; + ptr = os_ioremap[i].ptr + offset; } - if (pdev) - break; } - for (i = 0, info = NULL; pdev && i < ARRAY_SIZE(os_ioremap); i++) { - if (os_ioremap[i].refs) { - if (os_ioremap[i].addr != m_addr || - os_ioremap[i].size != m_size) - continue; - } else { - info = &os_ioremap[i]; - continue; + for (i = 0; !ptr && i < ARRAY_SIZE(os_ioremap); i++) { + if (!os_ioremap[i].refs && + !pci_device_map_range(pdev, base, size, + PCI_DEV_MAP_FLAG_WRITABLE, + &os_ioremap[i].ptr)) { + os_ioremap[i].pdev = pdev; + os_ioremap[i].refs = 1; + os_ioremap[i].addr = base; + os_ioremap[i].size = size; + ptr = os_ioremap[i].ptr + offset; } - - os_ioremap[i].refs++; - return os_ioremap[i].ptr + m_page; } + mutex_unlock(&os_ioremap_mutex); + + return ptr; +} - if (info) { - if (pci_device_map_range(pdev, m_addr, m_size, - PCI_DEV_MAP_FLAG_WRITABLE, - &info->ptr)) - return NULL; - - info->pdev = pdev; - info->refs = 1; - info->addr = m_addr; - info->size = m_size; - return info->ptr + m_page; +void __iomem * +nvos_ioremap(u64 addr, u64 size) +{ + struct os_device *odev; + int i; + + list_for_each_entry(odev, &os_device_list, head) { + struct pci_device *pdev = odev->base.pdev->pdev; + for (i = 0; i < ARRAY_SIZE(pdev->regions); i++) { + if (addr >= pdev->regions[i].base_addr && + addr + size <= pdev->regions[i].base_addr + + pdev->regions[i].size) { + return nvos_ioremap_bar(pdev, i, addr); + } + } } return NULL; @@ -114,17 +115,20 @@ nvos_iounmap(void __iomem *ptr) { int i; + mutex_lock(&os_ioremap_mutex); for (i = 0; ptr && i < ARRAY_SIZE(os_ioremap); i++) { if (os_ioremap[i].refs && ptr >= os_ioremap[i].ptr && ptr < os_ioremap[i].ptr + os_ioremap[i].size) { if (!--os_ioremap[i].refs) { - pci_device_unmap_range(os_ioremap[i].pdev, ptr, + pci_device_unmap_range(os_ioremap[i].pdev, + os_ioremap[i].ptr, os_ioremap[i].size); } break; } } + mutex_unlock(&os_ioremap_mutex); } /****************************************************************************** @@ -152,7 +156,7 @@ os_init_device(struct pci_device *pdev, u64 handle, const char *cfg, const char return -EEXIST; } - ldev = malloc(sizeof(*ldev)); + ldev = calloc(1, sizeof(*ldev)); ldev->pdev = pdev; ldev->device = pdev->dev; ldev->subsystem_vendor = pdev->subvendor_id; @@ -163,6 +167,7 @@ os_init_device(struct pci_device *pdev, u64 handle, const char *cfg, const char cfg, dbg, &odev); if (ret) { fprintf(stderr, "failed to create device, %d\n", ret); + free(name); return ret; } @@ -196,7 +201,7 @@ os_init(const char *cfg, const char *dbg, bool init) (pdev->dev << 8) | pdev->func; if (!init) { - printf("%d: 0x%010"PRIx64" PCI:%04x:%02x:%02x:%02x " + printf("%d: 0x%010llx PCI:%04x:%02x:%02x:%02x " "(%04x:%04x)\n", n++, handle, pdev->domain, pdev->bus, pdev->dev, pdev->func, pdev->vendor_id, pdev->device_id); diff --git a/lib/null.c b/lib/null.c index 45f613e85..8f35b944b 100644 --- a/lib/null.c +++ b/lib/null.c @@ -105,7 +105,7 @@ static int null_client_init(const char *name, u64 device, const char *cfg, const char *dbg, void **ppriv) { - struct nvkm_client *client; + struct nvkm_client *client = NULL; int ret; mutex_lock(&null_mutex); diff --git a/lib/work.c b/lib/work.c new file mode 100644 index 000000000..3311023ea --- /dev/null +++ b/lib/work.c @@ -0,0 +1,107 @@ +/* + * Copyright 2015 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ +#include "priv.h" + +struct nvos_work { + pthread_mutex_t mutex; + pthread_cond_t cond; + pthread_t thread; + bool done; + + void (*func)(void *); + void *priv; +}; + +static void * +nvos_work(void *data) +{ + struct nvos_work *work = data; + + do { + pthread_mutex_lock(&work->mutex); + while (!work->priv && !work->done) + pthread_cond_wait(&work->cond, &work->mutex); + if (work->priv) { + work->func(work->priv); + work->priv = NULL; + } + pthread_mutex_unlock(&work->mutex); + } while (!work->done); + + return NULL; +} + +void +nvos_work_fini(struct nvos_work **pwork) +{ + struct nvos_work *work = *pwork; + if (work) { + pthread_mutex_lock(&work->mutex); + work->done = true; + pthread_cond_signal(&work->cond); + pthread_mutex_unlock(&work->mutex); + + pthread_join(work->thread, NULL); + pthread_cond_destroy(&work->cond); + pthread_mutex_destroy(&work->mutex); + free(*pwork); + *pwork = NULL; + } +} + +bool +nvos_work_init(void (*func)(void *), void *priv, struct nvos_work **pwork) +{ + struct nvos_work *work = *pwork; + + if (unlikely(work == NULL)) { + if (!(work = calloc(1, sizeof(*work)))) + return false; + work->func = func; + work->priv = NULL; + work->done = false; + + if (pthread_mutex_init(&work->mutex, NULL)) + goto fail_mutex; + if (pthread_cond_init(&work->cond, NULL)) + goto fail_cond; + if (pthread_create(&work->thread, NULL, nvos_work, work)) + goto fail_thread; + *pwork = work; + } + + pthread_mutex_lock(&work->mutex); + work->priv = priv; + pthread_cond_signal(&work->cond); + pthread_mutex_unlock(&work->mutex); + return true; + +fail_thread: + pthread_cond_destroy(&work->cond); +fail_cond: + pthread_mutex_destroy(&work->mutex); +fail_mutex: + free(work); + return false; +} |