summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r--drivers/gpu/drm/nouveau/core/core/client.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/core/parent.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nve0.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c6
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/client.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bar/base.c14
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c16
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_platform.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vga.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvif/class.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvif/notify.c29
-rw-r--r--drivers/gpu/drm/nouveau/nvif/object.c4
22 files changed, 78 insertions, 44 deletions
diff --git a/drivers/gpu/drm/nouveau/core/core/client.c b/drivers/gpu/drm/nouveau/core/core/client.c
index 10598dede9e9..68bf06768123 100644
--- a/drivers/gpu/drm/nouveau/core/core/client.c
+++ b/drivers/gpu/drm/nouveau/core/core/client.c
@@ -132,12 +132,12 @@ nvkm_client_notify_new(struct nouveau_client *client,
if (ret == 0) {
client->notify[index] = notify;
notify->client = client;
- return 0;
+ return index;
}
}
kfree(notify);
- return 0;
+ return ret;
}
static int
diff --git a/drivers/gpu/drm/nouveau/core/core/parent.c b/drivers/gpu/drm/nouveau/core/core/parent.c
index 8701968a9743..30a2911878f8 100644
--- a/drivers/gpu/drm/nouveau/core/core/parent.c
+++ b/drivers/gpu/drm/nouveau/core/core/parent.c
@@ -86,7 +86,7 @@ nouveau_parent_lclass(struct nouveau_object *parent, u32 *lclass, int size)
sclass = nv_parent(parent)->sclass;
while (sclass) {
if (++nr < size)
- lclass[nr] = sclass->oclass->handle;
+ lclass[nr] = sclass->oclass->handle & 0xffff;
sclass = sclass->sclass;
}
@@ -96,7 +96,7 @@ nouveau_parent_lclass(struct nouveau_object *parent, u32 *lclass, int size)
if (engine && (oclass = engine->sclass)) {
while (oclass->ofuncs) {
if (++nr < size)
- lclass[nr] = oclass->handle;
+ lclass[nr] = oclass->handle & 0xffff;
oclass++;
}
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
index 54ec53bc6252..cdf9147f32a1 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
@@ -163,6 +163,7 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = gk20a_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &gk20a_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
index db19191176fa..30fd1dc64f93 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
@@ -68,6 +68,9 @@ nvc0_graph_zbc_color_get(struct nvc0_graph_priv *priv, int format,
}
}
+ if (zbc < 0)
+ return zbc;
+
memcpy(priv->zbc_color[zbc].ds, ds, sizeof(priv->zbc_color[zbc].ds));
memcpy(priv->zbc_color[zbc].l2, l2, sizeof(priv->zbc_color[zbc].l2));
priv->zbc_color[zbc].format = format;
@@ -109,6 +112,9 @@ nvc0_graph_zbc_depth_get(struct nvc0_graph_priv *priv, int format,
}
}
+ if (zbc < 0)
+ return zbc;
+
priv->zbc_depth[zbc].format = format;
priv->zbc_depth[zbc].ds = ds;
priv->zbc_depth[zbc].l2 = l2;
diff --git a/drivers/gpu/drm/nouveau/core/include/core/client.h b/drivers/gpu/drm/nouveau/core/include/core/client.h
index 4fc6ab12382d..1794a05205d8 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/client.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/client.h
@@ -14,7 +14,7 @@ struct nouveau_client {
void *data;
int (*ntfy)(const void *, u32, const void *, u32);
- struct nvkm_client_notify *notify[8];
+ struct nvkm_client_notify *notify[16];
};
static inline struct nouveau_client *
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
index 73b1ed20c8d5..8bcbdf39cfb2 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c
@@ -99,8 +99,13 @@ nouveau_bar_alloc(struct nouveau_bar *bar, struct nouveau_object *parent,
struct nouveau_mem *mem, struct nouveau_object **pobject)
{
struct nouveau_object *engine = nv_object(bar);
- return nouveau_object_ctor(parent, engine, &nouveau_barobj_oclass,
- mem, 0, pobject);
+ int ret = -ENOMEM;
+ if (bar->iomem) {
+ ret = nouveau_object_ctor(parent, engine,
+ &nouveau_barobj_oclass,
+ mem, 0, pobject);
+ }
+ return ret;
}
int
@@ -118,9 +123,12 @@ nouveau_bar_create_(struct nouveau_object *parent,
if (ret)
return ret;
- if (nv_device_resource_len(device, 3) != 0)
+ if (nv_device_resource_len(device, 3) != 0) {
bar->iomem = ioremap(nv_device_resource_start(device, 3),
nv_device_resource_len(device, 3));
+ if (!bar->iomem)
+ nv_warn(bar, "PRAMIN ioremap failed\n");
+ }
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
index 0a44459844e3..05a278bab247 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
@@ -200,7 +200,6 @@ nvc0_bar_init(struct nouveau_object *object)
nv_mask(priv, 0x000200, 0x00000100, 0x00000000);
nv_mask(priv, 0x000200, 0x00000100, 0x00000100);
- nv_mask(priv, 0x100c80, 0x00000001, 0x00000000);
nv_wr32(priv, 0x001704, 0x80000000 | priv->bar[1].mem->addr >> 12);
if (priv->bar[0].mem)
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
index b19a2b3c1081..32f28dc73ef2 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
@@ -60,6 +60,7 @@ nvc0_fb_init(struct nouveau_object *object)
if (priv->r100c10_page)
nv_wr32(priv, 0x100c10, priv->r100c10 >> 8);
+ nv_mask(priv, 0x100c80, 0x00000001, 0x00000000); /* 128KiB lpg */
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
index 946518572346..2b284b192763 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
@@ -554,13 +554,13 @@ nvc0_ram_create_(struct nouveau_object *parent, struct nouveau_object *engine,
} else {
/* otherwise, address lowest common amount from 0GiB */
ret = nouveau_mm_init(&pfb->vram, rsvd_head,
- (bsize << 8) * parts, 1);
+ (bsize << 8) * parts - rsvd_head, 1);
if (ret)
return ret;
/* and the rest starting from (8GiB + common_size) */
offset = (0x0200000000ULL >> 12) + (bsize << 8);
- length = (ram->size >> 12) - (bsize << 8) - rsvd_tail;
+ length = (ram->size >> 12) - ((bsize * parts) << 8) - rsvd_tail;
ret = nouveau_mm_init(&pfb->vram, offset, length, 0);
if (ret)
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c b/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c
index 9e00a1ede120..d5d65285efe5 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c
@@ -98,6 +98,7 @@ static int
gf100_ltc_init(struct nouveau_object *object)
{
struct nvkm_ltc_priv *priv = (void *)object;
+ u32 lpg128 = !(nv_rd32(priv, 0x100c80) & 0x00000001);
int ret;
ret = nvkm_ltc_init(priv);
@@ -107,6 +108,7 @@ gf100_ltc_init(struct nouveau_object *object)
nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
nv_wr32(priv, 0x17e8d8, priv->ltc_nr);
nv_wr32(priv, 0x17e8d4, priv->tag_base);
+ nv_mask(priv, 0x17e8c0, 0x00000002, lpg128 ? 0x00000002 : 0x00000000);
return 0;
}
@@ -156,7 +158,7 @@ gf100_ltc_init_tag_ram(struct nouveau_fb *pfb, struct nvkm_ltc_priv *priv)
if (ret) {
priv->num_tags = 0;
} else {
- u64 tag_base = (priv->tag_ram->offset << 12) + tag_margin;
+ u64 tag_base = ((u64)priv->tag_ram->offset << 12) + tag_margin;
tag_base += tag_align - 1;
ret = do_div(tag_base, tag_align);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c b/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c
index ea716569745d..b39b5d0eb8f9 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c
@@ -28,6 +28,7 @@ static int
gk104_ltc_init(struct nouveau_object *object)
{
struct nvkm_ltc_priv *priv = (void *)object;
+ u32 lpg128 = !(nv_rd32(priv, 0x100c80) & 0x00000001);
int ret;
ret = nvkm_ltc_init(priv);
@@ -37,6 +38,7 @@ gk104_ltc_init(struct nouveau_object *object)
nv_wr32(priv, 0x17e8d8, priv->ltc_nr);
nv_wr32(priv, 0x17e000, priv->ltc_nr);
nv_wr32(priv, 0x17e8d4, priv->tag_base);
+ nv_mask(priv, 0x17e8c0, 0x00000002, lpg128 ? 0x00000002 : 0x00000000);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c b/drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c
index 4761b2e9af00..a4de64289762 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c
@@ -98,6 +98,7 @@ static int
gm107_ltc_init(struct nouveau_object *object)
{
struct nvkm_ltc_priv *priv = (void *)object;
+ u32 lpg128 = !(nv_rd32(priv, 0x100c80) & 0x00000001);
int ret;
ret = nvkm_ltc_init(priv);
@@ -106,6 +107,7 @@ gm107_ltc_init(struct nouveau_object *object)
nv_wr32(priv, 0x17e27c, priv->ltc_nr);
nv_wr32(priv, 0x17e278, priv->tag_base);
+ nv_mask(priv, 0x17e264, 0x00000002, lpg128 ? 0x00000002 : 0x00000000);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index 279206997e5c..622424692b3b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -46,7 +46,6 @@ static struct nouveau_dsm_priv {
bool dsm_detected;
bool optimus_detected;
acpi_handle dhandle;
- acpi_handle other_handle;
acpi_handle rom_handle;
} nouveau_dsm_priv;
@@ -222,10 +221,9 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
if (!dhandle)
return false;
- if (!acpi_has_method(dhandle, "_DSM")) {
- nouveau_dsm_priv.other_handle = dhandle;
+ if (!acpi_has_method(dhandle, "_DSM"))
return false;
- }
+
if (acpi_check_dsm(dhandle, nouveau_dsm_muid, 0x00000102,
1 << NOUVEAU_DSM_POWER))
retval |= NOUVEAU_DSM_HAS_MUX;
@@ -301,16 +299,6 @@ static bool nouveau_dsm_detect(void)
printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
acpi_method_name);
nouveau_dsm_priv.dsm_detected = true;
- /*
- * On some systems hotplug events are generated for the device
- * being switched off when _DSM is executed. They cause ACPI
- * hotplug to trigger and attempt to remove the device from
- * the system, which causes it to break down. Prevent that from
- * happening by setting the no_hotplug flag for the involved
- * ACPI device objects.
- */
- acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle);
- acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle);
ret = true;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index da5d631aa5b9..01da508625f2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1228,7 +1228,6 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
struct nouveau_drm *drm = nouveau_bdev(bdev);
struct nouveau_mem *node = mem->mm_node;
- struct drm_device *dev = drm->dev;
int ret;
mem->bus.addr = NULL;
@@ -1247,7 +1246,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
if (drm->agp.stat == ENABLED) {
mem->bus.offset = mem->start << PAGE_SHIFT;
mem->bus.base = drm->agp.base;
- mem->bus.is_iomem = !dev->agp->cant_use_aperture;
+ mem->bus.is_iomem = !drm->dev->agp->cant_use_aperture;
}
#endif
if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA || !node->memtype)
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 1cc7b603c753..65b4fd53dd4e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -592,7 +592,9 @@ nouveau_display_repin(struct drm_device *dev)
if (!nouveau_fb || !nouveau_fb->nvbo)
continue;
- nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
+ ret = nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
+ if (ret)
+ NV_ERROR(drm, "Could not pin framebuffer\n");
}
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 250a5e88c751..9c3af96a7153 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -627,6 +627,7 @@ int nouveau_pmops_suspend(struct device *dev)
pci_save_state(pdev);
pci_disable_device(pdev);
+ pci_ignore_hotplug(pdev);
pci_set_power_state(pdev, PCI_D3hot);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index ebfe3180109e..8bdd27091db8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -226,7 +226,7 @@ nouveau_fbcon_accel_restore(struct drm_device *dev)
}
}
-void
+static void
nouveau_fbcon_accel_fini(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
@@ -246,7 +246,7 @@ nouveau_fbcon_accel_fini(struct drm_device *dev)
}
}
-void
+static void
nouveau_fbcon_accel_init(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c
index 0ffeb50d0088..246a824c16ca 100644
--- a/drivers/gpu/drm/nouveau/nouveau_platform.c
+++ b/drivers/gpu/drm/nouveau/nouveau_platform.c
@@ -149,7 +149,8 @@ power_down:
static int nouveau_platform_remove(struct platform_device *pdev)
{
struct drm_device *drm_dev = platform_get_drvdata(pdev);
- struct nouveau_device *device = nouveau_dev(drm_dev);
+ struct nouveau_drm *drm = nouveau_drm(drm_dev);
+ struct nouveau_device *device = nvkm_device(&drm->device);
struct nouveau_platform_gpu *gpu = nv_device_to_platform(device)->gpu;
nouveau_drm_device_remove(drm_dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
index 18d55d447248..c7592ec8ecb8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
@@ -108,7 +108,16 @@ void
nouveau_vga_fini(struct nouveau_drm *drm)
{
struct drm_device *dev = drm->dev;
+ bool runtime = false;
+
+ if (nouveau_runtime_pm == 1)
+ runtime = true;
+ if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm()))
+ runtime = true;
+
vga_switcheroo_unregister_client(dev->pdev);
+ if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())
+ vga_switcheroo_fini_domain_pm_ops(drm->dev->dev);
vga_client_register(dev->pdev, NULL, NULL, NULL);
}
diff --git a/drivers/gpu/drm/nouveau/nvif/class.h b/drivers/gpu/drm/nouveau/nvif/class.h
index cc81e0e5fd30..573491f84792 100644
--- a/drivers/gpu/drm/nouveau/nvif/class.h
+++ b/drivers/gpu/drm/nouveau/nvif/class.h
@@ -428,8 +428,8 @@ struct nv50_disp_dac_pwr_v0 {
struct nv50_disp_dac_load_v0 {
__u8 version;
__u8 load;
- __u16 data;
- __u8 pad04[4];
+ __u8 pad02[2];
+ __u32 data;
};
struct nv50_disp_sor_pwr_v0 {
diff --git a/drivers/gpu/drm/nouveau/nvif/notify.c b/drivers/gpu/drm/nouveau/nvif/notify.c
index 7c06123a559c..0898c3155292 100644
--- a/drivers/gpu/drm/nouveau/nvif/notify.c
+++ b/drivers/gpu/drm/nouveau/nvif/notify.c
@@ -87,12 +87,25 @@ nvif_notify_get(struct nvif_notify *notify)
return 0;
}
+static inline int
+nvif_notify_func(struct nvif_notify *notify, bool keep)
+{
+ int ret = notify->func(notify);
+ if (ret == NVIF_NOTIFY_KEEP ||
+ !test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
+ if (!keep)
+ atomic_dec(&notify->putcnt);
+ else
+ nvif_notify_get_(notify);
+ }
+ return ret;
+}
+
static void
nvif_notify_work(struct work_struct *work)
{
struct nvif_notify *notify = container_of(work, typeof(*notify), work);
- if (notify->func(notify) == NVIF_NOTIFY_KEEP)
- nvif_notify_get_(notify);
+ nvif_notify_func(notify, true);
}
int
@@ -113,19 +126,15 @@ nvif_notify(const void *header, u32 length, const void *data, u32 size)
if (!WARN_ON(notify == NULL)) {
struct nvif_client *client = nvif_client(notify->object);
if (!WARN_ON(notify->size != size)) {
+ atomic_inc(&notify->putcnt);
if (test_bit(NVIF_NOTIFY_WORK, &notify->flags)) {
- atomic_inc(&notify->putcnt);
memcpy((void *)notify->data, data, size);
schedule_work(&notify->work);
return NVIF_NOTIFY_DROP;
}
notify->data = data;
- ret = notify->func(notify);
+ ret = nvif_notify_func(notify, client->driver->keep);
notify->data = NULL;
- if (ret != NVIF_NOTIFY_DROP && client->driver->keep) {
- atomic_inc(&notify->putcnt);
- nvif_notify_get_(notify);
- }
}
}
@@ -228,8 +237,10 @@ nvif_notify_new(struct nvif_object *object, int (*func)(struct nvif_notify *),
if (notify) {
int ret = nvif_notify_init(object, nvif_notify_del, func, work,
type, data, size, reply, notify);
- if (ret)
+ if (ret) {
kfree(notify);
+ notify = NULL;
+ }
*pnotify = notify;
return ret;
}
diff --git a/drivers/gpu/drm/nouveau/nvif/object.c b/drivers/gpu/drm/nouveau/nvif/object.c
index b0c82206ece2..dd85b56f6aa5 100644
--- a/drivers/gpu/drm/nouveau/nvif/object.c
+++ b/drivers/gpu/drm/nouveau/nvif/object.c
@@ -275,8 +275,10 @@ nvif_object_new(struct nvif_object *parent, u32 handle, u32 oclass,
if (object) {
int ret = nvif_object_init(parent, nvif_object_del, handle,
oclass, data, size, object);
- if (ret)
+ if (ret) {
kfree(object);
+ object = NULL;
+ }
*pobject = object;
return ret;
}