Matthew Garrett ([info]mjg59) wrote,
@ 2008-06-15 16:20:00
Previous Entry  Add to memories!  Tell a Friend!  Next Entry
Entry tags:advogato, fedora

Nvidia resume
As I've mentioned before, one of the major problems facing reliable suspend/resume is graphics reinitialisation. Modern AMD and Nvidia chipsets contain a set of bytecode scripts making up information on how to program a specific card. At boot time the BIOS executes a small native interpreter that runs these. After boot, the driver can execute the scripts itself. This removes the need to have the driver make BIOS calls, and also means that the driver can filter out commands that it feels are undesirable at the time.

The nouveau project have reverse engineered the majority of the BIOS script format for older nvidia hardware. I've stolenmade use of their code by wedging it into a kernel module. On suspend various bits of register state are saved - on resume, they're poked back into the card and the init scripts are run. This is enough to get me some semblance of graphics back on my nvidia laptop, which previously didn't support this at all.

There's a few caveats. First, it doesn't support nv50 based hardware (8000 series and above). There's a hacky alternative method that basically works there for now. Secondly, it doesn't restore text mode correctly. Your consoles won't work again. Thirdly, it doesn't reinitialise the 3D core at all. If you're using nouveau then this means that it'll wedge itself unless you disable acceleration (option "NoAccel" "true" in xorg.conf). If you do use it with nouveau, you need to load the nv_bios module before the nouveau module is probed, since otherwise it'll grab the PCI device. And fourthly, this obviously won't work at all with the binary nvidia drivers. They ought to be doing much the same thing anyway.

The code's here, and I'm interested in finding out how well it works. Especially on desktops, which I can't test myself.

Thanks go to Stuart Bennett, who not only took a painfully bad laptop off my hands but also helped me hugely in working out why the existing code didn't quite work on my hardware (the ptimer values need saving and restoring, for those who have an excessive degree of interest)




(Post a new comment)

Testing
(Anonymous)
2008-06-16 06:57 pm UTC (link)
I'm interested in testing this (on a nv50-based HP8510w).

Two questions:

a) Does it work when using the xorg "nv" driver?

b) "it doesn't support nv50 based hardware (8000 series and above). There's a hacky alternative method that basically works there for now" seems a bit contradictory...does it work for nv50?

(Reply to this) (Thread)

Re: Testing
[info]ajaxxx
2008-06-16 08:41 pm UTC (link)
"It", the code he's working on, does not apply to nv50. There is existing code to try fitfully to resume nv50+ chips. It mostly doesn't work, but sometimes it does, and it's all you get for now.

(Reply to this) (Parent)

Re: Testing
[info]mjg59
2008-06-16 09:06 pm UTC (link)
It works with nv, but it doesn't work with nv50 (yet)

(Reply to this) (Parent)

Explanation for broken nv resume to ram
(Anonymous)
2008-06-28 05:44 pm UTC (link)
I read a slightly technical explanation about nv resume being broken over on katzj's blog (http://katzj.livejournal.com/407566.html?thread=350990#t350990). It sounds like you've sussed the asic init part. Is that right?

(Reply to this) (Thread)

Re: Explanation for broken nv resume to ram
[info]mjg59
2008-06-28 11:28 pm UTC (link)
Not me - the hard code was all written by others. I've just glued it into the kernel. But yes, this is the code that does the asic init.

(Reply to this) (Parent)

Testing nv_bios on Dell Inspiron 8500
(Anonymous)
2009-01-26 01:29 pm UTC (link)
Tested on kernel 2.6.28.2. Not fully as expected: after resuming, the screen becomes more or less white, instead on staying black. dmesg says following when loading the module:

nvidia_resume 0000:01:00.0: PCI INT A -> Link[LNKA] -> GSI 11 (level, low) -> IRQ 11
Attempting to locate BIOS image in PROM
... appears to be valid

and when resuming:

nvidia_resume 0000:01:00.0: restoring config space at offset 0xc (was 0x0, writing 0x80000000)
BMP BIOS found
BMP version 5.39
Bios version 04.28.20.31
0xE73D: Parsing init table 0
0xE73D: ------ EXECUTING FOLLOWING COMMANDS ------
0xE73D: [ (0x65) - INIT_RESET ]
0xE74A: [ (0x6E) - INIT_NV_REG ]
0xE757: [ (0x75) - INIT_CONDITION ]
0xE757: ------ SKIPPING FOLLOWING COMMANDS ------
0xE759: [ (0x62) - INIT_ZM_INDEX_IO ]
0xE75E: [ (0x38) - INIT_NOT ]
0xE75E: ------ EXECUTING FOLLOWING COMMANDS ------
0xE75F: [ (0x62) - INIT_ZM_INDEX_IO ]
0xE764: [ (0x72) - INIT_RESUME ]
0xE765: [ (0x37) - INIT_COPY ]
0xE770: [ (0x6E) - INIT_NV_REG ]
0xE77D: [ (0x78) - INIT_INDEX_IO ]
0xE783: [ (0x78) - INIT_INDEX_IO ]
0xE789: [ (0x7A) - INIT_ZM_REG ]
0xE792: [ (0x78) - INIT_INDEX_IO ]
0xE798: [ (0x79) - INIT_PLL ]
0xE79F: [ (0x79) - INIT_PLL ]
0xE7A6: [ (0x7A) - INIT_ZM_REG ]
0xE7AF: [ (0x7A) - INIT_ZM_REG ]
0xE7B8: [ (0x7A) - INIT_ZM_REG ]
0xE7C1: [ (0x6E) - INIT_NV_REG ]
0xE7CE: [ (0x7A) - INIT_ZM_REG ]
0xE7D7: [ (0x7A) - INIT_ZM_REG ]
0xE7E0: [ (0x7A) - INIT_ZM_REG ]
0xE7E9: [ (0x7A) - INIT_ZM_REG ]
0xE7F2: [ (0x7A) - INIT_ZM_REG ]
0xE7FB: [ (0x7A) - INIT_ZM_REG ]
0xE804: [ (0x7A) - INIT_ZM_REG ]
0xE80D: [ (0x7A) - INIT_ZM_REG ]
0xE816: [ (0x7A) - INIT_ZM_REG ]
0xE81F: [ (0x7A) - INIT_ZM_REG ]
0xE828: [ (0x71) - INIT_DONE ]
... (tables 1 to 5, avoid exceeding max length of this post)
0xE9DB: Parsing init table 6
0xE9DB: ------ EXECUTING FOLLOWING COMMANDS ------
0xE9DB: [ (0x6E) - INIT_NV_REG ]
0xE9E8: [ (0x71) - INIT_DONE ]
Found LVDS manufacturer table revision 0.10
Found flat panel mode table revision 1.0
Display Configuration Block version 2.2 found
Raw DCB entry 0: 01000100 000088b8
Raw DCB entry 1: 02110223 00000064
Unknown LVDS configuration bits, please report

So, here I am, reporting. Not sure what all this means though...

Risto




(Reply to this)


Create an Account
Forgot your login or password?
Login w/ OpenID
English • Español • Deutsch • Русский…