diff options
-rw-r--r-- | shared-core/nouveau_drm.h | 1 | ||||
-rw-r--r-- | shared-core/nouveau_drv.h | 29 | ||||
-rw-r--r-- | shared-core/nouveau_fifo.c | 8 | ||||
-rw-r--r-- | shared-core/nouveau_mem.c | 43 | ||||
-rw-r--r-- | shared-core/nouveau_object.c | 67 | ||||
-rw-r--r-- | shared-core/nouveau_state.c | 3 |
6 files changed, 81 insertions, 70 deletions
diff --git a/shared-core/nouveau_drm.h b/shared-core/nouveau_drm.h index 2517bbc3..2874d36a 100644 --- a/shared-core/nouveau_drm.h +++ b/shared-core/nouveau_drm.h @@ -69,6 +69,7 @@ drm_nouveau_dma_object_init_t; #define NOUVEAU_MEM_PINNED 0x00000010 #define NOUVEAU_MEM_USER_BACKED 0x00000020 #define NOUVEAU_MEM_MAPPED 0x00000040 +#define NOUVEAU_MEM_INSTANCE 0x00000080 /* internal */ typedef struct drm_nouveau_mem_alloc { int flags; diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 93887839..be8f4cf4 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -52,11 +52,12 @@ struct nouveau_object struct nouveau_object *next; struct nouveau_object *prev; + struct mem_block *instance; + uint32_t ht_loc; + uint32_t handle; int class; int engine; - uint32_t instance; - uint32_t ht_loc; }; #define NV_DMA_TARGET_VIDMEM 0 @@ -77,14 +78,6 @@ struct nouveau_fifo struct nouveau_object *objs; }; -struct nouveau_object_store -{ - uint32_t *inst_bmap; - uint32_t first_instance; - int num_instance; - int free_instance; -}; - struct mem_block { struct mem_block *next; struct mem_block *prev; @@ -119,7 +112,7 @@ typedef struct drm_nouveau_private { int fifo_alloc_count; struct nouveau_fifo fifos[NV_MAX_FIFO_NUMBER]; - struct nouveau_object_store objs; + /* RAMFC and RAMRO offsets */ uint32_t ramht_offset; uint32_t ramht_size; @@ -132,6 +125,7 @@ typedef struct drm_nouveau_private { struct mem_block *agp_heap; struct mem_block *fb_heap; struct mem_block *fb_nomap_heap; + struct mem_block *ramin_heap; struct nouveau_config config; } @@ -155,6 +149,12 @@ extern struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment extern void nouveau_mem_free(struct drm_device* dev, struct mem_block*); extern int nouveau_mem_init(struct drm_device *dev); extern void nouveau_mem_close(struct drm_device *dev); +extern int nouveau_instmem_init(struct drm_device *dev, + uint32_t offset, uint32_t size); +extern struct mem_block* nouveau_instmem_alloc(struct drm_device *dev, + uint32_t size, uint32_t align); +extern void nouveau_instmem_free(struct drm_device *dev, + struct mem_block *block); /* nouveau_fifo.c */ extern int nouveau_fifo_init(drm_device_t *dev); @@ -163,13 +163,12 @@ extern void nouveau_fifo_cleanup(drm_device_t *dev, DRMFILE filp); extern int nouveau_fifo_id_get(drm_device_t *dev, DRMFILE filp); /* nouveau_object.c */ -extern int nouveau_object_init(drm_device_t *dev); extern void nouveau_object_cleanup(drm_device_t *dev, DRMFILE filp); extern struct nouveau_object *nouveau_dma_object_create(drm_device_t *dev, uint32_t offset, uint32_t size, int access, uint32_t target); extern int nouveau_ioctl_object_init(DRM_IOCTL_ARGS); extern int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS); -extern uint32_t nouveau_chip_instance_get(drm_device_t *dev, uint32_t instance); +extern uint32_t nouveau_chip_instance_get(drm_device_t *dev, struct mem_block *mem); /* nouveau_irq.c */ extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); @@ -188,8 +187,8 @@ extern long nouveau_compat_ioctl(struct file *filp, unsigned int cmd, #define NV_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) #endif -#define INSTANCE_WR(inst,ofs,val) NV_WRITE(NV_RAMIN+(inst)+((ofs)<<2),(val)) -#define INSTANCE_RD(inst,ofs) NV_READ(NV_RAMIN+(inst)+((ofs)<<2)) +#define INSTANCE_WR(mem,ofs,val) NV_WRITE(NV_RAMIN+(uint32_t)(mem)->start+((ofs)<<2),(val)) +#define INSTANCE_RD(mem,ofs) NV_READ(NV_RAMIN+(uint32_t)(mem)->start+((ofs)<<2)) #endif /* __NOUVEAU_DRV_H__ */ diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 9ff0563c..94762139 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -69,6 +69,7 @@ static int nouveau_fifo_ctx_size(drm_device_t* dev) static int nouveau_fifo_instmem_configure(drm_device_t *dev) { drm_nouveau_private_t *dev_priv = dev->dev_private; + uint32_t obj_base, obj_size; int i; /* Clear RAMIN */ @@ -123,6 +124,13 @@ static int nouveau_fifo_instmem_configure(drm_device_t *dev) dev_priv->ramfc_offset, dev_priv->ramfc_size); + obj_base = dev_priv->ramfc_offset + dev_priv->ramfc_size; + obj_size = (512*1024) - obj_base; /*XXX: probably wrong on some cards*/ + if (nouveau_instmem_init(dev, obj_base, obj_size)) + return 1; + DRM_DEBUG("RAMIN object space: offset=0x%08x, size=%dKiB\n", + obj_base, obj_size>>10); + return 0; } diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c index 897badd4..93b9c869 100644 --- a/shared-core/nouveau_mem.c +++ b/shared-core/nouveau_mem.c @@ -443,6 +443,49 @@ void nouveau_mem_free(struct drm_device* dev, struct mem_block* block) free_block(block); } +int nouveau_instmem_init(struct drm_device *dev, uint32_t offset, + uint32_t size) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + int ret; + + ret = init_heap(&dev_priv->ramin_heap, offset, size); + if (ret) { + dev_priv->ramin_heap = NULL; + DRM_ERROR("Failed to init RAMIN heap\n"); + } + + return ret; +} + +struct mem_block *nouveau_instmem_alloc(struct drm_device *dev, + uint32_t size, uint32_t align) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct mem_block *block; + + if (!dev_priv->ramin_heap) { + DRM_ERROR("instmem alloc called without init\n"); + return NULL; + } + + block = alloc_block(dev_priv->ramin_heap, size, align, (DRMFILE)-2); + if (block) { + block->flags = NOUVEAU_MEM_INSTANCE; + DRM_DEBUG("instance(size=%d, align=%d) alloc'd at 0x%08x\n", + size, (1<<align), block->start); + } + + return block; +} + +void nouveau_instmem_free(struct drm_device *dev, struct mem_block *block) +{ + if (dev && block) { + free_block(block); + } +} + /* * Ioctls */ diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c index 2c899335..c11b05eb 100644 --- a/shared-core/nouveau_object.c +++ b/shared-core/nouveau_object.c @@ -44,9 +44,13 @@ * in the future when we can access more instance ram which isn't mapped into * the PRAMIN aperture */ -uint32_t nouveau_chip_instance_get(drm_device_t *dev, uint32_t instance) +uint32_t nouveau_chip_instance_get(drm_device_t *dev, + struct mem_block *mem) { - return (instance>>4); + uint32_t inst = (uint32_t)mem->start >> 4; + DRM_DEBUG("****** on-chip instance for 0x%016llx = 0x%08x\n", + mem->start, inst); + return inst; } static void nouveau_object_link(drm_device_t *dev, int fifo_num, @@ -212,27 +216,7 @@ static void nouveau_hash_table_remove(drm_device_t* dev, static struct nouveau_object *nouveau_instance_alloc(drm_device_t* dev) { drm_nouveau_private_t *dev_priv=dev->dev_private; - struct nouveau_object_store *objs=&dev_priv->objs; struct nouveau_object *obj; - int instance = -1; - int i = 0, j = 0; - - /* Allocate a block of instance RAM */ - if (!objs->free_instance) { - DRM_ERROR("no free instance ram\n"); - return NULL; - } - for (i=0;i<(objs->num_instance>>5);i++) { - if (objs->inst_bmap[i] == ~0) continue; - for (j=0;j<32;j++) { - if (!(objs->inst_bmap[i] & (1<<j))) { - instance = (i<<5) + j; - break; - } - } - if (instance != -1) break; - } - DRM_DEBUG("alloced instance %d (slot %d/%d)\n", instance, i, j); /* Create object struct */ obj = drm_calloc(1, sizeof(struct nouveau_object), DRM_MEM_DRIVER); @@ -240,13 +224,13 @@ static struct nouveau_object *nouveau_instance_alloc(drm_device_t* dev) DRM_ERROR("couldn't alloc memory for object\n"); return NULL; } - obj->instance = objs->first_instance; - obj->instance += (instance << (dev_priv->card_type >= NV_40 ? 5 : 4)); - DRM_DEBUG("instance address is 0x%08x\n", instance); - - /* Mark instance slot as used */ - objs->inst_bmap[i] |= (1 << j); - objs->free_instance--; + obj->instance = nouveau_instmem_alloc(dev, + (dev_priv->card_type >= NV_40 ? 32 : 16), 4); + if (!obj->instance) { + DRM_ERROR("couldn't alloc RAMIN for object\n"); + drm_free(obj, sizeof(struct nouveau_object), DRM_MEM_DRIVER); + return NULL; + } return obj; } @@ -255,9 +239,7 @@ static void nouveau_object_instance_free(drm_device_t *dev, struct nouveau_object *obj) { drm_nouveau_private_t *dev_priv=dev->dev_private; - struct nouveau_object_store *objs=&dev_priv->objs; int count, i; - uint32_t be, bb; if (dev_priv->card_type >= NV_40) count = 8; @@ -274,27 +256,8 @@ static void nouveau_object_instance_free(drm_device_t *dev, INSTANCE_WR(obj->instance, i, 0x00000000); } - /* Mark instance as free */ - obj->instance -= objs->first_instance; - obj->instance >>= (dev_priv->card_type >=NV_40 ? 5 : 4); - be = obj->instance / 32; - bb = obj->instance % 32; - objs->inst_bmap[be] &= ~(1<<bb); - objs->free_instance++; -} - -int nouveau_object_init(drm_device_t* dev) -{ - drm_nouveau_private_t *dev_priv=dev->dev_private; - - dev_priv->objs.first_instance = - dev_priv->ramfc_offset +dev_priv->ramfc_size; - dev_priv->objs.free_instance = 1024; /*FIXME*/ - dev_priv->objs.num_instance = 1024; /*FIXME*/ - dev_priv->objs.inst_bmap = drm_calloc - (1, dev_priv->objs.num_instance/32, DRM_MEM_DRIVER); - - return 0; + /* Free RAMIN */ + nouveau_instmem_free(dev, obj->instance); } /* diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 1128da54..b2934b43 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -70,9 +70,6 @@ int nouveau_firstopen(struct drm_device *dev) */ ret = nouveau_fifo_init(dev); if (ret) return ret; - /* Initialise instance memory allocation */ - ret = nouveau_object_init(dev); - if (ret) return ret; /* FIXME: doesn't belong here, and have no idea what it's for.. */ if (dev_priv->card_type >= NV_40) { |