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

Reply via email to