Skip to contentSkip to conversation

Hibernation broken on machines with radeon/KMS and r300

Regression, post-2.6.34 In review Rafael J. Wysocki 5 participants 35 messages Jun 14, 2010 – Jun 18, 2010

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Thanks,
Rafael

00:00.0 RAM memory: nVidia Corporation MCP55 Memory Controller (rev a1)
Subsystem: Micro-Star International Co., Ltd. Device 7250
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
Capabilities: [44] HyperTransport: Slave or Primary Interface
Command: BaseUnitID=0 UnitCnt=15 MastHost- DefDir- DUL-
Link Control 0: CFlE+ CST- CFE- <LkFail- Init+ EOC- TXO- <CRCErr=0 IsocEn- LSEn+ ExtCTL- 64b- Link Config 0: MLWI=16bit DwFcIn- MLWO=16bit DwFcOut- LWI=16bit DwFcInEn- LWO=16bit DwFcOutEn- Link Control 1: CFlE- CST- CFE- <LkFail+ Init- EOC+ TXO+ <CRCErr=0 IsocEn- LSEn- ExtCTL- 64b- Link Config 1: MLWI=8bit DwFcIn- MLWO=8bit DwFcOut- LWI=8bit DwFcInEn- LWO=8bit DwFcOutEn- Revision ID: 1.03
Link Frequency 0: 1.0GHz
Link Error 0: <Prot- <Ovfl- <EOC- CTLTm-
Link Frequency Capability 0: 200MHz+ 300MHz+ 400MHz+ 500MHz+ 600MHz+ 800MHz+ 1.0GHz+ 1.2GHz- 1.4GHz- 1.6GHz- Vend- Feature Capability: IsocFC+ LDTSTOP+ CRCTM- ECTLT- 64bA- UIDRD-
Link Frequency 1: 200MHz
Link Error 1: <Prot- <Ovfl- <EOC- CTLTm-
Link Frequency Capability 1: 200MHz- 300MHz- 400MHz- 500MHz- 600MHz- 800MHz- 1.0GHz- 1.2GHz- 1.4GHz- 1.6GHz- Vend- Error Handling: PFlE+ OFlE+ PFE- OFE- EOCFE- RFE- CRCFE- SERRFE- CF- RE- PNFE- ONFE- EOCNFE- RNFE- CRCNFE- SERRNFE- Prefetchable memory behind bridge Upper: 00-00
Bus Number: 00
Capabilities: [dc] HyperTransport: MSI Mapping Enable+ Fixed-
Mapping Address Base: 00000000fee00000

00:01.0 ISA bridge: nVidia Corporation MCP55 LPC Bridge (rev a2)
Subsystem: Micro-Star International Co., Ltd. Device 7250
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

00:01.1 SMBus: nVidia Corporation MCP55 SMBus (rev a2)
Subsystem: Micro-Star International Co., Ltd. Device 7250
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-
Interrupt: pin A routed to IRQ 11
Region 4: I/O ports at 2d00 [size=64]
Region 5: I/O ports at 2e00 [size=64]
Capabilities: [44] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Kernel driver in use: nForce2_smbus

00:01.2 RAM memory: nVidia Corporation MCP55 Memory Controller (rev a2)
Subsystem: Micro-Star International Co., Ltd. Device 7250
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-

00:02.0 USB Controller: nVidia Corporation MCP55 USB Controller (rev a1) (prog-if 10 [OHCI])
Subsystem: Micro-Star International Co., Ltd. Device 7250
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 (750ns min, 250ns max)
Interrupt: pin A routed to IRQ 23
Region 0: Memory at feafb000 (32-bit, non-prefetchable) [size=4K]
Capabilities: [44] Power Management version 2
Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Kernel driver in use: ohci_hcd

00:02.1 USB Controller: nVidia Corporation MCP55 USB Controller (rev a2) (prog-if 20 [EHCI])
Subsystem: Micro-Star International Co., Ltd. Device 7250
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 (750ns min, 250ns max)
Interrupt: pin B routed to IRQ 20
Region 0: Memory at feafac00 (32-bit, non-prefetchable) [size=256]
Capabilities: [44] Debug port: BAR=1 offset=0098
Capabilities: [80] Power Management version 2
Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Kernel driver in use: ehci_hcd

00:04.0 IDE interface: nVidia Corporation MCP55 IDE (rev a1) (prog-if 8a [Master SecP PriP])
Subsystem: Micro-Star International Co., Ltd. Device 7250
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 (750ns min, 250ns max)
Region 0: [virtual] Memory at 000001f0 (32-bit, non-prefetchable) [size=8]
Region 1: [virtual] Memory at 000003f0 (type 3, non-prefetchable) [size=1]
Region 2: [virtual] Memory at 00000170 (32-bit, non-prefetchable) [size=8]
Region 3: [virtual] Memory at 00000370 (type 3, non-prefetchable) [size=1]
Region 4: I/O ports at ffa0 [size=16]
Capabilities: [44] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Kernel driver in use: pata_amd

00:05.0 IDE interface: nVidia Corporation MCP55 SATA Controller (rev a2) (prog-if 85 [Master SecO PriO])

	Subsystem: Micro-Star International Co., Ltd. Device 7250
	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 (750ns min, 250ns max)
	Interrupt: pin A routed to IRQ 23
	Region 0: I/O ports at d800 [size=8]
	Region 1: I/O ports at d480 [size=4]
	Region 2: I/O ports at d400 [size=8]
	Region 3: I/O ports at d080 [size=4]
	Region 4: I/O ports at d000 [size=16]
	Region 5: Memory at feaf9000 (32-bit, non-prefetchable) [size=4K]
	Capabilities: [44] Power Management version 2
		Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
		Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
	Capabilities: [b0] MSI: Enable- Count=1/4 Maskable- 64bit+
		Address: 0000000000000000  Data: 0000
	Capabilities: [cc] HyperTransport: MSI Mapping Enable- Fixed+
	Kernel driver in use: sata_nv

00:05.1 IDE interface: nVidia Corporation MCP55 SATA Controller (rev a2) (prog-if 85 [Master SecO PriO])
Subsystem: Micro-Star International Co., Ltd. Device 7250
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 (750ns min, 250ns max)
Interrupt: pin B routed to IRQ 22
Region 0: I/O ports at cc00 [size=8]
Region 1: I/O ports at c880 [size=4]
Region 2: I/O ports at c800 [size=8]
Region 3: I/O ports at c480 [size=4]
Region 4: I/O ports at c400 [size=16]
Region 5: Memory at feaf8000 (32-bit, non-prefetchable) [size=4K]
Capabilities: [44] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [b0] MSI: Enable- Count=1/4 Maskable- 64bit+
Address: 0000000000000000 Data: 0000
Capabilities: [cc] HyperTransport: MSI Mapping Enable- Fixed+
Kernel driver in use: sata_nv

00:05.2 IDE interface: nVidia Corporation MCP55 SATA Controller (rev a2) (prog-if 85 [Master SecO PriO])
Subsystem: Micro-Star International Co., Ltd. Device 7250
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 (750ns min, 250ns max)
Interrupt: pin C routed to IRQ 21
Region 0: I/O ports at c080 [size=8]
Region 1: I/O ports at c000 [size=4]
Region 2: I/O ports at bc00 [size=8]
Region 3: I/O ports at b880 [size=4]
Region 4: I/O ports at b800 [size=16]
Region 5: Memory at feaf7000 (32-bit, non-prefetchable) [size=4K]
Capabilities: [44] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [b0] MSI: Enable- Count=1/4 Maskable- 64bit+
Address: 0000000000000000 Data: 0000
Capabilities: [cc] HyperTransport: MSI Mapping Enable- Fixed+
Kernel driver in use: sata_nv

00:06.0 PCI bridge: nVidia Corporation MCP55 PCI bridge (rev a2) (prog-if 01 [Subtractive decode])
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
Bus: primary=00, secondary=01, subordinate=01, sec-latency=64
I/O behind bridge: 0000f000-00000fff
Memory behind bridge: fff00000-000fffff
Prefetchable memory behind bridge: fff00000-000fffff
Secondary status: 66MHz- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity- SERR+ NoISA- VGA- MAbort- >Reset- FastB2B-
PriDiscTmr- SecDiscTmr+ DiscTmrStat- DiscTmrSERREn-
Capabilities: [b8] Subsystem: Gammagraphx, Inc. (or missing ID) Device 0000
Capabilities: [8c] HyperTransport: MSI Mapping Enable- Fixed-
Mapping Address Base: 00000000fee00000

00:06.1 Audio device: nVidia Corporation MCP55 High Definition Audio (rev a2)
Subsystem: Micro-Star International Co., Ltd. Device 7250
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 (500ns min, 1250ns max)
Interrupt: pin B routed to IRQ 21
Region 0: Memory at feaf0000 (32-bit, non-prefetchable) [size=16K]
Capabilities: [44] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [50] MSI: Enable- Count=1/1 Maskable+ 64bit+
Address: 0000000000000000 Data: 0000
Masking: 00000000 Pending: 00000000
Capabilities: [6c] HyperTransport: MSI Mapping Enable- Fixed+
Kernel driver in use: HDA Intel

00:08.0 Bridge: nVidia Corporation MCP55 Ethernet (rev a2)

	Subsystem: Micro-Star International Co., Ltd. Device 7250
	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 (250ns min, 5000ns max)
	Interrupt: pin A routed to IRQ 31
	Region 0: Memory at feaf6000 (32-bit, non-prefetchable) [size=4K]
	Region 1: I/O ports at b480 [size=8]
	Region 2: Memory at feafa800 (32-bit, non-prefetchable) [size=256]
	Region 3: Memory at feafa400 (32-bit, non-prefetchable) [size=16]
	Capabilities: [44] Power Management version 2
		Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
		Status: D0 NoSoftRst- PME-Enable+ DSel=0 DScale=0 PME-
	Capabilities: [70] MSI-X: Enable- Count=8 Masked-
		Vector table: BAR=2 offset=00000000
		PBA: BAR=3 offset=00000000
	Capabilities: [50] MSI: Enable+ Count=1/8 Maskable+ 64bit+
		Address: 00000000fee0300c  Data: 41a1
		Masking: 000000fe  Pending: 00000000
	Capabilities: [6c] HyperTransport: MSI Mapping Enable- Fixed+
	Kernel driver in use: forcedeth

00:09.0 Bridge: nVidia Corporation MCP55 Ethernet (rev a2)

	Subsystem: Micro-Star International Co., Ltd. Device 7250
	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 (250ns min, 5000ns max)
	Interrupt: pin A routed to IRQ 20
	Region 0: Memory at feaf5000 (32-bit, non-prefetchable) [size=4K]
	Region 1: I/O ports at b400 [size=8]
	Region 2: Memory at feafa000 (32-bit, non-prefetchable) [size=256]
	Region 3: Memory at feaf4c00 (32-bit, non-prefetchable) [size=16]
	Capabilities: [44] Power Management version 2
		Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
		Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
	Capabilities: [70] MSI-X: Enable- Count=8 Masked-
		Vector table: BAR=2 offset=00000000
		PBA: BAR=3 offset=00000000
	Capabilities: [50] MSI: Enable- Count=1/8 Maskable+ 64bit+
		Address: 0000000000000000  Data: 0000
		Masking: 00000000  Pending: 00000000
	Capabilities: [6c] HyperTransport: MSI Mapping Enable- Fixed+
	Kernel driver in use: forcedeth

00:0a.0 PCI bridge: nVidia Corporation MCP55 PCI Express bridge (rev a2) (prog-if 00 [Normal decode])
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
Bus: primary=00, secondary=02, subordinate=02, sec-latency=0
I/O behind bridge: 0000f000-00000fff
Memory behind bridge: fff00000-000fffff
Prefetchable memory behind bridge: 00000000fff00000-00000000000fffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity- SERR+ NoISA- VGA- MAbort- >Reset- FastB2B-
PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
Capabilities: [40] Subsystem: nVidia Corporation Device 0000
Capabilities: [48] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [50] MSI: Enable+ Count=1/2 Maskable- 64bit+
Address: 00000000fee0300c Data: 4129
Capabilities: [60] HyperTransport: MSI Mapping Enable- Fixed-
Mapping Address Base: 00000000fee00000
Capabilities: [80] Express (v1) Root Port (Slot+), MSI 00
DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s <512ns, L1 <4us
ExtTag- RBE+ FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
MaxPayload 128 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
LnkCap: Port #5, Speed 2.5GT/s, Width x8, ASPM L0s L1, Latency L0 <512ns, L1 <4us
ClockPM- Surprise- LLActRep+ BwNot-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 2.5GT/s, Width x8, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
SltCap: AttnBtn- PwrCtrl- MRL- AttnInd- PwrInd- HotPlug- Surpise-
Slot # 0, PowerLimit 0.000000; Interlock- NoCompl-
SltCtl: Enable: AttnBtn- PwrFlt- MRL- PresDet- CmdCplt- HPIrq- LinkChg-
Control: AttnInd Off, PwrInd On, Power- Interlock-
SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt- PresDet+ Interlock-
Changed: MRL- PresDet+ LinkState-
RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna- CRSVisible-
RootCap: CRSVisible-
RootSta: PME ReqID 0000, PMEStatus- PMEPending-
Kernel driver in use: pcieport

00:0b.0 PCI bridge: nVidia Corporation MCP55 PCI Express bridge (rev a2) (prog-if 00 [Normal decode])
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
Bus: primary=00, secondary=03, subordinate=03, sec-latency=0
I/O behind bridge: 0000f000-00000fff
Memory behind bridge: fff00000-000fffff
Prefetchable memory behind bridge: 00000000fff00000-00000000000fffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity- SERR+ NoISA- VGA- MAbort- >Reset- FastB2B-
PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
Capabilities: [40] Subsystem: nVidia Corporation Device 0000
Capabilities: [48] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [50] MSI: Enable+ Count=1/2 Maskable- 64bit+
Address: 00000000fee0300c Data: 4141
Capabilities: [60] HyperTransport: MSI Mapping Enable- Fixed-
Mapping Address Base: 00000000fee00000
Capabilities: [80] Express (v1) Root Port (Slot+), MSI 00
DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s <512ns, L1 <4us
ExtTag- RBE+ FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
MaxPayload 128 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
LnkCap: Port #4, Speed 2.5GT/s, Width x1, ASPM L0s L1, Latency L0 <512ns, L1 <4us
ClockPM- Surprise- LLActRep+ BwNot-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 2.5GT/s, Width x4, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
SltCap: AttnBtn- PwrCtrl- MRL- AttnInd- PwrInd- HotPlug- Surpise-
Slot # 0, PowerLimit 0.000000; Interlock- NoCompl-
SltCtl: Enable: AttnBtn- PwrFlt- MRL- PresDet- CmdCplt- HPIrq- LinkChg-
Control: AttnInd Off, PwrInd On, Power- Interlock-
SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt- PresDet- Interlock-
Changed: MRL- PresDet- LinkState-
RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna- CRSVisible-
RootCap: CRSVisible-
RootSta: PME ReqID 0000, PMEStatus- PMEPending-
Kernel driver in use: pcieport

00:0c.0 PCI bridge: nVidia Corporation MCP55 PCI Express bridge (rev a2) (prog-if 00 [Normal decode])
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
Bus: primary=00, secondary=04, subordinate=04, sec-latency=0
I/O behind bridge: 0000f000-00000fff
Memory behind bridge: fff00000-000fffff
Prefetchable memory behind bridge: 00000000fff00000-00000000000fffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity- SERR+ NoISA- VGA- MAbort- >Reset- FastB2B-
PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
Capabilities: [40] Subsystem: nVidia Corporation Device 0000
Capabilities: [48] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [50] MSI: Enable+ Count=1/2 Maskable- 64bit+
Address: 00000000fee0300c Data: 4149
Capabilities: [60] HyperTransport: MSI Mapping Enable- Fixed-
Mapping Address Base: 00000000fee00000
Capabilities: [80] Express (v1) Root Port (Slot+), MSI 00
DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s <512ns, L1 <4us
ExtTag- RBE+ FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
MaxPayload 128 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
LnkCap: Port #3, Speed 2.5GT/s, Width x1, ASPM L0s L1, Latency L0 <512ns, L1 <4us
ClockPM- Surprise- LLActRep+ BwNot-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 2.5GT/s, Width x4, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
SltCap: AttnBtn- PwrCtrl- MRL- AttnInd- PwrInd- HotPlug- Surpise-
Slot # 0, PowerLimit 0.000000; Interlock- NoCompl-
SltCtl: Enable: AttnBtn- PwrFlt- MRL- PresDet- CmdCplt- HPIrq- LinkChg-
Control: AttnInd Off, PwrInd On, Power- Interlock-
SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt- PresDet+ Interlock-
Changed: MRL- PresDet+ LinkState-
RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna- CRSVisible-
RootCap: CRSVisible-
RootSta: PME ReqID 0000, PMEStatus- PMEPending-
Kernel driver in use: pcieport

00:0d.0 PCI bridge: nVidia Corporation MCP55 PCI Express bridge (rev a2) (prog-if 00 [Normal decode])
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
Bus: primary=00, secondary=05, subordinate=05, sec-latency=0
I/O behind bridge: 0000f000-00000fff
Memory behind bridge: fff00000-000fffff
Prefetchable memory behind bridge: 00000000fff00000-00000000000fffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity- SERR+ NoISA- VGA- MAbort- >Reset- FastB2B-
PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
Capabilities: [40] Subsystem: nVidia Corporation Device 0000
Capabilities: [48] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [50] MSI: Enable+ Count=1/2 Maskable- 64bit+
Address: 00000000fee0300c Data: 4151
Capabilities: [60] HyperTransport: MSI Mapping Enable- Fixed-
Mapping Address Base: 00000000fee00000
Capabilities: [80] Express (v1) Root Port (Slot+), MSI 00
DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s <512ns, L1 <4us
ExtTag- RBE+ FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
MaxPayload 128 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
LnkCap: Port #2, Speed 2.5GT/s, Width x1, ASPM L0s L1, Latency L0 <512ns, L1 <4us
ClockPM- Surprise- LLActRep+ BwNot-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 2.5GT/s, Width x4, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
SltCap: AttnBtn- PwrCtrl- MRL- AttnInd- PwrInd- HotPlug- Surpise-
Slot # 0, PowerLimit 0.000000; Interlock- NoCompl-
SltCtl: Enable: AttnBtn- PwrFlt- MRL- PresDet- CmdCplt- HPIrq- LinkChg-
Control: AttnInd Off, PwrInd On, Power- Interlock-
SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt- PresDet+ Interlock-
Changed: MRL- PresDet+ LinkState-
RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna- CRSVisible-
RootCap: CRSVisible-
RootSta: PME ReqID 0000, PMEStatus- PMEPending-
Kernel driver in use: pcieport

00:0e.0 PCI bridge: nVidia Corporation MCP55 PCI Express bridge (rev a2) (prog-if 00 [Normal decode])
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
Bus: primary=00, secondary=06, subordinate=06, sec-latency=0
I/O behind bridge: 0000f000-00000fff
Memory behind bridge: fff00000-000fffff
Prefetchable memory behind bridge: 00000000fff00000-00000000000fffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity- SERR+ NoISA- VGA- MAbort- >Reset- FastB2B-
PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
Capabilities: [40] Subsystem: nVidia Corporation Device 0000
Capabilities: [48] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [50] MSI: Enable+ Count=1/2 Maskable- 64bit+
Address: 00000000fee0300c Data: 4159
Capabilities: [60] HyperTransport: MSI Mapping Enable- Fixed-
Mapping Address Base: 00000000fee00000
Capabilities: [80] Express (v1) Root Port (Slot+), MSI 00
DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s <512ns, L1 <4us
ExtTag- RBE+ FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
MaxPayload 128 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
LnkCap: Port #1, Speed 2.5GT/s, Width x1, ASPM L0s L1, Latency L0 <512ns, L1 <4us
ClockPM- Surprise- LLActRep+ BwNot-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 2.5GT/s, Width x8, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
SltCap: AttnBtn- PwrCtrl- MRL- AttnInd- PwrInd- HotPlug- Surpise-
Slot # 0, PowerLimit 0.000000; Interlock- NoCompl-
SltCtl: Enable: AttnBtn- PwrFlt- MRL- PresDet- CmdCplt- HPIrq- LinkChg-
Control: AttnInd Off, PwrInd On, Power- Interlock-
SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt- PresDet+ Interlock-
Changed: MRL- PresDet+ LinkState-
RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna- CRSVisible-
RootCap: CRSVisible-
RootSta: PME ReqID 0000, PMEStatus- PMEPending-
Kernel driver in use: pcieport

00:0f.0 PCI bridge: nVidia Corporation MCP55 PCI Express bridge (rev a2) (prog-if 00 [Normal decode])
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
Bus: primary=00, secondary=07, subordinate=07, sec-latency=0
I/O behind bridge: 0000e000-0000efff
Memory behind bridge: feb00000-febfffff
Prefetchable memory behind bridge: 00000000d0000000-00000000dfffffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity- SERR+ NoISA- VGA+ MAbort- >Reset- FastB2B-
PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
Capabilities: [40] Subsystem: nVidia Corporation Device 0000
Capabilities: [48] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [50] MSI: Enable+ Count=1/2 Maskable- 64bit+
Address: 00000000fee0300c Data: 4161
Capabilities: [60] HyperTransport: MSI Mapping Enable- Fixed-
Mapping Address Base: 00000000fee00000
Capabilities: [80] Express (v1) Root Port (Slot+), MSI 00
DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s <512ns, L1 <4us
ExtTag- RBE+ FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
MaxPayload 128 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
LnkCap: Port #0, Speed 2.5GT/s, Width x16, ASPM L0s L1, Latency L0 <512ns, L1 <4us
ClockPM- Surprise- LLActRep+ BwNot-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 2.5GT/s, Width x16, TrErr- Train- SlotClk+ DLActive+ BWMgmt- ABWMgmt-
SltCap: AttnBtn- PwrCtrl- MRL- AttnInd- PwrInd- HotPlug- Surpise-
Slot # 0, PowerLimit 0.000000; Interlock- NoCompl-
SltCtl: Enable: AttnBtn- PwrFlt- MRL- PresDet- CmdCplt- HPIrq- LinkChg-
Control: AttnInd Off, PwrInd On, Power- Interlock-
SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt- PresDet+ Interlock-
Changed: MRL- PresDet+ LinkState+
RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna- CRSVisible-
RootCap: CRSVisible-
RootSta: PME ReqID 0000, PMEStatus- PMEPending-
Kernel driver in use: pcieport

00:18.0 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] HyperTransport Technology Configuration
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-
Capabilities: [80] HyperTransport: Host or Secondary Interface
Command: WarmRst+ DblEnd- DevNum=0 ChainSide- HostHide+ Slave- <EOCErr- DUL-
Link Control: CFlE- CST- CFE- <LkFail- Init+ EOC- TXO- <CRCErr=0 IsocEn- LSEn- ExtCTL- 64b- Link Config: MLWI=16bit DwFcIn- MLWO=16bit DwFcOut- LWI=16bit DwFcInEn- LWO=16bit DwFcOutEn- Revision ID: 1.02
Link Frequency: 1.0GHz
Link Error: <Prot- <Ovfl- <EOC- CTLTm-
Link Frequency Capability: 200MHz+ 300MHz- 400MHz+ 500MHz- 600MHz+ 800MHz+ 1.0GHz+ 1.2GHz- 1.4GHz- 1.6GHz- Vend- Feature Capability: IsocFC- LDTSTOP+ CRCTM- ECTLT- 64bA- UIDRD- ExtRS- UCnfE-

00:18.1 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] Address Map
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-

00:18.2 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] DRAM Controller
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-

00:18.3 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] Miscellaneous Control
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-
Capabilities: [f0] Secure device <?>

07:00.0 VGA compatible controller: ATI Technologies Inc RV515 [Radeon X1300] (prog-if 00 [VGA controller])
Subsystem: Giga-byte Technology Device 2144
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 30
Region 0: Memory at d0000000 (64-bit, prefetchable) [size=256M]
Region 2: Memory at febf0000 (64-bit, non-prefetchable) [size=64K]
Region 4: I/O ports at e000 [size=256]
Expansion ROM at febc0000 [disabled] [size=128K]
Capabilities: [50] Power Management version 2
Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [58] Express (v1) Endpoint, MSI 00
DevCap: MaxPayload 128 bytes, PhantFunc 0, Latency L0s <4us, L1 unlimited
ExtTag+ AttnBtn- AttnInd- PwrInd- RBE- FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
MaxPayload 128 bytes, MaxReadReq 128 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
LnkCap: Port #0, Speed 2.5GT/s, Width x16, ASPM L0s L1, Latency L0 <64ns, L1 <1us
ClockPM- Surprise- LLActRep- BwNot-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 2.5GT/s, Width x16, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
Capabilities: [80] MSI: Enable+ Count=1/1 Maskable- 64bit+
Address: 00000000fee0100c Data: 4171
Kernel driver in use: radeon

07:00.1 Display controller: ATI Technologies Inc RV515 [Radeon X1300] (Secondary)
Subsystem: Giga-byte Technology Device 2145
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
Region 0: Memory at febe0000 (64-bit, non-prefetchable) [size=64K]
Capabilities: [50] Power Management version 2
Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [58] Express (v1) Endpoint, MSI 00
DevCap: MaxPayload 128 bytes, PhantFunc 0, Latency L0s <4us, L1 unlimited
ExtTag- AttnBtn- AttnInd- PwrInd- RBE- FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop-
MaxPayload 128 bytes, MaxReadReq 128 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
LnkCap: Port #0, Speed 2.5GT/s, Width x16, ASPM L0s L1, Latency L0 <64ns, L1 <1us
ClockPM- Surprise- LLActRep- BwNot-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 2.5GT/s, Width x16, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-

#1 lore raw
Quoted 10 lines · Rafael J. Wysocki

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management).  At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Quoted 9 lines

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure.  However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Does it work any better after Dave's last drm pull request? With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Alex

Quoted 3 lines

Thanks,
Rafael

#2 lore raw
Quoted 21 lines · Alex Deucher
Quoted 10 lines · Rafael J. Wysocki

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Quoted 9 lines

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Rafael

#3 lore raw

2010/6/14 Rafael J. Wysocki <[email protected]>:

Quoted 22 lines · Alex Deucher
Quoted 21 lines · Rafael J. Wysocki
Quoted 19 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management).  At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure.  However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 4 lines
Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope.  The symptom is slightly different, though, because now it hangs after turning off the screen.

"Just" turning the screen off (like dpms force off) or turning it off while suspending?

Maybe it could be worth enabling drm.debug option and logging using netconsole or similar...

Signature · 1 line
Rafał
#4 lore raw
Quoted 23 lines · Rafał Miłecki

2010/6/14 Rafael J. Wysocki <[email protected]>:

Quoted 22 lines · Alex Deucher
Quoted 21 lines · Rafael J. Wysocki
Quoted 19 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

"Just" turning the screen off (like dpms force off) or turning it off while suspending?

Turning it off while suspending.

Quoted 2 lines

Maybe it could be worth enabling drm.debug option and logging using netconsole or similar...

That doesn't work during suspend, unfortunately.

Perhaps I'll try to use a serial console if I don't fugure out what's wrong.

Rafael
_______________________________________________
linux-pm mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

#5 lore raw
In reply to Rafał Miłecki
Quoted 23 lines · Rafał Miłecki

2010/6/14 Rafael J. Wysocki <[email protected]>:

Quoted 22 lines · Alex Deucher
Quoted 21 lines · Rafael J. Wysocki
Quoted 19 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

"Just" turning the screen off (like dpms force off) or turning it off while suspending?

Turning it off while suspending.

Quoted 2 lines

Maybe it could be worth enabling drm.debug option and logging using netconsole or similar...

That doesn't work during suspend, unfortunately.

Perhaps I'll try to use a serial console if I don't fugure out what's wrong.

Rafael
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#6 lore raw
In reply to Rafael J. Wysocki

2010/6/14 Rafael J. Wysocki <[email protected]>:

Quoted 22 lines · Alex Deucher
Quoted 21 lines · Rafael J. Wysocki
Quoted 19 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management).  At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure.  However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 4 lines
Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope.  The symptom is slightly different, though, because now it hangs after turning off the screen.

"Just" turning the screen off (like dpms force off) or turning it off while suspending?

Maybe it could be worth enabling drm.debug option and logging using netconsole or similar...

Signature · 5 lines
Rafał
_______________________________________________
linux-pm mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/linux-pm
#7 lore raw
In reply to Rafael J. Wysocki
Quoted 24 lines · Rafael J. Wysocki
Quoted 21 lines · Alex Deucher
Quoted 10 lines · Rafael J. Wysocki

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management).  At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Quoted 9 lines

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure.  However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Quoted 7 lines

Nope.  The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

Alex

#8 lore raw
In reply to Rafael J. Wysocki
Quoted 24 lines · Rafael J. Wysocki
Quoted 21 lines · Alex Deucher
Quoted 10 lines · Rafael J. Wysocki

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management).  At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Quoted 9 lines

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure.  However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Quoted 7 lines

Nope.  The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

Alex

#9 lore raw
Quoted 28 lines · Alex Deucher
Quoted 27 lines · Rafael J. Wysocki
Quoted 21 lines · Alex Deucher
Quoted 10 lines · Rafael J. Wysocki

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Quoted 9 lines

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

No, it doesn't. I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid). Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

Rafael

#10 lore raw
Quoted 37 lines · Rafael J. Wysocki
Quoted 28 lines · Alex Deucher
Quoted 27 lines · Rafael J. Wysocki
Quoted 21 lines · Alex Deucher
Quoted 10 lines · Rafael J. Wysocki

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Quoted 9 lines

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

Quoted 7 lines

No, it doesn't. I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid). Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase. Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

Rafael

#11 lore raw
In reply to Rafael J. Wysocki
Quoted 37 lines · Rafael J. Wysocki
Quoted 28 lines · Alex Deucher
Quoted 27 lines · Rafael J. Wysocki
Quoted 21 lines · Alex Deucher
Quoted 10 lines · Rafael J. Wysocki

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Quoted 9 lines

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

Quoted 7 lines

No, it doesn't. I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid). Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase. Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

Rafael

#12 lore raw
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · Rafael J. Wysocki
Quoted 3 lines · Alex Deucher
Quoted 2 lines · Rafael J. Wysocki
Quoted 1 line · Alex Deucher

On Mon, Jun 14, 2010 at 10:53 AM, Rafael J. Wysocki <[email protected]>

Quoted 39 lines · wrote:
Quoted 39 lines
Quoted 27 lines
Quoted 27 lines
Quoted 22 lines
Quoted 14 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Quoted 7 lines

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

No, it doesn't. I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid). Normally, it would turn the screen back on and continue with saving the image.

Quoted 8 lines
Quoted 3 lines

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase. Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

It takes 2 minutes on RV530:
https://bugzilla.redhat.com/show_bug.cgi?id=586522

Signature · 1 line
Ondrej Zary
#13 lore raw
Quoted 50 lines · Ondrej Zary
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · Rafael J. Wysocki
Quoted 3 lines · Alex Deucher
Quoted 2 lines · Rafael J. Wysocki
Quoted 1 line · Alex Deucher

On Mon, Jun 14, 2010 at 10:53 AM, Rafael J. Wysocki <[email protected]>

Quoted 43 lines · wrote:
Quoted 42 lines
Quoted 27 lines
Quoted 27 lines
Quoted 22 lines
Quoted 14 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Quoted 7 lines

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

No, it doesn't. I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid). Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

Quoted 7 lines
Quoted 4 lines

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase. Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

It takes 2 minutes on RV530:
https://bugzilla.redhat.com/show_bug.cgi?id=586522

Well, my second affected box appears to hang somewhere in the radeon's suspend routine.

Rafael

#14 lore raw
Quoted 56 lines · Rafael J. Wysocki
Quoted 55 lines · Ondrej Zary
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · Rafael J. Wysocki
Quoted 3 lines · Alex Deucher
Quoted 2 lines · Rafael J. Wysocki
Quoted 1 line · Alex Deucher

On Mon, Jun 14, 2010 at 10:53 AM, Rafael J. Wysocki <[email protected]>

Quoted 47 lines · wrote:
Quoted 35 lines
Quoted 27 lines
Quoted 27 lines
Quoted 22 lines
Quoted 14 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management).  At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Quoted 7 lines

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure.  However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope.  The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

Quoted 7 lines

No, it doesn't.  I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid).  Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase.  Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

Quoted 5 lines
Quoted 2 lines

It takes 2 minutes on RV530:
https://bugzilla.redhat.com/show_bug.cgi?id=586522

Well, my second affected box appears to hang somewhere in the radeon's suspend routine.

Does the attached patch help?

Alex

From 9d2600fd31c1dda6f41e569fd8aff45c9e5ce54f Mon Sep 17 00:00:00 2001
From: Alex Deucher <[email protected]>
Date: Wed, 16 Jun 2010 16:41:38 -0400
Subject: [PATCH] drm/radeon/kms: only attempt to cancel delayed work if pm method is PM_METHOD_DYNPM

delayed work is only scheduled if pm method is PM_METHOD_DYNPM.

---
 drivers/gpu/drm/radeon/radeon_pm.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)
drivers/gpu/drm/radeon/radeon_pm.c +5 -3
index b9ad366..0751fc8 100644
@@ -407,11 +407,12 @@ static ssize_t radeon_set_pm_method(struct device *dev,
 		mutex_unlock(&rdev->pm.mutex);
 	} else if (strncmp("profile", buf, strlen("profile")) == 0) {
 		mutex_lock(&rdev->pm.mutex);
-		rdev->pm.pm_method = PM_METHOD_PROFILE;
+		if (rdev->pm.pm_method == PM_METHOD_DYNPM)
+			cancel_delayed_work(&rdev->pm.dynpm_idle_work);
 		/* disable dynpm */
 		rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
 		rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-		cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+		rdev->pm.pm_method = PM_METHOD_PROFILE;
 		mutex_unlock(&rdev->pm.mutex);
 	} else {
 		DRM_ERROR("invalid power method!\n");
@@ -428,7 +429,8 @@ static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon
 void radeon_pm_suspend(struct radeon_device *rdev)
 {
 	mutex_lock(&rdev->pm.mutex);
-	cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+	if (rdev->pm.pm_method == PM_METHOD_DYNPM)
+		cancel_delayed_work(&rdev->pm.dynpm_idle_work);
 	mutex_unlock(&rdev->pm.mutex);
 }
 
Signature · 1 line
1.7.0.1
#15 lore raw
Quoted 57 lines · Alex Deucher
Quoted 56 lines · Rafael J. Wysocki
Quoted 55 lines · Ondrej Zary
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · Rafael J. Wysocki
Quoted 3 lines · Alex Deucher
Quoted 2 lines · Rafael J. Wysocki
Quoted 1 line · Alex Deucher

On Mon, Jun 14, 2010 at 10:53 AM, Rafael J. Wysocki <[email protected]>

Quoted 47 lines · wrote:
Quoted 35 lines
Quoted 27 lines
Quoted 27 lines
Quoted 22 lines
Quoted 14 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Quoted 7 lines

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

Quoted 7 lines

No, it doesn't. I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid). Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase. Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

It takes 2 minutes on RV530:
https://bugzilla.redhat.com/show_bug.cgi?id=586522

Well, my second affected box appears to hang somewhere in the radeon's suspend routine.

Does the attached patch help?

It helps, but from what I can see in the code, it still has a few problems.

First, the mutex around cancel_delayed_work() in radeon_pm_suspend() doesn't really serve any purpose, because rdev->pm.pm_method cannot change at this point and cancel_delayed_work() only tries to delete the work's timer. Moreover, it doesn't prevent the work handler from running, in which case the handler can do some wrong things and will rearm itself to do some more wrong things going forward. So, I think it's better to wait for the handler to run in case it's already been queued up and it should also be prevented from rearming itself in that case.

Second, in radeon_set_pm_method() the cancel_delayed_work() is not sufficient to prevent the work handler from running and queing up itself for the next run (the failure scenario is that cancel_delayed_work_sync() returns 0, so the handler is run, it waits on the mutex and then rearms itself after the mutex has been released), so it looks like cancel_delayed_work_sync() should be used to make sure it's not going to run again, but calling that cancel_delayed_work_sync() from under the mutex is not a good idea.

Finally, there's a potential deadlock in radeon_pm_fini(), where cancel_delayed_work_sync() is called under rdev->pm.mutex, but the work handler tries to acquire the same mutex (if it wins the race).

So, I think something like the appended patch is needed.

Rafael

---
 drivers/gpu/drm/radeon/radeon.h    |    3 +-
 drivers/gpu/drm/radeon/radeon_pm.c |   41 ++++++++++++++++++++++++++++++-------
 2 files changed, 36 insertions(+), 8 deletions(-)
drivers/gpu/drm/radeon/radeon_pm.c +34 -7
Index: linux-2.6/drivers/gpu/drm/radeon/radeon_pm.c
===================================================================
@@ -397,13 +397,20 @@ static ssize_t radeon_set_pm_method(stru
 		rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
 		mutex_unlock(&rdev->pm.mutex);
 	} else if (strncmp("profile", buf, strlen("profile")) == 0) {
+		bool flush_wq = false;
+
 		mutex_lock(&rdev->pm.mutex);
-		rdev->pm.pm_method = PM_METHOD_PROFILE;
+		if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+			cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+			flush_wq = true;
+		}
 		/* disable dynpm */
 		rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
 		rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-		cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+		rdev->pm.pm_method = PM_METHOD_PROFILE;
 		mutex_unlock(&rdev->pm.mutex);
+		if (flush_wq)
+			flush_workqueue(rdev->wq);
 	} else {
 		DRM_ERROR("invalid power method!\n");
 		goto fail;
@@ -418,9 +425,18 @@ static DEVICE_ATTR(power_method, S_IRUGO
 
 void radeon_pm_suspend(struct radeon_device *rdev)
 {
+	bool flush_wq = false;
+
 	mutex_lock(&rdev->pm.mutex);
-	cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+	if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+		cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+		if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+			rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+		flush_wq = true;
+	}
 	mutex_unlock(&rdev->pm.mutex);
+	if (flush_wq)
+		flush_workqueue(rdev->wq);
 }
 
 void radeon_pm_resume(struct radeon_device *rdev)
@@ -432,6 +448,12 @@ void radeon_pm_resume(struct radeon_devi
 	rdev->pm.current_sclk = rdev->clock.default_sclk;
 	rdev->pm.current_mclk = rdev->clock.default_mclk;
 	rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+	if (rdev->pm.pm_method == PM_METHOD_DYNPM
+	    && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+		rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+		queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+	}
 	mutex_unlock(&rdev->pm.mutex);
 	radeon_pm_compute_clocks(rdev);
 }
@@ -486,6 +508,8 @@ int radeon_pm_init(struct radeon_device
 void radeon_pm_fini(struct radeon_device *rdev)
 {
 	if (rdev->pm.num_power_states > 1) {
+		bool flush_wq = false;
+
 		mutex_lock(&rdev->pm.mutex);
 		if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
 			rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -493,13 +517,16 @@ void radeon_pm_fini(struct radeon_device
 			radeon_pm_set_clocks(rdev);
 		} else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
 			/* cancel work */
-			cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+			cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+			flush_wq = true;
 			/* reset default clocks */
 			rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
 			rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
 			radeon_pm_set_clocks(rdev);
 		}
 		mutex_unlock(&rdev->pm.mutex);
+		if (flush_wq)
+			flush_workqueue(rdev->wq);
 
 		device_remove_file(rdev->dev, &dev_attr_power_profile);
 		device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -720,12 +747,12 @@ static void radeon_dynpm_idle_work_handl
 			radeon_pm_get_dynpm_state(rdev);
 			radeon_pm_set_clocks(rdev);
 		}
+
+		queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 	}
 	mutex_unlock(&rdev->pm.mutex);
 	ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
-	queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 }
 
 /*
drivers/gpu/drm/radeon/radeon.h +2 -1
Index: linux-2.6/drivers/gpu/drm/radeon/radeon.h
===================================================================
@@ -619,7 +619,8 @@ enum radeon_dynpm_state {
 	DYNPM_STATE_DISABLED,
 	DYNPM_STATE_MINIMUM,
 	DYNPM_STATE_PAUSED,
-	DYNPM_STATE_ACTIVE
+	DYNPM_STATE_ACTIVE,
+	DYNPM_STATE_SUSPENDED,
 };
 enum radeon_dynpm_action {
 	DYNPM_ACTION_NONE,
#16 lore raw

2010/6/17 Rafael J. Wysocki <[email protected]>:

Quoted 85 lines · Alex Deucher
Quoted 57 lines · Rafael J. Wysocki
Quoted 56 lines · Ondrej Zary
Quoted 55 lines · Rafael J. Wysocki
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · Alex Deucher
Quoted 3 lines · Rafael J. Wysocki
Quoted 2 lines · Alex Deucher
Quoted 1 line

On Mon, Jun 14, 2010 at 10:53 AM, Rafael J. Wysocki <[email protected]>

Quoted 47 lines · wrote:
Quoted 35 lines
Quoted 27 lines
Quoted 27 lines
Quoted 22 lines
Quoted 14 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management).  At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Quoted 7 lines

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure.  However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope.  The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

Quoted 7 lines

No, it doesn't.  I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid).  Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase.  Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

It takes 2 minutes on RV530:
https://bugzilla.redhat.com/show_bug.cgi?id=586522

Well, my second affected box appears to hang somewhere in the radeon's suspend routine.

Does the attached patch help?

It helps, but from what I can see in the code, it still has a few problems.

First, the mutex around cancel_delayed_work() in radeon_pm_suspend() doesn't really serve any purpose, because rdev->pm.pm_method cannot change at this point and cancel_delayed_work() only tries to delete the work's timer. Moreover, it doesn't prevent the work handler from running, in which case the handler can do some wrong things and will rearm itself to do some more wrong things going forward.  So, I think it's better to wait for the handler to run in case it's already been queued up and it should also be prevented from rearming itself in that case.

Second, in radeon_set_pm_method() the cancel_delayed_work() is not sufficient to prevent the work handler from running and queing up itself for the next run (the failure scenario is that cancel_delayed_work_sync() returns 0, so the handler is run, it waits on the mutex and then rearms itself after the mutex has been released), so it looks like cancel_delayed_work_sync() should be used to make sure it's not going to run again, but calling that cancel_delayed_work_sync() from under the mutex is not a good idea.

Quoted 6 lines

Finally, there's a potential deadlock in radeon_pm_fini(), where cancel_delayed_work_sync() is called under rdev->pm.mutex, but the work handler tries to acquire the same mutex (if it wins the race).

So, I think something like the appended patch is needed.

Looks reasonable. Does it fix the suspend issue?

Alex

Quoted 127 lines

Rafael

---
 drivers/gpu/drm/radeon/radeon.h    |    3 +- drivers/gpu/drm/radeon/radeon_pm.c |   41 ++++++++++++++++++++++++++++++-------

 2 files changed, 36 insertions(+), 8 deletions(-)

Index: linux-2.6/drivers/gpu/drm/radeon/radeon_pm.c
===================================================================

drivers/gpu/drm/radeon/radeon_pm.c +34 -7
@@ -397,13 +397,20 @@ static ssize_t radeon_set_pm_method(stru
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                mutex_unlock(&rdev->pm.mutex);
        } else if (strncmp("profile", buf, strlen("profile")) == 0) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
-               rdev->pm.pm_method = PM_METHOD_PROFILE;
+               if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
+               }
                /* disable dynpm */
                rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               rdev->pm.pm_method = PM_METHOD_PROFILE;
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
        } else {
                DRM_ERROR("invalid power method!\n");
                goto fail;
@@ -418,9 +425,18 @@ static DEVICE_ATTR(power_method, S_IRUGO
 
  void radeon_pm_suspend(struct radeon_device *rdev)
  {
+       bool flush_wq = false;
+
        mutex_lock(&rdev->pm.mutex);
-       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+                       rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+               flush_wq = true;
+       }
        mutex_unlock(&rdev->pm.mutex);
+       if (flush_wq)
+               flush_workqueue(rdev->wq);
  }
 
  void radeon_pm_resume(struct radeon_device *rdev)
@@ -432,6 +448,12 @@ void radeon_pm_resume(struct radeon_devi
        rdev->pm.current_sclk = rdev->clock.default_sclk;
        rdev->pm.current_mclk = rdev->clock.default_mclk;
        rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM
+           && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+               rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+       }
        mutex_unlock(&rdev->pm.mutex);
        radeon_pm_compute_clocks(rdev);
  }
@@ -486,6 +508,8 @@ int radeon_pm_init(struct radeon_device
  void radeon_pm_fini(struct radeon_device *rdev)
  {
        if (rdev->pm.num_power_states > 1) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
                if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
                        rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -493,13 +517,16 @@ void radeon_pm_fini(struct radeon_device
                        radeon_pm_set_clocks(rdev);
                } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
                        /* cancel work */
-                       cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
                        /* reset default clocks */
                        rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                        rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                        radeon_pm_set_clocks(rdev);
                }
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
 
                device_remove_file(rdev->dev, &dev_attr_power_profile);
                device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -720,12 +747,12 @@ static void radeon_dynpm_idle_work_handl
                        radeon_pm_get_dynpm_state(rdev);
                        radeon_pm_set_clocks(rdev);
                }
+
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
        }
        mutex_unlock(&rdev->pm.mutex);
        ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
-       queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
  }
 
  /*

Index: linux-2.6/drivers/gpu/drm/radeon/radeon.h
===================================================================

drivers/gpu/drm/radeon/radeon.h +2 -1
@@ -619,7 +619,8 @@ enum radeon_dynpm_state {
        DYNPM_STATE_DISABLED,
        DYNPM_STATE_MINIMUM,
        DYNPM_STATE_PAUSED,
-       DYNPM_STATE_ACTIVE
+       DYNPM_STATE_ACTIVE,
+       DYNPM_STATE_SUSPENDED,
  };
  enum radeon_dynpm_action {
        DYNPM_ACTION_NONE,
#17 lore raw
Quoted 86 lines · Alex Deucher

2010/6/17 Rafael J. Wysocki <[email protected]>:

Quoted 85 lines · Alex Deucher
Quoted 57 lines · Rafael J. Wysocki
Quoted 56 lines · Ondrej Zary
Quoted 55 lines · Rafael J. Wysocki
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · Alex Deucher
Quoted 3 lines · Rafael J. Wysocki
Quoted 2 lines · Alex Deucher
Quoted 1 line

On Mon, Jun 14, 2010 at 10:53 AM, Rafael J. Wysocki <[email protected]>

Quoted 47 lines · wrote:
Quoted 35 lines
Quoted 27 lines
Quoted 27 lines
Quoted 22 lines
Quoted 14 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Quoted 7 lines

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

Quoted 7 lines

No, it doesn't. I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid). Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase. Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

It takes 2 minutes on RV530:
https://bugzilla.redhat.com/show_bug.cgi?id=586522

Well, my second affected box appears to hang somewhere in the radeon's suspend routine.

Does the attached patch help?

It helps, but from what I can see in the code, it still has a few problems.

First, the mutex around cancel_delayed_work() in radeon_pm_suspend() doesn't really serve any purpose, because rdev->pm.pm_method cannot change at this point and cancel_delayed_work() only tries to delete the work's timer. Moreover, it doesn't prevent the work handler from running, in which case the handler can do some wrong things and will rearm itself to do some more wrong things going forward. So, I think it's better to wait for the handler to run in case it's already been queued up and it should also be prevented from rearming itself in that case.

Second, in radeon_set_pm_method() the cancel_delayed_work() is not sufficient to prevent the work handler from running and queing up itself for the next run (the failure scenario is that cancel_delayed_work_sync() returns 0, so the handler is run, it waits on the mutex and then rearms itself after the mutex has been released), so it looks like cancel_delayed_work_sync() should be used to make sure it's not going to run again, but calling that cancel_delayed_work_sync() from under the mutex is not a good idea.

Quoted 8 lines
Quoted 6 lines

Finally, there's a potential deadlock in radeon_pm_fini(), where cancel_delayed_work_sync() is called under rdev->pm.mutex, but the work handler tries to acquire the same mutex (if it wins the race).

So, I think something like the appended patch is needed.

Looks reasonable. Does it fix the suspend issue?

Do you mean the $subject one? Yes, it does.

Rafael

Quoted 126 lines
Quoted 124 lines
---
 drivers/gpu/drm/radeon/radeon.h    |    3 +-
 drivers/gpu/drm/radeon/radeon_pm.c |   41 ++++++++++++++++++++++++++++++-------
 2 files changed, 36 insertions(+), 8 deletions(-)

Index: linux-2.6/drivers/gpu/drm/radeon/radeon_pm.c
===================================================================

drivers/gpu/drm/radeon/radeon_pm.c +34 -7
@@ -397,13 +397,20 @@ static ssize_t radeon_set_pm_method(stru
               rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
               mutex_unlock(&rdev->pm.mutex);
       } else if (strncmp("profile", buf, strlen("profile")) == 0) {
+               bool flush_wq = false;
+
               mutex_lock(&rdev->pm.mutex);
-               rdev->pm.pm_method = PM_METHOD_PROFILE;
+               if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
+               }
               /* disable dynpm */
               rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
               rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               rdev->pm.pm_method = PM_METHOD_PROFILE;
               mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
       } else {
               DRM_ERROR("invalid power method!\n");
               goto fail;
@@ -418,9 +425,18 @@ static DEVICE_ATTR(power_method, S_IRUGO
 
 void radeon_pm_suspend(struct radeon_device *rdev)
 {
+       bool flush_wq = false;
+
       mutex_lock(&rdev->pm.mutex);
-       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+                       rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+               flush_wq = true;
+       }
       mutex_unlock(&rdev->pm.mutex);
+       if (flush_wq)
+               flush_workqueue(rdev->wq);
 }
 
 void radeon_pm_resume(struct radeon_device *rdev)
@@ -432,6 +448,12 @@ void radeon_pm_resume(struct radeon_devi
       rdev->pm.current_sclk = rdev->clock.default_sclk;
       rdev->pm.current_mclk = rdev->clock.default_mclk;
       rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM
+           && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+               rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+       }
       mutex_unlock(&rdev->pm.mutex);
       radeon_pm_compute_clocks(rdev);
 }
@@ -486,6 +508,8 @@ int radeon_pm_init(struct radeon_device
 void radeon_pm_fini(struct radeon_device *rdev)
 {
       if (rdev->pm.num_power_states > 1) {
+               bool flush_wq = false;
+
               mutex_lock(&rdev->pm.mutex);
               if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
                       rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -493,13 +517,16 @@ void radeon_pm_fini(struct radeon_device
                       radeon_pm_set_clocks(rdev);
               } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
                       /* cancel work */
-                       cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
                       /* reset default clocks */
                       rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                       rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                       radeon_pm_set_clocks(rdev);
               }
               mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
 
               device_remove_file(rdev->dev, &dev_attr_power_profile);
               device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -720,12 +747,12 @@ static void radeon_dynpm_idle_work_handl
                       radeon_pm_get_dynpm_state(rdev);
                       radeon_pm_set_clocks(rdev);
               }
+
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
       }
       mutex_unlock(&rdev->pm.mutex);
       ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
-       queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 }
 
 /*

Index: linux-2.6/drivers/gpu/drm/radeon/radeon.h
===================================================================

drivers/gpu/drm/radeon/radeon.h +2 -1
@@ -619,7 +619,8 @@ enum radeon_dynpm_state {
       DYNPM_STATE_DISABLED,
       DYNPM_STATE_MINIMUM,
       DYNPM_STATE_PAUSED,
-       DYNPM_STATE_ACTIVE
+       DYNPM_STATE_ACTIVE,
+       DYNPM_STATE_SUSPENDED,
 };
 enum radeon_dynpm_action {
       DYNPM_ACTION_NONE,
#18 lore raw
In reply to Alex Deucher
Quoted 86 lines · Alex Deucher

2010/6/17 Rafael J. Wysocki <[email protected]>:

Quoted 85 lines · Alex Deucher
Quoted 57 lines · Rafael J. Wysocki
Quoted 56 lines · Ondrej Zary
Quoted 55 lines · Rafael J. Wysocki
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · Alex Deucher
Quoted 3 lines · Rafael J. Wysocki
Quoted 2 lines · Alex Deucher
Quoted 1 line

On Mon, Jun 14, 2010 at 10:53 AM, Rafael J. Wysocki <[email protected]>

Quoted 47 lines · wrote:
Quoted 35 lines
Quoted 27 lines
Quoted 27 lines
Quoted 22 lines
Quoted 14 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Quoted 7 lines

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

Quoted 7 lines

No, it doesn't. I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid). Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase. Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

It takes 2 minutes on RV530:
https://bugzilla.redhat.com/show_bug.cgi?id=586522

Well, my second affected box appears to hang somewhere in the radeon's suspend routine.

Does the attached patch help?

It helps, but from what I can see in the code, it still has a few problems.

First, the mutex around cancel_delayed_work() in radeon_pm_suspend() doesn't really serve any purpose, because rdev->pm.pm_method cannot change at this point and cancel_delayed_work() only tries to delete the work's timer. Moreover, it doesn't prevent the work handler from running, in which case the handler can do some wrong things and will rearm itself to do some more wrong things going forward. So, I think it's better to wait for the handler to run in case it's already been queued up and it should also be prevented from rearming itself in that case.

Second, in radeon_set_pm_method() the cancel_delayed_work() is not sufficient to prevent the work handler from running and queing up itself for the next run (the failure scenario is that cancel_delayed_work_sync() returns 0, so the handler is run, it waits on the mutex and then rearms itself after the mutex has been released), so it looks like cancel_delayed_work_sync() should be used to make sure it's not going to run again, but calling that cancel_delayed_work_sync() from under the mutex is not a good idea.

Quoted 8 lines
Quoted 6 lines

Finally, there's a potential deadlock in radeon_pm_fini(), where cancel_delayed_work_sync() is called under rdev->pm.mutex, but the work handler tries to acquire the same mutex (if it wins the race).

So, I think something like the appended patch is needed.

Looks reasonable. Does it fix the suspend issue?

Do you mean the $subject one? Yes, it does.

Rafael

Quoted 126 lines
Quoted 124 lines
---
 drivers/gpu/drm/radeon/radeon.h    |    3 +-
 drivers/gpu/drm/radeon/radeon_pm.c |   41 ++++++++++++++++++++++++++++++-------
 2 files changed, 36 insertions(+), 8 deletions(-)

Index: linux-2.6/drivers/gpu/drm/radeon/radeon_pm.c
===================================================================

drivers/gpu/drm/radeon/radeon_pm.c +34 -7
@@ -397,13 +397,20 @@ static ssize_t radeon_set_pm_method(stru
               rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
               mutex_unlock(&rdev->pm.mutex);
       } else if (strncmp("profile", buf, strlen("profile")) == 0) {
+               bool flush_wq = false;
+
               mutex_lock(&rdev->pm.mutex);
-               rdev->pm.pm_method = PM_METHOD_PROFILE;
+               if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
+               }
               /* disable dynpm */
               rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
               rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               rdev->pm.pm_method = PM_METHOD_PROFILE;
               mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
       } else {
               DRM_ERROR("invalid power method!\n");
               goto fail;
@@ -418,9 +425,18 @@ static DEVICE_ATTR(power_method, S_IRUGO
 
 void radeon_pm_suspend(struct radeon_device *rdev)
 {
+       bool flush_wq = false;
+
       mutex_lock(&rdev->pm.mutex);
-       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+                       rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+               flush_wq = true;
+       }
       mutex_unlock(&rdev->pm.mutex);
+       if (flush_wq)
+               flush_workqueue(rdev->wq);
 }
 
 void radeon_pm_resume(struct radeon_device *rdev)
@@ -432,6 +448,12 @@ void radeon_pm_resume(struct radeon_devi
       rdev->pm.current_sclk = rdev->clock.default_sclk;
       rdev->pm.current_mclk = rdev->clock.default_mclk;
       rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM
+           && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+               rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+       }
       mutex_unlock(&rdev->pm.mutex);
       radeon_pm_compute_clocks(rdev);
 }
@@ -486,6 +508,8 @@ int radeon_pm_init(struct radeon_device
 void radeon_pm_fini(struct radeon_device *rdev)
 {
       if (rdev->pm.num_power_states > 1) {
+               bool flush_wq = false;
+
               mutex_lock(&rdev->pm.mutex);
               if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
                       rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -493,13 +517,16 @@ void radeon_pm_fini(struct radeon_device
                       radeon_pm_set_clocks(rdev);
               } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
                       /* cancel work */
-                       cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
                       /* reset default clocks */
                       rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                       rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                       radeon_pm_set_clocks(rdev);
               }
               mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
 
               device_remove_file(rdev->dev, &dev_attr_power_profile);
               device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -720,12 +747,12 @@ static void radeon_dynpm_idle_work_handl
                       radeon_pm_get_dynpm_state(rdev);
                       radeon_pm_set_clocks(rdev);
               }
+
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
       }
       mutex_unlock(&rdev->pm.mutex);
       ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
-       queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 }
 
 /*

Index: linux-2.6/drivers/gpu/drm/radeon/radeon.h
===================================================================

drivers/gpu/drm/radeon/radeon.h +2 -1
@@ -619,7 +619,8 @@ enum radeon_dynpm_state {
       DYNPM_STATE_DISABLED,
       DYNPM_STATE_MINIMUM,
       DYNPM_STATE_PAUSED,
-       DYNPM_STATE_ACTIVE
+       DYNPM_STATE_ACTIVE,
+       DYNPM_STATE_SUSPENDED,
 };
 enum radeon_dynpm_action {
       DYNPM_ACTION_NONE,
Reviewed-by
#19 lore raw
Quoted 91 lines · Rafael J. Wysocki
Quoted 90 lines · Alex Deucher

2010/6/17 Rafael J. Wysocki <[email protected]>:

Quoted 89 lines · Alex Deucher
Quoted 57 lines · Rafael J. Wysocki
Quoted 56 lines · Ondrej Zary
Quoted 55 lines · Rafael J. Wysocki
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · Alex Deucher
Quoted 3 lines · Rafael J. Wysocki
Quoted 2 lines · Alex Deucher
Quoted 1 line

On Mon, Jun 14, 2010 at 10:53 AM, Rafael J. Wysocki <[email protected]>

Quoted 47 lines · wrote:
Quoted 35 lines
Quoted 27 lines
Quoted 27 lines
Quoted 22 lines
Quoted 14 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management).  At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Quoted 7 lines

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure.  However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope.  The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

Quoted 7 lines

No, it doesn't.  I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid).  Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase.  Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

It takes 2 minutes on RV530:
https://bugzilla.redhat.com/show_bug.cgi?id=586522

Well, my second affected box appears to hang somewhere in the radeon's suspend routine.

Does the attached patch help?

It helps, but from what I can see in the code, it still has a few problems.

First, the mutex around cancel_delayed_work() in radeon_pm_suspend() doesn't really serve any purpose, because rdev->pm.pm_method cannot change at this point and cancel_delayed_work() only tries to delete the work's timer. Moreover, it doesn't prevent the work handler from running, in which case the handler can do some wrong things and will rearm itself to do some more wrong things going forward.  So, I think it's better to wait for the handler to run in case it's already been queued up and it should also be prevented from rearming itself in that case.

Second, in radeon_set_pm_method() the cancel_delayed_work() is not sufficient to prevent the work handler from running and queing up itself for the next run (the failure scenario is that cancel_delayed_work_sync() returns 0, so the handler is run, it waits on the mutex and then rearms itself after the mutex has been released), so it looks like cancel_delayed_work_sync() should be used to make sure it's not going to run again, but calling that cancel_delayed_work_sync() from under the mutex is not a good idea.

Finally, there's a potential deadlock in radeon_pm_fini(), where cancel_delayed_work_sync() is called under rdev->pm.mutex, but the work handler tries to acquire the same mutex (if it wins the race).

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

So, I think something like the appended patch is needed.

Looks reasonable.  Does it fix the suspend issue?

Do you mean the $subject one?  Yes, it does.

Great. Thanks for fixing that up.

Quoted 132 lines

Rafael

Quoted 126 lines
Quoted 124 lines

---
 drivers/gpu/drm/radeon/radeon.h    |    3 +- drivers/gpu/drm/radeon/radeon_pm.c |   41 ++++++++++++++++++++++++++++++-------

 2 files changed, 36 insertions(+), 8 deletions(-)

Index: linux-2.6/drivers/gpu/drm/radeon/radeon_pm.c
===================================================================

drivers/gpu/drm/radeon/radeon_pm.c +34 -7
@@ -397,13 +397,20 @@ static ssize_t radeon_set_pm_method(stru
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                mutex_unlock(&rdev->pm.mutex);
        } else if (strncmp("profile", buf, strlen("profile")) == 0) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
-               rdev->pm.pm_method = PM_METHOD_PROFILE;
+               if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
+               }
                /* disable dynpm */
                rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               rdev->pm.pm_method = PM_METHOD_PROFILE;
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
        } else {
                DRM_ERROR("invalid power method!\n");
                goto fail;
@@ -418,9 +425,18 @@ static DEVICE_ATTR(power_method, S_IRUGO
 
  void radeon_pm_suspend(struct radeon_device *rdev)
  {
+       bool flush_wq = false;
+
        mutex_lock(&rdev->pm.mutex);
-       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+                       rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+               flush_wq = true;
+       }
        mutex_unlock(&rdev->pm.mutex);
+       if (flush_wq)
+               flush_workqueue(rdev->wq);
  }
 
  void radeon_pm_resume(struct radeon_device *rdev)
@@ -432,6 +448,12 @@ void radeon_pm_resume(struct radeon_devi
        rdev->pm.current_sclk = rdev->clock.default_sclk;
        rdev->pm.current_mclk = rdev->clock.default_mclk;
        rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM
+           && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+               rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+       }
        mutex_unlock(&rdev->pm.mutex);
        radeon_pm_compute_clocks(rdev);
  }
@@ -486,6 +508,8 @@ int radeon_pm_init(struct radeon_device
  void radeon_pm_fini(struct radeon_device *rdev)
  {
        if (rdev->pm.num_power_states > 1) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
                if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
                        rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -493,13 +517,16 @@ void radeon_pm_fini(struct radeon_device
                        radeon_pm_set_clocks(rdev);
                } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
                        /* cancel work */
-                       cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
                        /* reset default clocks */
                        rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                        rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                        radeon_pm_set_clocks(rdev);
                }
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
 
                device_remove_file(rdev->dev, &dev_attr_power_profile);
                device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -720,12 +747,12 @@ static void radeon_dynpm_idle_work_handl
                        radeon_pm_get_dynpm_state(rdev);
                        radeon_pm_set_clocks(rdev);
                }
+
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
        }
        mutex_unlock(&rdev->pm.mutex);
        ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
-       queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
  }
 
  /*

Index: linux-2.6/drivers/gpu/drm/radeon/radeon.h
===================================================================

drivers/gpu/drm/radeon/radeon.h +2 -1
@@ -619,7 +619,8 @@ enum radeon_dynpm_state {
        DYNPM_STATE_DISABLED,
        DYNPM_STATE_MINIMUM,
        DYNPM_STATE_PAUSED,
-       DYNPM_STATE_ACTIVE
+       DYNPM_STATE_ACTIVE,
+       DYNPM_STATE_SUSPENDED,
  };
  enum radeon_dynpm_action {
        DYNPM_ACTION_NONE,
#20 lore raw

PATCH 1/1 DRM / radeon / KMS: Fix hibernation regression related to radeon PM (was: Re: [Regression, post-2.6.34] Hibernation broken on machines with radeon/KMS and r300)

From: Rafael J. Wysocki <[email protected]>

There is a regression from 2.6.34 related to the recent radeon power management changes, caused by attempting to cancel a delayed work item that's never been scheduled. However, the code as is has some other issues potentially leading to visible problems.

First, the mutex around cancel_delayed_work() in radeon_pm_suspend() doesn't really serve any purpose, because cancel_delayed_work() only tries to delete the work's timer. Moreover, it doesn't prevent the work handler from running, so the handler can do some wrong things if it wins the race and in that case it will rearm itself to do some more wrong things going forward. So, I think it's better to wait for the handler to return in case it's already been queued up for execution. Also, it should be prevented from rearming itself in that case.

Second, in radeon_set_pm_method() the cancel_delayed_work() is not sufficient to prevent the work handler from running and queing up itself for the next run (the failure scenario is that cancel_delayed_work() returns 0, so the handler is run, it waits on the mutex and then rearms itself after the mutex has been released), so again the work handler should be prevented from rearming itself in that case..

Finally, there's a potential deadlock in radeon_pm_fini(), because cancel_delayed_work_sync() is called under rdev->pm.mutex, but the work handler tries to acquire the same mutex (if it wins the race).

Fix the issues described above.

---
 drivers/gpu/drm/radeon/radeon.h    |    3 +-
 drivers/gpu/drm/radeon/radeon_pm.c |   41 ++++++++++++++++++++++++++++++-------
 2 files changed, 36 insertions(+), 8 deletions(-)
drivers/gpu/drm/radeon/radeon_pm.c +34 -7
Index: linux-2.6/drivers/gpu/drm/radeon/radeon_pm.c
===================================================================
@@ -397,13 +397,20 @@ static ssize_t radeon_set_pm_method(stru
 		rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
 		mutex_unlock(&rdev->pm.mutex);
 	} else if (strncmp("profile", buf, strlen("profile")) == 0) {
+		bool flush_wq = false;
+
 		mutex_lock(&rdev->pm.mutex);
-		rdev->pm.pm_method = PM_METHOD_PROFILE;
+		if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+			cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+			flush_wq = true;
+		}
 		/* disable dynpm */
 		rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
 		rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-		cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+		rdev->pm.pm_method = PM_METHOD_PROFILE;
 		mutex_unlock(&rdev->pm.mutex);
+		if (flush_wq)
+			flush_workqueue(rdev->wq);
 	} else {
 		DRM_ERROR("invalid power method!\n");
 		goto fail;
@@ -418,9 +425,18 @@ static DEVICE_ATTR(power_method, S_IRUGO
 
 void radeon_pm_suspend(struct radeon_device *rdev)
 {
+	bool flush_wq = false;
+
 	mutex_lock(&rdev->pm.mutex);
-	cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+	if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+		cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+		if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+			rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+		flush_wq = true;
+	}
 	mutex_unlock(&rdev->pm.mutex);
+	if (flush_wq)
+		flush_workqueue(rdev->wq);
 }
 
 void radeon_pm_resume(struct radeon_device *rdev)
@@ -432,6 +448,12 @@ void radeon_pm_resume(struct radeon_devi
 	rdev->pm.current_sclk = rdev->clock.default_sclk;
 	rdev->pm.current_mclk = rdev->clock.default_mclk;
 	rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+	if (rdev->pm.pm_method == PM_METHOD_DYNPM
+	    && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+		rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+		queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+	}
 	mutex_unlock(&rdev->pm.mutex);
 	radeon_pm_compute_clocks(rdev);
 }
@@ -486,6 +508,8 @@ int radeon_pm_init(struct radeon_device
 void radeon_pm_fini(struct radeon_device *rdev)
 {
 	if (rdev->pm.num_power_states > 1) {
+		bool flush_wq = false;
+
 		mutex_lock(&rdev->pm.mutex);
 		if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
 			rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -493,13 +517,16 @@ void radeon_pm_fini(struct radeon_device
 			radeon_pm_set_clocks(rdev);
 		} else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
 			/* cancel work */
-			cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+			cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+			flush_wq = true;
 			/* reset default clocks */
 			rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
 			rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
 			radeon_pm_set_clocks(rdev);
 		}
 		mutex_unlock(&rdev->pm.mutex);
+		if (flush_wq)
+			flush_workqueue(rdev->wq);
 
 		device_remove_file(rdev->dev, &dev_attr_power_profile);
 		device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -720,12 +747,12 @@ static void radeon_dynpm_idle_work_handl
 			radeon_pm_get_dynpm_state(rdev);
 			radeon_pm_set_clocks(rdev);
 		}
+
+		queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 	}
 	mutex_unlock(&rdev->pm.mutex);
 	ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
-	queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 }
 
 /*
drivers/gpu/drm/radeon/radeon.h +2 -1
Index: linux-2.6/drivers/gpu/drm/radeon/radeon.h
===================================================================
@@ -619,7 +619,8 @@ enum radeon_dynpm_state {
 	DYNPM_STATE_DISABLED,
 	DYNPM_STATE_MINIMUM,
 	DYNPM_STATE_PAUSED,
-	DYNPM_STATE_ACTIVE
+	DYNPM_STATE_ACTIVE,
+	DYNPM_STATE_SUSPENDED,
 };
 enum radeon_dynpm_action {
 	DYNPM_ACTION_NONE,
#21 lore raw

Re: [PATCH] DRM / radeon / KMS: Fix hibernation regression related to radeon PM (was: Re: [Regression, post-2.6.34] Hibernation broken on machines with radeon/KMS and r300)

Quoted 155 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

There is a regression from 2.6.34 related to the recent radeon power management changes, caused by attempting to cancel a delayed work item that's never been scheduled.  However, the code as is has some other issues potentially leading to visible problems.

First, the mutex around cancel_delayed_work() in radeon_pm_suspend() doesn't really serve any purpose, because cancel_delayed_work() only tries to delete the work's timer.  Moreover, it doesn't prevent the work handler from running, so the handler can do some wrong things if it wins the race and in that case it will rearm itself to do some more wrong things going forward.  So, I think it's better to wait for the handler to return in case it's already been queued up for execution.  Also, it should be prevented from rearming itself in that case.

Second, in radeon_set_pm_method() the cancel_delayed_work() is not sufficient to prevent the work handler from running and queing up itself for the next run (the failure scenario is that cancel_delayed_work() returns 0, so the handler is run, it waits on the mutex and then rearms itself after the mutex has been released), so again the work handler should be prevented from rearming itself in that case..

Finally, there's a potential deadlock in radeon_pm_fini(), because cancel_delayed_work_sync() is called under rdev->pm.mutex, but the work handler tries to acquire the same mutex (if it wins the race).

Fix the issues described above.

---
 drivers/gpu/drm/radeon/radeon.h    |    3 +- drivers/gpu/drm/radeon/radeon_pm.c |   41 ++++++++++++++++++++++++++++++-------

 2 files changed, 36 insertions(+), 8 deletions(-)

Index: linux-2.6/drivers/gpu/drm/radeon/radeon_pm.c
===================================================================

drivers/gpu/drm/radeon/radeon_pm.c +34 -7
@@ -397,13 +397,20 @@ static ssize_t radeon_set_pm_method(stru
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                mutex_unlock(&rdev->pm.mutex);
        } else if (strncmp("profile", buf, strlen("profile")) == 0) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
-               rdev->pm.pm_method = PM_METHOD_PROFILE;
+               if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
+               }
                /* disable dynpm */
                rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               rdev->pm.pm_method = PM_METHOD_PROFILE;
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
        } else {
                DRM_ERROR("invalid power method!\n");
                goto fail;
@@ -418,9 +425,18 @@ static DEVICE_ATTR(power_method, S_IRUGO
 
  void radeon_pm_suspend(struct radeon_device *rdev)
  {
+       bool flush_wq = false;
+
        mutex_lock(&rdev->pm.mutex);
-       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+                       rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+               flush_wq = true;
+       }
        mutex_unlock(&rdev->pm.mutex);
+       if (flush_wq)
+               flush_workqueue(rdev->wq);
  }
 
  void radeon_pm_resume(struct radeon_device *rdev)
@@ -432,6 +448,12 @@ void radeon_pm_resume(struct radeon_devi
        rdev->pm.current_sclk = rdev->clock.default_sclk;
        rdev->pm.current_mclk = rdev->clock.default_mclk;
        rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM
+           && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+               rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+       }
        mutex_unlock(&rdev->pm.mutex);
        radeon_pm_compute_clocks(rdev);
  }
@@ -486,6 +508,8 @@ int radeon_pm_init(struct radeon_device
  void radeon_pm_fini(struct radeon_device *rdev)
  {
        if (rdev->pm.num_power_states > 1) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
                if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
                        rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -493,13 +517,16 @@ void radeon_pm_fini(struct radeon_device
                        radeon_pm_set_clocks(rdev);
                } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
                        /* cancel work */
-                       cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
                        /* reset default clocks */
                        rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                        rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                        radeon_pm_set_clocks(rdev);
                }
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
 
                device_remove_file(rdev->dev, &dev_attr_power_profile);
                device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -720,12 +747,12 @@ static void radeon_dynpm_idle_work_handl
                        radeon_pm_get_dynpm_state(rdev);
                        radeon_pm_set_clocks(rdev);
                }
+
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
        }
        mutex_unlock(&rdev->pm.mutex);
        ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
-       queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
  }
 
  /*

Index: linux-2.6/drivers/gpu/drm/radeon/radeon.h
===================================================================

drivers/gpu/drm/radeon/radeon.h +2 -1
@@ -619,7 +619,8 @@ enum radeon_dynpm_state {
        DYNPM_STATE_DISABLED,
        DYNPM_STATE_MINIMUM,
        DYNPM_STATE_PAUSED,
-       DYNPM_STATE_ACTIVE
+       DYNPM_STATE_ACTIVE,
+       DYNPM_STATE_SUSPENDED,
  };
  enum radeon_dynpm_action {
        DYNPM_ACTION_NONE,
Quoted 4 lines

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Probably want to shorten the commit title a bit.

Matt

#22 lore raw

Re: [PATCH] DRM / radeon / KMS: Fix hibernation regression related to radeon PM (was: Re: [Regression, post-2.6.34] Hibernation broken on machines with radeon/KMS and r300)

Quoted 2 lines · Matt Turner
Quoted 1 line · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

...

Quoted 3 lines
Quoted 1 line

http://lists.freedesktop.org/mailman/listinfo/dri-devel

Probably want to shorten the commit title a bit.

In fact the title is just "DRM / radeon / KMS: Fix hibernation regression related to radeon PM", the rest is to preserve the context.

Thanks,
Rafael

#23 lore raw

Re: [PATCH] DRM / radeon / KMS: Fix hibernation regression related to radeon PM (was: Re: [Regression, post-2.6.34] Hibernation broken on machines with radeon/KMS and r300)

In reply to Matt Turner
Quoted 2 lines · Matt Turner
Quoted 1 line · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

...

Quoted 3 lines
Quoted 1 line

http://lists.freedesktop.org/mailman/listinfo/dri-devel

Probably want to shorten the commit title a bit.

In fact the title is just "DRM / radeon / KMS: Fix hibernation regression related to radeon PM", the rest is to preserve the context.

Thanks,
Rafael

#24 lore raw

Re: [PATCH] DRM / radeon / KMS: Fix hibernation regression related to radeon PM (was: Re: [Regression, post-2.6.34] Hibernation broken on machines with radeon/KMS and r300)

In reply to Rafael J. Wysocki
Quoted 155 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

There is a regression from 2.6.34 related to the recent radeon power management changes, caused by attempting to cancel a delayed work item that's never been scheduled.  However, the code as is has some other issues potentially leading to visible problems.

First, the mutex around cancel_delayed_work() in radeon_pm_suspend() doesn't really serve any purpose, because cancel_delayed_work() only tries to delete the work's timer.  Moreover, it doesn't prevent the work handler from running, so the handler can do some wrong things if it wins the race and in that case it will rearm itself to do some more wrong things going forward.  So, I think it's better to wait for the handler to return in case it's already been queued up for execution.  Also, it should be prevented from rearming itself in that case.

Second, in radeon_set_pm_method() the cancel_delayed_work() is not sufficient to prevent the work handler from running and queing up itself for the next run (the failure scenario is that cancel_delayed_work() returns 0, so the handler is run, it waits on the mutex and then rearms itself after the mutex has been released), so again the work handler should be prevented from rearming itself in that case..

Finally, there's a potential deadlock in radeon_pm_fini(), because cancel_delayed_work_sync() is called under rdev->pm.mutex, but the work handler tries to acquire the same mutex (if it wins the race).

Fix the issues described above.

---
 drivers/gpu/drm/radeon/radeon.h    |    3 +- drivers/gpu/drm/radeon/radeon_pm.c |   41 ++++++++++++++++++++++++++++++-------

 2 files changed, 36 insertions(+), 8 deletions(-)

Index: linux-2.6/drivers/gpu/drm/radeon/radeon_pm.c
===================================================================

drivers/gpu/drm/radeon/radeon_pm.c +34 -7
@@ -397,13 +397,20 @@ static ssize_t radeon_set_pm_method(stru
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                mutex_unlock(&rdev->pm.mutex);
        } else if (strncmp("profile", buf, strlen("profile")) == 0) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
-               rdev->pm.pm_method = PM_METHOD_PROFILE;
+               if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
+               }
                /* disable dynpm */
                rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               rdev->pm.pm_method = PM_METHOD_PROFILE;
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
        } else {
                DRM_ERROR("invalid power method!\n");
                goto fail;
@@ -418,9 +425,18 @@ static DEVICE_ATTR(power_method, S_IRUGO
 
  void radeon_pm_suspend(struct radeon_device *rdev)
  {
+       bool flush_wq = false;
+
        mutex_lock(&rdev->pm.mutex);
-       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+                       rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+               flush_wq = true;
+       }
        mutex_unlock(&rdev->pm.mutex);
+       if (flush_wq)
+               flush_workqueue(rdev->wq);
  }
 
  void radeon_pm_resume(struct radeon_device *rdev)
@@ -432,6 +448,12 @@ void radeon_pm_resume(struct radeon_devi
        rdev->pm.current_sclk = rdev->clock.default_sclk;
        rdev->pm.current_mclk = rdev->clock.default_mclk;
        rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM
+           && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+               rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+       }
        mutex_unlock(&rdev->pm.mutex);
        radeon_pm_compute_clocks(rdev);
  }
@@ -486,6 +508,8 @@ int radeon_pm_init(struct radeon_device
  void radeon_pm_fini(struct radeon_device *rdev)
  {
        if (rdev->pm.num_power_states > 1) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
                if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
                        rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -493,13 +517,16 @@ void radeon_pm_fini(struct radeon_device
                        radeon_pm_set_clocks(rdev);
                } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
                        /* cancel work */
-                       cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
                        /* reset default clocks */
                        rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                        rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                        radeon_pm_set_clocks(rdev);
                }
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
 
                device_remove_file(rdev->dev, &dev_attr_power_profile);
                device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -720,12 +747,12 @@ static void radeon_dynpm_idle_work_handl
                        radeon_pm_get_dynpm_state(rdev);
                        radeon_pm_set_clocks(rdev);
                }
+
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
        }
        mutex_unlock(&rdev->pm.mutex);
        ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
-       queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
  }
 
  /*

Index: linux-2.6/drivers/gpu/drm/radeon/radeon.h
===================================================================

drivers/gpu/drm/radeon/radeon.h +2 -1
@@ -619,7 +619,8 @@ enum radeon_dynpm_state {
        DYNPM_STATE_DISABLED,
        DYNPM_STATE_MINIMUM,
        DYNPM_STATE_PAUSED,
-       DYNPM_STATE_ACTIVE
+       DYNPM_STATE_ACTIVE,
+       DYNPM_STATE_SUSPENDED,
  };
  enum radeon_dynpm_action {
        DYNPM_ACTION_NONE,
Quoted 4 lines

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Probably want to shorten the commit title a bit.

Matt

#25 lore raw

PATCH 1/1 DRM / radeon / KMS: Fix hibernation regression related to radeon PM (was: Re: [Regression, post-2.6.34] Hibernation broken on machines with radeon/KMS and r300)

In reply to Alex Deucher

From: Rafael J. Wysocki <[email protected]>

There is a regression from 2.6.34 related to the recent radeon power management changes, caused by attempting to cancel a delayed work item that's never been scheduled. However, the code as is has some other issues potentially leading to visible problems.

First, the mutex around cancel_delayed_work() in radeon_pm_suspend() doesn't really serve any purpose, because cancel_delayed_work() only tries to delete the work's timer. Moreover, it doesn't prevent the work handler from running, so the handler can do some wrong things if it wins the race and in that case it will rearm itself to do some more wrong things going forward. So, I think it's better to wait for the handler to return in case it's already been queued up for execution. Also, it should be prevented from rearming itself in that case.

Second, in radeon_set_pm_method() the cancel_delayed_work() is not sufficient to prevent the work handler from running and queing up itself for the next run (the failure scenario is that cancel_delayed_work() returns 0, so the handler is run, it waits on the mutex and then rearms itself after the mutex has been released), so again the work handler should be prevented from rearming itself in that case..

Finally, there's a potential deadlock in radeon_pm_fini(), because cancel_delayed_work_sync() is called under rdev->pm.mutex, but the work handler tries to acquire the same mutex (if it wins the race).

Fix the issues described above.

---
 drivers/gpu/drm/radeon/radeon.h    |    3 +-
 drivers/gpu/drm/radeon/radeon_pm.c |   41 ++++++++++++++++++++++++++++++-------
 2 files changed, 36 insertions(+), 8 deletions(-)
drivers/gpu/drm/radeon/radeon_pm.c +34 -7
Index: linux-2.6/drivers/gpu/drm/radeon/radeon_pm.c
===================================================================
@@ -397,13 +397,20 @@ static ssize_t radeon_set_pm_method(stru
 		rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
 		mutex_unlock(&rdev->pm.mutex);
 	} else if (strncmp("profile", buf, strlen("profile")) == 0) {
+		bool flush_wq = false;
+
 		mutex_lock(&rdev->pm.mutex);
-		rdev->pm.pm_method = PM_METHOD_PROFILE;
+		if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+			cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+			flush_wq = true;
+		}
 		/* disable dynpm */
 		rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
 		rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-		cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+		rdev->pm.pm_method = PM_METHOD_PROFILE;
 		mutex_unlock(&rdev->pm.mutex);
+		if (flush_wq)
+			flush_workqueue(rdev->wq);
 	} else {
 		DRM_ERROR("invalid power method!\n");
 		goto fail;
@@ -418,9 +425,18 @@ static DEVICE_ATTR(power_method, S_IRUGO
 
 void radeon_pm_suspend(struct radeon_device *rdev)
 {
+	bool flush_wq = false;
+
 	mutex_lock(&rdev->pm.mutex);
-	cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+	if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+		cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+		if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+			rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+		flush_wq = true;
+	}
 	mutex_unlock(&rdev->pm.mutex);
+	if (flush_wq)
+		flush_workqueue(rdev->wq);
 }
 
 void radeon_pm_resume(struct radeon_device *rdev)
@@ -432,6 +448,12 @@ void radeon_pm_resume(struct radeon_devi
 	rdev->pm.current_sclk = rdev->clock.default_sclk;
 	rdev->pm.current_mclk = rdev->clock.default_mclk;
 	rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+	if (rdev->pm.pm_method == PM_METHOD_DYNPM
+	    && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+		rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+		queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+	}
 	mutex_unlock(&rdev->pm.mutex);
 	radeon_pm_compute_clocks(rdev);
 }
@@ -486,6 +508,8 @@ int radeon_pm_init(struct radeon_device
 void radeon_pm_fini(struct radeon_device *rdev)
 {
 	if (rdev->pm.num_power_states > 1) {
+		bool flush_wq = false;
+
 		mutex_lock(&rdev->pm.mutex);
 		if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
 			rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -493,13 +517,16 @@ void radeon_pm_fini(struct radeon_device
 			radeon_pm_set_clocks(rdev);
 		} else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
 			/* cancel work */
-			cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+			cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+			flush_wq = true;
 			/* reset default clocks */
 			rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
 			rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
 			radeon_pm_set_clocks(rdev);
 		}
 		mutex_unlock(&rdev->pm.mutex);
+		if (flush_wq)
+			flush_workqueue(rdev->wq);
 
 		device_remove_file(rdev->dev, &dev_attr_power_profile);
 		device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -720,12 +747,12 @@ static void radeon_dynpm_idle_work_handl
 			radeon_pm_get_dynpm_state(rdev);
 			radeon_pm_set_clocks(rdev);
 		}
+
+		queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 	}
 	mutex_unlock(&rdev->pm.mutex);
 	ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
-	queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 }
 
 /*
drivers/gpu/drm/radeon/radeon.h +2 -1
Index: linux-2.6/drivers/gpu/drm/radeon/radeon.h
===================================================================
@@ -619,7 +619,8 @@ enum radeon_dynpm_state {
 	DYNPM_STATE_DISABLED,
 	DYNPM_STATE_MINIMUM,
 	DYNPM_STATE_PAUSED,
-	DYNPM_STATE_ACTIVE
+	DYNPM_STATE_ACTIVE,
+	DYNPM_STATE_SUSPENDED,
 };
 enum radeon_dynpm_action {
 	DYNPM_ACTION_NONE,
Reviewed-by
#26 lore raw
In reply to Rafael J. Wysocki
Quoted 91 lines · Rafael J. Wysocki
Quoted 90 lines · Alex Deucher

2010/6/17 Rafael J. Wysocki <[email protected]>:

Quoted 89 lines · Alex Deucher
Quoted 57 lines · Rafael J. Wysocki
Quoted 56 lines · Ondrej Zary
Quoted 55 lines · Rafael J. Wysocki
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · Alex Deucher
Quoted 3 lines · Rafael J. Wysocki
Quoted 2 lines · Alex Deucher
Quoted 1 line

On Mon, Jun 14, 2010 at 10:53 AM, Rafael J. Wysocki <[email protected]>

Quoted 47 lines · wrote:
Quoted 35 lines
Quoted 27 lines
Quoted 27 lines
Quoted 22 lines
Quoted 14 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management).  At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Quoted 7 lines

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure.  However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope.  The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

Quoted 7 lines

No, it doesn't.  I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid).  Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase.  Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

It takes 2 minutes on RV530:
https://bugzilla.redhat.com/show_bug.cgi?id=586522

Well, my second affected box appears to hang somewhere in the radeon's suspend routine.

Does the attached patch help?

It helps, but from what I can see in the code, it still has a few problems.

First, the mutex around cancel_delayed_work() in radeon_pm_suspend() doesn't really serve any purpose, because rdev->pm.pm_method cannot change at this point and cancel_delayed_work() only tries to delete the work's timer. Moreover, it doesn't prevent the work handler from running, in which case the handler can do some wrong things and will rearm itself to do some more wrong things going forward.  So, I think it's better to wait for the handler to run in case it's already been queued up and it should also be prevented from rearming itself in that case.

Second, in radeon_set_pm_method() the cancel_delayed_work() is not sufficient to prevent the work handler from running and queing up itself for the next run (the failure scenario is that cancel_delayed_work_sync() returns 0, so the handler is run, it waits on the mutex and then rearms itself after the mutex has been released), so it looks like cancel_delayed_work_sync() should be used to make sure it's not going to run again, but calling that cancel_delayed_work_sync() from under the mutex is not a good idea.

Finally, there's a potential deadlock in radeon_pm_fini(), where cancel_delayed_work_sync() is called under rdev->pm.mutex, but the work handler tries to acquire the same mutex (if it wins the race).

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

So, I think something like the appended patch is needed.

Looks reasonable.  Does it fix the suspend issue?

Do you mean the $subject one?  Yes, it does.

Great. Thanks for fixing that up.

Quoted 132 lines

Rafael

Quoted 126 lines
Quoted 124 lines

---
 drivers/gpu/drm/radeon/radeon.h    |    3 +- drivers/gpu/drm/radeon/radeon_pm.c |   41 ++++++++++++++++++++++++++++++-------

 2 files changed, 36 insertions(+), 8 deletions(-)

Index: linux-2.6/drivers/gpu/drm/radeon/radeon_pm.c
===================================================================

drivers/gpu/drm/radeon/radeon_pm.c +34 -7
@@ -397,13 +397,20 @@ static ssize_t radeon_set_pm_method(stru
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                mutex_unlock(&rdev->pm.mutex);
        } else if (strncmp("profile", buf, strlen("profile")) == 0) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
-               rdev->pm.pm_method = PM_METHOD_PROFILE;
+               if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
+               }
                /* disable dynpm */
                rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               rdev->pm.pm_method = PM_METHOD_PROFILE;
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
        } else {
                DRM_ERROR("invalid power method!\n");
                goto fail;
@@ -418,9 +425,18 @@ static DEVICE_ATTR(power_method, S_IRUGO
 
  void radeon_pm_suspend(struct radeon_device *rdev)
  {
+       bool flush_wq = false;
+
        mutex_lock(&rdev->pm.mutex);
-       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+                       rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+               flush_wq = true;
+       }
        mutex_unlock(&rdev->pm.mutex);
+       if (flush_wq)
+               flush_workqueue(rdev->wq);
  }
 
  void radeon_pm_resume(struct radeon_device *rdev)
@@ -432,6 +448,12 @@ void radeon_pm_resume(struct radeon_devi
        rdev->pm.current_sclk = rdev->clock.default_sclk;
        rdev->pm.current_mclk = rdev->clock.default_mclk;
        rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM
+           && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+               rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+       }
        mutex_unlock(&rdev->pm.mutex);
        radeon_pm_compute_clocks(rdev);
  }
@@ -486,6 +508,8 @@ int radeon_pm_init(struct radeon_device
  void radeon_pm_fini(struct radeon_device *rdev)
  {
        if (rdev->pm.num_power_states > 1) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
                if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
                        rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -493,13 +517,16 @@ void radeon_pm_fini(struct radeon_device
                        radeon_pm_set_clocks(rdev);
                } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
                        /* cancel work */
-                       cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
                        /* reset default clocks */
                        rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                        rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                        radeon_pm_set_clocks(rdev);
                }
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
 
                device_remove_file(rdev->dev, &dev_attr_power_profile);
                device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -720,12 +747,12 @@ static void radeon_dynpm_idle_work_handl
                        radeon_pm_get_dynpm_state(rdev);
                        radeon_pm_set_clocks(rdev);
                }
+
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
        }
        mutex_unlock(&rdev->pm.mutex);
        ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
-       queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
  }
 
  /*

Index: linux-2.6/drivers/gpu/drm/radeon/radeon.h
===================================================================

drivers/gpu/drm/radeon/radeon.h +2 -1
@@ -619,7 +619,8 @@ enum radeon_dynpm_state {
        DYNPM_STATE_DISABLED,
        DYNPM_STATE_MINIMUM,
        DYNPM_STATE_PAUSED,
-       DYNPM_STATE_ACTIVE
+       DYNPM_STATE_ACTIVE,
+       DYNPM_STATE_SUSPENDED,
  };
  enum radeon_dynpm_action {
        DYNPM_ACTION_NONE,
#27 lore raw
In reply to Rafael J. Wysocki

2010/6/17 Rafael J. Wysocki <[email protected]>:

Quoted 85 lines · Alex Deucher
Quoted 57 lines · Rafael J. Wysocki
Quoted 56 lines · Ondrej Zary
Quoted 55 lines · Rafael J. Wysocki
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · Alex Deucher
Quoted 3 lines · Rafael J. Wysocki
Quoted 2 lines · Alex Deucher
Quoted 1 line

On Mon, Jun 14, 2010 at 10:53 AM, Rafael J. Wysocki <[email protected]>

Quoted 47 lines · wrote:
Quoted 35 lines
Quoted 27 lines
Quoted 27 lines
Quoted 22 lines
Quoted 14 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management).  At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Quoted 7 lines

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure.  However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope.  The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

Quoted 7 lines

No, it doesn't.  I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid).  Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase.  Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

It takes 2 minutes on RV530:
https://bugzilla.redhat.com/show_bug.cgi?id=586522

Well, my second affected box appears to hang somewhere in the radeon's suspend routine.

Does the attached patch help?

It helps, but from what I can see in the code, it still has a few problems.

First, the mutex around cancel_delayed_work() in radeon_pm_suspend() doesn't really serve any purpose, because rdev->pm.pm_method cannot change at this point and cancel_delayed_work() only tries to delete the work's timer. Moreover, it doesn't prevent the work handler from running, in which case the handler can do some wrong things and will rearm itself to do some more wrong things going forward.  So, I think it's better to wait for the handler to run in case it's already been queued up and it should also be prevented from rearming itself in that case.

Second, in radeon_set_pm_method() the cancel_delayed_work() is not sufficient to prevent the work handler from running and queing up itself for the next run (the failure scenario is that cancel_delayed_work_sync() returns 0, so the handler is run, it waits on the mutex and then rearms itself after the mutex has been released), so it looks like cancel_delayed_work_sync() should be used to make sure it's not going to run again, but calling that cancel_delayed_work_sync() from under the mutex is not a good idea.

Quoted 6 lines

Finally, there's a potential deadlock in radeon_pm_fini(), where cancel_delayed_work_sync() is called under rdev->pm.mutex, but the work handler tries to acquire the same mutex (if it wins the race).

So, I think something like the appended patch is needed.

Looks reasonable. Does it fix the suspend issue?

Alex

Quoted 127 lines

Rafael

---
 drivers/gpu/drm/radeon/radeon.h    |    3 +- drivers/gpu/drm/radeon/radeon_pm.c |   41 ++++++++++++++++++++++++++++++-------

 2 files changed, 36 insertions(+), 8 deletions(-)

Index: linux-2.6/drivers/gpu/drm/radeon/radeon_pm.c
===================================================================

drivers/gpu/drm/radeon/radeon_pm.c +34 -7
@@ -397,13 +397,20 @@ static ssize_t radeon_set_pm_method(stru
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                mutex_unlock(&rdev->pm.mutex);
        } else if (strncmp("profile", buf, strlen("profile")) == 0) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
-               rdev->pm.pm_method = PM_METHOD_PROFILE;
+               if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
+               }
                /* disable dynpm */
                rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               rdev->pm.pm_method = PM_METHOD_PROFILE;
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
        } else {
                DRM_ERROR("invalid power method!\n");
                goto fail;
@@ -418,9 +425,18 @@ static DEVICE_ATTR(power_method, S_IRUGO
 
  void radeon_pm_suspend(struct radeon_device *rdev)
  {
+       bool flush_wq = false;
+
        mutex_lock(&rdev->pm.mutex);
-       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+               cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+               if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+                       rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+               flush_wq = true;
+       }
        mutex_unlock(&rdev->pm.mutex);
+       if (flush_wq)
+               flush_workqueue(rdev->wq);
  }
 
  void radeon_pm_resume(struct radeon_device *rdev)
@@ -432,6 +448,12 @@ void radeon_pm_resume(struct radeon_devi
        rdev->pm.current_sclk = rdev->clock.default_sclk;
        rdev->pm.current_mclk = rdev->clock.default_mclk;
        rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+       if (rdev->pm.pm_method == PM_METHOD_DYNPM
+           && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+               rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+       }
        mutex_unlock(&rdev->pm.mutex);
        radeon_pm_compute_clocks(rdev);
  }
@@ -486,6 +508,8 @@ int radeon_pm_init(struct radeon_device
  void radeon_pm_fini(struct radeon_device *rdev)
  {
        if (rdev->pm.num_power_states > 1) {
+               bool flush_wq = false;
+
                mutex_lock(&rdev->pm.mutex);
                if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
                        rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -493,13 +517,16 @@ void radeon_pm_fini(struct radeon_device
                        radeon_pm_set_clocks(rdev);
                } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
                        /* cancel work */
-                       cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+                       cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+                       flush_wq = true;
                        /* reset default clocks */
                        rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
                        rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
                        radeon_pm_set_clocks(rdev);
                }
                mutex_unlock(&rdev->pm.mutex);
+               if (flush_wq)
+                       flush_workqueue(rdev->wq);
 
                device_remove_file(rdev->dev, &dev_attr_power_profile);
                device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -720,12 +747,12 @@ static void radeon_dynpm_idle_work_handl
                        radeon_pm_get_dynpm_state(rdev);
                        radeon_pm_set_clocks(rdev);
                }
+
+               queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
        }
        mutex_unlock(&rdev->pm.mutex);
        ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
-       queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-                                       msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
  }
 
  /*

Index: linux-2.6/drivers/gpu/drm/radeon/radeon.h
===================================================================

drivers/gpu/drm/radeon/radeon.h +2 -1
@@ -619,7 +619,8 @@ enum radeon_dynpm_state {
        DYNPM_STATE_DISABLED,
        DYNPM_STATE_MINIMUM,
        DYNPM_STATE_PAUSED,
-       DYNPM_STATE_ACTIVE
+       DYNPM_STATE_ACTIVE,
+       DYNPM_STATE_SUSPENDED,
  };
  enum radeon_dynpm_action {
        DYNPM_ACTION_NONE,
#28 lore raw
In reply to Alex Deucher
Quoted 57 lines · Alex Deucher
Quoted 56 lines · Rafael J. Wysocki
Quoted 55 lines · Ondrej Zary
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · Rafael J. Wysocki
Quoted 3 lines · Alex Deucher
Quoted 2 lines · Rafael J. Wysocki
Quoted 1 line · Alex Deucher

On Mon, Jun 14, 2010 at 10:53 AM, Rafael J. Wysocki <[email protected]>

Quoted 47 lines · wrote:
Quoted 35 lines
Quoted 27 lines
Quoted 27 lines
Quoted 22 lines
Quoted 14 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Quoted 7 lines

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

Quoted 7 lines

No, it doesn't. I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid). Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase. Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

It takes 2 minutes on RV530:
https://bugzilla.redhat.com/show_bug.cgi?id=586522

Well, my second affected box appears to hang somewhere in the radeon's suspend routine.

Does the attached patch help?

It helps, but from what I can see in the code, it still has a few problems.

First, the mutex around cancel_delayed_work() in radeon_pm_suspend() doesn't really serve any purpose, because rdev->pm.pm_method cannot change at this point and cancel_delayed_work() only tries to delete the work's timer. Moreover, it doesn't prevent the work handler from running, in which case the handler can do some wrong things and will rearm itself to do some more wrong things going forward. So, I think it's better to wait for the handler to run in case it's already been queued up and it should also be prevented from rearming itself in that case.

Second, in radeon_set_pm_method() the cancel_delayed_work() is not sufficient to prevent the work handler from running and queing up itself for the next run (the failure scenario is that cancel_delayed_work_sync() returns 0, so the handler is run, it waits on the mutex and then rearms itself after the mutex has been released), so it looks like cancel_delayed_work_sync() should be used to make sure it's not going to run again, but calling that cancel_delayed_work_sync() from under the mutex is not a good idea.

Finally, there's a potential deadlock in radeon_pm_fini(), where cancel_delayed_work_sync() is called under rdev->pm.mutex, but the work handler tries to acquire the same mutex (if it wins the race).

So, I think something like the appended patch is needed.

Rafael

---
 drivers/gpu/drm/radeon/radeon.h    |    3 +-
 drivers/gpu/drm/radeon/radeon_pm.c |   41 ++++++++++++++++++++++++++++++-------
 2 files changed, 36 insertions(+), 8 deletions(-)
drivers/gpu/drm/radeon/radeon_pm.c +34 -7
Index: linux-2.6/drivers/gpu/drm/radeon/radeon_pm.c
===================================================================
@@ -397,13 +397,20 @@ static ssize_t radeon_set_pm_method(stru
 		rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
 		mutex_unlock(&rdev->pm.mutex);
 	} else if (strncmp("profile", buf, strlen("profile")) == 0) {
+		bool flush_wq = false;
+
 		mutex_lock(&rdev->pm.mutex);
-		rdev->pm.pm_method = PM_METHOD_PROFILE;
+		if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+			cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+			flush_wq = true;
+		}
 		/* disable dynpm */
 		rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
 		rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-		cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+		rdev->pm.pm_method = PM_METHOD_PROFILE;
 		mutex_unlock(&rdev->pm.mutex);
+		if (flush_wq)
+			flush_workqueue(rdev->wq);
 	} else {
 		DRM_ERROR("invalid power method!\n");
 		goto fail;
@@ -418,9 +425,18 @@ static DEVICE_ATTR(power_method, S_IRUGO
 
 void radeon_pm_suspend(struct radeon_device *rdev)
 {
+	bool flush_wq = false;
+
 	mutex_lock(&rdev->pm.mutex);
-	cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+	if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
+		cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+		if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE)
+			rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED;
+		flush_wq = true;
+	}
 	mutex_unlock(&rdev->pm.mutex);
+	if (flush_wq)
+		flush_workqueue(rdev->wq);
 }
 
 void radeon_pm_resume(struct radeon_device *rdev)
@@ -432,6 +448,12 @@ void radeon_pm_resume(struct radeon_devi
 	rdev->pm.current_sclk = rdev->clock.default_sclk;
 	rdev->pm.current_mclk = rdev->clock.default_mclk;
 	rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+	if (rdev->pm.pm_method == PM_METHOD_DYNPM
+	    && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
+		rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
+		queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+	}
 	mutex_unlock(&rdev->pm.mutex);
 	radeon_pm_compute_clocks(rdev);
 }
@@ -486,6 +508,8 @@ int radeon_pm_init(struct radeon_device
 void radeon_pm_fini(struct radeon_device *rdev)
 {
 	if (rdev->pm.num_power_states > 1) {
+		bool flush_wq = false;
+
 		mutex_lock(&rdev->pm.mutex);
 		if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
 			rdev->pm.profile = PM_PROFILE_DEFAULT;
@@ -493,13 +517,16 @@ void radeon_pm_fini(struct radeon_device
 			radeon_pm_set_clocks(rdev);
 		} else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
 			/* cancel work */
-			cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
+			cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+			flush_wq = true;
 			/* reset default clocks */
 			rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
 			rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
 			radeon_pm_set_clocks(rdev);
 		}
 		mutex_unlock(&rdev->pm.mutex);
+		if (flush_wq)
+			flush_workqueue(rdev->wq);
 
 		device_remove_file(rdev->dev, &dev_attr_power_profile);
 		device_remove_file(rdev->dev, &dev_attr_power_method);
@@ -720,12 +747,12 @@ static void radeon_dynpm_idle_work_handl
 			radeon_pm_get_dynpm_state(rdev);
 			radeon_pm_set_clocks(rdev);
 		}
+
+		queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
+					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 	}
 	mutex_unlock(&rdev->pm.mutex);
 	ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-
-	queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
-					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 }
 
 /*
drivers/gpu/drm/radeon/radeon.h +2 -1
Index: linux-2.6/drivers/gpu/drm/radeon/radeon.h
===================================================================
@@ -619,7 +619,8 @@ enum radeon_dynpm_state {
 	DYNPM_STATE_DISABLED,
 	DYNPM_STATE_MINIMUM,
 	DYNPM_STATE_PAUSED,
-	DYNPM_STATE_ACTIVE
+	DYNPM_STATE_ACTIVE,
+	DYNPM_STATE_SUSPENDED,
 };
 enum radeon_dynpm_action {
 	DYNPM_ACTION_NONE,
#29 lore raw
In reply to Rafael J. Wysocki
Quoted 56 lines · Rafael J. Wysocki
Quoted 55 lines · Ondrej Zary
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · Rafael J. Wysocki
Quoted 3 lines · Alex Deucher
Quoted 2 lines · Rafael J. Wysocki
Quoted 1 line · Alex Deucher

On Mon, Jun 14, 2010 at 10:53 AM, Rafael J. Wysocki <[email protected]>

Quoted 47 lines · wrote:
Quoted 35 lines
Quoted 27 lines
Quoted 27 lines
Quoted 22 lines
Quoted 14 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management).  At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Quoted 7 lines

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure.  However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope.  The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

Quoted 7 lines

No, it doesn't.  I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid).  Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase.  Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

Quoted 5 lines
Quoted 2 lines

It takes 2 minutes on RV530:
https://bugzilla.redhat.com/show_bug.cgi?id=586522

Well, my second affected box appears to hang somewhere in the radeon's suspend routine.

Does the attached patch help?

Alex

From 9d2600fd31c1dda6f41e569fd8aff45c9e5ce54f Mon Sep 17 00:00:00 2001
From: Alex Deucher <[email protected]>
Date: Wed, 16 Jun 2010 16:41:38 -0400
Subject: [PATCH] drm/radeon/kms: only attempt to cancel delayed work if pm method is PM_METHOD_DYNPM

delayed work is only scheduled if pm method is PM_METHOD_DYNPM.

---
 drivers/gpu/drm/radeon/radeon_pm.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)
drivers/gpu/drm/radeon/radeon_pm.c +5 -3
index b9ad366..0751fc8 100644
@@ -407,11 +407,12 @@ static ssize_t radeon_set_pm_method(struct device *dev,
 		mutex_unlock(&rdev->pm.mutex);
 	} else if (strncmp("profile", buf, strlen("profile")) == 0) {
 		mutex_lock(&rdev->pm.mutex);
-		rdev->pm.pm_method = PM_METHOD_PROFILE;
+		if (rdev->pm.pm_method == PM_METHOD_DYNPM)
+			cancel_delayed_work(&rdev->pm.dynpm_idle_work);
 		/* disable dynpm */
 		rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
 		rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
-		cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+		rdev->pm.pm_method = PM_METHOD_PROFILE;
 		mutex_unlock(&rdev->pm.mutex);
 	} else {
 		DRM_ERROR("invalid power method!\n");
@@ -428,7 +429,8 @@ static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon
 void radeon_pm_suspend(struct radeon_device *rdev)
 {
 	mutex_lock(&rdev->pm.mutex);
-	cancel_delayed_work(&rdev->pm.dynpm_idle_work);
+	if (rdev->pm.pm_method == PM_METHOD_DYNPM)
+		cancel_delayed_work(&rdev->pm.dynpm_idle_work);
 	mutex_unlock(&rdev->pm.mutex);
 }
 
Signature · 1 line
1.7.0.1
#30 lore raw
In reply to Ondrej Zary
Quoted 50 lines · Ondrej Zary
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · Rafael J. Wysocki
Quoted 3 lines · Alex Deucher
Quoted 2 lines · Rafael J. Wysocki
Quoted 1 line · Alex Deucher

On Mon, Jun 14, 2010 at 10:53 AM, Rafael J. Wysocki <[email protected]>

Quoted 43 lines · wrote:
Quoted 42 lines
Quoted 27 lines
Quoted 27 lines
Quoted 22 lines
Quoted 14 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Quoted 7 lines

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

No, it doesn't. I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid). Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

Quoted 7 lines
Quoted 4 lines

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase. Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

It takes 2 minutes on RV530:
https://bugzilla.redhat.com/show_bug.cgi?id=586522

Well, my second affected box appears to hang somewhere in the radeon's suspend routine.

Rafael

#31 lore raw
In reply to Rafael J. Wysocki
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · Rafael J. Wysocki
Quoted 3 lines · Alex Deucher
Quoted 2 lines · Rafael J. Wysocki
Quoted 1 line · Alex Deucher

On Mon, Jun 14, 2010 at 10:53 AM, Rafael J. Wysocki <[email protected]>

Quoted 39 lines · wrote:
Quoted 39 lines
Quoted 27 lines
Quoted 27 lines
Quoted 22 lines
Quoted 14 lines

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Suspend to RAM appears to work fine at least on one of the affected boxes.

Quoted 7 lines

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

No, it doesn't. I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid). Normally, it would turn the screen back on and continue with saving the image.

Quoted 8 lines
Quoted 3 lines

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

I've just verified that in fact hibernation works on HP nx6325 with 2.6.35-rc3, but it takes about 55 sec. to suspend the graphics adapter in the "freeze" phase. Surprisingly enough, during suspend to RAM it works normally (as well as in the "poweroff" phase of hibernation).

It takes 2 minutes on RV530:
https://bugzilla.redhat.com/show_bug.cgi?id=586522

Signature · 1 line
Ondrej Zary
#32 lore raw
In reply to Alex Deucher
Quoted 28 lines · Alex Deucher
Quoted 27 lines · Rafael J. Wysocki
Quoted 21 lines · Alex Deucher
Quoted 10 lines · Rafael J. Wysocki

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Quoted 9 lines

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Does this patch help?
http://lists.freedesktop.org/archives/dri-devel/2010-June/001314.html

No, it doesn't. I try to hibernate, everything works to the point where the screen goes off and the box hangs (solid). Normally, it would turn the screen back on and continue with saving the image.

But, since that happens with the patch above applied, I think it doesn't really pass the suspend phase (IOW, it probably hangs somewhere in the radeon's suspend routine).

Rafael

#33 lore raw
In reply to Alex Deucher
Quoted 21 lines · Alex Deucher
Quoted 10 lines · Rafael J. Wysocki

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management). At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Quoted 9 lines

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure. However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Quoted 1 line

Does it work any better after Dave's last drm pull request?

Nope. The symptom is slightly different, though, because now it hangs after turning off the screen.

Quoted 2 lines

With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Well, I guess the first pm patch changed more than just pm, then.

Rafael

#34 lore raw
In reply to Rafael J. Wysocki
Quoted 10 lines · Rafael J. Wysocki

Alex, Dave,

I'm afraid hibernation is broken on all machines using radeon/KMS with r300 after commit ce8f53709bf440100cb9d31b1303291551cf517f (drm/radeon/kms/pm: rework power management).  At least, I'm able to reproduce the symptom, which is that the machine hangs hard around the point where an image is created (probably during the device thaw phase), on two different boxes with r300 (the output of lspci from one of them is attached for reference, the other one is HP nx6325).

Quoted 9 lines

Suspend to RAM appears to work fine at least on one of the affected boxes.

Unfortunately, the commit above changes a lot of code and it's not too easy to figure out what's wrong with it and I didn't have the time to look more into details of this failure.  However, it looks like you use .suspend() and .resume() callbacks as .freeze() and .thaw() which may not be 100% correct (in fact it looks like the "legacy" PCI suspend/resume is used, which is not recommended any more).

Does it work any better after Dave's last drm pull request? With the latest changes, pm should not be a factor unless it's explicitly enabled via sysfs.

Alex

Quoted 3 lines

Thanks,
Rafael