Subject: Re: [0/5] bcma/brcmsmac suspend/resume cleanups and fixes

From: "Arend van Spriel" <[email-masked]>
Date: Thu, 19 Jan 2012 10:42:03 +0100

On 01/17/2012 02:12 AM, Linus Torvalds wrote:
> 2012/1/16 Arend van Spriel <[email-masked]>:
>>
>> I build a new kernel with MCE enabled. Same issue. I did not load bcma
>> or brcmsmac yet. Attached is trace I could pull from the kernel log
>> (str-test-*).
> 
> Oh well. Everything looks fine in the test traces - the warnings are
> annoying and nasty, but a known issue and not dangerous (and I have a
> patch in my tree to fix them now).
> 
> So if the real suspend fails, it's some other subsystem that has
> gotten broken. I don't think I have any other reports like that yet,
> and there is not a lot to go on. If you could try to bisect it (I
> assume plain Linux-3.2 works fine?) that woudl be wonderful, otherwise
> I think we're stuck waiting for somebody else to hit it and figure it
> out.
> 
>                  Linus
> 

Hi Linus,

No trivial bisect. I wish I had a faster build machine, but alas. I
suspected some issue in DRM and the bisect took me into drm-core-next
branch. I ended up at the following commit:

dc97b3409a790d2a21aac6e5cdb99558b5944119 is the first bad commit
commit dc97b3409a790d2a21aac6e5cdb99558b5944119
Author: Jerome Glisse <[email-masked]>
Date:   Fri Nov 18 11:47:03 2011 -0500

    drm/ttm: callback move_notify any time bo placement change v4

    Previously we were calling back move_notify in error path when the
    bo is returned to it's original position or when destroy the bo.
    When destroying the bo set the new mem placement as NULL when calling
    back in the driver.

    Updating nouveau to deal with NULL placement properly.

    v2: reserve the object before calling move_notify in bo destroy path
        at that point ttm should be the only piece of code interacting
        with the object so atomic_set is safe here.
    v3: callback move notify only once the bo is in its new position
        call move notify want swaping out the buffer
    v4:- don't call move_notify when swapin out bo, assume driver should
         do what is appropriate in swap notify
       - move move_notify call back to ttm_bo_cleanup_memtype_use for
         destroy path

    Reviewed-by: Jerome Glisse <[email-masked]>
    Reviewed-by: Thomas Hellstrom <[email-masked]>

Actually, this commit was already bothering my bisect as it gave me a
NULL pointer deref on system startup. I patched it to proceed the bisect
(see attached diff). The NULL deref was fixed in the drm-nouveau-next
branch (f7b24c4 drm/nouveau/ttm: fix crash as a result of a recent ttm
change). However, the suspend/resume issue was not resolved.

Gr. AvS
---------------------
01:00.0 VGA compatible controller: nVidia Corporation GT218 [NVS 3100M]
(rev a2) (prog-if 00 [VGA controller])
        Subsystem: Dell Device 040a
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop-
ParErr- Stepping- SERR- FastB2B- DisINTx-
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort-
<TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Interrupt: pin A routed to IRQ 16
        Region 0: Memory at e2000000 (32-bit, non-prefetchable) [size=16M]
        Region 1: Memory at d0000000 (64-bit, prefetchable) [size=256M]
        Region 3: Memory at e0000000 (64-bit, prefetchable) [size=32M]
        Region 5: I/O ports at 7000 [size=128]
        Expansion ROM at e3000000 [disabled] [size=512K]
        Capabilities: <access denied>
        Kernel driver in use: nouveau
        Kernel modules: nouveau, nvidiafb
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index b1b33a1..680b2f7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -810,7 +810,7 @@ out:
 static void
 nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
 {
-	struct nouveau_mem *node = new_mem->mm_node;
+	struct nouveau_mem *node;
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
 	struct nouveau_vma *vma;
 
@@ -820,6 +820,7 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
 		} else
 		if (new_mem && new_mem->mem_type == TTM_PL_TT &&
 		    nvbo->page_shift == vma->vm->spg_shift) {
+			node = new_mem->mm_node;
 			nouveau_vm_map_sg(vma, 0, new_mem->
 					  num_pages << PAGE_SHIFT,
 					  node, node->pages);