From 24896ddaada09f9d5764927753869437bc3c9d3b Mon Sep 17 00:00:00 2001 From: Shinpei Kato Date: Wed, 7 Dec 2011 19:11:33 -0800 Subject: [PATCH] pscnv: fixed missing pscnv_mem_free() in pscnv_mm.c gdev: added LOCK() and UNLOCK() macros gdev: added vas_list to the gdev device object --- common/gdev_api.c | 32 +++++++++++++++++++------------- common/gdev_list.h | 22 +++++++++++++++++++++- common/gdev_nvidia.c | 19 +++++++++++++------ common/gdev_nvidia.h | 1 + common/gdev_proto.h | 13 ++++++++----- driver/gdev/gdev_drv.h | 16 ++++++++++++++++ driver/pscnv/nvc0_vm.c | 5 ++++- driver/pscnv/pscnv_gdev.c | 4 ++++ runtime/user/gdev/gdev_lib.h | 21 +++++++++++++++++++++ 9 files changed, 107 insertions(+), 26 deletions(-) diff --git a/common/gdev_api.c b/common/gdev_api.c index e69bf817..ab60890f 100644 --- a/common/gdev_api.c +++ b/common/gdev_api.c @@ -106,9 +106,6 @@ struct gdev_handle *gopen(int minor) if (!ctx) goto fail_ctx; - /* initialize the list of memory spaces. */ - gdev_heap_init(vas); - /* allocate static bounce bound buffer objects. */ dma_mem = __malloc_dma(h, vas, GDEV_CHUNK_DEFAULT_SIZE); if (!dma_mem) @@ -120,6 +117,11 @@ struct gdev_handle *gopen(int minor) h->gdev = gdev; h->dev_id = minor; + /* insert the created VAS object to the device VAS list. */ + LOCK(&gdev->vas_lock); + gdev_vas_list_add(vas); + UNLOCK(&gdev->vas_lock); + GDEV_PRINT("Opened gdev%d.\n", minor); return h; @@ -162,6 +164,10 @@ int gclose(struct gdev_handle *h) if (!dma_mem) return -ENOENT; + /* delete the VAS object from the device VAS list. */ + LOCK(&gdev->vas_lock); + gdev_vas_list_del(vas); + UNLOCK(&gdev->vas_lock); /* free the bounce buffer. */ __free_dma(h, dma_mem); /* free all memory left in heap. */ @@ -198,7 +204,7 @@ uint64_t gmalloc(struct gdev_handle *h, uint64_t size) return 0; } - gdev_heap_add(mem, GDEV_MEM_DEVICE); + gdev_mem_list_add(mem, GDEV_MEM_DEVICE); GDEV_DPRINT("Allocated 0x%x at 0x%x in device.\n", (uint32_t) size, (uint32_t) GDEV_MEM_ADDR(mem)); @@ -214,8 +220,8 @@ int gfree(struct gdev_handle *h, uint64_t addr) gdev_vas_t *vas = h->vas; gdev_mem_t *mem; - if ((mem = gdev_heap_lookup(vas, addr, GDEV_MEM_DEVICE))) { - gdev_heap_del(mem); + if ((mem = gdev_mem_lookup(vas, addr, GDEV_MEM_DEVICE))) { + gdev_mem_list_del(mem); gdev_mem_free(mem); GDEV_DPRINT("Freed at 0x%x.\n", (uint32_t) GDEV_MEM_ADDR(mem)); return 0; @@ -244,7 +250,7 @@ void *gmalloc_dma(struct gdev_handle *h, uint64_t size) return 0; } - gdev_heap_add(mem, GDEV_MEM_DMA); + gdev_mem_list_add(mem, GDEV_MEM_DMA); GDEV_DPRINT("Allocated 0x%x at 0x%x in host DMA.\n", (uint32_t) size, (uint32_t) GDEV_MEM_ADDR(mem)); @@ -260,8 +266,8 @@ int gfree_dma(struct gdev_handle *h, void *buf) gdev_vas_t *vas = h->vas; gdev_mem_t *mem; - if ((mem = gdev_heap_lookup(vas, (uint64_t)buf, GDEV_MEM_DMA))) { - gdev_heap_del(mem); + if ((mem = gdev_mem_lookup(vas, (uint64_t)buf, GDEV_MEM_DMA))) { + gdev_mem_list_del(mem); gdev_mem_free(mem); GDEV_DPRINT("Freed at 0x%x.\n", (uint32_t) GDEV_MEM_ADDR(mem)); return 0; @@ -608,7 +614,7 @@ int gmemcpy_to_device (struct gdev_handle *h, uint64_t dst_addr, const void *src_buf, uint64_t size) { gdev_vas_t *vas = h->vas; - gdev_mem_t *hmem = gdev_heap_lookup(vas, (uint64_t)src_buf, GDEV_MEM_DMA); + gdev_mem_t *hmem = gdev_mem_lookup(vas, (uint64_t)src_buf, GDEV_MEM_DMA); if (hmem) return __gmemcpy_dma_to_device(h, dst_addr, hmem->addr, size); @@ -628,7 +634,7 @@ int gmemcpy_user_to_device (struct gdev_handle *h, uint64_t dst_addr, const void *src_buf, uint64_t size) { gdev_vas_t *vas = h->vas; - gdev_mem_t *hmem = gdev_heap_lookup(vas, (uint64_t)src_buf, GDEV_MEM_DMA); + gdev_mem_t *hmem = gdev_mem_lookup(vas, (uint64_t)src_buf, GDEV_MEM_DMA); if (hmem) return __gmemcpy_dma_to_device(h, dst_addr, hmem->addr, size); @@ -648,7 +654,7 @@ int gmemcpy_from_device (struct gdev_handle *h, void *dst_buf, uint64_t src_addr, uint64_t size) { gdev_vas_t *vas = h->vas; - gdev_mem_t *hmem = gdev_heap_lookup(vas, (uint64_t)dst_buf, GDEV_MEM_DMA); + gdev_mem_t *hmem = gdev_mem_lookup(vas, (uint64_t)dst_buf, GDEV_MEM_DMA); if (hmem) return __gmemcpy_dma_from_device(h, hmem->addr, src_addr, size); @@ -668,7 +674,7 @@ int gmemcpy_user_from_device (struct gdev_handle *h, void *dst_buf, uint64_t src_addr, uint64_t size) { gdev_vas_t *vas = h->vas; - gdev_mem_t *hmem = gdev_heap_lookup(vas, (uint64_t)dst_buf, GDEV_MEM_DMA); + gdev_mem_t *hmem = gdev_mem_lookup(vas, (uint64_t)dst_buf, GDEV_MEM_DMA); if (hmem) return __gmemcpy_dma_from_device(h, hmem->addr, src_addr, size); diff --git a/common/gdev_list.h b/common/gdev_list.h index bf2d0c6c..2e8a4fd4 100644 --- a/common/gdev_list.h +++ b/common/gdev_list.h @@ -47,7 +47,7 @@ static inline void gdev_list_add (struct gdev_list *entry, struct gdev_list *head) { struct gdev_list *next = head->next; - + entry->next = next; if (next) next->prev = entry; @@ -69,6 +69,11 @@ static inline void gdev_list_del(struct gdev_list *entry) } } +static inline int gdev_list_empty(struct gdev_list *entry) +{ + return entry->next == entry->prev; +} + static inline struct gdev_list *gdev_list_head(struct gdev_list *head) { return head ? head->next : NULL; @@ -84,4 +89,19 @@ static inline void *gdev_list_container(struct gdev_list *entry) p != NULL; \ p = gdev_list_container((p)->list_entry.next)) +#define gdev_list_add_ordered(entry, head, member) \ + do { \ + struct gdev_list *p, *tail = head; \ + (entry)->next = (entry)->prev = NULL; \ + gdev_list_for_each(p, head) { \ + if ((entry)->member <= p->member) { \ + gdev_list_add(entry, p); \ + break; \ + } \ + tail = p; \ + } \ + if (gdev_list_empty(entry)) \ + gdev_list_add(entry, tail); \ + } while (0) + #endif diff --git a/common/gdev_nvidia.c b/common/gdev_nvidia.c index 7a4a8e27..c749d338 100644 --- a/common/gdev_nvidia.c +++ b/common/gdev_nvidia.c @@ -40,6 +40,7 @@ int gdev_compute_init(struct gdev_device *gdev, int minor, void *priv) gdev->mem_used = 0; gdev_query(gdev, GDEV_NVIDIA_QUERY_DEVICE_MEM_SIZE, &gdev->mem_size); gdev_query(gdev, GDEV_NVIDIA_QUERY_CHIPSET, (uint64_t*) &gdev->chipset); + gdev_list_init(&gdev->vas_list, NULL); /* VAS list. */ switch (gdev->chipset & 0xf0) { case 0xC0: @@ -60,14 +61,20 @@ int gdev_compute_init(struct gdev_device *gdev, int minor, void *priv) return 0; } -void gdev_heap_init(struct gdev_vas *vas) +void gdev_vas_list_add(struct gdev_vas *vas) { - gdev_list_init(&vas->mem_list, NULL); /* device memory list. */ - gdev_list_init(&vas->dma_mem_list, NULL); /* host dma memory list. */ + struct gdev_device *gdev = vas->gdev; + gdev_list_add(&vas->list_entry, &gdev->vas_list); +} + +/* delete the VAS object from the device VAS list. */ +void gdev_vas_list_del(struct gdev_vas *vas) +{ + gdev_list_del(&vas->list_entry); } /* add the device memory object to the memory list. */ -void gdev_heap_add(struct gdev_mem *mem, int type) +void gdev_mem_list_add(struct gdev_mem *mem, int type) { struct gdev_vas *vas = mem->vas; @@ -84,13 +91,13 @@ void gdev_heap_add(struct gdev_mem *mem, int type) } /* delete the device memory object from the memory list. */ -void gdev_heap_del(struct gdev_mem *mem) +void gdev_mem_list_del(struct gdev_mem *mem) { gdev_list_del(&mem->list_entry); } /* look up the memory object allocated at the specified address. */ -struct gdev_mem *gdev_heap_lookup(struct gdev_vas *vas, uint64_t addr, int type) +struct gdev_mem *gdev_mem_lookup(struct gdev_vas *vas, uint64_t addr, int type) { struct gdev_mem *mem; diff --git a/common/gdev_nvidia.h b/common/gdev_nvidia.h index 45b72ab8..7a8595a4 100644 --- a/common/gdev_nvidia.h +++ b/common/gdev_nvidia.h @@ -99,6 +99,7 @@ struct gdev_vas { struct gdev_device *gdev; /* vas is associated with a specific device. */ struct gdev_list mem_list; /* list of device memory spaces. */ struct gdev_list dma_mem_list; /* list of host dma memory spaces. */ + struct gdev_list list_entry; /* entry to the vas list. */ }; /** diff --git a/common/gdev_proto.h b/common/gdev_proto.h index e86aa614..6012b525 100644 --- a/common/gdev_proto.h +++ b/common/gdev_proto.h @@ -51,6 +51,8 @@ struct gdev_device { uint64_t dma_mem_used; void *priv; /* private device object */ void *compute; /* private set of compute functions */ + struct gdev_list vas_list; /* list of VASes allocated to this device. */ + gdev_lock_t vas_lock; }; /** @@ -74,13 +76,14 @@ uint32_t gdev_launch(gdev_ctx_t *, struct gdev_kernel *); int gdev_poll(gdev_ctx_t *, int, uint32_t, struct gdev_time *); /** - * runtime/driver/architecture-independent heap operations. + * runtime/driver/architecture-independent operations. */ int gdev_compute_init(struct gdev_device *, int, void *); -void gdev_heap_init(gdev_vas_t *); -void gdev_heap_add(gdev_mem_t *, int); -void gdev_heap_del(gdev_mem_t *); -gdev_mem_t *gdev_heap_lookup(gdev_vas_t *, uint64_t, int); +void gdev_vas_list_add(gdev_vas_t *); +void gdev_vas_list_del(gdev_vas_t *); +void gdev_mem_list_add(gdev_mem_t *, int); +void gdev_mem_list_del(gdev_mem_t *); +gdev_mem_t *gdev_mem_lookup(gdev_vas_t *, uint64_t, int); void gdev_garbage_collect(gdev_vas_t *); #endif diff --git a/driver/gdev/gdev_drv.h b/driver/gdev/gdev_drv.h index a09ef2b7..cf5c8d95 100644 --- a/driver/gdev/gdev_drv.h +++ b/driver/gdev/gdev_drv.h @@ -46,6 +46,22 @@ copy_from_user(dst, (void __user *) src, size) #define COPY_TO_USER(dst, src, size) \ copy_to_user((void __user *) dst, src, size) +#define LOCK(ptr) gdev_lock_drv(ptr) +#define UNLOCK(ptr) gdev_unlock_drv(ptr) + +/* typedefs for kernel-specific types. */ +typedef spinlock_t gdev_lock_t; + +static inline void gdev_lock_drv(gdev_lock_t *lock) +{ + spin_lock_irq(lock); +} + +static inline void gdev_unlock_drv(gdev_lock_t *lock) +{ + spin_unlock_irq(lock); +} + /** * Gdev init/exit functions: diff --git a/driver/pscnv/nvc0_vm.c b/driver/pscnv/nvc0_vm.c index b5e72dea..1c1aeea8 100644 --- a/driver/pscnv/nvc0_vm.c +++ b/driver/pscnv/nvc0_vm.c @@ -134,8 +134,11 @@ void nvc0_pgt_del(struct pscnv_vspace *vs, struct nvc0_pgt *pgt) { pscnv_vram_free(pgt->bo[1]); - if (pgt->bo[0]) + pscnv_mem_free(pgt->bo[1]); + if (pgt->bo[0]) { pscnv_vram_free(pgt->bo[0]); + pscnv_mem_free(pgt->bo[0]); + } list_del(&pgt->head); nv_wv32(nvc0_vs(vs)->pd, pgt->pde * 8 + 0, 0); diff --git a/driver/pscnv/pscnv_gdev.c b/driver/pscnv/pscnv_gdev.c index 3cba1648..2b06d1f3 100644 --- a/driver/pscnv/pscnv_gdev.c +++ b/driver/pscnv/pscnv_gdev.c @@ -172,6 +172,10 @@ struct gdev_vas *gdev_vas_new(struct gdev_device *gdev, uint64_t size) vas->gdev = gdev; vas->pvas = vspace; /* driver private object. */ + gdev_list_init(&vas->list_entry, (void *) vas); /* entry to VAS list. */ + gdev_list_init(&vas->mem_list, NULL); /* device memory list. */ + gdev_list_init(&vas->dma_mem_list, NULL); /* host dma memory list. */ + return vas; fail_vspace: diff --git a/runtime/user/gdev/gdev_lib.h b/runtime/user/gdev/gdev_lib.h index c50cdb0c..46d1773f 100644 --- a/runtime/user/gdev/gdev_lib.h +++ b/runtime/user/gdev/gdev_lib.h @@ -31,6 +31,7 @@ #include /* printf, etc. */ #include /* malloc/free, etc. */ #include /* memcpy, etc. */ +#include /* struct sembuf */ #define GDEV_PRINT(fmt, arg...) fprintf(stderr, "[gdev] " fmt, ##arg) #define GDEV_DPRINT(fmt, arg...) \ @@ -47,6 +48,26 @@ #endif #define COPY_FROM_USER(dst, src, size) memcpy(dst, src, size) #define COPY_TO_USER(dst, src, size) memcpy(dst, src, size) +#define LOCK(ptr) gdev_lock_user(ptr) +#define UNLOCK(ptr) gdev_unlock_user(ptr) + +/* typedefs for user-specific types. */ +typedef struct gdev_sem_struct { + int semid; + struct sembuf sembuf; +} gdev_lock_t; + +static inline void gdev_init_lock_user(gdev_lock_t *lock) +{ +} + +static inline void gdev_lock_user(gdev_lock_t *lock) +{ +} + +static inline void gdev_unlock_user(gdev_lock_t *lock) +{ +} #define DRM_DIR_NAME "/dev/dri" #define DRM_DEV_NAME "%s/card%d"