mirror of https://gitee.com/openkylin/linux.git
drm/nouveau: fix gpuobj refcount to use atomics
Reviewed-by: Francisco Jerez <currojerez@riseup.net> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
dac7900804
commit
eb9bcbdc45
|
@ -137,6 +137,7 @@ enum nouveau_flags {
|
||||||
#define NVOBJ_FLAG_ZERO_FREE (1 << 2)
|
#define NVOBJ_FLAG_ZERO_FREE (1 << 2)
|
||||||
struct nouveau_gpuobj {
|
struct nouveau_gpuobj {
|
||||||
struct drm_device *dev;
|
struct drm_device *dev;
|
||||||
|
struct kref refcount;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
|
||||||
struct drm_mm_node *im_pramin;
|
struct drm_mm_node *im_pramin;
|
||||||
|
@ -145,7 +146,6 @@ struct nouveau_gpuobj {
|
||||||
int im_bound;
|
int im_bound;
|
||||||
|
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
int refcount;
|
|
||||||
|
|
||||||
u32 size;
|
u32 size;
|
||||||
u32 pinst;
|
u32 pinst;
|
||||||
|
|
|
@ -90,7 +90,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
|
||||||
NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
|
NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
|
||||||
gpuobj->dev = dev;
|
gpuobj->dev = dev;
|
||||||
gpuobj->flags = flags;
|
gpuobj->flags = flags;
|
||||||
gpuobj->refcount = 1;
|
kref_init(&gpuobj->refcount);
|
||||||
gpuobj->size = size;
|
gpuobj->size = size;
|
||||||
|
|
||||||
list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
|
list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
|
||||||
|
@ -198,25 +198,15 @@ void
|
||||||
nouveau_gpuobj_late_takedown(struct drm_device *dev)
|
nouveau_gpuobj_late_takedown(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||||
struct nouveau_gpuobj *gpuobj = NULL;
|
|
||||||
struct list_head *entry, *tmp;
|
|
||||||
|
|
||||||
NV_DEBUG(dev, "\n");
|
BUG_ON(!list_empty(&dev_priv->gpuobj_list));
|
||||||
|
|
||||||
list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) {
|
|
||||||
gpuobj = list_entry(entry, struct nouveau_gpuobj, list);
|
|
||||||
|
|
||||||
NV_ERROR(dev, "gpuobj %p still exists at takedown, refs=%d\n",
|
|
||||||
gpuobj, gpuobj->refcount);
|
|
||||||
|
|
||||||
gpuobj->refcount = 1;
|
|
||||||
nouveau_gpuobj_ref(NULL, &gpuobj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
nouveau_gpuobj_del(struct nouveau_gpuobj *gpuobj)
|
nouveau_gpuobj_del(struct kref *ref)
|
||||||
{
|
{
|
||||||
|
struct nouveau_gpuobj *gpuobj =
|
||||||
|
container_of(ref, struct nouveau_gpuobj, refcount);
|
||||||
struct drm_device *dev = gpuobj->dev;
|
struct drm_device *dev = gpuobj->dev;
|
||||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||||
struct nouveau_engine *engine = &dev_priv->engine;
|
struct nouveau_engine *engine = &dev_priv->engine;
|
||||||
|
@ -242,17 +232,16 @@ nouveau_gpuobj_del(struct nouveau_gpuobj *gpuobj)
|
||||||
list_del(&gpuobj->list);
|
list_del(&gpuobj->list);
|
||||||
|
|
||||||
kfree(gpuobj);
|
kfree(gpuobj);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nouveau_gpuobj_ref(struct nouveau_gpuobj *ref, struct nouveau_gpuobj **ptr)
|
nouveau_gpuobj_ref(struct nouveau_gpuobj *ref, struct nouveau_gpuobj **ptr)
|
||||||
{
|
{
|
||||||
if (ref)
|
if (ref)
|
||||||
ref->refcount++;
|
kref_get(&ref->refcount);
|
||||||
|
|
||||||
if (*ptr && --(*ptr)->refcount == 0)
|
if (*ptr)
|
||||||
nouveau_gpuobj_del(*ptr);
|
kref_put(&(*ptr)->refcount, nouveau_gpuobj_del);
|
||||||
|
|
||||||
*ptr = ref;
|
*ptr = ref;
|
||||||
}
|
}
|
||||||
|
@ -275,7 +264,7 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst,
|
||||||
NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
|
NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
|
||||||
gpuobj->dev = dev;
|
gpuobj->dev = dev;
|
||||||
gpuobj->flags = flags;
|
gpuobj->flags = flags;
|
||||||
gpuobj->refcount = 1;
|
kref_init(&gpuobj->refcount);
|
||||||
gpuobj->size = size;
|
gpuobj->size = size;
|
||||||
gpuobj->pinst = pinst;
|
gpuobj->pinst = pinst;
|
||||||
gpuobj->cinst = 0xdeadbeef;
|
gpuobj->cinst = 0xdeadbeef;
|
||||||
|
@ -561,7 +550,7 @@ nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
|
||||||
gpuobj->dev = chan->dev;
|
gpuobj->dev = chan->dev;
|
||||||
gpuobj->engine = NVOBJ_ENGINE_SW;
|
gpuobj->engine = NVOBJ_ENGINE_SW;
|
||||||
gpuobj->class = class;
|
gpuobj->class = class;
|
||||||
gpuobj->refcount = 1;
|
kref_init(&gpuobj->refcount);
|
||||||
gpuobj->cinst = 0x40;
|
gpuobj->cinst = 0x40;
|
||||||
|
|
||||||
list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
|
list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
|
||||||
|
|
Loading…
Reference in New Issue