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
parent
beaa0c9a28
commit
97770db720
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue