Hi Randy,
I think I've found a problem with s3-suspend/resume for devices that are
behind a pci-pci bridge.
I've noticed the problem on my Tecra S1 laptop, where I'm running a
modified "ipw" wlan driver which has suspend/resume code added.
A test suspend/resume for the ipw driver hangs the system during ipw
driver resume.
Root case for the hang seems to be that on
ipw2100_attach(...DDI_RESUME...) the hardware is still in D3 sleep state,
and not in D0 active state. The ipw2100_intr() interrupt handler reads
0xffffffff from the device's interrupt status register and tells the
caller that the device has claimed an interrupt (=> endless loop trying
to handle interrupts by calling ipw2100_intr() over and over again).
Device tree looks like this:
DEVINFO NAME
c700bd78 i86pc (driver name: rootnex)
c700b970 pci, instance #0 (driver name: pci)
c700b008 pciclass,060400, instance #1 (driver name: pci_pci)
c7006418 pci8086,1043, instance #0 (driver name: ipw)
What seems to happen:
- pci_post_suspend() is called twice (!) for the ipw0 device;
The first call puts the hardware from active to sleep state (D0->D3).
The second call changes nothing in the hw (device remains in sleep
state; D3->D3); but the pci_pm_context_t on the device node is updated
with state information of the sleeping (!) device
The first pci_post_suspend() call is via the immediate parent of the
ipw#0 device, the pci_pci#1 bridge.
The second pci_post_suspend() call seems to happen because the
suspend event is passed up to the parent device (pci#0 bus)
which seems to repeat the suspend op on it's grand child devices
(ipw#0).
- on system resume, pci_pre_resume() is called for the ipw0 device,
and here we find the pci_pm_context_t information of the sleeping
device (D3 state):
[0]> c9402bc8::print pci_pm_context_t
{
ppc_flags = 0
ppc_cap_offset = 0xdc
ppc_pmcsr = 0x2003
ppc_suspend_level = 0x3
}
Instead of waking up the device hw, pci_pre_resume() leaves the
hw in sleeping state (D3). This confuses the ipw driver, which isn't
able to read the device's registers.
Do we really have to call pci_pre_resume() / pci_post_suspend()
for the DDI_CTLOPS_ATTACH / DDI_CTLOPS_DETACH ops in
usr/src/uts/intel/io/pci/pci_pci.c, function ppb_ctlops()?
Isn't is ok to just pass the DDI_CTLOPS_ATTACH / DDI_CTLOPS_DETACH ops
up to the parent(s), until we reach the pci bus device, which
finally does the pci_pre_resume() / pci_post_suspend()?
(I've currently commented out the DDI_CTLOPS_ATTACH / DDI_CTLOPS_DETACH
case in ppb_ctlops(), and now ipw suspens / resumes ok)
_______________________________________________
driver-discuss mailing list
[email protected]
http://mail.opensolaris.org/mailman/listinfo/driver-discuss