nouveau: Various internal and external API changes

1. DRM_NOUVEAU_GPUOBJ_FREE
	Used to free GPU objects.  The obvious usage case is for Gr objects,
	but notifiers can also be destroyed in the same way.

	GPU objects gain a destructor method and private data fields with
	this change, so other specialised cases (like notifiers) can be
	implemented on top of gpuobjs.

2. DRM_NOUVEAU_CHANNEL_FREE

3. DRM_NOUVEAU_CARD_INIT
	Ideally we'd do init during module load, but this isn't currently
	possible.  Doing init during firstopen() is bad as X has a love of
	opening/closing the DRM many times during startup.  Once the
	modesetting-101 branch is merged this can go away.

	IRQs are enabled in nouveau_card_init() now, rather than having the
	X server call drmCtlInstHandler().  We'll need this for when we give
	the kernel module its own channel.

4. DRM_NOUVEAU_GETPARAM
	Add CHIPSET_ID value, which will return the chipset id derived
	from NV_PMC_BOOT_0.

4. Use list_* in a few places, rather than home-brewed stuff.
main
Ben Skeggs 2007-08-06 21:45:18 +10:00
parent beaa0c9a28
commit 97770db720
10 changed files with 205 additions and 94 deletions

View File

@ -1075,6 +1075,7 @@ extern void drm_core_reclaim_buffers(struct drm_device *dev,
extern int drm_control(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
extern int drm_irq_install(struct drm_device *dev);
extern int drm_irq_uninstall(struct drm_device *dev);
extern void drm_driver_irq_preinstall(struct drm_device *dev);
extern void drm_driver_irq_postinstall(struct drm_device *dev);

View File

@ -80,7 +80,7 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
* \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
* before and after the installation.
*/
static int drm_irq_install(struct drm_device * dev)
int drm_irq_install(struct drm_device * dev)
{
int ret;
unsigned long sh_flags = 0;
@ -140,6 +140,7 @@ static int drm_irq_install(struct drm_device * dev)
return 0;
}
EXPORT_SYMBOL(drm_irq_install);
/**
* Uninstall the IRQ handler.

View File

@ -25,9 +25,9 @@
#ifndef __NOUVEAU_DRM_H__
#define __NOUVEAU_DRM_H__
#define NOUVEAU_DRM_HEADER_PATCHLEVEL 9
#define NOUVEAU_DRM_HEADER_PATCHLEVEL 10
struct drm_nouveau_fifo_alloc {
struct drm_nouveau_channel_alloc {
uint32_t fb_ctxdma_handle;
uint32_t tt_ctxdma_handle;
@ -44,6 +44,10 @@ struct drm_nouveau_fifo_alloc {
int notifier_size;
};
struct drm_nouveau_channel_free {
int channel;
};
struct drm_nouveau_grobj_alloc {
int channel;
uint32_t handle;
@ -53,7 +57,7 @@ struct drm_nouveau_grobj_alloc {
#define NOUVEAU_MEM_ACCESS_RO 1
#define NOUVEAU_MEM_ACCESS_WO 2
#define NOUVEAU_MEM_ACCESS_RW 3
struct drm_nouveau_notifier_alloc {
struct drm_nouveau_notifierobj_alloc {
int channel;
uint32_t handle;
int count;
@ -61,6 +65,11 @@ struct drm_nouveau_notifier_alloc {
uint32_t offset;
};
struct drm_nouveau_gpuobj_free {
int channel;
uint32_t handle;
};
#define NOUVEAU_MEM_FB 0x00000001
#define NOUVEAU_MEM_AGP 0x00000002
#define NOUVEAU_MEM_FB_ACCEPTABLE 0x00000004
@ -95,6 +104,7 @@ struct drm_nouveau_mem_free {
#define NOUVEAU_GETPARAM_FB_SIZE 8
#define NOUVEAU_GETPARAM_AGP_SIZE 9
#define NOUVEAU_GETPARAM_PCI_PHYSICAL 10
#define NOUVEAU_GETPARAM_CHIPSET_ID 11
struct drm_nouveau_getparam {
uint64_t param;
uint64_t value;
@ -141,13 +151,16 @@ struct drm_nouveau_sarea {
unsigned int nbox;
};
#define DRM_NOUVEAU_FIFO_ALLOC 0x00
#define DRM_NOUVEAU_GROBJ_ALLOC 0x01
#define DRM_NOUVEAU_NOTIFIER_ALLOC 0x02
#define DRM_NOUVEAU_MEM_ALLOC 0x03
#define DRM_NOUVEAU_MEM_FREE 0x04
#define DRM_NOUVEAU_GETPARAM 0x05
#define DRM_NOUVEAU_SETPARAM 0x06
#define DRM_NOUVEAU_CARD_INIT 0x00
#define DRM_NOUVEAU_GETPARAM 0x01
#define DRM_NOUVEAU_SETPARAM 0x02
#define DRM_NOUVEAU_CHANNEL_ALLOC 0x03
#define DRM_NOUVEAU_CHANNEL_FREE 0x04
#define DRM_NOUVEAU_GROBJ_ALLOC 0x05
#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x06
#define DRM_NOUVEAU_GPUOBJ_FREE 0x07
#define DRM_NOUVEAU_MEM_ALLOC 0x08
#define DRM_NOUVEAU_MEM_FREE 0x09
#endif /* __NOUVEAU_DRM_H__ */

View File

@ -34,7 +34,7 @@
#define DRIVER_MAJOR 0
#define DRIVER_MINOR 0
#define DRIVER_PATCHLEVEL 9
#define DRIVER_PATCHLEVEL 10
#define NOUVEAU_FAMILY 0x0000FFFF
#define NOUVEAU_FLAGS 0xFFFF0000
@ -67,8 +67,7 @@ enum nouveau_flags {
#define NVOBJ_FLAG_ZERO_FREE (1 << 2)
#define NVOBJ_FLAG_FAKE (1 << 3)
struct nouveau_gpuobj {
struct nouveau_gpuobj *next;
struct nouveau_gpuobj *prev;
struct list_head list;
int im_channel;
struct mem_block *im_pramin;
@ -80,10 +79,13 @@ struct nouveau_gpuobj {
uint32_t engine;
uint32_t class;
void (*dtor)(struct drm_device *, struct nouveau_gpuobj *);
void *priv;
};
struct nouveau_gpuobj_ref {
struct nouveau_gpuobj_ref *next;
struct list_head list;
struct nouveau_gpuobj *gpuobj;
uint32_t instance;
@ -129,7 +131,7 @@ struct nouveau_channel
struct nouveau_gpuobj_ref *ramin; /* Private instmem */
struct mem_block *ramin_heap; /* Private PRAMIN heap */
struct nouveau_gpuobj_ref *ramht; /* Hash table */
struct nouveau_gpuobj_ref *ramht_refs; /* Objects referenced by RAMHT */
struct list_head ramht_refs; /* Objects referenced by RAMHT */
};
struct nouveau_config {
@ -269,9 +271,17 @@ struct drm_nouveau_private {
struct nouveau_config config;
struct nouveau_gpuobj *gpuobj_all;
struct list_head gpuobj_list;
};
#define NOUVEAU_CHECK_INITIALISED_WITH_RETURN do { \
struct drm_nouveau_private *nv = dev->dev_private; \
if (nv->init_state != NOUVEAU_CARD_INIT_DONE) { \
DRM_ERROR("called without init\n"); \
return -EINVAL; \
} \
} while(0)
#define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id,cl,ch) do { \
struct drm_nouveau_private *nv = dev->dev_private; \
if (!nouveau_fifo_owner(dev, (cl), (id))) { \
@ -293,6 +303,7 @@ extern int nouveau_ioctl_getparam(struct drm_device *, void *data,
extern int nouveau_ioctl_setparam(struct drm_device *, void *data,
struct drm_file *);
extern void nouveau_wait_for_idle(struct drm_device *);
extern int nouveau_card_init(struct drm_device *);
extern int nouveau_ioctl_card_init(struct drm_device *, void *data,
struct drm_file *);
@ -324,6 +335,8 @@ extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle,
int cout, uint32_t *offset);
extern int nouveau_ioctl_notifier_alloc(struct drm_device *, void *data,
struct drm_file *);
extern int nouveau_ioctl_notifier_free(struct drm_device *, void *data,
struct drm_file *);
/* nouveau_fifo.c */
extern int nouveau_fifo_init(struct drm_device *);
@ -335,6 +348,7 @@ extern int nouveau_fifo_owner(struct drm_device *, struct drm_file *,
extern void nouveau_fifo_free(struct nouveau_channel *);
/* nouveau_object.c */
extern int nouveau_gpuobj_init(struct drm_device *);
extern void nouveau_gpuobj_takedown(struct drm_device *);
extern int nouveau_gpuobj_channel_init(struct nouveau_channel *,
uint32_t vram_h, uint32_t tt_h);
@ -348,6 +362,8 @@ extern int nouveau_gpuobj_ref_add(struct drm_device *, struct nouveau_channel *,
struct nouveau_gpuobj_ref **);
extern int nouveau_gpuobj_ref_del(struct drm_device *,
struct nouveau_gpuobj_ref **);
extern int nouveau_gpuobj_ref_find(struct nouveau_channel *, uint32_t handle,
struct nouveau_gpuobj_ref **ref_ret);
extern int nouveau_gpuobj_new_ref(struct drm_device *,
struct nouveau_channel *alloc_chan,
struct nouveau_channel *ref_chan,
@ -368,6 +384,8 @@ extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class,
struct nouveau_gpuobj **);
extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data,
struct drm_file *);
extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data,
struct drm_file *);
/* nouveau_irq.c */
extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS);

View File

@ -302,6 +302,13 @@ int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret,
DRM_INFO("Allocating FIFO number %d\n", channel);
/* Allocate space for per-channel fixed notifier memory */
ret = nouveau_notifier_init_channel(chan);
if (ret) {
nouveau_fifo_free(chan);
return ret;
}
/* Setup channel's default objects */
ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle);
if (ret) {
@ -316,13 +323,6 @@ int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret,
return ret;
}
/* Allocate space for per-channel fixed notifier memory */
ret = nouveau_notifier_init_channel(chan);
if (ret) {
nouveau_fifo_free(chan);
return ret;
}
nouveau_wait_for_idle(dev);
/* disable the fifo caches */
@ -426,11 +426,11 @@ void nouveau_fifo_free(struct nouveau_channel *chan)
chan->pushbuf_mem = NULL;
}
nouveau_notifier_takedown_channel(chan);
/* Destroy objects belonging to the channel */
nouveau_gpuobj_channel_takedown(chan);
nouveau_notifier_takedown_channel(chan);
dev_priv->fifos[chan->id] = NULL;
dev_priv->fifo_alloc_count--;
drm_free(chan, sizeof(*chan), DRM_MEM_DRIVER);
@ -468,14 +468,17 @@ nouveau_fifo_owner(struct drm_device *dev, struct drm_file *file_priv,
* ioctls wrapping the functions
***********************************/
static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct drm_nouveau_fifo_alloc *init = data;
struct drm_nouveau_channel_alloc *init = data;
struct drm_map_list *entry;
struct nouveau_channel *chan;
int res;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
return -EINVAL;
@ -519,18 +522,34 @@ static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, struct d
return 0;
}
static int nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_nouveau_channel_free *cfree = data;
struct nouveau_channel *chan;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan);
nouveau_fifo_free(chan);
return 0;
}
/***********************************
* finally, the ioctl table
***********************************/
struct drm_ioctl_desc nouveau_ioctls[] = {
DRM_IOCTL_DEF(DRM_NOUVEAU_FIFO_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH),
DRM_IOCTL_DEF(DRM_NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH),
DRM_IOCTL_DEF(DRM_NOUVEAU_NOTIFIER_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH),
DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_ALLOC, nouveau_ioctl_mem_alloc, DRM_AUTH),
DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_FREE, nouveau_ioctl_mem_free, DRM_AUTH),
DRM_IOCTL_DEF(DRM_NOUVEAU_CARD_INIT, nouveau_ioctl_card_init, DRM_AUTH),
DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH),
DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH),
DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH),
DRM_IOCTL_DEF(DRM_NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH),
DRM_IOCTL_DEF(DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH),
DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH),
DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_ALLOC, nouveau_ioctl_mem_alloc, DRM_AUTH),
DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_FREE, nouveau_ioctl_mem_free, DRM_AUTH),
};
int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls);

View File

@ -549,14 +549,10 @@ void nouveau_mem_free(struct drm_device* dev, struct mem_block* block)
int nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct drm_nouveau_mem_alloc *alloc = data;
struct mem_block *block;
if (!dev_priv) {
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return -EINVAL;
}
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
block=nouveau_mem_alloc(dev, alloc->alignment, alloc->size,
alloc->flags, file_priv);
@ -575,6 +571,8 @@ int nouveau_ioctl_mem_free(struct drm_device *dev, void *data, struct drm_file *
struct drm_nouveau_mem_free *memfree = data;
struct mem_block *block;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
block=NULL;
if (memfree->flags & NOUVEAU_MEM_FB)
block = find_block(dev_priv->fb_heap, memfree->offset);

View File

@ -73,6 +73,16 @@ nouveau_notifier_takedown_channel(struct nouveau_channel *chan)
nouveau_mem_takedown(&chan->notifier_heap);
}
static void
nouveau_notifier_gpuobj_dtor(struct drm_device *dev,
struct nouveau_gpuobj *gpuobj)
{
DRM_DEBUG("\n");
if (gpuobj->priv)
nouveau_mem_free_block(gpuobj->priv);
}
int
nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
int count, uint32_t *b_offset)
@ -90,7 +100,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
}
mem = nouveau_mem_alloc_block(chan->notifier_heap, 32, 0,
chan->file_priv);
(struct drm_file *)-2);
if (!mem) {
DRM_ERROR("Channel %d notifier block full\n", chan->id);
return -ENOMEM;
@ -117,6 +127,8 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
DRM_ERROR("Error creating notifier ctxdma: %d\n", ret);
return ret;
}
nobj->dtor = nouveau_notifier_gpuobj_dtor;
nobj->priv = mem;
if ((ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL))) {
nouveau_gpuobj_del(dev, &nobj);
@ -133,10 +145,11 @@ int
nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_nouveau_notifier_alloc *na = data;
struct drm_nouveau_notifierobj_alloc *na = data;
struct nouveau_channel *chan;
int ret;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan);
ret = nouveau_notifier_alloc(chan, na->handle, na->count, &na->offset);

View File

@ -131,6 +131,8 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
ref->channel, co, ref->handle, ctx);
INSTANCE_WR(ramht, (co + 0)/4, ref->handle);
INSTANCE_WR(ramht, (co + 4)/4, ctx);
list_add_tail(&ref->list, &chan->ramht_refs);
return 0;
}
DRM_DEBUG("collision ch%d 0x%08x: h=0x%08x\n",
@ -167,6 +169,8 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
INSTANCE_RD(ramht, (co + 4)));
INSTANCE_WR(ramht, (co + 0)/4, 0x00000000);
INSTANCE_WR(ramht, (co + 4)/4, 0x00000000);
list_del(&ref->list);
return;
}
@ -203,6 +207,8 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
gpuobj->flags = flags;
gpuobj->im_channel = chan ? chan->id : -1;
list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
/* Choose between global instmem heap, and per-channel private
* instmem heap. On <NV50 allow requests for private instmem
* to be satisfied from global heap if no per-channel area
@ -254,24 +260,44 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
INSTANCE_WR(gpuobj, i/4, 0);
}
if (dev_priv->gpuobj_all) {
gpuobj->next = dev_priv->gpuobj_all;
gpuobj->next->prev = gpuobj;
}
dev_priv->gpuobj_all = gpuobj;
*gpuobj_ret = gpuobj;
return 0;
}
void nouveau_gpuobj_takedown(struct drm_device *dev)
int
nouveau_gpuobj_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
int ret;
INIT_LIST_HEAD(&dev_priv->gpuobj_list);
if (dev_priv->card_type < NV_50) {
if ((ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramht_offset,
dev_priv->ramht_size,
NVOBJ_FLAG_ZERO_ALLOC |
NVOBJ_FLAG_ALLOW_NO_REFS,
&dev_priv->ramht, NULL)))
return ret;
}
return 0;
}
void
nouveau_gpuobj_takedown(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpuobj *gpuobj = NULL;
struct list_head *entry, *tmp;
DRM_DEBUG("\n");
while ((gpuobj = dev_priv->gpuobj_all)) {
nouveau_gpuobj_del(dev, &dev_priv->ramht);
list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) {
gpuobj = list_entry(entry, struct nouveau_gpuobj, list);
DRM_ERROR("gpuobj %p still exists at takedown, refs=%d\n",
gpuobj, gpuobj->refcount);
gpuobj->refcount = 0;
@ -279,7 +305,8 @@ void nouveau_gpuobj_takedown(struct drm_device *dev)
}
}
int nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
int
nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_engine *engine = &dev_priv->Engine;
@ -296,6 +323,9 @@ int nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
return -EINVAL;
}
if (gpuobj->dtor)
gpuobj->dtor(dev, gpuobj);
engine->instmem.clear(dev, gpuobj);
if (gpuobj->im_pramin) {
@ -306,12 +336,7 @@ int nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
nouveau_mem_free_block(gpuobj->im_pramin);
}
if (gpuobj->next)
gpuobj->next->prev = gpuobj->prev;
if (gpuobj->prev)
gpuobj->prev->next = gpuobj->next;
else
dev_priv->gpuobj_all = gpuobj->next;
list_del(&gpuobj->list);
*pgpuobj = NULL;
drm_free(gpuobj, sizeof(*gpuobj), DRM_MEM_DRIVER);
@ -403,9 +428,6 @@ nouveau_gpuobj_ref_add(struct drm_device *dev, struct nouveau_channel *chan,
drm_free(ref, sizeof(*ref), DRM_MEM_DRIVER);
return ret;
}
ref->next = chan->ramht_refs;
chan->ramht_refs = ref;
} else {
ref->handle = ~0;
*ref_ret = ref;
@ -462,19 +484,21 @@ nouveau_gpuobj_new_ref(struct drm_device *dev,
return 0;
}
static int
int
nouveau_gpuobj_ref_find(struct nouveau_channel *chan, uint32_t handle,
struct nouveau_gpuobj_ref **ref_ret)
{
struct nouveau_gpuobj_ref *ref = chan->ramht_refs;
struct nouveau_gpuobj_ref *ref;
struct list_head *entry, *tmp;
list_for_each_safe(entry, tmp, &chan->ramht_refs) {
ref = list_entry(entry, struct nouveau_gpuobj_ref, list);
while (ref) {
if (ref->handle == handle) {
if (ref_ret)
*ref_ret = ref;
return 0;
}
ref = ref->next;
}
return -EINVAL;
@ -499,6 +523,8 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t offset, uint32_t size,
gpuobj->im_channel = -1;
gpuobj->flags = flags | NVOBJ_FLAG_FAKE;
list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
gpuobj->im_pramin = drm_calloc(1, sizeof(struct mem_block),
DRM_MEM_DRIVER);
if (!gpuobj->im_pramin) {
@ -897,6 +923,8 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
struct nouveau_gpuobj *vram = NULL, *tt = NULL;
int ret, i;
INIT_LIST_HEAD(&chan->ramht_refs);
DRM_DEBUG("ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
/* Reserve a block of PRAMIN for the channel
@ -994,14 +1022,17 @@ void
nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
{
struct drm_device *dev = chan->dev;
struct list_head *entry, *tmp;
struct nouveau_gpuobj_ref *ref;
DRM_DEBUG("ch%d\n", chan->id);
while ((ref = chan->ramht_refs)) {
chan->ramht_refs = ref->next;
list_for_each_safe(entry, tmp, &chan->ramht_refs) {
ref = list_entry(entry, struct nouveau_gpuobj_ref, list);
nouveau_gpuobj_ref_del(dev, &ref);
}
nouveau_gpuobj_ref_del(dev, &chan->ramht);
nouveau_gpuobj_del(dev, &chan->vm_pd);
@ -1022,6 +1053,7 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
struct nouveau_gpuobj *gr = NULL;
int ret;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan);
//FIXME: check args, only allow trusted objects to be created
@ -1029,8 +1061,7 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
if (init->handle == ~0)
return -EINVAL;
if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) ==
0)
if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) == 0)
return -EEXIST;
ret = nouveau_gpuobj_gr_new(chan, init->class, &gr);
@ -1050,3 +1081,21 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
return 0;
}
int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_nouveau_gpuobj_free *objfree = data;
struct nouveau_gpuobj_ref *ref;
struct nouveau_channel *chan;
int ret;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan);
if ((ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref)))
return ret;
nouveau_gpuobj_ref_del(dev, &ref);
return 0;
}

View File

@ -267,12 +267,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
return 0;
}
static int nouveau_card_init(struct drm_device *dev)
int
nouveau_card_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_engine *engine;
int ret;
if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE)
return 0;
/* Map any PCI resources we need on the card */
ret = nouveau_init_card_mappings(dev);
if (ret) return ret;
@ -290,6 +294,9 @@ static int nouveau_card_init(struct drm_device *dev)
engine = &dev_priv->Engine;
dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED;
ret = drm_irq_install(dev);
if (ret) return ret;
/* Initialise instance memory, must happen before mem_init so we
* know exactly how much VRAM we're able to use for "normal"
* purposes.
@ -301,6 +308,9 @@ static int nouveau_card_init(struct drm_device *dev)
ret = nouveau_mem_init(dev);
if (ret) return ret;
ret = nouveau_gpuobj_init(dev);
if (ret) return ret;
/* Parse BIOS tables / Run init tables? */
/* PMC */
@ -349,6 +359,8 @@ static void nouveau_card_takedown(struct drm_device *dev)
nouveau_mem_close(dev);
engine->instmem.takedown(dev);
drm_irq_uninstall(dev);
dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
}
}
@ -368,14 +380,6 @@ void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv)
/* first module load, setup the mmio/fb mapping */
int nouveau_firstopen(struct drm_device *dev)
{
int ret;
ret = nouveau_card_init(dev);
if (ret) {
DRM_ERROR("nouveau_card_init() failed! (%d)\n", ret);
return ret;
}
return 0;
}
@ -395,15 +399,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
dev->dev_private = (void *)dev_priv;
#if 0
ret = nouveau_card_init(dev);
if (ret) {
DRM_ERROR("nouveau_card_init() failed! (%d)\n", ret);
return ret;
}
#endif
return 0;
}
@ -427,12 +422,24 @@ int nouveau_unload(struct drm_device *dev)
return 0;
}
int
nouveau_ioctl_card_init(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
return nouveau_card_init(dev);
}
int nouveau_ioctl_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct drm_nouveau_getparam *getparam = data;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
switch (getparam->param) {
case NOUVEAU_GETPARAM_CHIPSET_ID:
getparam->value = dev_priv->chipset;
break;
case NOUVEAU_GETPARAM_PCI_VENDOR:
getparam->value=dev->pci_vendor;
break;
@ -481,6 +488,8 @@ int nouveau_ioctl_setparam(struct drm_device *dev, void *data, struct drm_file *
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct drm_nouveau_setparam *setparam = data;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
switch (setparam->param) {
case NOUVEAU_SETPARAM_CMDBUF_LOCATION:
switch (setparam->value) {

View File

@ -93,13 +93,6 @@ int nv04_instmem_init(struct drm_device *dev)
nv04_instmem_determine_amount(dev);
nv04_instmem_configure_fixed_tables(dev);
if ((ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramht_offset,
dev_priv->ramht_size,
NVOBJ_FLAG_ZERO_ALLOC |
NVOBJ_FLAG_ALLOW_NO_REFS,
&dev_priv->ramht, NULL)))
return ret;
/* Create a heap to manage RAMIN allocations, we don't allocate
* the space that was reserved for RAMHT/FC/RO.
*/
@ -117,9 +110,6 @@ int nv04_instmem_init(struct drm_device *dev)
void
nv04_instmem_takedown(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
nouveau_gpuobj_del(dev, &dev_priv->ramht);
}
int