summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2015-08-20 14:54:05 +1000
committerBen Skeggs <bskeggs@redhat.com>2015-08-28 12:37:26 +1000
commitcf43fc0391a257fb17414d8b41746b9e16093578 (patch)
tree389b7f77db26a321fe0368262aa8888edcb55a5c /lib
parenta1d7077da37dfe2c3f89d1445f5b78e63de5666c (diff)
downloadnouveau-cf43fc0391a257fb17414d8b41746b9e16093578.tar.gz
lib: various tweaks
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile8
-rw-r--r--lib/bit.c28
-rw-r--r--lib/drm.c21
-rw-r--r--lib/include/nvif/list.h3
-rw-r--r--lib/include/nvif/os.h105
-rw-r--r--lib/main.c89
-rw-r--r--lib/null.c2
-rw-r--r--lib/work.c107
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 = {
+};
diff --git a/lib/drm.c b/lib/drm.c
index ac68e1f8d..bb96a7f2d 100644
--- a/lib/drm.c
+++ b/lib/drm.c
@@ -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;
+}