On Wednesday 24 January 2007 6:15 pm, David Brownell wrote: > > So, what kind of devices do support these files? I can think of: > > PCI > > Actually, PCI still doesn't because of strangeness in the init > sequencing on at least PPC ... I can forward the patch that makes > X86 init the wakeup flag from the PM attributes. And here it is. Last refreshed against 2.6.20-rc5; it still works like a charm on x86. (As it did since before that PPC patch...) I have no idea whether this still makes trouble on PPC. - Dave ================= CUT HERE This patch teaches "pci_dev" about the driver model wakeup support: - It marks devices as supporting wakeup when the PME# capability is listed in its PCI PM capability. - pci_enable_wake() refuses to enable wake if that's been disabled (e.g. through sysfs). NOTE that PowerPC does PCI probing a bit differently ... which evidently causes this to fail on that platform (and maybe others). One issue is that the driver model "init + add == register" pattern isn't used inside PCI ... and the PCI probe change that made PowerPC happier worsened the problem by making "add" do some "init" too. Maybe PCI should match the driver model a lot more closely and grow a "pci_dev_init()". Index: g26/drivers/pci/probe.c =================================================================== --- g26.orig/drivers/pci/probe.c 2007-01-20 05:09:21.000000000 -0800 +++ g26/drivers/pci/probe.c 2007-01-20 05:18:42.000000000 -0800 @@ -654,6 +654,7 @@ static void pci_read_irq(struct pci_dev static int pci_setup_device(struct pci_dev * dev) { u32 class; + u16 pm; sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); @@ -682,6 +683,19 @@ static int pci_setup_device(struct pci_d pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor); pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device); + /* PCI PM capable devices may be able to issue PME# (wakeup) */ + pm = pci_find_capability(dev, PCI_CAP_ID_PM); + if (pm) { + pci_read_config_word(dev, pm + PCI_PM_PMC, &pm); + if (pm & PCI_PM_CAP_PME_MASK) + device_init_wakeup(&dev->dev, 1); + + /* REVISIT: if (pm & PCI_PM_CAP_PME_D3cold) then + * pci pm spec 1.2, section 3.2.4 says we should + * init PCI_PM_CTRL_PME_{STATUS,ENABLE} ... + */ + } + /* * Do the ugly legacy mode stuff here rather than broken chip * quirk code. Legacy mode ATA controllers have fixed @@ -848,6 +862,7 @@ pci_scan_device(struct pci_bus *bus, int dev->bus = bus; dev->sysdata = bus->sysdata; + device_initialize(&dev->dev); dev->dev.parent = bus->bridge; dev->dev.bus = &pci_bus_type; dev->devfn = devfn; @@ -871,7 +886,6 @@ pci_scan_device(struct pci_bus *bus, int void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus) { - device_initialize(&dev->dev); dev->dev.release = pci_release_dev; pci_dev_get(dev); Index: g26/drivers/pci/pci.c =================================================================== --- g26.orig/drivers/pci/pci.c 2007-01-20 05:18:31.000000000 -0800 +++ g26/drivers/pci/pci.c 2007-01-20 05:18:42.000000000 -0800 @@ -817,6 +817,10 @@ int pci_enable_wake(struct pci_dev *dev, if (!pm) return enable ? -EIO : 0; + /* don't enable unless policy set through driver core allows it */ + if (!device_may_wakeup(&dev->dev) && enable) + return -EROFS; + /* Check device's ability to generate PME# */ pci_read_config_word(dev,pm+PCI_PM_PMC,&value);