From 1e98380cbd3894de2b3c1ea182d62e946555f7d0 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Sat, 12 Jan 2013 13:03:16 +0100 Subject: drm/nouveau: use different register to wait for secret scrubber Fixes long delay when waiting for scrubber on some secret engines. The exit interrupt seems to not always be generated, so use secret scrubber active register instead. Later fuc engines also no longer generate an interrupt, so don't wait there. Signed-off-by: Maarten Lankhorst Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/falcon.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/core/falcon.c b/drivers/gpu/drm/nouveau/core/core/falcon.c index 6b0843c3387..e05c1577758 100644 --- a/drivers/gpu/drm/nouveau/core/core/falcon.c +++ b/drivers/gpu/drm/nouveau/core/core/falcon.c @@ -73,8 +73,11 @@ _nouveau_falcon_init(struct nouveau_object *object) nv_debug(falcon, "data limit: %d\n", falcon->data.limit); /* wait for 'uc halted' to be signalled before continuing */ - if (falcon->secret) { - nv_wait(falcon, 0x008, 0x00000010, 0x00000010); + if (falcon->secret && falcon->version < 4) { + if (!falcon->version) + nv_wait(falcon, 0x008, 0x00000010, 0x00000010); + else + nv_wait(falcon, 0x180, 0x80000000, 0); nv_wo32(falcon, 0x004, 0x00000010); } -- cgit v1.2.3 From 526810adb93554e17bdb83023a01cfa8758960b2 Mon Sep 17 00:00:00 2001 From: Roy Spliet Date: Wed, 9 Jan 2013 03:40:33 +0100 Subject: drm/nv50/fb: Fix nullptr-deref on IGPs When COMP_MAX_TAG == 0, the tags mm was uninitialised. Fixed by initialising with zero length. v2: Fix style error Signed-off-by: Roy Spliet Tested-by: Roy Spliet Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/fb/base.c | 4 ++-- drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/base.c b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c index d6d16007ec1..d62045f454b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c @@ -86,8 +86,8 @@ nouveau_fb_preinit(struct nouveau_fb *pfb) return ret; } - if (!nouveau_mm_initialised(&pfb->tags) && tags) { - ret = nouveau_mm_init(&pfb->tags, 0, ++tags, 1); + if (!nouveau_mm_initialised(&pfb->tags)) { + ret = nouveau_mm_init(&pfb->tags, 0, tags ? ++tags : 0, 1); if (ret) return ret; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index 487cb8c6c20..eac236ed19b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -99,7 +99,7 @@ nv50_fb_vram_init(struct nouveau_fb *pfb) struct nouveau_bios *bios = nouveau_bios(device); const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ - u32 size; + u32 size, tags = 0; int ret; pfb->ram.size = nv_rd32(pfb, 0x10020c); @@ -140,10 +140,11 @@ nv50_fb_vram_init(struct nouveau_fb *pfb) return ret; pfb->ram.ranks = (nv_rd32(pfb, 0x100200) & 0x4) ? 2 : 1; + tags = nv_rd32(pfb, 0x100320); break; } - return nv_rd32(pfb, 0x100320); + return tags; } static int -- cgit v1.2.3 From 5f97ab913cf0fbc378ea8ffc3ee66f4890d11c55 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 4 Feb 2013 21:52:54 +0100 Subject: drm/nouveau: add lockdep annotations 1) Lockdep thinks all nouveau subdevs belong to the same class and can be locked in arbitrary order, which is not true (at least in general case). Tell it to distinguish subdevs by (o)class type. 2) DRM client can be locked under user client lock - tell lockdep to put DRM client lock in a separate class. Reported-by: Arend van Spriel Reported-by: Peter Hurley Reported-by: Maarten Lankhorst Reported-by: Daniel J Blueman Signed-off-by: Marcin Slusarz Cc: stable@vger.kernel.org [3.7, but needs s/const ofuncs/ofuncs/ to build] Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/core/subdev.c | 2 +- drivers/gpu/drm/nouveau/core/include/core/object.h | 7 +++++-- drivers/gpu/drm/nouveau/nouveau_drm.c | 3 +++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/core/subdev.c b/drivers/gpu/drm/nouveau/core/core/subdev.c index f74c30aa33a..48f06378d3f 100644 --- a/drivers/gpu/drm/nouveau/core/core/subdev.c +++ b/drivers/gpu/drm/nouveau/core/core/subdev.c @@ -99,7 +99,7 @@ nouveau_subdev_create_(struct nouveau_object *parent, if (ret) return ret; - mutex_init(&subdev->mutex); + __mutex_init(&subdev->mutex, subname, &oclass->lock_class_key); subdev->name = subname; if (parent) { diff --git a/drivers/gpu/drm/nouveau/core/include/core/object.h b/drivers/gpu/drm/nouveau/core/include/core/object.h index 5982935ee23..106bb19fdd9 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/object.h +++ b/drivers/gpu/drm/nouveau/core/include/core/object.h @@ -50,10 +50,13 @@ int nouveau_object_fini(struct nouveau_object *, bool suspend); extern struct nouveau_ofuncs nouveau_object_ofuncs; +/* Don't allocate dynamically, because lockdep needs lock_class_keys to be in + * ".data". */ struct nouveau_oclass { u32 handle; - struct nouveau_ofuncs *ofuncs; - struct nouveau_omthds *omthds; + struct nouveau_ofuncs * const ofuncs; + struct nouveau_omthds * const omthds; + struct lock_class_key lock_class_key; }; #define nv_oclass(o) nv_object(o)->oclass diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index efcfefa0412..43c78516941 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -245,6 +245,8 @@ nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent) return 0; } +static struct lock_class_key drm_client_lock_class_key; + static int nouveau_drm_load(struct drm_device *dev, unsigned long flags) { @@ -256,6 +258,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) ret = nouveau_cli_create(pdev, "DRM", sizeof(*drm), (void**)&drm); if (ret) return ret; + lockdep_set_class(&drm->client.mutex, &drm_client_lock_class_key); dev->dev_private = drm; drm->dev = dev; -- cgit v1.2.3