Merge git://git.infradead.org/battery-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 2 Feb 2008 04:13:05 +0000 (15:13 +1100)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 2 Feb 2008 04:13:05 +0000 (15:13 +1100)
* git://git.infradead.org/battery-2.6:
  apm_power: check I.intval for zero value, we use it as the divisor
  MAINTAINERS: remove kernel-discuss@handhelds.org list
  pda_power: implement polling
  pda_power: various cleanups
  apm_power: support using VOLTAGE_* properties for apm calculations
  pda_power: add suspend/resume support
  power_supply: add few more values and props
  pda_power: only register available psu
  power: fix incorrect unregistration in power_supply_create_attrs error path
  power: remove POWER_SUPPLY_PROP_CAPACITY_LEVEL
  [BATTERY] power_supply_leds: use kasprintf
  [BATTERY] Every file should include the headers containing the prototypes for its global functions.

304 files changed:
Documentation/ABI/testing/sysfs-bus-usb
Documentation/feature-removal-schedule.txt
Documentation/kernel-parameters.txt
Documentation/pci.txt
Documentation/power/basic-pm-debugging.txt
Documentation/power/devices.txt
Documentation/power/drivers-testing.txt
Documentation/power/notifiers.txt
Documentation/power/userland-swsusp.txt
Documentation/usb/gadget_printer.txt [new file with mode: 0644]
Documentation/usb/iuu_phoenix.txt [new file with mode: 0644]
MAINTAINERS
arch/alpha/Kconfig
arch/arm/Kconfig
arch/arm/mach-at91/pm.c
arch/arm/mach-pxa/tosa.c
arch/blackfin/Kconfig
arch/frv/Kconfig
arch/m32r/Kconfig
arch/m68k/Kconfig
arch/mips/Kconfig
arch/powerpc/Kconfig
arch/powerpc/platforms/52xx/lite5200_pm.c
arch/sh/Kconfig
arch/sh/drivers/pci/Kconfig
arch/sparc64/Kconfig
arch/x86/Kconfig
arch/x86/kernel/quirks.c
arch/x86/kernel/suspend_64.c
arch/x86/mm/init_32.c
arch/x86/pci/fixup.c
arch/xtensa/Kconfig
drivers/acpi/hardware/hwsleep.c
drivers/acpi/sleep/main.c
drivers/acpi/sleep/sleep.h
drivers/ata/pata_cs5520.c
drivers/base/power/Makefile
drivers/block/ub.c
drivers/i2c/busses/scx200_acb.c
drivers/ide/pci/cs5520.c
drivers/ide/setup-pci.c
drivers/pci/bus.c
drivers/pci/dmar.c
drivers/pci/hotplug/Kconfig
drivers/pci/hotplug/Makefile
drivers/pci/hotplug/acpiphp.h
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/fakephp.c
drivers/pci/hotplug/ibmphp_core.c
drivers/pci/hotplug/pci_hotplug_core.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/pciehp_pci.c
drivers/pci/hotplug/rpaphp.h
drivers/pci/hotplug/rpaphp_pci.c
drivers/pci/hotplug/rpaphp_slot.c
drivers/pci/hotplug/shpchp_hpc.c
drivers/pci/intel-iommu.c
drivers/pci/msi.c
drivers/pci/pci-acpi.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/Kconfig
drivers/pci/pcie/Makefile
drivers/pci/pcie/aer/aerdrv_acpi.c
drivers/pci/pcie/aspm.c [new file with mode: 0644]
drivers/pci/pcie/portdrv_core.c
drivers/pci/probe.c
drivers/pci/proc.c
drivers/pci/quirks.c
drivers/pci/remove.c
drivers/pci/rom.c
drivers/pci/setup-bus.c
drivers/pci/setup-res.c
drivers/pci/syscall.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_os.c
drivers/usb/Kconfig
drivers/usb/atm/Kconfig
drivers/usb/atm/ueagle-atm.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.h
drivers/usb/core/Kconfig
drivers/usb/core/buffer.c
drivers/usb/core/config.c
drivers/usb/core/devices.c
drivers/usb/core/devio.c
drivers/usb/core/driver.c
drivers/usb/core/file.c
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd.c
drivers/usb/core/hcd.h
drivers/usb/core/hub.c
drivers/usb/core/hub.h
drivers/usb/core/inode.c
drivers/usb/core/message.c
drivers/usb/core/notify.c
drivers/usb/core/otg_whitelist.h
drivers/usb/core/sysfs.c
drivers/usb/core/urb.c
drivers/usb/core/usb.c
drivers/usb/core/usb.h
drivers/usb/gadget/Kconfig
drivers/usb/gadget/Makefile
drivers/usb/gadget/amd5536udc.c
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/at91_udc.h
drivers/usb/gadget/atmel_usba_udc.c
drivers/usb/gadget/atmel_usba_udc.h
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/fsl_usb2_udc.c
drivers/usb/gadget/fsl_usb2_udc.h
drivers/usb/gadget/gmidi.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/lh7a40x_udc.c
drivers/usb/gadget/m66592-udc.c
drivers/usb/gadget/m66592-udc.h
drivers/usb/gadget/net2280.c
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/omap_udc.h
drivers/usb/gadget/printer.c [new file with mode: 0644]
drivers/usb/gadget/pxa2xx_udc.c
drivers/usb/gadget/pxa2xx_udc.h
drivers/usb/gadget/rndis.c
drivers/usb/gadget/s3c2410_udc.c
drivers/usb/gadget/serial.c
drivers/usb/gadget/zero.c
drivers/usb/host/Kconfig
drivers/usb/host/ehci-au1xxx.c
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-ixp4xx.c [new file with mode: 0644]
drivers/usb/host/ehci-orion.c [new file with mode: 0644]
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-ppc-of.c [new file with mode: 0644]
drivers/usb/host/ehci-ppc-soc.c
drivers/usb/host/ehci-ps3.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci.h
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-dbg.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-sh.c [new file with mode: 0644]
drivers/usb/host/ohci-sm501.c [new file with mode: 0644]
drivers/usb/host/ohci.h
drivers/usb/host/pci-quirks.c
drivers/usb/host/r8a66597.h
drivers/usb/image/mdc800.c
drivers/usb/misc/cypress_cy7c63.c
drivers/usb/misc/iowarrior.c
drivers/usb/misc/legousbtower.c
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/misc/sisusbvga/sisusb.h
drivers/usb/misc/usbtest.c
drivers/usb/mon/mon_bin.c
drivers/usb/serial/Kconfig
drivers/usb/serial/Makefile
drivers/usb/serial/airprime.c
drivers/usb/serial/ark3116.c
drivers/usb/serial/belkin_sa.c
drivers/usb/serial/console.c
drivers/usb/serial/cp2101.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/ezusb.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/generic.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/iuu_phoenix.c [new file with mode: 0644]
drivers/usb/serial/iuu_phoenix.h [new file with mode: 0644]
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/mct_u232.h
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/option.c
drivers/usb/serial/oti6858.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/serial/sierra.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c
drivers/usb/serial/visor.c
drivers/usb/serial/whiteheat.c
drivers/usb/storage/initializers.c
drivers/usb/storage/isd200.c
drivers/usb/storage/unusual_devs.h
drivers/video/sis/sis.h
drivers/video/sis/sis_main.c
fs/Kconfig
fs/lockd/host.c
fs/lockd/svc.c
fs/lockd/svc4proc.c
fs/lockd/svclock.c
fs/lockd/svcproc.c
fs/lockd/svcsubs.c
fs/nfs/callback.c
fs/nfsd/auth.h [moved from include/linux/nfsd/auth.h with 87% similarity]
fs/nfsd/export.c
fs/nfsd/nfs2acl.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4idmap.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfscache.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsfh.c
fs/nfsd/nfssvc.c
fs/nfsd/nfsxdr.c
fs/nfsd/vfs.c
include/acpi/acpixf.h
include/asm-arm/arch-at91/board.h
include/asm-arm/mach/udc_pxa2xx.h
include/linux/Kbuild
include/linux/aspm.h [new file with mode: 0644]
include/linux/lockd/lockd.h
include/linux/lockd/xdr.h
include/linux/nfsd/Kbuild
include/linux/nfsd/cache.h
include/linux/nfsd/export.h
include/linux/nfsd/nfsd.h
include/linux/nfsd/syscall.h
include/linux/nfsd/xdr.h
include/linux/nfsd/xdr3.h
include/linux/nfsd/xdr4.h
include/linux/nfsd_idmap.h
include/linux/notifier.h
include/linux/pci-acpi.h
include/linux/pci.h
include/linux/pci_regs.h
include/linux/sunrpc/cache.h
include/linux/sunrpc/debug.h
include/linux/sunrpc/svc.h
include/linux/sunrpc/svc_rdma.h [new file with mode: 0644]
include/linux/sunrpc/svc_xprt.h [new file with mode: 0644]
include/linux/sunrpc/svcsock.h
include/linux/sunrpc/xdr.h
include/linux/suspend.h
include/linux/suspend_ioctls.h [new file with mode: 0644]
include/linux/usb.h
include/linux/usb/Kbuild
include/linux/usb/audio.h
include/linux/usb/cdc.h
include/linux/usb/g_printer.h [new file with mode: 0644]
include/linux/usb/gadget.h
include/linux/usb/gadgetfs.h
include/linux/usb/iowarrior.h
include/linux/usb/isp116x.h
include/linux/usb/midi.h
include/linux/usb/net2280.h
include/linux/usb/otg.h
include/linux/usb/serial.h
include/linux/usb/sl811.h
include/linux/usb_usual.h
include/linux/usbdevice_fs.h
kernel/power/Kconfig
kernel/power/disk.c
kernel/power/main.c
kernel/power/power.h
kernel/power/snapshot.c
kernel/power/swap.c
kernel/power/swsusp.c
kernel/power/user.c
kernel/softlockup.c
net/sunrpc/Makefile
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/cache.c
net/sunrpc/stats.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/svc.c
net/sunrpc/svc_xprt.c [new file with mode: 0644]
net/sunrpc/svcauth.c
net/sunrpc/svcauth_unix.c
net/sunrpc/svcsock.c
net/sunrpc/sysctl.c
net/sunrpc/xdr.c
net/sunrpc/xprtrdma/Makefile
net/sunrpc/xprtrdma/svc_rdma.c [new file with mode: 0644]
net/sunrpc/xprtrdma/svc_rdma_marshal.c [new file with mode: 0644]
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c [new file with mode: 0644]
net/sunrpc/xprtrdma/svc_rdma_sendto.c [new file with mode: 0644]
net/sunrpc/xprtrdma/svc_rdma_transport.c [new file with mode: 0644]
scripts/mod/file2alias.c

index 9734577d171154630f49be83779863ef875d6b7e..11a3c1682cecb87e16514249d6877a18608ccf01 100644 (file)
@@ -52,3 +52,36 @@ Description:
                facility is inherently dangerous, it is disabled by default
                for all devices except hubs.  For more information, see
                Documentation/usb/persist.txt.
+
+What:          /sys/bus/usb/device/.../power/connected_duration
+Date:          January 2008
+KernelVersion: 2.6.25
+Contact:       Sarah Sharp <sarah.a.sharp@intel.com>
+Description:
+               If CONFIG_PM and CONFIG_USB_SUSPEND are enabled, then this file
+               is present.  When read, it returns the total time (in msec)
+               that the USB device has been connected to the machine.  This
+               file is read-only.
+Users:
+               PowerTOP <power@bughost.org>
+               http://www.lesswatts.org/projects/powertop/
+
+What:          /sys/bus/usb/device/.../power/active_duration
+Date:          January 2008
+KernelVersion: 2.6.25
+Contact:       Sarah Sharp <sarah.a.sharp@intel.com>
+Description:
+               If CONFIG_PM and CONFIG_USB_SUSPEND are enabled, then this file
+               is present.  When read, it returns the total time (in msec)
+               that the USB device has been active, i.e. not in a suspended
+               state.  This file is read-only.
+
+               Tools can use this file and the connected_duration file to
+               compute the percentage of time that a device has been active.
+               For example,
+               echo $((100 * `cat active_duration` / `cat connected_duration`))
+               will give an integer percentage.  Note that this does not
+               account for counter wrap.
+Users:
+               PowerTOP <power@bughost.org>
+               http://www.lesswatts.org/projects/powertop/
index 181bff00516784e3b4bc0c8a7f2b94ed47b76e70..a7d9d179131a76c1f3ef297792ddaae95786e283 100644 (file)
@@ -156,22 +156,6 @@ Who:       Arjan van de Ven <arjan@linux.intel.com>
 
 ---------------------------
 
-What:  USB driver API moves to EXPORT_SYMBOL_GPL
-When:  February 2008
-Files: include/linux/usb.h, drivers/usb/core/driver.c
-Why:   The USB subsystem has changed a lot over time, and it has been
-       possible to create userspace USB drivers using usbfs/libusb/gadgetfs
-       that operate as fast as the USB bus allows.  Because of this, the USB
-       subsystem will not be allowing closed source kernel drivers to
-       register with it, after this grace period is over.  If anyone needs
-       any help in converting their closed source drivers over to use the
-       userspace filesystems, please contact the
-       linux-usb-devel@lists.sourceforge.net mailing list, and the developers
-       there will be glad to help you out.
-Who:   Greg Kroah-Hartman <gregkh@suse.de>
-
----------------------------
-
 What:  vm_ops.nopage
 When:  Soon, provided in-kernel callers have been converted
 Why:   This interface is replaced by vm_ops.fault, but it has been around
index 92c40d174355505555642cbe3a0ea137881dcbd4..cf3868956f1e852850fa7ac3a680f0b4b6e25ee6 100644 (file)
@@ -168,6 +168,11 @@ and is between 256 and 4096 characters. It is defined in the file
        acpi_irq_isa=   [HW,ACPI] If irq_balance, mark listed IRQs used by ISA
                        Format: <irq>,<irq>...
 
+       acpi_new_pts_ordering [HW,ACPI]
+                       Enforce the ACPI 2.0 ordering of the _PTS control
+                       method wrt putting devices into low power states
+                       default: pre ACPI 2.0 ordering of _PTS
+
        acpi_no_auto_ssdt       [HW,ACPI] Disable automatic loading of SSDT
 
        acpi_os_name=   [HW,ACPI] Tell ACPI BIOS the name of the OS
index 7754f5aea4e9b0bdd62280fb4f9fe88b23dce3fc..72b20c63959651ce7be7dad2f2e854c983f660e0 100644 (file)
@@ -274,8 +274,6 @@ the PCI device by calling pci_enable_device(). This will:
        o allocate an IRQ (if BIOS did not).
 
 NOTE: pci_enable_device() can fail! Check the return value.
-NOTE2: Also see pci_enable_device_bars() below. Drivers can
-    attempt to enable only a subset of BARs they need.
 
 [ OS BUG: we don't check resource allocations before enabling those
   resources. The sequence would make more sense if we called
@@ -605,40 +603,7 @@ device lists. This is still possible but discouraged.
 
 
 
-10. pci_enable_device_bars() and Legacy I/O Port space
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Large servers may not be able to provide I/O port resources to all PCI
-devices. I/O Port space is only 64KB on Intel Architecture[1] and is
-likely also fragmented since the I/O base register of PCI-to-PCI
-bridge will usually be aligned to a 4KB boundary[2]. On such systems,
-pci_enable_device() and pci_request_region() will fail when
-attempting to enable I/O Port regions that don't have I/O Port
-resources assigned.
-
-Fortunately, many PCI devices which request I/O Port resources also
-provide access to the same registers via MMIO BARs. These devices can
-be handled without using I/O port space and the drivers typically
-offer a CONFIG_ option to only use MMIO regions
-(e.g. CONFIG_TULIP_MMIO). PCI devices typically provide I/O port
-interface for legacy OSes and will work when I/O port resources are not
-assigned. The "PCI Local Bus Specification Revision 3.0" discusses
-this on p.44, "IMPLEMENTATION NOTE".
-
-If your PCI device driver doesn't need I/O port resources assigned to
-I/O Port BARs, you should use pci_enable_device_bars() instead of
-pci_enable_device() in order not to enable I/O port regions for the
-corresponding devices. In addition, you should use
-pci_request_selected_regions() and pci_release_selected_regions()
-instead of pci_request_regions()/pci_release_regions() in order not to
-request/release I/O port regions for the corresponding devices.
-
-[1] Some systems support 64KB I/O port space per PCI segment.
-[2] Some PCI-to-PCI bridges support optional 1KB aligned I/O base.
-
-
-
-11. MMIO Space and "Write Posting"
+10. MMIO Space and "Write Posting"
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Converting a driver from using I/O Port space to using MMIO space
index 57aef2f6e0de6ad30673d8ce34a5430dc59ec5ab..1555001bc73394dbed7fccbc9a10917671e403e1 100644 (file)
-Debugging suspend and resume
+Debugging hibernation and suspend
        (C) 2007 Rafael J. Wysocki <rjw@sisk.pl>, GPL
 
-1. Testing suspend to disk (STD)
+1. Testing hibernation (aka suspend to disk or STD)
 
-To verify that the STD works, you can try to suspend in the "reboot" mode:
+To check if hibernation works, you can try to hibernate in the "reboot" mode:
 
 # echo reboot > /sys/power/disk
 # echo disk > /sys/power/state
 
-and the system should suspend, reboot, resume and get back to the command prompt
-where you have started the transition.  If that happens, the STD is most likely
-to work correctly, but you need to repeat the test at least a couple of times in
-a row for confidence.  This is necessary, because some problems only show up on
-a second attempt at suspending and resuming the system.  You should also test
-the "platform" and "shutdown" modes of suspend:
+and the system should create a hibernation image, reboot, resume and get back to
+the command prompt where you have started the transition.  If that happens,
+hibernation is most likely to work correctly.  Still, you need to repeat the
+test at least a couple of times in a row for confidence.  [This is necessary,
+because some problems only show up on a second attempt at suspending and
+resuming the system.]  Moreover, hibernating in the "reboot" and "shutdown"
+modes causes the PM core to skip some platform-related callbacks which on ACPI
+systems might be necessary to make hibernation work.  Thus, if you machine fails
+to hibernate or resume in the "reboot" mode, you should try the "platform" mode:
 
 # echo platform > /sys/power/disk
 # echo disk > /sys/power/state
 
-or
+which is the default and recommended mode of hibernation.
+
+Unfortunately, the "platform" mode of hibernation does not work on some systems
+with broken BIOSes.  In such cases the "shutdown" mode of hibernation might
+work:
 
 # echo shutdown > /sys/power/disk
 # echo disk > /sys/power/state
 
-in which cases you will have to press the power button to make the system
-resume.  If that does not work, you will need to identify what goes wrong.
+(it is similar to the "reboot" mode, but it requires you to press the power
+button to make the system resume).
+
+If neither "platform" nor "shutdown" hibernation mode works, you will need to
+identify what goes wrong.
+
+a) Test modes of hibernation
+
+To find out why hibernation fails on your system, you can use a special testing
+facility available if the kernel is compiled with CONFIG_PM_DEBUG set.  Then,
+there is the file /sys/power/pm_test that can be used to make the hibernation
+core run in a test mode.  There are 5 test modes available:
+
+freezer
+- test the freezing of processes
+
+devices
+- test the freezing of processes and suspending of devices
 
-a) Test mode of STD
+platform
+- test the freezing of processes, suspending of devices and platform
+  global control methods(*)
 
-To verify if there are any drivers that cause problems you can run the STD
-in the test mode:
+processors
+- test the freezing of processes, suspending of devices, platform
+  global control methods(*) and the disabling of nonboot CPUs
 
-# echo test > /sys/power/disk
+core
+- test the freezing of processes, suspending of devices, platform global
+  control methods(*), the disabling of nonboot CPUs and suspending of
+  platform/system devices
+
+(*) the platform global control methods are only available on ACPI systems
+    and are only tested if the hibernation mode is set to "platform"
+
+To use one of them it is necessary to write the corresponding string to
+/sys/power/pm_test (eg. "devices" to test the freezing of processes and
+suspending devices) and issue the standard hibernation commands.  For example,
+to use the "devices" test mode along with the "platform" mode of hibernation,
+you should do the following:
+
+# echo devices > /sys/power/pm_test
+# echo platform > /sys/power/disk
 # echo disk > /sys/power/state
 
-in which case the system should freeze tasks, suspend devices, disable nonboot
-CPUs (if any), wait for 5 seconds, enable nonboot CPUs, resume devices, thaw
-tasks and return to your command prompt.  If that fails, most likely there is
-a driver that fails to either suspend or resume (in the latter case the system
-may hang or be unstable after the test, so please take that into consideration).
-To find this driver, you can carry out a binary search according to the rules:
+Then, the kernel will try to freeze processes, suspend devices, wait 5 seconds,
+resume devices and thaw processes.  If "platform" is written to
+/sys/power/pm_test , then after suspending devices the kernel will additionally
+invoke the global control methods (eg. ACPI global control methods) used to
+prepare the platform firmware for hibernation.  Next, it will wait 5 seconds and
+invoke the platform (eg. ACPI) global methods used to cancel hibernation etc.
+
+Writing "none" to /sys/power/pm_test causes the kernel to switch to the normal
+hibernation/suspend operations.  Also, when open for reading, /sys/power/pm_test
+contains a space-separated list of all available tests (including "none" that
+represents the normal functionality) in which the current test level is
+indicated by square brackets.
+
+Generally, as you can see, each test level is more "invasive" than the previous
+one and the "core" level tests the hardware and drivers as deeply as possible
+without creating a hibernation image.  Obviously, if the "devices" test fails,
+the "platform" test will fail as well and so on.  Thus, as a rule of thumb, you
+should try the test modes starting from "freezer", through "devices", "platform"
+and "processors" up to "core" (repeat the test on each level a couple of times
+to make sure that any random factors are avoided).
+
+If the "freezer" test fails, there is a task that cannot be frozen (in that case
+it usually is possible to identify the offending task by analysing the output of
+dmesg obtained after the failing test).  Failure at this level usually means
+that there is a problem with the tasks freezer subsystem that should be
+reported.
+
+If the "devices" test fails, most likely there is a driver that cannot suspend
+or resume its device (in the latter case the system may hang or become unstable
+after the test, so please take that into consideration).  To find this driver,
+you can carry out a binary search according to the rules:
 - if the test fails, unload a half of the drivers currently loaded and repeat
 (that would probably involve rebooting the system, so always note what drivers
 have been loaded before the test),
@@ -47,23 +113,46 @@ have been loaded before the test),
 recently and repeat.
 
 Once you have found the failing driver (there can be more than just one of
-them), you have to unload it every time before the STD transition.  In that case
-please make sure to report the problem with the driver.
-
-It is also possible that a cycle can still fail after you have unloaded
-all modules. In that case, you would want to look in your kernel configuration
-for the drivers that can be compiled as modules (testing again with them as
-modules), and possibly also try boot time options such as "noapic" or "noacpi".
+them), you have to unload it every time before hibernation.  In that case please
+make sure to report the problem with the driver.
+
+It is also possible that the "devices" test will still fail after you have
+unloaded all modules. In that case, you may want to look in your kernel
+configuration for the drivers that can be compiled as modules (and test again
+with these drivers compiled as modules).  You may also try to use some special
+kernel command line options such as "noapic", "noacpi" or even "acpi=off".
+
+If the "platform" test fails, there is a problem with the handling of the
+platform (eg. ACPI) firmware on your system.  In that case the "platform" mode
+of hibernation is not likely to work.  You can try the "shutdown" mode, but that
+is rather a poor man's workaround.
+
+If the "processors" test fails, the disabling/enabling of nonboot CPUs does not
+work (of course, this only may be an issue on SMP systems) and the problem
+should be reported.  In that case you can also try to switch the nonboot CPUs
+off and on using the /sys/devices/system/cpu/cpu*/online sysfs attributes and
+see if that works.
+
+If the "core" test fails, which means that suspending of the system/platform
+devices has failed (these devices are suspended on one CPU with interrupts off),
+the problem is most probably hardware-related and serious, so it should be
+reported.
+
+A failure of any of the "platform", "processors" or "core" tests may cause your
+system to hang or become unstable, so please beware.  Such a failure usually
+indicates a serious problem that very well may be related to the hardware, but
+please report it anyway.
 
 b) Testing minimal configuration
 
-If the test mode of STD works, you can boot the system with "init=/bin/bash"
-and attempt to suspend in the "reboot", "shutdown" and "platform" modes.  If
-that does not work, there probably is a problem with a driver statically
-compiled into the kernel and you can try to compile more drivers as modules,
-so that they can be tested individually.  Otherwise, there is a problem with a
-modular driver and you can find it by loading a half of the modules you normally
-use and binary searching in accordance with the algorithm:
+If all of the hibernation test modes work, you can boot the system with the
+"init=/bin/bash" command line parameter and attempt to hibernate in the
+"reboot", "shutdown" and "platform" modes.  If that does not work, there
+probably is a problem with a driver statically compiled into the kernel and you
+can try to compile more drivers as modules, so that they can be tested
+individually.  Otherwise, there is a problem with a modular driver and you can
+find it by loading a half of the modules you normally use and binary searching
+in accordance with the algorithm:
 - if there are n modules loaded and the attempt to suspend and resume fails,
 unload n/2 of the modules and try again (that would probably involve rebooting
 the system),
@@ -71,19 +160,19 @@ the system),
 load n/2 modules more and try again.
 
 Again, if you find the offending module(s), it(they) must be unloaded every time
-before the STD transition, and please report the problem with it(them).
+before hibernation, and please report the problem with it(them).
 
 c) Advanced debugging
 
-In case the STD does not work on your system even in the minimal configuration
-and compiling more drivers as modules is not practical or some modules cannot
-be unloaded, you can use one of the more advanced debugging techniques to find
-the problem.  First, if there is a serial port in your box, you can boot the
-kernel with the 'no_console_suspend' parameter and try to log kernel
-messages using the serial console.  This may provide you with some information
-about the reasons of the suspend (resume) failure.  Alternatively, it may be
-possible to use a FireWire port for debugging with firescope
-(ftp://ftp.firstfloor.org/pub/ak/firescope/).  On i386 it is also possible to
+In case that hibernation does not work on your system even in the minimal
+configuration and compiling more drivers as modules is not practical or some
+modules cannot be unloaded, you can use one of the more advanced debugging
+techniques to find the problem.  First, if there is a serial port in your box,
+you can boot the kernel with the 'no_console_suspend' parameter and try to log
+kernel messages using the serial console.  This may provide you with some
+information about the reasons of the suspend (resume) failure.  Alternatively,
+it may be possible to use a FireWire port for debugging with firescope
+(ftp://ftp.firstfloor.org/pub/ak/firescope/).  On x86 it is also possible to
 use the PM_TRACE mechanism documented in Documentation/s2ram.txt .
 
 2. Testing suspend to RAM (STR)
@@ -91,16 +180,25 @@ use the PM_TRACE mechanism documented in Documentation/s2ram.txt .
 To verify that the STR works, it is generally more convenient to use the s2ram
 tool available from http://suspend.sf.net and documented at
 http://en.opensuse.org/s2ram .  However, before doing that it is recommended to
-carry out the procedure described in section 1.
-
-Assume you have resolved the problems with the STD and you have found some
-failing drivers.  These drivers are also likely to fail during the STR or
-during the resume, so it is better to unload them every time before the STR
-transition.  Now, you can follow the instructions at
-http://en.opensuse.org/s2ram to test the system, but if it does not work
-"out of the box", you may need to boot it with "init=/bin/bash" and test
-s2ram in the minimal configuration.  In that case, you may be able to search
-for failing drivers by following the procedure analogous to the one described in
-1b).  If you find some failing drivers, you will have to unload them every time
-before the STR transition (ie. before you run s2ram), and please report the
-problems with them.
+carry out STR testing using the facility described in section 1.
+
+Namely, after writing "freezer", "devices", "platform", "processors", or "core"
+into /sys/power/pm_test (available if the kernel is compiled with
+CONFIG_PM_DEBUG set) the suspend code will work in the test mode corresponding
+to given string.  The STR test modes are defined in the same way as for
+hibernation, so please refer to Section 1 for more information about them.  In
+particular, the "core" test allows you to test everything except for the actual
+invocation of the platform firmware in order to put the system into the sleep
+state.
+
+Among other things, the testing with the help of /sys/power/pm_test may allow
+you to identify drivers that fail to suspend or resume their devices.  They
+should be unloaded every time before an STR transition.
+
+Next, you can follow the instructions at http://en.opensuse.org/s2ram to test
+the system, but if it does not work "out of the box", you may need to boot it
+with "init=/bin/bash" and test s2ram in the minimal configuration.  In that
+case, you may be able to search for failing drivers by following the procedure
+analogous to the one described in section 1.  If you find some failing drivers,
+you will have to unload them every time before an STR transition (ie. before
+you run s2ram), and please report the problems with them.
index d0e79d5820a5e7a7237f36a1cb5776ec589552d8..c53d263619194f7e04719e0a7250944b0134d598 100644 (file)
@@ -502,52 +502,3 @@ If the CPU can have a "cpufreq" driver, there also may be opportunities
 to shift to lower voltage settings and reduce the power cost of executing
 a given number of instructions.  (Without voltage adjustment, it's rare
 for cpufreq to save much power; the cost-per-instruction must go down.)
-
-
-/sys/devices/.../power/state files
-==================================
-For now you can also test some of this functionality using sysfs.
-
-       DEPRECATED:  USE "power/state" ONLY FOR DRIVER TESTING, AND
-       AVOID USING dev->power.power_state IN DRIVERS.
-
-       THESE WILL BE REMOVED.  IF THE "power/state" FILE GETS REPLACED,
-       IT WILL BECOME SOMETHING COUPLED TO THE BUS OR DRIVER.
-
-In each device's directory, there is a 'power' directory, which contains
-at least a 'state' file.  The value of this field is effectively boolean,
-PM_EVENT_ON or PM_EVENT_SUSPEND.
-
-   *   Reading from this file displays a value corresponding to
-       the power.power_state.event field.  All nonzero values are
-       displayed as "2", corresponding to a low power state; zero
-       is displayed as "0", corresponding to normal operation.
-
-   *   Writing to this file initiates a transition using the
-       specified event code number; only '0', '2', and '3' are
-       accepted (without a newline); '2' and '3' are both
-       mapped to PM_EVENT_SUSPEND.
-
-On writes, the PM core relies on that recorded event code and the device/bus
-capabilities to determine whether it uses a partial suspend() or resume()
-sequence to change things so that the recorded event corresponds to the
-numeric parameter.
-
-   -   If the bus requires the irqs-disabled suspend_late()/resume_early()
-       phases, writes fail because those operations are not supported here.
-
-   -   If the recorded value is the expected value, nothing is done.
-
-   -   If the recorded value is nonzero, the device is partially resumed,
-       using the bus.resume() and/or class.resume() methods.
-
-   -   If the target value is nonzero, the device is partially suspended,
-       using the class.suspend() and/or bus.suspend() methods and the
-       PM_EVENT_SUSPEND message.
-
-Drivers have no way to tell whether their suspend() and resume() calls
-have come through the sysfs power/state file or as part of entering a
-system sleep state, except that when accessed through sysfs the normal
-parent/child sequencing rules are ignored.  Drivers (such as bus, bridge,
-or hub drivers) which expose child devices may need to enforce those rules
-on their own.
index e4bdcaee24e46e6805caf0e0a9edfc9d57638402..7f7a737f7f9fd785deacaf4f3aaaf56d87a21c11 100644 (file)
@@ -6,9 +6,9 @@ Testing suspend and resume support in device drivers
 Unfortunately, to effectively test the support for the system-wide suspend and
 resume transitions in a driver, it is necessary to suspend and resume a fully
 functional system with this driver loaded.  Moreover, that should be done
-several times, preferably several times in a row, and separately for the suspend
-to disk (STD) and the suspend to RAM (STR) transitions, because each of these
-cases involves different ordering of operations and different interactions with
+several times, preferably several times in a row, and separately for hibernation
+(aka suspend to disk or STD) and suspend to RAM (STR), because each of these
+cases involves slightly different operations and different interactions with
 the machine's BIOS.
 
 Of course, for this purpose the test system has to be known to suspend and
@@ -22,20 +22,24 @@ for more information about the debugging of suspend/resume functionality.
 Once you have resolved the suspend/resume-related problems with your test system
 without the new driver, you are ready to test it:
 
-a) Build the driver as a module, load it and try the STD in the test mode (see:
-Documents/power/basic-pm-debugging.txt, 1a)).
+a) Build the driver as a module, load it and try the test modes of hibernation
+   (see: Documents/power/basic-pm-debugging.txt, 1).
 
-b) Load the driver and attempt to suspend to disk in the "reboot", "shutdown"
-and "platform" modes (see: Documents/power/basic-pm-debugging.txt, 1).
+b) Load the driver and attempt to hibernate in the "reboot", "shutdown" and
+   "platform" modes (see: Documents/power/basic-pm-debugging.txt, 1).
 
-c) Compile the driver directly into the kernel and try the STD in the test mode.
+c) Compile the driver directly into the kernel and try the test modes of
+   hibernation.
 
-d) Attempt to suspend to disk with the driver compiled directly into the kernel
-in the "reboot", "shutdown" and "platform" modes.
+d) Attempt to hibernate with the driver compiled directly into the kernel
+   in the "reboot", "shutdown" and "platform" modes.
 
-e) Attempt to suspend to RAM using the s2ram tool with the driver loaded (see:
-Documents/power/basic-pm-debugging.txt, 2).  As far as the STR tests are
-concerned, it should not matter whether or not the driver is built as a module.
+e) Try the test modes of suspend (see: Documents/power/basic-pm-debugging.txt,
+   2).  [As far as the STR tests are concerned, it should not matter whether or
+   not the driver is built as a module.]
+
+f) Attempt to suspend to RAM using the s2ram tool with the driver loaded
+   (see: Documents/power/basic-pm-debugging.txt, 2).
 
 Each of the above tests should be repeated several times and the STD tests
 should be mixed with the STR tests.  If any of them fails, the driver cannot be
index 9293e4bc857c6bb7a049b8951c97ee42ab306d9c..ae1b7ec07684bad822171767bba66fc9798cc204 100644 (file)
@@ -28,6 +28,14 @@ PM_POST_HIBERNATION  The system memory state has been restored from a
                        hibernation.  Device drivers' .resume() callbacks have
                        been executed and tasks have been thawed.
 
+PM_RESTORE_PREPARE     The system is going to restore a hibernation image.
+                       If all goes well the restored kernel will issue a
+                       PM_POST_HIBERNATION notification.
+
+PM_POST_RESTORE                An error occurred during the hibernation restore.
+                       Device drivers' .resume() callbacks have been executed
+                       and tasks have been thawed.
+
 PM_SUSPEND_PREPARE     The system is preparing for a suspend.
 
 PM_POST_SUSPEND                The system has just resumed or an error occured during
index e00c6cf09e85aad17e587f0ac9d19d0a543a4cad..7b99636564c8cbc608ff6fb1a24b883c254bf8e3 100644 (file)
@@ -14,7 +14,7 @@ are going to develop your own suspend/resume utilities.
 
 The interface consists of a character device providing the open(),
 release(), read(), and write() operations as well as several ioctl()
-commands defined in kernel/power/power.h.  The major and minor
+commands defined in include/linux/suspend_ioctls.h .  The major and minor
 numbers of the device are, respectively, 10 and 231, and they can
 be read from /sys/class/misc/snapshot/dev.
 
@@ -27,17 +27,17 @@ once at a time.
 The ioctl() commands recognized by the device are:
 
 SNAPSHOT_FREEZE - freeze user space processes (the current process is
-       not frozen); this is required for SNAPSHOT_ATOMIC_SNAPSHOT
+       not frozen); this is required for SNAPSHOT_CREATE_IMAGE
        and SNAPSHOT_ATOMIC_RESTORE to succeed
 
 SNAPSHOT_UNFREEZE - thaw user space processes frozen by SNAPSHOT_FREEZE
 
-SNAPSHOT_ATOMIC_SNAPSHOT - create a snapshot of the system memory; the
+SNAPSHOT_CREATE_IMAGE - create a snapshot of the system memory; the
        last argument of ioctl() should be a pointer to an int variable,
        the value of which will indicate whether the call returned after
        creating the snapshot (1) or after restoring the system memory state
        from it (0) (after resume the system finds itself finishing the
-       SNAPSHOT_ATOMIC_SNAPSHOT ioctl() again); after the snapshot
+       SNAPSHOT_CREATE_IMAGE ioctl() again); after the snapshot
        has been created the read() operation can be used to transfer
        it out of the kernel
 
@@ -49,39 +49,37 @@ SNAPSHOT_ATOMIC_RESTORE - restore the system memory state from the
 
 SNAPSHOT_FREE - free memory allocated for the snapshot image
 
-SNAPSHOT_SET_IMAGE_SIZE - set the preferred maximum size of the image
+SNAPSHOT_PREF_IMAGE_SIZE - set the preferred maximum size of the image
        (the kernel will do its best to ensure the image size will not exceed
        this number, but if it turns out to be impossible, the kernel will
        create the smallest image possible)
 
-SNAPSHOT_AVAIL_SWAP - return the amount of available swap in bytes (the last
-       argument should be a pointer to an unsigned int variable that will
+SNAPSHOT_GET_IMAGE_SIZE - return the actual size of the hibernation image
+
+SNAPSHOT_AVAIL_SWAP_SIZE - return the amount of available swap in bytes (the
+       last argument should be a pointer to an unsigned int variable that will
        contain the result if the call is successful).
 
-SNAPSHOT_GET_SWAP_PAGE - allocate a swap page from the resume partition
+SNAPSHOT_ALLOC_SWAP_PAGE - allocate a swap page from the resume partition
        (the last argument should be a pointer to a loff_t variable that
        will contain the swap page offset if the call is successful)
 
-SNAPSHOT_FREE_SWAP_PAGES - free all swap pages allocated with
-       SNAPSHOT_GET_SWAP_PAGE
-
-SNAPSHOT_SET_SWAP_FILE - set the resume partition (the last ioctl() argument
-       should specify the device's major and minor numbers in the old
-       two-byte format, as returned by the stat() function in the .st_rdev
-       member of the stat structure)
+SNAPSHOT_FREE_SWAP_PAGES - free all swap pages allocated by
+       SNAPSHOT_ALLOC_SWAP_PAGE
 
 SNAPSHOT_SET_SWAP_AREA - set the resume partition and the offset (in <PAGE_SIZE>
        units) from the beginning of the partition at which the swap header is
        located (the last ioctl() argument should point to a struct
-       resume_swap_area, as defined in kernel/power/power.h, containing the
-       resume device specification, as for the SNAPSHOT_SET_SWAP_FILE ioctl(),
-       and the offset); for swap partitions the offset is always 0, but it is
-       different to zero for swap files (please see
-       Documentation/swsusp-and-swap-files.txt for details).
-       The SNAPSHOT_SET_SWAP_AREA ioctl() is considered as a replacement for
-       SNAPSHOT_SET_SWAP_FILE which is regarded as obsolete.   It is
-       recommended to always use this call, because the code to set the resume
-       partition may be removed from future kernels
+       resume_swap_area, as defined in kernel/power/suspend_ioctls.h,
+       containing the resume device specification and the offset); for swap
+       partitions the offset is always 0, but it is different from zero for
+       swap files (see Documentation/swsusp-and-swap-files.txt for details).
+
+SNAPSHOT_PLATFORM_SUPPORT - enable/disable the hibernation platform support,
+       depending on the argument value (enable, if the argument is nonzero)
+
+SNAPSHOT_POWER_OFF - make the kernel transition the system to the hibernation
+       state (eg. ACPI S4) using the platform (eg. ACPI) driver
 
 SNAPSHOT_S2RAM - suspend to RAM; using this call causes the kernel to
        immediately enter the suspend-to-RAM state, so this call must always
@@ -93,24 +91,6 @@ SNAPSHOT_S2RAM - suspend to RAM; using this call causes the kernel to
        to resume the system from RAM if there's enough battery power or restore
        its state on the basis of the saved suspend image otherwise)
 
-SNAPSHOT_PMOPS - enable the usage of the hibernation_ops->prepare,
-       hibernate_ops->enter and hibernation_ops->finish methods (the in-kernel
-       swsusp knows these as the "platform method") which are needed on many
-       machines to (among others) speed up the resume by letting the BIOS skip
-       some steps or to let the system recognise the correct state of the
-       hardware after the resume (in particular on many machines this ensures
-       that unplugged AC adapters get correctly detected and that kacpid does
-       not run wild after the resume).  The last ioctl() argument can take one
-       of the three values, defined in kernel/power/power.h:
-       PMOPS_PREPARE - make the kernel carry out the
-               hibernation_ops->prepare() operation
-       PMOPS_ENTER - make the kernel power off the system by calling
-               hibernation_ops->enter()
-       PMOPS_FINISH - make the kernel carry out the
-               hibernation_ops->finish() operation
-       Note that the actual constants are misnamed because they surface
-       internal kernel implementation details that have changed.
-
 The device's read() operation can be used to transfer the snapshot image from
 the kernel.  It has the following limitations:
 - you cannot read() more than one virtual memory page at a time
@@ -122,7 +102,7 @@ The device's write() operation is used for uploading the system memory snapshot
 into the kernel.  It has the same limitations as the read() operation.
 
 The release() operation frees all memory allocated for the snapshot image
-and all swap pages allocated with SNAPSHOT_GET_SWAP_PAGE (if any).
+and all swap pages allocated with SNAPSHOT_ALLOC_SWAP_PAGE (if any).
 Thus it is not necessary to use either SNAPSHOT_FREE or
 SNAPSHOT_FREE_SWAP_PAGES before closing the device (in fact it will also
 unfreeze user space processes frozen by SNAPSHOT_UNFREEZE if they are
@@ -133,16 +113,12 @@ snapshot image from/to the kernel will use a swap parition, called the resume
 partition, or a swap file as storage space (if a swap file is used, the resume
 partition is the partition that holds this file).  However, this is not really
 required, as they can use, for example, a special (blank) suspend partition or
-a file on a partition that is unmounted before SNAPSHOT_ATOMIC_SNAPSHOT and
+a file on a partition that is unmounted before SNAPSHOT_CREATE_IMAGE and
 mounted afterwards.
 
-These utilities SHOULD NOT make any assumptions regarding the ordering of
-data within the snapshot image, except for the image header that MAY be
-assumed to start with an swsusp_info structure, as specified in
-kernel/power/power.h.  This structure MAY be used by the userland utilities
-to obtain some information about the snapshot image, such as the size
-of the snapshot image, including the metadata and the header itself,
-contained in the .size member of swsusp_info.
+These utilities MUST NOT make any assumptions regarding the ordering of
+data within the snapshot image.  The contents of the image are entirely owned
+by the kernel and its structure may be changed in future kernel releases.
 
 The snapshot image MUST be written to the kernel unaltered (ie. all of the image
 data, metadata and header MUST be written in _exactly_ the same amount, form
@@ -159,7 +135,7 @@ means, such as checksums, to ensure the integrity of the snapshot image.
 The suspending and resuming utilities MUST lock themselves in memory,
 preferrably using mlockall(), before calling SNAPSHOT_FREEZE.
 
-The suspending utility MUST check the value stored by SNAPSHOT_ATOMIC_SNAPSHOT
+The suspending utility MUST check the value stored by SNAPSHOT_CREATE_IMAGE
 in the memory location pointed to by the last argument of ioctl() and proceed
 in accordance with it:
 1.     If the value is 1 (ie. the system memory snapshot has just been
@@ -173,7 +149,7 @@ in accordance with it:
                image has been saved.
        (b)     The suspending utility SHOULD NOT attempt to perform any
                file system operations (including reads) on the file systems
-               that were mounted before SNAPSHOT_ATOMIC_SNAPSHOT has been
+               that were mounted before SNAPSHOT_CREATE_IMAGE has been
                called.  However, it MAY mount a file system that was not
                mounted at that time and perform some operations on it (eg.
                use it for saving the image).
diff --git a/Documentation/usb/gadget_printer.txt b/Documentation/usb/gadget_printer.txt
new file mode 100644 (file)
index 0000000..ad995bf
--- /dev/null
@@ -0,0 +1,510 @@
+
+                       Linux USB Printer Gadget Driver
+                                 06/04/2007
+
+              Copyright (C) 2007 Craig W. Nadler <craig@nadler.us>
+
+
+
+GENERAL
+=======
+
+This driver may be used if you are writing printer firmware using Linux as
+the embedded OS. This driver has nothing to do with using a printer with
+your Linux host system.
+
+You will need a USB device controller and a Linux driver for it that accepts
+a gadget / "device class" driver using the Linux USB Gadget API. After the
+USB device controller driver is loaded then load the printer gadget driver.
+This will present a printer interface to the USB Host that your USB Device
+port is connected to.
+
+This driver is structured for printer firmware that runs in user mode. The
+user mode printer firmware will read and write data from the kernel mode
+printer gadget driver using a device file. The printer returns a printer status
+byte when the USB HOST sends a device request to get the printer status.  The
+user space firmware can read or write this status byte using a device file
+/dev/g_printer . Both blocking and non-blocking read/write calls are supported.
+
+
+
+
+HOWTO USE THIS DRIVER
+=====================
+
+To load the USB device controller driver and the printer gadget driver. The
+following example uses the Netchip 2280 USB device controller driver:
+
+modprobe net2280
+modprobe g_printer
+
+
+The follow command line parameter can be used when loading the printer gadget
+(ex: modprobe g_printer idVendor=0x0525 idProduct=0xa4a8 ):
+
+idVendor - This is the Vendor ID used in the device descriptor. The default is
+       the Netchip vendor id 0x0525. YOU MUST CHANGE TO YOUR OWN VENDOR ID
+       BEFORE RELEASING A PRODUCT. If you plan to release a product and don't
+       already have a Vendor ID please see www.usb.org for details on how to
+       get one.
+
+idProduct - This is the Product ID used in the device descriptor. The default
+       is 0xa4a8, you should change this to an ID that's not used by any of
+       your other USB products if you have any. It would be a good idea to
+       start numbering your products starting with say 0x0001.
+
+bcdDevice - This is the version number of your product. It would be a good idea
+       to put your firmware version here.
+
+iManufacturer - A string containing the name of the Vendor.
+
+iProduct - A string containing the Product Name.
+
+iSerialNum - A string containing the Serial Number. This should be changed for
+       each unit of your product.
+
+iPNPstring -  The PNP ID string used for this printer. You will want to set
+       either on the command line or hard code the PNP ID string used for
+       your printer product.
+
+qlen - The number of 8k buffers to use per endpoint. The default is 10, you
+       should tune this for your product. You may also want to tune the
+       size of each buffer for your product.
+
+
+
+
+USING THE EXAMPLE CODE
+======================
+
+This example code talks to stdout, instead of a print engine.
+
+To compile the test code below:
+
+1) save it to a file called prn_example.c
+2) compile the code with the follow command:
+        gcc prn_example.c -o prn_example
+
+
+
+To read printer data from the host to stdout:
+
+       # prn_example -read_data
+
+
+To write printer data from a file (data_file) to the host:
+
+       # cat data_file | prn_example -write_data
+
+
+To get the current printer status for the gadget driver:
+
+       # prn_example -get_status
+
+       Printer status is:
+            Printer is NOT Selected
+            Paper is Out
+            Printer OK
+
+
+To set printer to Selected/On-line:
+
+       # prn_example -selected
+
+
+To set printer to Not Selected/Off-line:
+
+       # prn_example -not_selected
+
+
+To set paper status to paper out:
+
+       # prn_example -paper_out
+
+
+To set paper status to paper loaded:
+
+       # prn_example -paper_loaded
+
+
+To set error status to printer OK:
+
+       # prn_example -no_error
+
+
+To set error status to ERROR:
+
+       # prn_example -error
+
+
+
+
+EXAMPLE CODE
+============
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <linux/poll.h>
+#include <sys/ioctl.h>
+#include <linux/usb/g_printer.h>
+
+#define PRINTER_FILE                   "/dev/g_printer"
+#define BUF_SIZE                       512
+
+
+/*
+ * 'usage()' - Show program usage.
+ */
+
+static void
+usage(const char *option)              /* I - Option string or NULL */
+{
+       if (option) {
+               fprintf(stderr,"prn_example: Unknown option \"%s\"!\n",
+                               option);
+       }
+
+       fputs("\n", stderr);
+       fputs("Usage: prn_example -[options]\n", stderr);
+       fputs("Options:\n", stderr);
+       fputs("\n", stderr);
+       fputs("-get_status    Get the current printer status.\n", stderr);
+       fputs("-selected      Set the selected status to selected.\n", stderr);
+       fputs("-not_selected  Set the selected status to NOT selected.\n",
+                       stderr);
+       fputs("-error         Set the error status to error.\n", stderr);
+       fputs("-no_error      Set the error status to NO error.\n", stderr);
+       fputs("-paper_out     Set the paper status to paper out.\n", stderr);
+       fputs("-paper_loaded  Set the paper status to paper loaded.\n",
+                       stderr);
+       fputs("-read_data     Read printer data from driver.\n", stderr);
+       fputs("-write_data    Write printer sata to driver.\n", stderr);
+       fputs("-NB_read_data  (Non-Blocking) Read printer data from driver.\n",
+                       stderr);
+       fputs("\n\n", stderr);
+
+       exit(1);
+}
+
+
+static int
+read_printer_data()
+{
+       struct pollfd   fd[1];
+
+       /* Open device file for printer gadget. */
+       fd[0].fd = open(PRINTER_FILE, O_RDWR);
+       if (fd[0].fd < 0) {
+               printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
+               close(fd[0].fd);
+               return(-1);
+       }
+
+       fd[0].events = POLLIN | POLLRDNORM;
+
+       while (1) {
+               static char buf[BUF_SIZE];
+               int bytes_read;
+               int retval;
+
+               /* Wait for up to 1 second for data. */
+               retval = poll(fd, 1, 1000);
+
+               if (retval && (fd[0].revents & POLLRDNORM)) {
+
+                       /* Read data from printer gadget driver. */
+                       bytes_read = read(fd[0].fd, buf, BUF_SIZE);
+
+                       if (bytes_read < 0) {
+                               printf("Error %d reading from %s\n",
+                                               fd[0].fd, PRINTER_FILE);
+                               close(fd[0].fd);
+                               return(-1);
+                       } else if (bytes_read > 0) {
+                               /* Write data to standard OUTPUT (stdout). */
+                               fwrite(buf, 1, bytes_read, stdout);
+                               fflush(stdout);
+                       }
+
+               }
+
+       }
+
+       /* Close the device file. */
+       close(fd[0].fd);
+
+       return 0;
+}
+
+
+static int
+write_printer_data()
+{
+       struct pollfd   fd[1];
+
+       /* Open device file for printer gadget. */
+       fd[0].fd = open (PRINTER_FILE, O_RDWR);
+       if (fd[0].fd < 0) {
+               printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
+               close(fd[0].fd);
+               return(-1);
+       }
+
+       fd[0].events = POLLOUT | POLLWRNORM;
+
+       while (1) {
+               int retval;
+               static char buf[BUF_SIZE];
+               /* Read data from standard INPUT (stdin). */
+               int bytes_read = fread(buf, 1, BUF_SIZE, stdin);
+
+               if (!bytes_read) {
+                       break;
+               }
+
+               while (bytes_read) {
+
+                       /* Wait for up to 1 second to sent data. */
+                       retval = poll(fd, 1, 1000);
+
+                       /* Write data to printer gadget driver. */
+                       if (retval && (fd[0].revents & POLLWRNORM)) {
+                               retval = write(fd[0].fd, buf, bytes_read);
+                               if (retval < 0) {
+                                       printf("Error %d writing to %s\n",
+                                                       fd[0].fd,
+                                                       PRINTER_FILE);
+                                       close(fd[0].fd);
+                                       return(-1);
+                               } else {
+                                       bytes_read -= retval;
+                               }
+
+                       }
+
+               }
+
+       }
+
+       /* Wait until the data has been sent. */
+       fsync(fd[0].fd);
+
+       /* Close the device file. */
+       close(fd[0].fd);
+
+       return 0;
+}
+
+
+static int
+read_NB_printer_data()
+{
+       int             fd;
+       static char     buf[BUF_SIZE];
+       int             bytes_read;
+
+       /* Open device file for printer gadget. */
+       fd = open(PRINTER_FILE, O_RDWR|O_NONBLOCK);
+       if (fd < 0) {
+               printf("Error %d opening %s\n", fd, PRINTER_FILE);
+               close(fd);
+               return(-1);
+       }
+
+       while (1) {
+               /* Read data from printer gadget driver. */
+               bytes_read = read(fd, buf, BUF_SIZE);
+               if (bytes_read <= 0) {
+                       break;
+               }
+
+               /* Write data to standard OUTPUT (stdout). */
+               fwrite(buf, 1, bytes_read, stdout);
+               fflush(stdout);
+       }
+
+       /* Close the device file. */
+       close(fd);
+
+       return 0;
+}
+
+
+static int
+get_printer_status()
+{
+       int     retval;
+       int     fd;
+
+       /* Open device file for printer gadget. */
+       fd = open(PRINTER_FILE, O_RDWR);
+       if (fd < 0) {
+               printf("Error %d opening %s\n", fd, PRINTER_FILE);
+               close(fd);
+               return(-1);
+       }
+
+       /* Make the IOCTL call. */
+       retval = ioctl(fd, GADGET_GET_PRINTER_STATUS);
+       if (retval < 0) {
+               fprintf(stderr, "ERROR: Failed to set printer status\n");
+               return(-1);
+       }
+
+       /* Close the device file. */
+       close(fd);
+
+       return(retval);
+}
+
+
+static int
+set_printer_status(unsigned char buf, int clear_printer_status_bit)
+{
+       int     retval;
+       int     fd;
+
+       retval = get_printer_status();
+       if (retval < 0) {
+               fprintf(stderr, "ERROR: Failed to get printer status\n");
+               return(-1);
+       }
+
+       /* Open device file for printer gadget. */
+       fd = open(PRINTER_FILE, O_RDWR);
+
+       if (fd < 0) {
+               printf("Error %d opening %s\n", fd, PRINTER_FILE);
+               close(fd);
+               return(-1);
+       }
+
+       if (clear_printer_status_bit) {
+               retval &= ~buf;
+       } else {
+               retval |= buf;
+       }
+
+       /* Make the IOCTL call. */
+       if (ioctl(fd, GADGET_SET_PRINTER_STATUS, (unsigned char)retval)) {
+               fprintf(stderr, "ERROR: Failed to set printer status\n");
+               return(-1);
+       }
+
+       /* Close the device file. */
+       close(fd);
+
+       return 0;
+}
+
+
+static int
+display_printer_status()
+{
+       char    printer_status;
+
+       printer_status = get_printer_status();
+       if (printer_status < 0) {
+               fprintf(stderr, "ERROR: Failed to get printer status\n");
+               return(-1);
+       }
+
+       printf("Printer status is:\n");
+       if (printer_status & PRINTER_SELECTED) {
+               printf("     Printer is Selected\n");
+       } else {
+               printf("     Printer is NOT Selected\n");
+       }
+       if (printer_status & PRINTER_PAPER_EMPTY) {
+               printf("     Paper is Out\n");
+       } else {
+               printf("     Paper is Loaded\n");
+       }
+       if (printer_status & PRINTER_NOT_ERROR) {
+               printf("     Printer OK\n");
+       } else {
+               printf("     Printer ERROR\n");
+       }
+
+       return(0);
+}
+
+
+int
+main(int  argc, char *argv[])
+{
+       int     i;              /* Looping var */
+       int     retval = 0;
+
+       /* No Args */
+       if (argc == 1) {
+               usage(0);
+               exit(0);
+       }
+
+       for (i = 1; i < argc && !retval; i ++) {
+
+               if (argv[i][0] != '-') {
+                       continue;
+               }
+
+               if (!strcmp(argv[i], "-get_status")) {
+                       if (display_printer_status()) {
+                               retval = 1;
+                       }
+
+               } else if (!strcmp(argv[i], "-paper_loaded")) {
+                       if (set_printer_status(PRINTER_PAPER_EMPTY, 1)) {
+                               retval = 1;
+                       }
+
+               } else if (!strcmp(argv[i], "-paper_out")) {
+                       if (set_printer_status(PRINTER_PAPER_EMPTY, 0)) {
+                               retval = 1;
+                       }
+
+               } else if (!strcmp(argv[i], "-selected")) {
+                       if (set_printer_status(PRINTER_SELECTED, 0)) {
+                               retval = 1;
+                       }
+
+               } else if (!strcmp(argv[i], "-not_selected")) {
+                       if (set_printer_status(PRINTER_SELECTED, 1)) {
+                               retval = 1;
+                       }
+
+               } else if (!strcmp(argv[i], "-error")) {
+                       if (set_printer_status(PRINTER_NOT_ERROR, 1)) {
+                               retval = 1;
+                       }
+
+               } else if (!strcmp(argv[i], "-no_error")) {
+                       if (set_printer_status(PRINTER_NOT_ERROR, 0)) {
+                               retval = 1;
+                       }
+
+               } else if (!strcmp(argv[i], "-read_data")) {
+                       if (read_printer_data()) {
+                               retval = 1;
+                       }
+
+               } else if (!strcmp(argv[i], "-write_data")) {
+                       if (write_printer_data()) {
+                               retval = 1;
+                       }
+
+               } else if (!strcmp(argv[i], "-NB_read_data")) {
+                       if (read_NB_printer_data()) {
+                               retval = 1;
+                       }
+
+               } else {
+                       usage(argv[i]);
+                       retval = 1;
+               }
+       }
+
+       exit(retval);
+}
diff --git a/Documentation/usb/iuu_phoenix.txt b/Documentation/usb/iuu_phoenix.txt
new file mode 100644 (file)
index 0000000..e5f0480
--- /dev/null
@@ -0,0 +1,84 @@
+Infinity Usb Unlimited Readme
+-----------------------------
+
+Hi all,
+
+
+This module provide a serial interface to use your
+IUU unit in phoenix mode. Loading this module will
+bring a ttyUSB[0-x] interface. This driver must be
+used by your favorite application to pilot the IUU
+
+This driver is still in beta stage, so bugs can
+occur and your system may freeze. As far I now,
+I never had any problem with it, but I'm not a real
+guru, so don't blame me if your system is unstable
+
+You can plug more than one IUU. Every unit will
+have his own device file(/dev/ttyUSB0,/dev/ttyUSB1,...)
+
+
+
+How to tune the reader speed ?
+
+ A few parameters can be used at load time
+ To use parameters, just unload the module if it is
+ already loaded and use modprobe iuu_phoenix param=value.
+ In case of prebuilt module, use the command
+ insmod iuu_phoenix param=value.
+
+ Example:
+
+ modprobe iuu_phoenix clockmode=3
+
+ The parameters are:
+
+ parm:           clockmode:1=3Mhz579,2=3Mhz680,3=6Mhz (int)
+ parm:           boost:overclock boost percent 100 to 500 (int)
+ parm:           cdmode:Card detect mode 0=none, 1=CD, 2=!CD, 3=DSR, 4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING (int)
+ parm:           xmas:xmas color enabled or not (bool)
+ parm:           debug:Debug enabled or not (bool)
+
+-  clockmode will provide 3 different base settings commonly adopted by
+   different software:
+       1. 3Mhz579
+       2. 3Mhz680
+       3. 6Mhz
+
+-  boost provide a way to overclock the reader ( my favorite :-)  )
+   For example to have best performance than a simple clockmode=3, try this:
+
+      modprobe boost=195
+
+   This will put the reader in a base of 3Mhz579 but boosted a 195 % !
+   the real clock will be now : 6979050 Hz ( 6Mhz979 ) and will increase
+   the speed to a score 10 to 20% better than the simple clockmode=3 !!!
+
+
+-  cdmode permit to setup the signal used to inform the userland ( ioctl answer )
+   if the card is present or not. Eight signals are possible.
+
+-  xmas is completely useless except for your eyes. This is one of my friend who was
+   so sad to have a nice device like the iuu without seeing all color range available.
+   So I have added this option to permit him to see a lot of color ( each activity change the color
+   and the frequency randomly )
+
+-  debug will produce a lot of debugging messages...
+
+
+ Last notes:
+
+ Don't worry about the serial settings, the serial emulation
+ is an abstraction, so use any speed or parity setting will
+ work. ( This will not change anything ).Later I will perhaps
+ use this settings to deduce de boost but is that feature
+ really necessary ?
+ The autodetect feature used is the serial CD. If that doesn't
+ work for your software, disable detection mechanism in it.
+
+
+ Have fun !
+
+ Alain Degreffe
+
+ eczema(at)ecze.com
index 61787801244ecf5e7e662f4cc1a0ac65d859e899..58b16038baea02ba54bbd115ea7964964cbc7f83 100644 (file)
@@ -2247,7 +2247,7 @@ P:        J. Bruce Fields
 M:     bfields@fieldses.org
 P:     Neil Brown
 M:     neilb@suse.de
-L:     nfs@lists.sourceforge.net
+L:     linux-nfs@vger.kernel.org
 W:     http://nfs.sourceforge.net/
 S:     Supported
 
index 4c002ba37e5076fe726826e3a2a73deb29d25176..c613d5fb0daa35774f2d8679f7e01a7bc0ee1de5 100644 (file)
@@ -318,11 +318,6 @@ config PCI
          your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
          VESA. If you have PCI, say Y, otherwise N.
 
-         The PCI-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, contains valuable
-         information about which PCI hardware does work under Linux and which
-         doesn't.
-
 config PCI_DOMAINS
        bool
        default y
index 77201d3f7479ccc65bf2e454fa310be75580a49b..4b1a8e3d292cfe74c864790c30cb08ca8dd59f63 100644 (file)
@@ -577,11 +577,6 @@ config PCI
          your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
          VESA. If you have PCI, say Y, otherwise N.
 
-         The PCI-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, contains valuable
-         information about which PCI hardware does work under Linux and which
-         doesn't.
-
 config PCI_SYSCALL
        def_bool PCI
 
@@ -1035,6 +1030,9 @@ menu "Power management options"
 
 source "kernel/power/Kconfig"
 
+config ARCH_SUSPEND_POSSIBLE
+       def_bool y
+
 endmenu
 
 source "net/Kconfig"
index 4b120cc361359760a542eaea0825365bba5e6b33..a67defd504387a2fc610be020695323947b60333 100644 (file)
@@ -52,7 +52,7 @@ static suspend_state_t target_state;
 /*
  * Called after processes are frozen, but before we shutdown devices.
  */
-static int at91_pm_set_target(suspend_state_t state)
+static int at91_pm_begin(suspend_state_t state)
 {
        target_state = state;
        return 0;
@@ -202,11 +202,20 @@ error:
        return 0;
 }
 
+/*
+ * Called right prior to thawing processes.
+ */
+static void at91_pm_end(void)
+{
+       target_state = PM_SUSPEND_ON;
+}
+
 
 static struct platform_suspend_ops at91_pm_ops ={
-       .valid          = at91_pm_valid_state,
-       .set_target     = at91_pm_set_target,
-       .enter          = at91_pm_enter,
+       .valid  = at91_pm_valid_state,
+       .begin  = at91_pm_begin,
+       .enter  = at91_pm_enter,
+       .end    = at91_pm_end,
 };
 
 static int __init at91_pm_init(void)
index 1919756900f48daa9c12d64508a218a86f330f75..1a9c844ac7eb39e940903e8834a837513e2a9477 100644 (file)
@@ -157,15 +157,10 @@ static void tosa_udc_command(int cmd)
        }
 }
 
-static int tosa_udc_is_connected(void)
-{
-       return ((GPLR(TOSA_GPIO_USB_IN) & GPIO_bit(TOSA_GPIO_USB_IN)) == 0);
-}
-
-
 static struct pxa2xx_udc_mach_info udc_info __initdata = {
        .udc_command            = tosa_udc_command,
-       .udc_is_connected       = tosa_udc_is_connected,
+       .gpio_vbus              = TOSA_GPIO_USB_IN,
+       .gpio_vbus_inverted     = 1,
 };
 
 /*
index fc7ca86ac8bf91627a627539da062d65da16a383..4802eb767dc98d7fc7f4dcdd4b80a64e6c211b58 100644 (file)
@@ -898,6 +898,10 @@ endmenu
 menu "Power management options"
 source "kernel/power/Kconfig"
 
+config ARCH_SUSPEND_POSSIBLE
+       def_bool y
+       depends on !SMP
+
 choice
        prompt "Select PM Wakeup Event Source"
        default PM_WAKEUP_GPIO_BY_SIC_IWR
index 43153e767bb1ab548f1edc52bb755233b38830c3..e3f965c91e2215815d7173a41c4b7e1e52b23a5a 100644 (file)
@@ -322,11 +322,6 @@ config PCI
          onboard. If you have one of these boards and you wish to use the PCI
          facilities, say Y here.
 
-         The PCI-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, contains valuable
-         information about which PCI hardware does work under Linux and which
-         doesn't.
-
 config RESERVE_DMA_COHERENT
        bool "Reserve DMA coherent memory"
        depends on PCI && !MMU
@@ -357,6 +352,11 @@ source "drivers/pcmcia/Kconfig"
 #        should probably wait a while.
 
 menu "Power management options"
+
+config ARCH_SUSPEND_POSSIBLE
+       def_bool y
+       depends on !SMP
+
 source kernel/power/Kconfig
 endmenu
 
index f7237c5f531e511806133f0223ecd48edb0399ab..49326e9d4413117165c26f96da89c2df4c51035e 100644 (file)
@@ -359,11 +359,6 @@ config PCI
          your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
          VESA. If you have PCI, say Y, otherwise N.
 
-         The PCI-HOWTO, available from
-         <http://www.linuxdoc.org/docs.html#howto>, contains valuable
-         information about which PCI hardware does work under Linux and which
-         doesn't.
-
 choice
        prompt "PCI access mode"
        depends on PCI
index 01dee84f840ac72608dae4fe0ea4997b3e911f81..24e6bc09e7a7ade51bba7235baf6ca134a9c51f8 100644 (file)
@@ -145,11 +145,6 @@ config PCI
          your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
          VESA. If you have PCI, say Y, otherwise N.
 
-         The PCI-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, contains valuable
-         information about which PCI hardware does work under Linux and which
-         doesn't.
-
 config MAC
        bool "Macintosh support"
        depends on !MMU_SUN3
index 4fad0a34b9974d31f16b5e1e6a8bb6e3c067e710..36a4018f71d26ea7d685ff72578ece6b21815501 100644 (file)
@@ -1961,11 +1961,6 @@ config PCI
          your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
          say Y, otherwise N.
 
-         The PCI-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, contains valuable
-         information about which PCI hardware does work under Linux and which
-         doesn't.
-
 config PCI_DOMAINS
        bool
 
@@ -2086,6 +2081,10 @@ endmenu
 
 menu "Power management options"
 
+config ARCH_SUSPEND_POSSIBLE
+       def_bool y
+       depends on !SMP
+
 source "kernel/power/Kconfig"
 
 endmenu
index 9c44af3db8d9e542f88f4c1c3df3caee21c447f0..4a22c992861837e21eac00b220869b1e56155209 100644 (file)
@@ -151,11 +151,25 @@ config DEFAULT_UIMAGE
 config REDBOOT
        bool
 
-config PPC64_SWSUSP
+config HIBERNATE_32
        bool
-       depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL))
+       depends on (PPC_PMAC && !SMP) || BROKEN
        default y
 
+config HIBERNATE_64
+       bool
+       depends on BROKEN || (PPC_PMAC64 && EXPERIMENTAL)
+       default y
+
+config ARCH_HIBERNATION_POSSIBLE
+       bool
+       depends on (PPC64 && HIBERNATE_64) || (PPC32 && HIBERNATE_32)
+       default y
+
+config ARCH_SUSPEND_POSSIBLE
+       def_bool y
+       depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200
+
 config PPC_DCR_NATIVE
        bool
        default n
@@ -391,6 +405,10 @@ config CMDLINE
          most cases you will need to specify the root device here.
 
 if !44x || BROKEN
+config ARCH_WANTS_FREEZER_CONTROL
+       def_bool y
+       depends on ADB_PMU
+
 source kernel/power/Kconfig
 endif
 
index c0f13e8deb0b482936528761e040fd8fd026e048..41c7fd91e99e5836cbaef5c7d6803334bc37a206 100644 (file)
@@ -31,7 +31,7 @@ static int lite5200_pm_valid(suspend_state_t state)
        }
 }
 
-static int lite5200_pm_set_target(suspend_state_t state)
+static int lite5200_pm_begin(suspend_state_t state)
 {
        if (lite5200_pm_valid(state)) {
                lite5200_pm_target_state = state;
@@ -219,12 +219,18 @@ static void lite5200_pm_finish(void)
                mpc52xx_pm_finish();
 }
 
+static void lite5200_pm_end(void)
+{
+       lite5200_pm_target_state = PM_SUSPEND_ON;
+}
+
 static struct platform_suspend_ops lite5200_pm_ops = {
        .valid          = lite5200_pm_valid,
-       .set_target     = lite5200_pm_set_target,
+       .begin          = lite5200_pm_begin,
        .prepare        = lite5200_pm_prepare,
        .enter          = lite5200_pm_enter,
        .finish         = lite5200_pm_finish,
+       .end            = lite5200_pm_end,
 };
 
 int __init lite5200_pm_init(void)
index 1cd9c8fd927d8dd20fba363aeea28718d4562328..b30c4c376a831c2a40563b1da7d16c3b64cac731 100644 (file)
@@ -882,6 +882,10 @@ endmenu
 menu "Power management options (EXPERIMENTAL)"
 depends on EXPERIMENTAL && SYS_SUPPORTS_PM
 
+config ARCH_SUSPEND_POSSIBLE
+       def_bool y
+       depends on !SMP
+
 source kernel/power/Kconfig
 
 endmenu
index fbc6f2c8649fa72f17c3c1157871a043a1ee38de..7e816ededed762db82b04ce39b7bc2b449e9f769 100644 (file)
@@ -6,11 +6,6 @@ config PCI
          bus system, i.e. the way the CPU talks to the other stuff inside
          your box. If you have PCI, say Y, otherwise N.
 
-         The PCI-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, contains valuable
-         information about which PCI hardware does work under Linux and which
-         doesn't.
-
 config SH_PCIDMA_NONCOHERENT
        bool "Cache and PCI noncoherent"
        depends on PCI
index 73fc05d0bfad4aa9662bd27e5b63da23527800ae..158522f51d31d4d6dac1d3a5c011156dc7c2f4e5 100644 (file)
@@ -351,11 +351,6 @@ config PCI
          your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
          VESA. If you have PCI, say Y, otherwise N.
 
-         The PCI-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, contains valuable
-         information about which PCI hardware does work under Linux and which
-         doesn't.
-
 config PCI_DOMAINS
        def_bool PCI
 
index 93e66678e158b4a1e9cb302aa467316253b0b991..7109037bdf7c27770a83f078bdd04f039a54e382 100644 (file)
@@ -112,6 +112,14 @@ config ARCH_SUPPORTS_OPROFILE
 
 select HAVE_KVM
 
+config ARCH_HIBERNATION_POSSIBLE
+       def_bool y
+       depends on !SMP || !X86_VOYAGER
+
+config ARCH_SUSPEND_POSSIBLE
+       def_bool y
+       depends on !X86_VOYAGER
+
 config ZONE_DMA32
        bool
        default X86_64
@@ -1369,11 +1377,6 @@ config PCI
          your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
          VESA. If you have PCI, say Y, otherwise N.
 
-         The PCI-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, contains valuable
-         information about which PCI hardware does work under Linux and which
-         doesn't.
-
 choice
        prompt "PCI access mode"
        depends on X86_32 && PCI && !X86_VISWS
index 150ba29a0d331a486e2cea33c3ce3d4aec1464d7..3cd7a2dcd4fe729986267ed1c3d2e20d35ab0a0e 100644 (file)
@@ -30,8 +30,8 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
        raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
 
        if (!(word & (1 << 13))) {
-               printk(KERN_INFO "Intel E7520/7320/7525 detected. "
-                       "Disabling irq balancing and affinity\n");
+               dev_info(&dev->dev, "Intel E7520/7320/7525 detected; "
+                       "disabling irq balancing and affinity\n");
 #ifdef CONFIG_IRQBALANCE
                irqbalance_disable("");
 #endif
@@ -104,14 +104,16 @@ static void ich_force_enable_hpet(struct pci_dev *dev)
        pci_read_config_dword(dev, 0xF0, &rcba);
        rcba &= 0xFFFFC000;
        if (rcba == 0) {
-               printk(KERN_DEBUG "RCBA disabled. Cannot force enable HPET\n");
+               dev_printk(KERN_DEBUG, &dev->dev, "RCBA disabled; "
+                       "cannot force enable HPET\n");
                return;
        }
 
        /* use bits 31:14, 16 kB aligned */
        rcba_base = ioremap_nocache(rcba, 0x4000);
        if (rcba_base == NULL) {
-               printk(KERN_DEBUG "ioremap failed. Cannot force enable HPET\n");
+               dev_printk(KERN_DEBUG, &dev->dev, "ioremap failed; "
+                       "cannot force enable HPET\n");
                return;
        }
 
@@ -122,8 +124,8 @@ static void ich_force_enable_hpet(struct pci_dev *dev)
                /* HPET is enabled in HPTC. Just not reported by BIOS */
                val = val & 0x3;
                force_hpet_address = 0xFED00000 | (val << 12);
-               printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
-                              force_hpet_address);
+               dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+                       "0x%lx\n", force_hpet_address);
                iounmap(rcba_base);
                return;
        }
@@ -142,11 +144,12 @@ static void ich_force_enable_hpet(struct pci_dev *dev)
        if (err) {
                force_hpet_address = 0;
                iounmap(rcba_base);
-               printk(KERN_DEBUG "Failed to force enable HPET\n");
+               dev_printk(KERN_DEBUG, &dev->dev,
+                       "Failed to force enable HPET\n");
        } else {
                force_hpet_resume_type = ICH_FORCE_HPET_RESUME;
-               printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
-                              force_hpet_address);
+               dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+                       "0x%lx\n", force_hpet_address);
        }
 }
 
@@ -208,8 +211,8 @@ static void old_ich_force_enable_hpet(struct pci_dev *dev)
        if (val & 0x4) {
                val &= 0x3;
                force_hpet_address = 0xFED00000 | (val << 12);
-               printk(KERN_DEBUG "HPET at base address 0x%lx\n",
-                              force_hpet_address);
+               dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
+                       force_hpet_address);
                return;
        }
 
@@ -229,14 +232,14 @@ static void old_ich_force_enable_hpet(struct pci_dev *dev)
                /* HPET is enabled in HPTC. Just not reported by BIOS */
                val &= 0x3;
                force_hpet_address = 0xFED00000 | (val << 12);
-               printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
-                              force_hpet_address);
+               dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+                       "0x%lx\n", force_hpet_address);
                cached_dev = dev;
                force_hpet_resume_type = OLD_ICH_FORCE_HPET_RESUME;
                return;
        }
 
-       printk(KERN_DEBUG "Failed to force enable HPET\n");
+       dev_printk(KERN_DEBUG, &dev->dev, "Failed to force enable HPET\n");
 }
 
 /*
@@ -294,8 +297,8 @@ static void vt8237_force_enable_hpet(struct pci_dev *dev)
         */
        if (val & 0x80) {
                force_hpet_address = (val & ~0x3ff);
-               printk(KERN_DEBUG "HPET at base address 0x%lx\n",
-                              force_hpet_address);
+               dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
+                       force_hpet_address);
                return;
        }
 
@@ -309,14 +312,14 @@ static void vt8237_force_enable_hpet(struct pci_dev *dev)
        pci_read_config_dword(dev, 0x68, &val);
        if (val & 0x80) {
                force_hpet_address = (val & ~0x3ff);
-               printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
-                              force_hpet_address);
+               dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+                       "0x%lx\n", force_hpet_address);
                cached_dev = dev;
                force_hpet_resume_type = VT8237_FORCE_HPET_RESUME;
                return;
        }
 
-       printk(KERN_DEBUG "Failed to force enable HPET\n");
+       dev_printk(KERN_DEBUG, &dev->dev, "Failed to force enable HPET\n");
 }
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235,
@@ -344,7 +347,7 @@ static void nvidia_force_enable_hpet(struct pci_dev *dev)
        pci_read_config_dword(dev, 0x44, &val);
        force_hpet_address = val & 0xfffffffe;
        force_hpet_resume_type = NVIDIA_FORCE_HPET_RESUME;
-       printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
+       dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n",
                force_hpet_address);
        cached_dev = dev;
        return;
index 09199511c25623057b8f3c60c96069c646ee27b8..7ac7130022f1a73926a392ee2a83d1c366d29164 100644 (file)
@@ -140,7 +140,12 @@ static void fix_processor_context(void)
        int cpu = smp_processor_id();
        struct tss_struct *t = &per_cpu(init_tss, cpu);
 
-       set_tss_desc(cpu,t);    /* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
+       /*
+        * This just modifies memory; should not be necessary. But... This
+        * is necessary, because 386 hardware has concept of busy TSS or some
+        * similar stupidity.
+        */
+       set_tss_desc(cpu, t);
 
        get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9;
 
@@ -160,7 +165,6 @@ static void fix_processor_context(void)
                 loaddebug(&current->thread, 6);
                 loaddebug(&current->thread, 7);
        }
-
 }
 
 #ifdef CONFIG_HIBERNATION
index da524fb22422eafc8b4d6514609aec749ffc2dc0..f2f36f8dae5214794c67d359fee416b7b716b1f7 100644 (file)
@@ -423,23 +423,23 @@ static void __init pagetable_init(void)
        paravirt_pagetable_setup_done(pgd_base);
 }
 
-#if defined(CONFIG_HIBERNATION) || defined(CONFIG_ACPI)
+#ifdef CONFIG_ACPI_SLEEP
 /*
- * Swap suspend & friends need this for resume because things like the intel-agp
+ * ACPI suspend needs this for resume, because things like the intel-agp
  * driver might have split up a kernel 4MB mapping.
  */
-char __nosavedata swsusp_pg_dir[PAGE_SIZE]
+char swsusp_pg_dir[PAGE_SIZE]
        __attribute__ ((aligned(PAGE_SIZE)));
 
 static inline void save_pg_dir(void)
 {
        memcpy(swsusp_pg_dir, swapper_pg_dir, PAGE_SIZE);
 }
-#else
+#else /* !CONFIG_ACPI_SLEEP */
 static inline void save_pg_dir(void)
 {
 }
-#endif
+#endif /* !CONFIG_ACPI_SLEEP */
 
 void zap_low_mappings(void)
 {
index cb63007e20b2af4142a6cf1703987a48ee86c944..74d30ff33c495319e6f45da8097f7fefc5f4f606 100644 (file)
@@ -17,7 +17,7 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
        int pxb, reg;
        u8 busno, suba, subb;
 
-       printk(KERN_WARNING "PCI: Searching for i450NX host bridges on %s\n", pci_name(d));
+       dev_warn(&d->dev, "Searching for i450NX host bridges\n");
        reg = 0xd0;
        for(pxb = 0; pxb < 2; pxb++) {
                pci_read_config_byte(d, reg++, &busno);
@@ -41,7 +41,7 @@ static void __devinit pci_fixup_i450gx(struct pci_dev *d)
         */
        u8 busno;
        pci_read_config_byte(d, 0x4a, &busno);
-       printk(KERN_INFO "PCI: i440KX/GX host bridge %s: secondary bus %02x\n", pci_name(d), busno);
+       dev_info(&d->dev, "i440KX/GX host bridge; secondary bus %02x\n", busno);
        pci_scan_bus_with_sysdata(busno);
        pcibios_last_bus = -1;
 }
@@ -55,7 +55,7 @@ static void __devinit  pci_fixup_umc_ide(struct pci_dev *d)
         */
        int i;
 
-       printk(KERN_WARNING "PCI: Fixing base address flags for device %s\n", pci_name(d));
+       dev_warn(&d->dev, "Fixing base address flags\n");
        for(i = 0; i < 4; i++)
                d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
 }
@@ -68,7 +68,7 @@ static void __devinit  pci_fixup_ncr53c810(struct pci_dev *d)
         * Fix class to be PCI_CLASS_STORAGE_SCSI
         */
        if (!d->class) {
-               printk(KERN_WARNING "PCI: fixing NCR 53C810 class code for %s\n", pci_name(d));
+               dev_warn(&d->dev, "Fixing NCR 53C810 class code\n");
                d->class = PCI_CLASS_STORAGE_SCSI << 8;
        }
 }
@@ -80,7 +80,7 @@ static void __devinit  pci_fixup_latency(struct pci_dev *d)
         *  SiS 5597 and 5598 chipsets require latency timer set to
         *  at most 32 to avoid lockups.
         */
-       DBG("PCI: Setting max latency to 32\n");
+       dev_dbg(&d->dev, "Setting max latency to 32\n");
        pcibios_max_latency = 32;
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency);
@@ -138,7 +138,7 @@ static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
 
        pci_read_config_byte(d, where, &v);
        if (v & ~mask) {
-               printk(KERN_WARNING "Disabling VIA memory write queue (PCI ID %04x, rev %02x): [%02x] %02x & %02x -> %02x\n", \
+               dev_warn(&d->dev, "Disabling VIA memory write queue (PCI ID %04x, rev %02x): [%02x] %02x & %02x -> %02x\n", \
                        d->device, d->revision, where, v, mask, v & mask);
                v &= mask;
                pci_write_config_byte(d, where, v);
@@ -200,7 +200,7 @@ static void pci_fixup_nforce2(struct pci_dev *dev)
         * Apply fixup if needed, but don't touch disconnect state
         */
        if ((val & 0x00FF0000) != 0x00010000) {
-               printk(KERN_WARNING "PCI: nForce2 C1 Halt Disconnect fixup\n");
+               dev_warn(&dev->dev, "nForce2 C1 Halt Disconnect fixup\n");
                pci_write_config_dword(dev, 0x6c, (val & 0xFF00FFFF) | 0x00010000);
        }
 }
@@ -348,7 +348,7 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev)
        pci_read_config_word(pdev, PCI_COMMAND, &config);
        if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
                pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
-               printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev));
+               dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
        }
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
@@ -388,11 +388,11 @@ static void __devinit pci_fixup_msi_k8t_onboard_sound(struct pci_dev *dev)
                /* verify the change for status output */
                pci_read_config_byte(dev, 0x50, &val);
                if (val & 0x40)
-                       printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, "
+                       dev_info(&dev->dev, "Detected MSI K8T Neo2-FIR; "
                                        "can't enable onboard soundcard!\n");
                else
-                       printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, "
-                                       "enabled onboard soundcard.\n");
+                       dev_info(&dev->dev, "Detected MSI K8T Neo2-FIR; "
+                                       "enabled onboard soundcard\n");
        }
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
index d3cb3d6af4c8da3249b4e4cda5602724831dd549..844721e8e3dd11a5924be7be42caf06b865e8ddd 100644 (file)
@@ -174,11 +174,6 @@ config PCI
          your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
          VESA. If you have PCI, say Y, otherwise N.
 
-         The PCI-HOWTO, available from
-         <http://www.linuxdoc.org/docs.html#howto>, contains valuable
-         information about which PCI hardware does work under Linux and which
-         doesn't
-
 source "drivers/pci/Kconfig"
 
 config HOTPLUG
index 81b2484297037e4b4c4e86e9b82d431e50021f00..fd1c4ba63367469f9826460c6b545407491f9f86 100644 (file)
@@ -192,18 +192,13 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
        arg.type = ACPI_TYPE_INTEGER;
        arg.integer.value = sleep_state;
 
-       /* Run the _PTS and _GTS methods */
+       /* Run the _PTS method */
 
        status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL);
        if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
                return_ACPI_STATUS(status);
        }
 
-       status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
-       if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-               return_ACPI_STATUS(status);
-       }
-
        /* Setup the argument to _SST */
 
        switch (sleep_state) {
@@ -234,10 +229,6 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
                                "While executing method _SST"));
        }
 
-       /* Disable/Clear all GPEs */
-
-       status = acpi_hw_disable_all_gpes();
-
        return_ACPI_STATUS(status);
 }
 
@@ -262,6 +253,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
        struct acpi_bit_register_info *sleep_type_reg_info;
        struct acpi_bit_register_info *sleep_enable_reg_info;
        u32 in_value;
+       struct acpi_object_list arg_list;
+       union acpi_object arg;
        acpi_status status;
 
        ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);
@@ -307,6 +300,18 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
                return_ACPI_STATUS(status);
        }
 
+       /* Execute the _GTS method */
+
+       arg_list.count = 1;
+       arg_list.pointer = &arg;
+       arg.type = ACPI_TYPE_INTEGER;
+       arg.integer.value = sleep_state;
+
+       status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
+       if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+               return_ACPI_STATUS(status);
+       }
+
        /* Get current value of PM1A control */
 
        status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
@@ -473,17 +478,18 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_leave_sleep_state
+ * FUNCTION:    acpi_leave_sleep_state_prep
  *
- * PARAMETERS:  sleep_state         - Which sleep state we just exited
+ * PARAMETERS:  sleep_state         - Which sleep state we are exiting
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
- *              Called with interrupts ENABLED.
+ * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
+ *              sleep.
+ *              Called with interrupts DISABLED.
  *
  ******************************************************************************/
-acpi_status acpi_leave_sleep_state(u8 sleep_state)
+acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
 {
        struct acpi_object_list arg_list;
        union acpi_object arg;
@@ -493,7 +499,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
        u32 PM1Acontrol;
        u32 PM1Bcontrol;
 
-       ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
+       ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
 
        /*
         * Set SLP_TYPE and SLP_EN to state S0.
@@ -540,6 +546,41 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
                }
        }
 
+       /* Execute the _BFS method */
+
+       arg_list.count = 1;
+       arg_list.pointer = &arg;
+       arg.type = ACPI_TYPE_INTEGER;
+       arg.integer.value = sleep_state;
+
+       status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
+       if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+               ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
+       }
+
+       return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_leave_sleep_state
+ *
+ * PARAMETERS:  sleep_state         - Which sleep state we just exited
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
+ *              Called with interrupts ENABLED.
+ *
+ ******************************************************************************/
+acpi_status acpi_leave_sleep_state(u8 sleep_state)
+{
+       struct acpi_object_list arg_list;
+       union acpi_object arg;
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
+
        /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
 
        acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
@@ -558,12 +599,6 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
                ACPI_EXCEPTION((AE_INFO, status, "During Method _SST"));
        }
 
-       arg.integer.value = sleep_state;
-       status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
-       if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-               ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
-       }
-
        /*
         * GPEs must be enabled before _WAK is called as GPEs
         * might get fired there
index 2c0b6630f8ba54603530fce4574f8697faaabe9e..485de1347075c812c4c7dbd4347c67cca7bd67b3 100644 (file)
@@ -26,9 +26,24 @@ u8 sleep_states[ACPI_S_STATE_COUNT];
 
 #ifdef CONFIG_PM_SLEEP
 static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+static bool acpi_sleep_finish_wake_up;
+
+/*
+ * ACPI 2.0 and later want us to execute _PTS after suspending devices, so we
+ * allow the user to request that behavior by using the 'acpi_new_pts_ordering'
+ * kernel command line option that causes the following variable to be set.
+ */
+static bool new_pts_ordering;
+
+static int __init acpi_new_pts_ordering(char *str)
+{
+       new_pts_ordering = true;
+       return 1;
+}
+__setup("acpi_new_pts_ordering", acpi_new_pts_ordering);
 #endif
 
-int acpi_sleep_prepare(u32 acpi_state)
+static int acpi_sleep_prepare(u32 acpi_state)
 {
 #ifdef CONFIG_ACPI_SLEEP
        /* do we have a wakeup address for S2 and S3? */
@@ -44,6 +59,8 @@ int acpi_sleep_prepare(u32 acpi_state)
        ACPI_FLUSH_CPU_CACHE();
        acpi_enable_wakeup_device_prep(acpi_state);
 #endif
+       printk(KERN_INFO PREFIX "Preparing to enter system sleep state S%d\n",
+               acpi_state);
        acpi_enter_sleep_state_prep(acpi_state);
        return 0;
 }
@@ -63,17 +80,25 @@ static u32 acpi_suspend_states[] = {
 static int init_8259A_after_S1;
 
 /**
- *     acpi_pm_set_target - Set the target system sleep state to the state
+ *     acpi_pm_begin - Set the target system sleep state to the state
  *             associated with given @pm_state, if supported.
  */
 
-static int acpi_pm_set_target(suspend_state_t pm_state)
+static int acpi_pm_begin(suspend_state_t pm_state)
 {
        u32 acpi_state = acpi_suspend_states[pm_state];
        int error = 0;
 
        if (sleep_states[acpi_state]) {
                acpi_target_sleep_state = acpi_state;
+               if (new_pts_ordering)
+                       return 0;
+
+               error = acpi_sleep_prepare(acpi_state);
+               if (error)
+                       acpi_target_sleep_state = ACPI_STATE_S0;
+               else
+                       acpi_sleep_finish_wake_up = true;
        } else {
                printk(KERN_ERR "ACPI does not support this state: %d\n",
                        pm_state);
@@ -91,12 +116,17 @@ static int acpi_pm_set_target(suspend_state_t pm_state)
 
 static int acpi_pm_prepare(void)
 {
-       int error = acpi_sleep_prepare(acpi_target_sleep_state);
+       if (new_pts_ordering) {
+               int error = acpi_sleep_prepare(acpi_target_sleep_state);
 
-       if (error)
-               acpi_target_sleep_state = ACPI_STATE_S0;
+               if (error) {
+                       acpi_target_sleep_state = ACPI_STATE_S0;
+                       return error;
+               }
+               acpi_sleep_finish_wake_up = true;
+       }
 
-       return error;
+       return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT;
 }
 
 /**
@@ -120,10 +150,8 @@ static int acpi_pm_enter(suspend_state_t pm_state)
        if (acpi_state == ACPI_STATE_S3) {
                int error = acpi_save_state_mem();
 
-               if (error) {
-                       acpi_target_sleep_state = ACPI_STATE_S0;
+               if (error)
                        return error;
-               }
        }
 
        local_irq_save(flags);
@@ -139,6 +167,9 @@ static int acpi_pm_enter(suspend_state_t pm_state)
                break;
        }
 
+       /* Reprogram control registers and execute _BFS */
+       acpi_leave_sleep_state_prep(acpi_state);
+
        /* ACPI 3.0 specs (P62) says that it's the responsabilty
         * of the OSPM to clear the status bit [ implying that the
         * POWER_BUTTON event should not reach userspace ]
@@ -146,6 +177,13 @@ static int acpi_pm_enter(suspend_state_t pm_state)
        if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3))
                acpi_clear_event(ACPI_EVENT_POWER_BUTTON);
 
+       /*
+        * Disable and clear GPE status before interrupt is enabled. Some GPEs
+        * (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
+        * acpi_leave_sleep_state will reenable specific GPEs later
+        */
+       acpi_hw_disable_all_gpes();
+
        local_irq_restore(flags);
        printk(KERN_DEBUG "Back to C!\n");
 
@@ -157,7 +195,7 @@ static int acpi_pm_enter(suspend_state_t pm_state)
 }
 
 /**
- *     acpi_pm_finish - Finish up suspend sequence.
+ *     acpi_pm_finish - Instruct the platform to leave a sleep state.
  *
  *     This is called after we wake back up (or if entering the sleep state
  *     failed). 
@@ -174,6 +212,7 @@ static void acpi_pm_finish(void)
        acpi_set_firmware_waking_vector((acpi_physical_address) 0);
 
        acpi_target_sleep_state = ACPI_STATE_S0;
+       acpi_sleep_finish_wake_up = false;
 
 #ifdef CONFIG_X86
        if (init_8259A_after_S1) {
@@ -183,6 +222,20 @@ static void acpi_pm_finish(void)
 #endif
 }
 
+/**
+ *     acpi_pm_end - Finish up suspend sequence.
+ */
+
+static void acpi_pm_end(void)
+{
+       /*
+        * This is necessary in case acpi_pm_finish() is not called directly
+        * during a failing transition to a sleep state.
+        */
+       if (acpi_sleep_finish_wake_up)
+               acpi_pm_finish();
+}
+
 static int acpi_pm_state_valid(suspend_state_t pm_state)
 {
        u32 acpi_state;
@@ -201,10 +254,11 @@ static int acpi_pm_state_valid(suspend_state_t pm_state)
 
 static struct platform_suspend_ops acpi_pm_ops = {
        .valid = acpi_pm_state_valid,
-       .set_target = acpi_pm_set_target,
+       .begin = acpi_pm_begin,
        .prepare = acpi_pm_prepare,
        .enter = acpi_pm_enter,
        .finish = acpi_pm_finish,
+       .end = acpi_pm_end,
 };
 
 /*
@@ -229,15 +283,36 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
 #endif /* CONFIG_SUSPEND */
 
 #ifdef CONFIG_HIBERNATION
-static int acpi_hibernation_start(void)
+static int acpi_hibernation_begin(void)
 {
+       int error;
+
        acpi_target_sleep_state = ACPI_STATE_S4;
-       return 0;
+       if (new_pts_ordering)
+               return 0;
+
+       error = acpi_sleep_prepare(ACPI_STATE_S4);
+       if (error)
+               acpi_target_sleep_state = ACPI_STATE_S0;
+       else
+               acpi_sleep_finish_wake_up = true;
+
+       return error;
 }
 
 static int acpi_hibernation_prepare(void)
 {
-       return acpi_sleep_prepare(ACPI_STATE_S4);
+       if (new_pts_ordering) {
+               int error = acpi_sleep_prepare(ACPI_STATE_S4);
+
+               if (error) {
+                       acpi_target_sleep_state = ACPI_STATE_S0;
+                       return error;
+               }
+               acpi_sleep_finish_wake_up = true;
+       }
+
+       return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT;
 }
 
 static int acpi_hibernation_enter(void)
@@ -251,6 +326,8 @@ static int acpi_hibernation_enter(void)
        acpi_enable_wakeup_device(ACPI_STATE_S4);
        /* This shouldn't return.  If it returns, we have a problem */
        status = acpi_enter_sleep_state(ACPI_STATE_S4);
+       /* Reprogram control registers and execute _BFS */
+       acpi_leave_sleep_state_prep(ACPI_STATE_S4);
        local_irq_restore(flags);
 
        return ACPI_SUCCESS(status) ? 0 : -EFAULT;
@@ -263,15 +340,12 @@ static void acpi_hibernation_leave(void)
         * enable it here.
         */
        acpi_enable();
+       /* Reprogram control registers and execute _BFS */
+       acpi_leave_sleep_state_prep(ACPI_STATE_S4);
 }
 
 static void acpi_hibernation_finish(void)
 {
-       /*
-        * If ACPI is not enabled by the BIOS and the boot kernel, we need to
-        * enable it here.
-        */
-       acpi_enable();
        acpi_disable_wakeup_device(ACPI_STATE_S4);
        acpi_leave_sleep_state(ACPI_STATE_S4);
 
@@ -279,6 +353,17 @@ static void acpi_hibernation_finish(void)
        acpi_set_firmware_waking_vector((acpi_physical_address) 0);
 
        acpi_target_sleep_state = ACPI_STATE_S0;
+       acpi_sleep_finish_wake_up = false;
+}
+
+static void acpi_hibernation_end(void)
+{
+       /*
+        * This is necessary in case acpi_hibernation_finish() is not called
+        * directly during a failing transition to the sleep state.
+        */
+       if (acpi_sleep_finish_wake_up)
+               acpi_hibernation_finish();
 }
 
 static int acpi_hibernation_pre_restore(void)
@@ -296,7 +381,8 @@ static void acpi_hibernation_restore_cleanup(void)
 }
 
 static struct platform_hibernation_ops acpi_hibernation_ops = {
-       .start = acpi_hibernation_start,
+       .begin = acpi_hibernation_begin,
+       .end = acpi_hibernation_end,
        .pre_snapshot = acpi_hibernation_prepare,
        .finish = acpi_hibernation_finish,
        .prepare = acpi_hibernation_prepare,
@@ -403,6 +489,7 @@ static void acpi_power_off_prepare(void)
 {
        /* Prepare to power off the system */
        acpi_sleep_prepare(ACPI_STATE_S5);
+       acpi_hw_disable_all_gpes();
 }
 
 static void acpi_power_off(void)
index a2ea125ae2d0e961c52aa909bdbb9083e2e5ea97..cfaf8f5b0a149b3b7bdcf056ebfcd2bfc7fb9870 100644 (file)
@@ -5,5 +5,3 @@ extern int acpi_suspend (u32 state);
 extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
 extern void acpi_enable_wakeup_device(u8 sleep_state);
 extern void acpi_disable_wakeup_device(u8 sleep_state);
-
-extern int acpi_sleep_prepare(u32 acpi_state);
index d4590f546c497c7aa2ae2a365bc1d2a0232b4bff..7ed279b0a12edb90af54c013261cfadf88a8d5c1 100644 (file)
@@ -229,7 +229,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
                return -ENOMEM;
 
        /* Perform set up for DMA */
-       if (pci_enable_device_bars(pdev, 1<<2)) {
+       if (pci_enable_device_io(pdev)) {
                printk(KERN_ERR DRV_NAME ": unable to configure BAR2.\n");
                return -ENODEV;
        }
index de28dfd3b96c6ff4db97ed85320f017a8542e799..911208b892593965857211727a51b028cbd4b10f 100644 (file)
@@ -1,6 +1,6 @@
 obj-$(CONFIG_PM)       += sysfs.o
 obj-$(CONFIG_PM_SLEEP) += main.o
-obj-$(CONFIG_PM_TRACE) += trace.o
+obj-$(CONFIG_PM_TRACE_RTC)     += trace.o
 
 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
 ccflags-$(CONFIG_PM_VERBOSE)   += -DDEBUG
index c6179d6ac6e430764b5c22e67f2b4130191ef599..a70c1c29a7aa2c28e99c9fa352fa6f42b2048d17 100644 (file)
@@ -922,11 +922,6 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
            bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
 
-       /* Fill what we shouldn't be filling, because usb-storage did so. */
-       sc->work_urb.actual_length = 0;
-       sc->work_urb.error_count = 0;
-       sc->work_urb.status = 0;
-
        if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
                /* XXX Clear stalls */
                ub_complete(&sc->work_done);
@@ -1313,9 +1308,6 @@ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        sc->last_pipe = pipe;
        usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, sg_virt(sg),
            sg->length, ub_urb_complete, sc);
-       sc->work_urb.actual_length = 0;
-       sc->work_urb.error_count = 0;
-       sc->work_urb.status = 0;
 
        if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
                /* XXX Clear stalls */
@@ -1356,9 +1348,6 @@ static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        sc->last_pipe = sc->recv_bulk_pipe;
        usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
            &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
-       sc->work_urb.actual_length = 0;
-       sc->work_urb.error_count = 0;
-       sc->work_urb.status = 0;
 
        if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
                /* XXX Clear stalls */
@@ -1473,9 +1462,6 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
 
        usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
            (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
-       sc->work_urb.actual_length = 0;
-       sc->work_urb.error_count = 0;
-       sc->work_urb.status = 0;
 
        if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
                ub_complete(&sc->work_done);
@@ -1953,9 +1939,6 @@ static int ub_sync_reset(struct ub_dev *sc)
 
        usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
            (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
-       sc->work_urb.actual_length = 0;
-       sc->work_urb.error_count = 0;
-       sc->work_urb.status = 0;
 
        if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
                printk(KERN_WARNING
@@ -2007,9 +1990,6 @@ static int ub_sync_getmaxlun(struct ub_dev *sc)
 
        usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe,
            (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl);
-       sc->work_urb.actual_length = 0;
-       sc->work_urb.error_count = 0;
-       sc->work_urb.status = 0;
 
        if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0)
                goto err_submit;
@@ -2077,9 +2057,6 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
 
        usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
            (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
-       sc->work_urb.actual_length = 0;
-       sc->work_urb.error_count = 0;
-       sc->work_urb.status = 0;
 
        if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
                printk(KERN_WARNING
index e6c4a2b762ec955497864f860815fb027d9aa275..f5e7a70da831b1c54b51e081bdf0c1a0bc6ef1f8 100644 (file)
@@ -492,7 +492,7 @@ static __init int scx200_create_pci(const char *text, struct pci_dev *pdev,
        iface->pdev = pdev;
        iface->bar = bar;
 
-       rc = pci_enable_device_bars(iface->pdev, 1 << iface->bar);
+       rc = pci_enable_device_io(iface->pdev);
        if (rc)
                goto errout_free;
 
index 9e01c6dc758eb6c0d898e22a523283d3392f6a8d..eb68a9ad0c98b26efd9db4672826cf9a569ca445 100644 (file)
@@ -156,8 +156,14 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
        ide_setup_pci_noise(dev, d);
 
        /* We must not grab the entire device, it has 'ISA' space in its
-          BARS too and we will freak out other bits of the kernel */
-       if (pci_enable_device_bars(dev, 1<<2)) {
+        * BARS too and we will freak out other bits of the kernel
+        *
+        * pci_enable_device_bars() is going away. I replaced it with
+        * IO only enable for now but I'll need confirmation this is
+        * allright for that device. If not, it will need some kind of
+        * quirk. --BenH.
+        */
+       if (pci_enable_device_io(dev)) {
                printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name);
                return -ENODEV;
        }
index 8ff5a0ef10adc35bc4e50c7dc4892b03fcf91617..05db429a7da8c60403c2b7d51a1ffbf3d82a8b22 100644 (file)
@@ -228,7 +228,9 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
  *     @d: IDE port info
  *
  *     Enable the IDE PCI device. We attempt to enable the device in full
- *     but if that fails then we only need BAR4 so we will enable that.
+ *     but if that fails then we only need IO space. The PCI code should
+ *     have setup the proper resources for us already for controllers in
+ *     legacy mode.
  *     
  *     Returns zero on success or an error code
  */
@@ -238,7 +240,7 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
        int ret;
 
        if (pci_enable_device(dev)) {
-               ret = pci_enable_device_bars(dev, 1 << 4);
+               ret = pci_enable_device_io(dev);
                if (ret < 0) {
                        printk(KERN_WARNING "%s: (ide_setup_pci_device:) "
                                "Could not enable device.\n", d->name);
index 9e5ea074ad20f56d041a2fbf82d19ab27f7dca43..ef5a6a245f5fa36363d513e5aa35fef248a499a4 100644 (file)
@@ -108,6 +108,7 @@ int pci_bus_add_device(struct pci_dev *dev)
 void pci_bus_add_devices(struct pci_bus *bus)
 {
        struct pci_dev *dev;
+       struct pci_bus *child_bus;
        int retval;
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -138,11 +139,19 @@ void pci_bus_add_devices(struct pci_bus *bus)
                               up_write(&pci_bus_sem);
                        }
                        pci_bus_add_devices(dev->subordinate);
-                       retval = sysfs_create_link(&dev->subordinate->class_dev.kobj,
-                                                  &dev->dev.kobj, "bridge");
+
+                       /* register the bus with sysfs as the parent is now
+                        * properly registered. */
+                       child_bus = dev->subordinate;
+                       child_bus->dev.parent = child_bus->bridge;
+                       retval = device_register(&child_bus->dev);
+                       if (!retval)
+                               retval = device_create_file(&child_bus->dev,
+                                                       &dev_attr_cpuaffinity);
                        if (retval)
-                               dev_err(&dev->dev, "Error creating sysfs "
-                                       "bridge symlink, continuing...\n");
+                               dev_err(&dev->dev, "Error registering pci_bus"
+                                       " device bridge symlink,"
+                                       " continuing...\n");
                }
        }
 }
@@ -204,7 +213,6 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
        }
        up_read(&pci_bus_sem);
 }
-EXPORT_SYMBOL_GPL(pci_walk_bus);
 
 EXPORT_SYMBOL(pci_bus_alloc_resource);
 EXPORT_SYMBOL_GPL(pci_bus_add_device);
index 5dfdfdac92e1bc83862707aab71d356d47a36eff..91b2dc956be5de68e1ebefe1585e6e79cea62fab 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <linux/pci.h>
 #include <linux/dmar.h>
+#include "iova.h"
 
 #undef PREFIX
 #define PREFIX "DMAR:"
@@ -263,8 +264,8 @@ parse_dmar_table(void)
        if (!dmar)
                return -ENODEV;
 
-       if (!dmar->width) {
-               printk (KERN_WARNING PREFIX "Zero: Invalid DMAR haw\n");
+       if (dmar->width < PAGE_SHIFT_4K - 1) {
+               printk(KERN_WARNING PREFIX "Invalid DMAR haw\n");
                return -EINVAL;
        }
 
@@ -301,11 +302,24 @@ parse_dmar_table(void)
 int __init dmar_table_init(void)
 {
 
-       parse_dmar_table();
+       int ret;
+
+       ret = parse_dmar_table();
+       if (ret) {
+               printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
+               return ret;
+       }
+
        if (list_empty(&dmar_drhd_units)) {
                printk(KERN_INFO PREFIX "No DMAR devices found\n");
                return -ENODEV;
        }
+
+       if (list_empty(&dmar_rmrr_units)) {
+               printk(KERN_INFO PREFIX "No RMRR found\n");
+               return -ENODEV;
+       }
+
        return 0;
 }
 
index a64449d489d635b9743ce79f2cf52c8904feb125..2cdd8326f1363d5916db000f1af7f2f6a5b22a2a 100644 (file)
@@ -3,8 +3,8 @@
 #
 
 menuconfig HOTPLUG_PCI
-       tristate "Support for PCI Hotplug (EXPERIMENTAL)"
-       depends on PCI && EXPERIMENTAL && HOTPLUG
+       tristate "Support for PCI Hotplug"
+       depends on PCI && HOTPLUG
        ---help---
          Say Y here if you have a motherboard with a PCI Hotplug controller.
          This allows you to add and remove PCI cards while the machine is
index 34a1891191fd4c06261de07a8671512869e3d08d..9bdbe1a6688f728b815014607e8bb8a5ef6ef562 100644 (file)
@@ -3,7 +3,6 @@
 #
 
 obj-$(CONFIG_HOTPLUG_PCI)              += pci_hotplug.o
-obj-$(CONFIG_HOTPLUG_PCI_FAKE)         += fakephp.o 
 obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)       += cpqphp.o
 obj-$(CONFIG_HOTPLUG_PCI_IBM)          += ibmphp.o
 obj-$(CONFIG_HOTPLUG_PCI_ACPI)         += acpiphp.o
@@ -16,6 +15,9 @@ obj-$(CONFIG_HOTPLUG_PCI_RPA)         += rpaphp.o
 obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR)    += rpadlpar_io.o
 obj-$(CONFIG_HOTPLUG_PCI_SGI)          += sgi_hotplug.o
 
+# Link this last so it doesn't claim devices that have a real hotplug driver
+obj-$(CONFIG_HOTPLUG_PCI_FAKE)         += fakephp.o
+
 pci_hotplug-objs       :=      pci_hotplug_core.o
 
 ifdef CONFIG_HOTPLUG_PCI_CPCI
index 1ef417cca2db2a370be207ce8db51146e5386cd5..7a29164d4b325aa2ee4219398b679b066f0e27a6 100644 (file)
@@ -113,7 +113,6 @@ struct acpiphp_slot {
        u8              device;         /* pci device# */
 
        u32             sun;            /* ACPI _SUN (slot unique number) */
-       u32             slotno;         /* slot number relative to bridge */
        u32             flags;          /* see below */
 };
 
index ff1b1c71291a84412086b25db6b99c0a1efc29d3..cf22f9e01e005721257bd61c7a2894008f65b497 100644 (file)
@@ -102,7 +102,7 @@ static int is_ejectable(acpi_handle handle)
 }
 
 
-/* callback routine to check the existence of ejectable slots */
+/* callback routine to check for the existence of ejectable slots */
 static acpi_status
 is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
@@ -117,7 +117,7 @@ is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
        }
 }
 
-/* callback routine to check for the existance of a pci dock device */
+/* callback routine to check for the existence of a pci dock device */
 static acpi_status
 is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
@@ -1528,7 +1528,6 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
                acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
                dbg("%s: re-enumerating slots under %s\n",
                        __FUNCTION__, objname);
-               acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
                acpiphp_check_bridge(bridge);
        }
        return AE_OK ;
index d7a293e3faf5debc9fb8d3df0b571bde3e663c33..94b640146d4456b4aa0b96b1022f7efcfadbd256 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
 #include "../pci.h"
 
 #if !defined(MODULE)
@@ -63,10 +64,16 @@ struct dummy_slot {
        struct list_head node;
        struct hotplug_slot *slot;
        struct pci_dev *dev;
+       struct work_struct remove_work;
+       unsigned long removed;
 };
 
 static int debug;
 static LIST_HEAD(slot_list);
+static struct workqueue_struct *dummyphp_wq;
+
+static void pci_rescan_worker(struct work_struct *work);
+static DECLARE_WORK(pci_rescan_work, pci_rescan_worker);
 
 static int enable_slot (struct hotplug_slot *slot);
 static int disable_slot (struct hotplug_slot *slot);
@@ -109,7 +116,7 @@ static int add_slot(struct pci_dev *dev)
        slot->name = &dev->dev.bus_id[0];
        dbg("slot->name = %s\n", slot->name);
 
-       dslot = kmalloc(sizeof(struct dummy_slot), GFP_KERNEL);
+       dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL);
        if (!dslot)
                goto error_info;
 
@@ -164,6 +171,14 @@ static void remove_slot(struct dummy_slot *dslot)
                err("Problem unregistering a slot %s\n", dslot->slot->name);
 }
 
+/* called from the single-threaded workqueue handler to remove a slot */
+static void remove_slot_worker(struct work_struct *work)
+{
+       struct dummy_slot *dslot =
+               container_of(work, struct dummy_slot, remove_work);
+       remove_slot(dslot);
+}
+
 /**
  * pci_rescan_slot - Rescan slot
  * @temp: Device template. Should be set: bus and devfn.
@@ -267,11 +282,17 @@ static inline void pci_rescan(void) {
        pci_rescan_buses(&pci_root_buses);
 }
 
+/* called from the single-threaded workqueue handler to rescan all pci buses */
+static void pci_rescan_worker(struct work_struct *work)
+{
+       pci_rescan();
+}
 
 static int enable_slot(struct hotplug_slot *hotplug_slot)
 {
        /* mis-use enable_slot for rescanning of the pci bus */
-       pci_rescan();
+       cancel_work_sync(&pci_rescan_work);
+       queue_work(dummyphp_wq, &pci_rescan_work);
        return -ENODEV;
 }
 
@@ -306,6 +327,10 @@ static int disable_slot(struct hotplug_slot *slot)
                err("Can't remove PCI devices with other PCI devices behind it yet.\n");
                return -ENODEV;
        }
+       if (test_and_set_bit(0, &dslot->removed)) {
+               dbg("Slot already scheduled for removal\n");
+               return -ENODEV;
+       }
        /* search for subfunctions and disable them first */
        if (!(dslot->dev->devfn & 7)) {
                for (func = 1; func < 8; func++) {
@@ -328,8 +353,9 @@ static int disable_slot(struct hotplug_slot *slot)
        /* remove the device from the pci core */
        pci_remove_bus_device(dslot->dev);
 
-       /* blow away this sysfs entry and other parts. */
-       remove_slot(dslot);
+       /* queue work item to blow away this sysfs entry and other parts. */
+       INIT_WORK(&dslot->remove_work, remove_slot_worker);
+       queue_work(dummyphp_wq, &dslot->remove_work);
 
        return 0;
 }
@@ -340,6 +366,7 @@ static void cleanup_slots (void)
        struct list_head *next;
        struct dummy_slot *dslot;
 
+       destroy_workqueue(dummyphp_wq);
        list_for_each_safe (tmp, next, &slot_list) {
                dslot = list_entry (tmp, struct dummy_slot, node);
                remove_slot(dslot);
@@ -351,6 +378,10 @@ static int __init dummyphp_init(void)
 {
        info(DRIVER_DESC "\n");
 
+       dummyphp_wq = create_singlethread_workqueue(MY_NAME);
+       if (!dummyphp_wq)
+               return -ENOMEM;
+
        return pci_scan_buses();
 }
 
index a90c28d0c69df75c3cb62b2ca19d3073b49839d1..87b6b8b280e65024fe112e06f1fe59e75a297aeb 100644 (file)
@@ -761,10 +761,13 @@ static void ibm_unconfigure_device(struct pci_func *func)
        debug("func->device << 3 | 0x0  = %x\n", func->device << 3 | 0x0);
 
        for (j = 0; j < 0x08; j++) {
-               temp = pci_find_slot(func->busno, (func->device << 3) | j);
-               if (temp)
+               temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j);
+               if (temp) {
                        pci_remove_bus_device(temp);
+                       pci_dev_put(temp);
+               }
        }
+       pci_dev_put(func->dev);
 }
 
 /*
@@ -823,7 +826,7 @@ static int ibm_configure_device(struct pci_func *func)
        if (!(bus_structure_fixup(func->busno)))
                flag = 1;
        if (func->dev == NULL)
-               func->dev = pci_find_slot(func->busno,
+               func->dev = pci_get_bus_and_slot(func->busno,
                                PCI_DEVFN(func->device, func->function));
 
        if (func->dev == NULL) {
@@ -836,7 +839,7 @@ static int ibm_configure_device(struct pci_func *func)
                if (num)
                        pci_bus_add_devices(bus);
 
-               func->dev = pci_find_slot(func->busno,
+               func->dev = pci_get_bus_and_slot(func->busno,
                                PCI_DEVFN(func->device, func->function));
                if (func->dev == NULL) {
                        err("ERROR... : pci_dev still NULL\n");
index 47bb0e1ff3faff303a72cbe17963da8e34f675fc..dd59a050260fe81035bd42193b1c5613d8c70b84 100644 (file)
@@ -137,7 +137,7 @@ static int get_##name (struct hotplug_slot *slot, type *value)              \
        int retval = 0;                                                 \
        if (try_module_get(ops->owner)) {                               \
                if (ops->get_##name)                                    \
-                       retval = ops->get_##name (slot, value);         \
+                       retval = ops->get_##name(slot, value);          \
                else                                                    \
                        *value = slot->info->name;                      \
                module_put(ops->owner);                                 \
@@ -625,7 +625,7 @@ int pci_hp_register (struct hotplug_slot *slot)
        if ((slot->info == NULL) || (slot->ops == NULL))
                return -EINVAL;
        if (slot->release == NULL) {
-               dbg("Why are you trying to register a hotplug slot"
+               dbg("Why are you trying to register a hotplug slot "
                    "without a proper release function?\n");
                return -EINVAL;
        }
index 7959c222dc24e939c7734fc201fab8491004a3b0..ca656b27a500bb1eb861284fae3a193d2d3181ec 100644 (file)
@@ -82,24 +82,18 @@ struct event_info {
 };
 
 struct controller {
-       struct controller *next;
        struct mutex crit_sect;         /* critical section mutex */
        struct mutex ctrl_lock;         /* controller lock */
        int num_slots;                  /* Number of slots on ctlr */
        int slot_num_inc;               /* 1 or -1 */
        struct pci_dev *pci_dev;
        struct list_head slot_list;
-       struct slot *slot;
        struct hpc_ops *hpc_ops;
        wait_queue_head_t queue;        /* sleep & wake process */
-       u8 bus;
-       u8 device;
-       u8 function;
        u8 slot_device_offset;
        u32 first_slot;         /* First physical slot number */  /* PCIE only has 1 slot */
        u8 slot_bus;            /* Bus where the slots handled by this controller sit */
        u8 ctrlcap;
-       u16 vendor_id;
        u8 cap_base;
        struct timer_list poll_timer;
        volatile int cmd_busy;
@@ -161,6 +155,9 @@ extern int pciehp_configure_device(struct slot *p_slot);
 extern int pciehp_unconfigure_device(struct slot *p_slot);
 extern void pciehp_queue_pushbutton_work(struct work_struct *work);
 int pcie_init(struct controller *ctrl, struct pcie_device *dev);
+int pciehp_enable_slot(struct slot *p_slot);
+int pciehp_disable_slot(struct slot *p_slot);
+int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev);
 
 static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
 {
index 6462ac3b405fcc722f1f57e345e441a94138410a..7f4836b8e71e31e9c68071d120114d9a4b8a3317 100644 (file)
@@ -453,13 +453,9 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
 
        pci_set_drvdata(pdev, ctrl);
 
-       ctrl->bus = pdev->bus->number;  /* ctrl bus */
-       ctrl->slot_bus = pdev->subordinate->number;  /* bus controlled by this HPC */
-
-       ctrl->device = PCI_SLOT(pdev->devfn);
-       ctrl->function = PCI_FUNC(pdev->devfn);
-       dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__,
-               ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
+       dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
+           __FUNCTION__, pdev->bus->number, PCI_SLOT(pdev->devfn),
+           PCI_FUNC(pdev->devfn), pdev->irq);
 
        /* Setup the slot information structures */
        rc = init_slots(ctrl);
@@ -471,6 +467,11 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
        t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
 
        t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
+       if (value) {
+               rc = pciehp_enable_slot(t_slot);
+               if (rc) /* -ENODEV: shouldn't happen, but deal with it */
+                       value = 0;
+       }
        if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
                rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
                if (rc)
@@ -509,6 +510,24 @@ static int pciehp_suspend (struct pcie_device *dev, pm_message_t state)
 static int pciehp_resume (struct pcie_device *dev)
 {
        printk("%s ENTRY\n", __FUNCTION__);
+       if (pciehp_force) {
+               struct pci_dev *pdev = dev->port;
+               struct controller *ctrl = pci_get_drvdata(pdev);
+               struct slot *t_slot;
+               u8 status;
+
+               /* reinitialize the chipset's event detection logic */
+               pcie_init_hardware_part2(ctrl, dev);
+
+               t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
+
+               /* Check if slot is occupied */
+               t_slot->hpc_ops->get_adapter_status(t_slot, &status);
+               if (status)
+                       pciehp_enable_slot(t_slot);
+               else
+                       pciehp_disable_slot(t_slot);
+       }
        return 0;
 }
 #endif
index f1e0966cee95b164d458c3126466d62f063cf00c..b23061c56115f9c65e5fb6dadedf3a1d5339d725 100644 (file)
@@ -37,8 +37,6 @@
 #include "pciehp.h"
 
 static void interrupt_event_handler(struct work_struct *work);
-static int pciehp_enable_slot(struct slot *p_slot);
-static int pciehp_disable_slot(struct slot *p_slot);
 
 static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
 {
@@ -197,12 +195,6 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
                            __FUNCTION__);
                        return;
                }
-               /*
-                * After turning power off, we must wait for at least
-                * 1 second before taking any action that relies on
-                * power having been removed from the slot/adapter.
-                */
-               msleep(1000);
        }
 }
 
@@ -215,15 +207,12 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
  */
 static int board_added(struct slot *p_slot)
 {
-       u8 hp_slot;
        int retval = 0;
        struct controller *ctrl = p_slot->ctrl;
 
-       hp_slot = p_slot->device - ctrl->slot_device_offset;
-
        dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
                        __FUNCTION__, p_slot->device,
-                       ctrl->slot_device_offset, hp_slot);
+                       ctrl->slot_device_offset, p_slot->hp_slot);
 
        if (POWER_CTRL(ctrl->ctrlcap)) {
                /* Power on slot */
@@ -281,8 +270,6 @@ err_exit:
  */
 static int remove_board(struct slot *p_slot)
 {
-       u8 device;
-       u8 hp_slot;
        int retval = 0;
        struct controller *ctrl = p_slot->ctrl;
 
@@ -290,11 +277,7 @@ static int remove_board(struct slot *p_slot)
        if (retval)
                return retval;
 
-       device = p_slot->device;
-       hp_slot = p_slot->device - ctrl->slot_device_offset;
-       p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
-       dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
+       dbg("In %s, hp_slot = %d\n", __FUNCTION__, p_slot->hp_slot);
 
        if (POWER_CTRL(ctrl->ctrlcap)) {
                /* power off slot */
@@ -621,12 +604,6 @@ int pciehp_disable_slot(struct slot *p_slot)
                        mutex_unlock(&p_slot->ctrl->crit_sect);
                        return -EINVAL;
                }
-               /*
-                * After turning power off, we must wait for at least
-                * 1 second before taking any action that relies on
-                * power having been removed from the slot/adapter.
-                */
-               msleep(1000);
        }
 
        ret = remove_board(p_slot);
index 06d025b8b13f6a8f276e396bfc36a742c5a676a4..6eba9b2cfb90b359fc1fb92b45408846b4694f6f 100644 (file)
@@ -636,15 +636,57 @@ static int hpc_power_on_slot(struct slot * slot)
        return retval;
 }
 
+static inline int pcie_mask_bad_dllp(struct controller *ctrl)
+{
+       struct pci_dev *dev = ctrl->pci_dev;
+       int pos;
+       u32 reg;
+
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+       if (!pos)
+               return 0;
+       pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
+       if (reg & PCI_ERR_COR_BAD_DLLP)
+               return 0;
+       reg |= PCI_ERR_COR_BAD_DLLP;
+       pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
+       return 1;
+}
+
+static inline void pcie_unmask_bad_dllp(struct controller *ctrl)
+{
+       struct pci_dev *dev = ctrl->pci_dev;
+       u32 reg;
+       int pos;
+
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+       if (!pos)
+               return;
+       pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
+       if (!(reg & PCI_ERR_COR_BAD_DLLP))
+               return;
+       reg &= ~PCI_ERR_COR_BAD_DLLP;
+       pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
+}
+
 static int hpc_power_off_slot(struct slot * slot)
 {
        struct controller *ctrl = slot->ctrl;
        u16 slot_cmd;
        u16 cmd_mask;
        int retval = 0;
+       int changed;
 
        dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
 
+       /*
+        * Set Bad DLLP Mask bit in Correctable Error Mask
+        * Register. This is the workaround against Bad DLLP error
+        * that sometimes happens during turning power off the slot
+        * which conforms to PCI Express 1.0a spec.
+        */
+       changed = pcie_mask_bad_dllp(ctrl);
+
        slot_cmd = POWER_OFF;
        cmd_mask = PWR_CTRL;
        /*
@@ -674,6 +716,16 @@ static int hpc_power_off_slot(struct slot * slot)
        dbg("%s: SLOTCTRL %x write cmd %x\n",
            __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 
+       /*
+        * After turning power off, we must wait for at least 1 second
+        * before taking any action that relies on power having been
+        * removed from the slot/adapter.
+        */
+       msleep(1000);
+
+       if (changed)
+               pcie_unmask_bad_dllp(ctrl);
+
        return retval;
 }
 
@@ -1067,13 +1119,143 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
 }
 #endif
 
-int pcie_init(struct controller * ctrl, struct pcie_device *dev)
+static int pcie_init_hardware_part1(struct controller *ctrl,
+                                   struct pcie_device *dev)
+{
+       int rc;
+       u16 temp_word;
+       u32 slot_cap;
+       u16 slot_status;
+
+       rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+       if (rc) {
+               err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
+               return -1;
+       }
+
+       /* Mask Hot-plug Interrupt Enable */
+       rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+       if (rc) {
+               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+               return -1;
+       }
+
+       dbg("%s: SLOTCTRL %x value read %x\n",
+           __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
+       temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
+               0x00;
+
+       rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+       if (rc) {
+               err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+               return -1;
+       }
+
+       rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+       if (rc) {
+               err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+               return -1;
+       }
+
+       temp_word = 0x1F; /* Clear all events */
+       rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+       if (rc) {
+               err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
+               return -1;
+       }
+       return 0;
+}
+
+int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
 {
        int rc;
        u16 temp_word;
-       u16 cap_reg;
        u16 intr_enable = 0;
        u32 slot_cap;
+       u16 slot_status;
+
+       rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+       if (rc) {
+               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+               goto abort;
+       }
+
+       intr_enable = intr_enable | PRSN_DETECT_ENABLE;
+
+       rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+       if (rc) {
+               err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
+               goto abort;
+       }
+
+       if (ATTN_BUTTN(slot_cap))
+               intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
+
+       if (POWER_CTRL(slot_cap))
+               intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
+
+       if (MRL_SENS(slot_cap))
+               intr_enable = intr_enable | MRL_DETECT_ENABLE;
+
+       temp_word = (temp_word & ~intr_enable) | intr_enable;
+
+       if (pciehp_poll_mode) {
+               temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
+       } else {
+               temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
+       }
+
+       /*
+        * Unmask Hot-plug Interrupt Enable for the interrupt
+        * notification mechanism case.
+        */
+       rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+       if (rc) {
+               err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+               goto abort;
+       }
+       rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+       if (rc) {
+               err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+               goto abort_disable_intr;
+       }
+
+       temp_word =  0x1F; /* Clear all events */
+       rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+       if (rc) {
+               err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
+               goto abort_disable_intr;
+       }
+
+       if (pciehp_force) {
+               dbg("Bypassing BIOS check for pciehp use on %s\n",
+                               pci_name(ctrl->pci_dev));
+       } else {
+               rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
+               if (rc)
+                       goto abort_disable_intr;
+       }
+
+       return 0;
+
+       /* We end up here for the many possible ways to fail this API. */
+abort_disable_intr:
+       rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+       if (!rc) {
+               temp_word &= ~(intr_enable | HP_INTR_ENABLE);
+               rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+       }
+       if (rc)
+               err("%s : disabling interrupts failed\n", __FUNCTION__);
+abort:
+       return -1;
+}
+
+int pcie_init(struct controller *ctrl, struct pcie_device *dev)
+{
+       int rc;
+       u16 cap_reg;
+       u32 slot_cap;
        int cap_base;
        u16 slot_status, slot_ctrl;
        struct pci_dev *pdev;
@@ -1084,9 +1266,10 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
        dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
                        __FUNCTION__, pdev->vendor, pdev->device);
 
-       if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) {
+       cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       if (cap_base == 0) {
                dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);
-               goto abort_free_ctlr;
+               goto abort;
        }
 
        ctrl->cap_base = cap_base;
@@ -1096,7 +1279,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
        rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
        if (rc) {
                err("%s: Cannot read CAPREG register\n", __FUNCTION__);
-               goto abort_free_ctlr;
+               goto abort;
        }
        dbg("%s: CAPREG offset %x cap_reg %x\n",
            __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg);
@@ -1106,26 +1289,26 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
                && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
                dbg("%s : This is not a root port or the port is not "
                    "connected to a slot\n", __FUNCTION__);
-               goto abort_free_ctlr;
+               goto abort;
        }
 
        rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
        if (rc) {
                err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
-               goto abort_free_ctlr;
+               goto abort;
        }
        dbg("%s: SLOTCAP offset %x slot_cap %x\n",
            __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap);
 
        if (!(slot_cap & HP_CAP)) {
                dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
-               goto abort_free_ctlr;
+               goto abort;
        }
        /* For debugging purpose */
        rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
        if (rc) {
                err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
-               goto abort_free_ctlr;
+               goto abort;
        }
        dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
            __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status);
@@ -1133,7 +1316,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
        rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
        if (rc) {
                err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-               goto abort_free_ctlr;
+               goto abort;
        }
        dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
            __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
@@ -1161,36 +1344,9 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
        ctrl->first_slot = slot_cap >> 19;
        ctrl->ctrlcap = slot_cap & 0x0000007f;
 
-       /* Mask Hot-plug Interrupt Enable */
-       rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-       if (rc) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
-
-       dbg("%s: SLOTCTRL %x value read %x\n",
-           __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
-       temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
-               0x00;
-
-       rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-       if (rc) {
-               err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
-
-       rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-       if (rc) {
-               err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
-
-       temp_word = 0x1F; /* Clear all events */
-       rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-       if (rc) {
-               err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
-               goto abort_free_ctlr;
-       }
+       rc = pcie_init_hardware_part1(ctrl, dev);
+       if (rc)
+               goto abort;
 
        if (pciehp_poll_mode) {
                /* Install interrupt polling timer. Start with 10 sec delay */
@@ -1206,7 +1362,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
                if (rc) {
                        err("Can't get irq %d for the hotplug controller\n",
                            ctrl->pci_dev->irq);
-                       goto abort_free_ctlr;
+                       goto abort;
                }
        }
        dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
@@ -1224,82 +1380,16 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
                }
        }
 
-       rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-       if (rc) {
-               err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
-               goto abort_free_irq;
+       rc = pcie_init_hardware_part2(ctrl, dev);
+       if (rc == 0) {
+               ctrl->hpc_ops = &pciehp_hpc_ops;
+               return 0;
        }
-
-       intr_enable = intr_enable | PRSN_DETECT_ENABLE;
-
-       if (ATTN_BUTTN(slot_cap))
-               intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
-
-       if (POWER_CTRL(slot_cap))
-               intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
-
-       if (MRL_SENS(slot_cap))
-               intr_enable = intr_enable | MRL_DETECT_ENABLE;
-
-       temp_word = (temp_word & ~intr_enable) | intr_enable;
-
-       if (pciehp_poll_mode) {
-               temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
-       } else {
-               temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
-       }
-
-       /*
-        * Unmask Hot-plug Interrupt Enable for the interrupt
-        * notification mechanism case.
-        */
-       rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-       if (rc) {
-               err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
-               goto abort_free_irq;
-       }
-       rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-       if (rc) {
-               err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
-               goto abort_disable_intr;
-       }
-
-       temp_word =  0x1F; /* Clear all events */
-       rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-       if (rc) {
-               err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
-               goto abort_disable_intr;
-       }
-
-       if (pciehp_force) {
-               dbg("Bypassing BIOS check for pciehp use on %s\n",
-                               pci_name(ctrl->pci_dev));
-       } else {
-               rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
-               if (rc)
-                       goto abort_disable_intr;
-       }
-
-       ctrl->hpc_ops = &pciehp_hpc_ops;
-
-       return 0;
-
-       /* We end up here for the many possible ways to fail this API. */
-abort_disable_intr:
-       rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-       if (!rc) {
-               temp_word &= ~(intr_enable | HP_INTR_ENABLE);
-               rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-       }
-       if (rc)
-               err("%s : disabling interrupts failed\n", __FUNCTION__);
-
 abort_free_irq:
        if (pciehp_poll_mode)
                del_timer_sync(&ctrl->poll_timer);
        else
                free_irq(ctrl->pci_dev->irq, ctrl);
-
-abort_free_ctlr:
+abort:
        return -1;
 }
index c424aded13fb43fb108d41870d1c4f46c207de28..dd50713966d1b011bc480aa9d2cab642c63bb7c9 100644 (file)
@@ -105,12 +105,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
        }
 
        /* Find Advanced Error Reporting Enhanced Capability */
-       pos = 256;
-       do {
-               pci_read_config_dword(dev, pos, &reg32);
-               if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
-                       break;
-       } while ((pos = PCI_EXT_CAP_NEXT(reg32)));
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
        if (!pos)
                return;
 
@@ -248,11 +243,15 @@ int pciehp_unconfigure_device(struct slot *p_slot)
        u8 bctl = 0;
        u8 presence = 0;
        struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+       u16 command;
 
        dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
                                p_slot->device);
+       ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence);
+       if (ret)
+               presence = 0;
 
-       for (j=0; j<8 ; j++) {
+       for (j = 0; j < 8; j++) {
                struct pci_dev* temp = pci_get_slot(parent,
                                (p_slot->device << 3) | j);
                if (!temp)
@@ -263,21 +262,26 @@ int pciehp_unconfigure_device(struct slot *p_slot)
                        pci_dev_put(temp);
                        continue;
                }
-               if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-                       ret = p_slot->hpc_ops->get_adapter_status(p_slot,
-                                                               &presence);
-                       if (!ret && presence) {
-                               pci_read_config_byte(temp, PCI_BRIDGE_CONTROL,
-                                       &bctl);
-                               if (bctl & PCI_BRIDGE_CTL_VGA) {
-                                       err("Cannot remove display device %s\n",
-                                               pci_name(temp));
-                                       pci_dev_put(temp);
-                                       continue;
-                               }
+               if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
+                       pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
+                       if (bctl & PCI_BRIDGE_CTL_VGA) {
+                               err("Cannot remove display device %s\n",
+                                   pci_name(temp));
+                               pci_dev_put(temp);
+                               continue;
                        }
                }
                pci_remove_bus_device(temp);
+               /*
+                * Ensure that no new Requests will be generated from
+                * the device.
+                */
+               if (presence) {
+                       pci_read_config_word(temp, PCI_COMMAND, &command);
+                       command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
+                       command |= PCI_COMMAND_INTX_DISABLE;
+                       pci_write_config_word(temp, PCI_COMMAND, command);
+               }
                pci_dev_put(temp);
        }
        /*
@@ -288,4 +292,3 @@ int pciehp_unconfigure_device(struct slot *p_slot)
 
        return rc;
 }
-
index c822a779653fd8cdf86e6d4056c5d1000c1a3897..7d5921b1ee7820960afcc6b2b0ae9d711172ea49 100644 (file)
@@ -74,7 +74,6 @@ struct slot {
        u32 type;
        u32 power_domain;
        char *name;
-       char *location;
        struct device_node *dn;
        struct pci_bus *bus;
        struct list_head *pci_devs;
index 0de84533cd80ffc196845677790fcea7211670ce..6571e9b4c2ec95b9f25df46bfd292a20e8160b2b 100644 (file)
@@ -64,19 +64,6 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state)
        return rc;
 }
 
-static void set_slot_name(struct slot *slot)
-{
-       struct pci_bus *bus = slot->bus;
-       struct pci_dev *bridge;
-
-       bridge = bus->self;
-       if (bridge)
-               strcpy(slot->name, pci_name(bridge));
-       else
-               sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus),
-                       bus->number);
-}
-
 /**
  * rpaphp_enable_slot - record slot state, config pci device
  * @slot: target &slot
@@ -115,7 +102,6 @@ int rpaphp_enable_slot(struct slot *slot)
        info->adapter_status = EMPTY;
        slot->bus = bus;
        slot->pci_devs = &bus->devices;
-       set_slot_name(slot);
 
        /* if there's an adapter in the slot, go add the pci devices */
        if (state == PRESENT) {
index d4ee8723fcb3d6f609b2ac24570e3464648280cd..8ad3debb3794a742db476d28f41ee5aef906a204 100644 (file)
 #include <asm/rtas.h>
 #include "rpaphp.h"
 
-static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf)
+static ssize_t address_read_file (struct hotplug_slot *php_slot, char *buf)
 {
-       char *value;
-       int retval = -ENOENT;
+       int retval;
        struct slot *slot = (struct slot *)php_slot->private;
+       struct pci_bus *bus;
 
        if (!slot)
-               return retval;
+               return -ENOENT;
+
+       bus = slot->bus;
+       if (!bus)
+               return -ENOENT;
+
+       if (bus->self)
+               retval = sprintf(buf, pci_name(bus->self));
+       else
+               retval = sprintf(buf, "%04x:%02x:00.0",
+                       pci_domain_nr(bus), bus->number);
 
-       value = slot->location;
-       retval = sprintf (buf, "%s\n", value);
        return retval;
 }
 
-static struct hotplug_slot_attribute php_attr_location = {
-       .attr = {.name = "phy_location", .mode = S_IFREG | S_IRUGO},
-       .show = location_read_file,
+static struct hotplug_slot_attribute php_attr_address = {
+       .attr = {.name = "address", .mode = S_IFREG | S_IRUGO},
+       .show = address_read_file,
 };
 
 /* free up the memory used by a slot */
@@ -64,7 +72,6 @@ void dealloc_slot_struct(struct slot *slot)
        kfree(slot->hotplug_slot->info);
        kfree(slot->hotplug_slot->name);
        kfree(slot->hotplug_slot);
-       kfree(slot->location);
        kfree(slot);
 }
 
@@ -83,16 +90,13 @@ struct slot *alloc_slot_struct(struct device_node *dn,
                                           GFP_KERNEL);
        if (!slot->hotplug_slot->info)
                goto error_hpslot;
-       slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL);
+       slot->hotplug_slot->name = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
        if (!slot->hotplug_slot->name)
                goto error_info;        
-       slot->location = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
-       if (!slot->location)
-               goto error_name;
        slot->name = slot->hotplug_slot->name;
+       strcpy(slot->name, drc_name);
        slot->dn = dn;
        slot->index = drc_index;
-       strcpy(slot->location, drc_name);
        slot->power_domain = power_domain;
        slot->hotplug_slot->private = slot;
        slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops;
@@ -100,8 +104,6 @@ struct slot *alloc_slot_struct(struct device_node *dn,
        
        return (slot);
 
-error_name:
-       kfree(slot->hotplug_slot->name);
 error_info:
        kfree(slot->hotplug_slot->info);
 error_hpslot:
@@ -133,8 +135,8 @@ int rpaphp_deregister_slot(struct slot *slot)
 
        list_del(&slot->rpaphp_slot_list);
        
-       /* remove "phy_location" file */
-       sysfs_remove_file(&php_slot->kobj, &php_attr_location.attr);
+       /* remove "address" file */
+       sysfs_remove_file(&php_slot->kobj, &php_attr_address.attr);
 
        retval = pci_hp_deregister(php_slot);
        if (retval)
@@ -166,8 +168,8 @@ int rpaphp_register_slot(struct slot *slot)
                return retval;
        }
 
-       /* create "phy_location" file */
-       retval = sysfs_create_file(&php_slot->kobj, &php_attr_location.attr);
+       /* create "address" file */
+       retval = sysfs_create_file(&php_slot->kobj, &php_attr_address.attr);
        if (retval) {
                err("sysfs_create_file failed with error %d\n", retval);
                goto sysfs_fail;
@@ -175,8 +177,7 @@ int rpaphp_register_slot(struct slot *slot)
 
        /* add slot to our internal list */
        list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
-       info("Slot [%s](PCI location=%s) registered\n", slot->name,
-                       slot->location);
+       info("Slot [%s] registered\n", slot->name);
        return 0;
 
 sysfs_fail:
index 5183a45d45b50f6a02b5ada18cdeb9e9a0893624..e8aa138128ce7c740a2d8a7c227791cc8df75a2c 100644 (file)
@@ -597,7 +597,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
        cleanup_slots(ctrl);
 
        /*
-        * Mask SERR and System Interrut generation
+        * Mask SERR and System Interrupt generation
         */
        serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
        serr_int |= (GLOBAL_INTR_MASK  | GLOBAL_SERR_MASK |
index e079a5237c9424e7064e1c0892377f2d9b78536b..4e01df99681ac79c1bbd0842d57ead2933af11d3 100644 (file)
@@ -1781,7 +1781,7 @@ __intel_alloc_iova(struct device *dev, struct dmar_domain *domain,
                /*
                 * First try to allocate an io virtual address in
                 * DMA_32BIT_MASK and if that fails then try allocating
-                * from higer range
+                * from higher range
                 */
                iova = iommu_alloc_iova(domain, size, DMA_32BIT_MASK);
                if (!iova)
index 07c9f09c856dba943a15f7e794ba8e1eaef78387..26938da8f4380c5fd0bdb1786c71f8adb8418046 100644 (file)
 
 static int pci_msi_enable = 1;
 
+/* Arch hooks */
+
+int __attribute__ ((weak))
+arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+{
+       return 0;
+}
+
+int __attribute__ ((weak))
+arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
+{
+       return 0;
+}
+
+int __attribute__ ((weak))
+arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+       struct msi_desc *entry;
+       int ret;
+
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               ret = arch_setup_msi_irq(dev, entry);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
+{
+       return;
+}
+
+void __attribute__ ((weak))
+arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+       struct msi_desc *entry;
+
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               if (entry->irq != 0)
+                       arch_teardown_msi_irq(entry->irq);
+       }
+}
+
 static void msi_set_enable(struct pci_dev *dev, int enable)
 {
        int pos;
@@ -230,7 +275,6 @@ static void pci_intx_for_msi(struct pci_dev *dev, int enable)
                pci_intx(dev, enable);
 }
 
-#ifdef CONFIG_PM
 static void __pci_restore_msi_state(struct pci_dev *dev)
 {
        int pos;
@@ -288,7 +332,7 @@ void pci_restore_msi_state(struct pci_dev *dev)
        __pci_restore_msi_state(dev);
        __pci_restore_msix_state(dev);
 }
-#endif /* CONFIG_PM */
+EXPORT_SYMBOL_GPL(pci_restore_msi_state);
 
 /**
  * msi_capability_init - configure device's MSI capability structure
@@ -683,49 +727,3 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)
 {
        INIT_LIST_HEAD(&dev->msi_list);
 }
-
-
-/* Arch hooks */
-
-int __attribute__ ((weak))
-arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
-{
-       return 0;
-}
-
-int __attribute__ ((weak))
-arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
-{
-       return 0;
-}
-
-int __attribute__ ((weak))
-arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
-       struct msi_desc *entry;
-       int ret;
-
-       list_for_each_entry(entry, &dev->msi_list, list) {
-               ret = arch_setup_msi_irq(dev, entry);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
-{
-       return;
-}
-
-void __attribute__ ((weak))
-arch_teardown_msi_irqs(struct pci_dev *dev)
-{
-       struct msi_desc *entry;
-
-       list_for_each_entry(entry, &dev->msi_list, list) {
-               if (entry->irq != 0)
-                       arch_teardown_msi_irq(entry->irq);
-       }
-}
index 5c6a5d043007ebec1418fe2d9a70cf5071cc06eb..e569645d59e2f3ef429cac60e1da67840277a348 100644 (file)
@@ -156,13 +156,13 @@ run_osc_out:
 }
 
 /**
- * pci_osc_support_set - register OS support to Firmware
+ * __pci_osc_support_set - register OS support to Firmware
  * @flags: OS support bits
  *
  * Update OS support fields and doing a _OSC Query to obtain an update
  * from Firmware on supported control bits.
  **/
-acpi_status pci_osc_support_set(u32 flags)
+acpi_status __pci_osc_support_set(u32 flags, const char *hid)
 {
        u32 temp;
        acpi_status retval;
@@ -176,7 +176,7 @@ acpi_status pci_osc_support_set(u32 flags)
        temp = ctrlset_buf[OSC_CONTROL_TYPE];
        ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
        ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
-       acpi_get_devices ( PCI_ROOT_HID_STRING,
+       acpi_get_devices(hid,
                        acpi_query_osc,
                        ctrlset_buf,
                        (void **) &retval );
@@ -188,7 +188,6 @@ acpi_status pci_osc_support_set(u32 flags)
        }
        return AE_OK;
 }
-EXPORT_SYMBOL(pci_osc_support_set);
 
 /**
  * pci_osc_control_set - commit requested control to Firmware
index c4fa35d1dd7721d7a8288b1bcba6978b6b9412a5..e571c72e67531017f140ee6e323e89644f7320b0 100644 (file)
@@ -186,13 +186,11 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
            set_cpus_allowed(current, node_to_cpumask(node));
        /* And set default memory allocation policy */
        oldpol = current->mempolicy;
-       current->mempolicy = &default_policy;
-       mpol_get(current->mempolicy);
+       current->mempolicy = NULL;      /* fall back to system default policy */
 #endif
        error = drv->probe(dev, id);
 #ifdef CONFIG_NUMA
        set_cpus_allowed(current, oldmask);
-       mpol_free(current->mempolicy);
        current->mempolicy = oldpol;
 #endif
        return error;
index 7d1877341aada287783065bf15ab9f6349b2b07a..abf4203304e405269dc111afbe19b02d1e14ff4d 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/topology.h>
 #include <linux/mm.h>
 #include <linux/capability.h>
+#include <linux/aspm.h>
 #include "pci.h"
 
 static int sysfs_initialized;  /* = 0 */
@@ -358,7 +359,7 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
                   char *buf, loff_t off, size_t count)
 {
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
-                                                      struct class_device,
+                                                      struct device,
                                                      kobj));
 
         /* Only support 1, 2 or 4 byte accesses */
@@ -383,7 +384,7 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
                    char *buf, loff_t off, size_t count)
 {
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
-                                                     struct class_device,
+                                                     struct device,
                                                      kobj));
         /* Only support 1, 2 or 4 byte accesses */
         if (count != 1 && count != 2 && count != 4)
@@ -407,7 +408,7 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
                     struct vm_area_struct *vma)
 {
         struct pci_bus *bus = to_pci_bus(container_of(kobj,
-                                                      struct class_device,
+                                                      struct device,
                                                      kobj));
 
         return pci_mmap_legacy_page_range(bus, vma);
@@ -650,6 +651,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
        if (pcibios_add_platform_entries(pdev))
                goto err_rom_file;
 
+       pcie_aspm_create_sysfs_dev_files(pdev);
+
        return 0;
 
 err_rom_file:
@@ -679,6 +682,8 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
        if (!sysfs_initialized)
                return;
 
+       pcie_aspm_remove_sysfs_dev_files(pdev);
+
        if (pdev->cfg_size < 4096)
                sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
        else
index 7d4ce906d207b5f9a40d7e6de1d398dbf6130216..b3e9294e4a0ede470f1c537e4b48e5b77380a175 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/log2.h>
+#include <linux/aspm.h>
 #include <asm/dma.h>   /* isa_dma_bridge_buggy */
 #include "pci.h"
 
@@ -314,6 +315,24 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
 }
 EXPORT_SYMBOL_GPL(pci_find_ht_capability);
 
+void pcie_wait_pending_transaction(struct pci_dev *dev)
+{
+       int pos;
+       u16 reg16;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (!pos)
+               return;
+       while (1) {
+               pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
+               if (!(reg16 & PCI_EXP_DEVSTA_TRPND))
+                       break;
+               cpu_relax();
+       }
+
+}
+EXPORT_SYMBOL_GPL(pcie_wait_pending_transaction);
+
 /**
  * pci_find_parent_resource - return resource region of parent bus of given region
  * @dev: PCI device structure contains resources to be searched
@@ -353,7 +372,7 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
  * Restore the BAR values for a given device, so as to make it
  * accessible by its driver.
  */
-void
+static void
 pci_restore_bars(struct pci_dev *dev)
 {
        int i, numres;
@@ -501,6 +520,9 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
        if (need_restore)
                pci_restore_bars(dev);
 
+       if (dev->bus->self)
+               pcie_aspm_pm_state_change(dev->bus->self);
+
        return 0;
 }
 
@@ -551,6 +573,7 @@ static int pci_save_pcie_state(struct pci_dev *dev)
        int pos, i = 0;
        struct pci_cap_saved_state *save_state;
        u16 *cap;
+       int found = 0;
 
        pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
        if (pos <= 0)
@@ -559,6 +582,8 @@ static int pci_save_pcie_state(struct pci_dev *dev)
        save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
        if (!save_state)
                save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
+       else
+               found = 1;
        if (!save_state) {
                dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
                return -ENOMEM;
@@ -569,7 +594,9 @@ static int pci_save_pcie_state(struct pci_dev *dev)
        pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
        pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
        pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
-       pci_add_saved_cap(dev, save_state);
+       save_state->cap_nr = PCI_CAP_ID_EXP;
+       if (!found)
+               pci_add_saved_cap(dev, save_state);
        return 0;
 }
 
@@ -597,14 +624,17 @@ static int pci_save_pcix_state(struct pci_dev *dev)
        int pos, i = 0;
        struct pci_cap_saved_state *save_state;
        u16 *cap;
+       int found = 0;
 
        pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
        if (pos <= 0)
                return 0;
 
-       save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
+       save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
        if (!save_state)
                save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
+       else
+               found = 1;
        if (!save_state) {
                dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
                return -ENOMEM;
@@ -612,7 +642,9 @@ static int pci_save_pcix_state(struct pci_dev *dev)
        cap = (u16 *)&save_state->data[0];
 
        pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]);
-       pci_add_saved_cap(dev, save_state);
+       save_state->cap_nr = PCI_CAP_ID_PCIX;
+       if (!found)
+               pci_add_saved_cap(dev, save_state);
        return 0;
 }
 
@@ -713,29 +745,51 @@ int pci_reenable_device(struct pci_dev *dev)
        return 0;
 }
 
-/**
- * pci_enable_device_bars - Initialize some of a device for use
- * @dev: PCI device to be initialized
- * @bars: bitmask of BAR's that must be configured
- *
- *  Initialize device before it's used by a driver. Ask low-level code
- *  to enable selected I/O and memory resources. Wake up the device if it
- *  was suspended. Beware, this function can fail.
- */
-int
-pci_enable_device_bars(struct pci_dev *dev, int bars)
+static int __pci_enable_device_flags(struct pci_dev *dev,
+                                    resource_size_t flags)
 {
        int err;
+       int i, bars = 0;
 
        if (atomic_add_return(1, &dev->enable_cnt) > 1)
                return 0;               /* already enabled */
 
+       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+               if (dev->resource[i].flags & flags)
+                       bars |= (1 << i);
+
        err = do_pci_enable_device(dev, bars);
        if (err < 0)
                atomic_dec(&dev->enable_cnt);
        return err;
 }
 
+/**
+ * pci_enable_device_io - Initialize a device for use with IO space
+ * @dev: PCI device to be initialized
+ *
+ *  Initialize device before it's used by a driver. Ask low-level code
+ *  to enable I/O resources. Wake up the device if it was suspended.
+ *  Beware, this function can fail.
+ */
+int pci_enable_device_io(struct pci_dev *dev)
+{
+       return __pci_enable_device_flags(dev, IORESOURCE_IO);
+}
+
+/**
+ * pci_enable_device_mem - Initialize a device for use with Memory space
+ * @dev: PCI device to be initialized
+ *
+ *  Initialize device before it's used by a driver. Ask low-level code
+ *  to enable Memory resources. Wake up the device if it was suspended.
+ *  Beware, this function can fail.
+ */
+int pci_enable_device_mem(struct pci_dev *dev)
+{
+       return __pci_enable_device_flags(dev, IORESOURCE_MEM);
+}
+
 /**
  * pci_enable_device - Initialize device before it's used by a driver.
  * @dev: PCI device to be initialized
@@ -749,7 +803,7 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
  */
 int pci_enable_device(struct pci_dev *dev)
 {
-       return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
+       return __pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
 }
 
 /*
@@ -885,6 +939,9 @@ pci_disable_device(struct pci_dev *dev)
        if (atomic_sub_return(1, &dev->enable_cnt) != 0)
                return;
 
+       /* Wait for all transactions are finished before disabling the device */
+       pcie_wait_pending_transaction(dev);
+
        pci_read_config_word(dev, PCI_COMMAND, &pci_command);
        if (pci_command & PCI_COMMAND_MASTER) {
                pci_command &= ~PCI_COMMAND_MASTER;
@@ -1619,9 +1676,9 @@ early_param("pci", pci_setup);
 
 device_initcall(pci_init);
 
-EXPORT_SYMBOL_GPL(pci_restore_bars);
 EXPORT_SYMBOL(pci_reenable_device);
-EXPORT_SYMBOL(pci_enable_device_bars);
+EXPORT_SYMBOL(pci_enable_device_io);
+EXPORT_SYMBOL(pci_enable_device_mem);
 EXPORT_SYMBOL(pci_enable_device);
 EXPORT_SYMBOL(pcim_enable_device);
 EXPORT_SYMBOL(pcim_pin_device);
index fc87e14b50de9a15b491ed800320fd9e01f6e7e5..eabeb1f2ec998b0cf39de823b7c0bfd7a237b6ba 100644 (file)
@@ -6,8 +6,10 @@ extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
 extern void pci_cleanup_rom(struct pci_dev *dev);
 
 /* Firmware callbacks */
-extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
-extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state);
+extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev,
+                                               pm_message_t state);
+extern int (*platform_pci_set_power_state)(struct pci_dev *dev,
+                                               pci_power_t state);
 
 extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
 extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
@@ -45,12 +47,6 @@ static inline void pci_no_msi(void) { }
 static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
 #endif
 
-#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)
-void pci_restore_msi_state(struct pci_dev *dev);
-#else
-static inline void pci_restore_msi_state(struct pci_dev *dev) {}
-#endif
-
 #ifdef CONFIG_PCIEAER
 void pci_no_aer(void);
 #else
@@ -68,14 +64,14 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
 }
 extern int pcie_mch_quirk;
 extern struct device_attribute pci_dev_attrs[];
-extern struct class_device_attribute class_device_attr_cpuaffinity;
+extern struct device_attribute dev_attr_cpuaffinity;
 
 /**
  * pci_match_one_device - Tell if a PCI device structure has a matching
  *                        PCI device id structure
  * @id: single PCI device id structure to match
  * @dev: the PCI device structure to match against
- * 
+ *
  * Returns the matching pci_device_id structure or %NULL if there is no match.
  */
 static inline const struct pci_device_id *
index 287a9311716c66b98fd06e7a44a3dff43738f27f..60104cf987966eb09f7cef369c680ad897b70408 100644 (file)
@@ -26,3 +26,23 @@ config HOTPLUG_PCI_PCIE
          When in doubt, say N.
 
 source "drivers/pci/pcie/aer/Kconfig"
+
+#
+# PCI Express ASPM
+#
+config PCIEASPM
+       bool "PCI Express ASPM support(Experimental)"
+       depends on PCI && EXPERIMENTAL
+       default y
+       help
+         This enables PCI Express ASPM (Active State Power Management) and
+         Clock Power Management. ASPM supports state L0/L0s/L1.
+
+         When in doubt, say N.
+config PCIEASPM_DEBUG
+       bool "Debug PCI Express ASPM"
+       depends on PCIEASPM
+       default n
+       help
+         This enables PCI Express ASPM debug support. It will add per-device
+         interface to control ASPM.
index e00fb99acf44434934d05db3dc33959eeebd5650..11f6bb1eae24b5816f37181fdbf6021add41099a 100644 (file)
@@ -2,6 +2,9 @@
 # Makefile for PCI-Express PORT Driver
 #
 
+# Build PCI Express ASPM if needed
+obj-$(CONFIG_PCIEASPM)         += aspm.o
+
 pcieportdrv-y                  := portdrv_core.o portdrv_pci.o portdrv_bus.o
 
 obj-$(CONFIG_PCIEPORTBUS)      += pcieportdrv.o
index 1a1eb45a779e3862f8ef634cd425d4f117444661..8c199ae84f6dbadc59d46d876448b3f522bd849b 100644 (file)
@@ -31,26 +31,16 @@ int aer_osc_setup(struct pcie_device *pciedev)
 {
        acpi_status status = AE_NOT_FOUND;
        struct pci_dev *pdev = pciedev->port;
-       acpi_handle handle = DEVICE_ACPI_HANDLE(&pdev->dev);
-       struct pci_bus *parent;
+       acpi_handle handle = 0;
 
-       while (!handle) {
-               if (!pdev || !pdev->bus->parent)
-                       break;
-               parent = pdev->bus->parent;
-               if (!parent->self)
-                       /* Parent must be a host bridge */
-                       handle = acpi_get_pci_rootbridge_handle(
-                                       pci_domain_nr(parent),
-                                       parent->number);
-               else
-                       handle = DEVICE_ACPI_HANDLE(
-                                       &(parent->self->dev));
-               pdev = parent->self;
-       }
+       /* Find root host bridge */
+       while (pdev->bus && pdev->bus->self)
+               pdev = pdev->bus->self;
+       handle = acpi_get_pci_rootbridge_handle(
+               pci_domain_nr(pdev->bus), pdev->bus->number);
 
        if (handle) {
-               pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
+               pcie_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
                status = pci_osc_control_set(handle,
                                        OSC_PCI_EXPRESS_AER_CONTROL |
                                        OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
new file mode 100644 (file)
index 0000000..1a5adeb
--- /dev/null
@@ -0,0 +1,802 @@
+/*
+ * File:       drivers/pci/pcie/aspm.c
+ * Enabling PCIE link L0s/L1 state and Clock Power Management
+ *
+ * Copyright (C) 2007 Intel
+ * Copyright (C) Zhang Yanmin (yanmin.zhang@intel.com)
+ * Copyright (C) Shaohua Li (shaohua.li@intel.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/aspm.h>
+#include <acpi/acpi_bus.h>
+#include <linux/pci-acpi.h>
+#include "../pci.h"
+
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+#define MODULE_PARAM_PREFIX "pcie_aspm."
+
+struct endpoint_state {
+       unsigned int l0s_acceptable_latency;
+       unsigned int l1_acceptable_latency;
+};
+
+struct pcie_link_state {
+       struct list_head sibiling;
+       struct pci_dev *pdev;
+
+       /* ASPM state */
+       unsigned int support_state;
+       unsigned int enabled_state;
+       unsigned int bios_aspm_state;
+       /* upstream component */
+       unsigned int l0s_upper_latency;
+       unsigned int l1_upper_latency;
+       /* downstream component */
+       unsigned int l0s_down_latency;
+       unsigned int l1_down_latency;
+       /* Clock PM state*/
+       unsigned int clk_pm_capable;
+       unsigned int clk_pm_enabled;
+       unsigned int bios_clk_state;
+
+       /*
+        * A pcie downstream port only has one slot under it, so at most there
+        * are 8 functions
+        */
+       struct endpoint_state endpoints[8];
+};
+
+static int aspm_disabled;
+static DEFINE_MUTEX(aspm_lock);
+static LIST_HEAD(link_list);
+
+#define POLICY_DEFAULT 0       /* BIOS default setting */
+#define POLICY_PERFORMANCE 1   /* high performance */
+#define POLICY_POWERSAVE 2     /* high power saving */
+static int aspm_policy;
+static const char *policy_str[] = {
+       [POLICY_DEFAULT] = "default",
+       [POLICY_PERFORMANCE] = "performance",
+       [POLICY_POWERSAVE] = "powersave"
+};
+
+static int policy_to_aspm_state(struct pci_dev *pdev)
+{
+       struct pcie_link_state *link_state = pdev->link_state;
+
+       switch (aspm_policy) {
+       case POLICY_PERFORMANCE:
+               /* Disable ASPM and Clock PM */
+               return 0;
+       case POLICY_POWERSAVE:
+               /* Enable ASPM L0s/L1 */
+               return PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
+       case POLICY_DEFAULT:
+               return link_state->bios_aspm_state;
+       }
+       return 0;
+}
+
+static int policy_to_clkpm_state(struct pci_dev *pdev)
+{
+       struct pcie_link_state *link_state = pdev->link_state;
+
+       switch (aspm_policy) {
+       case POLICY_PERFORMANCE:
+               /* Disable ASPM and Clock PM */
+               return 0;
+       case POLICY_POWERSAVE:
+               /* Disable Clock PM */
+               return 1;
+       case POLICY_DEFAULT:
+               return link_state->bios_clk_state;
+       }
+       return 0;
+}
+
+static void pcie_set_clock_pm(struct pci_dev *pdev, int enable)
+{
+       struct pci_dev *child_dev;
+       int pos;
+       u16 reg16;
+       struct pcie_link_state *link_state = pdev->link_state;
+
+       list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+               pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+               if (!pos)
+                       return;
+               pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
+               if (enable)
+                       reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN;
+               else
+                       reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
+               pci_write_config_word(child_dev, pos + PCI_EXP_LNKCTL, reg16);
+       }
+       link_state->clk_pm_enabled = !!enable;
+}
+
+static void pcie_check_clock_pm(struct pci_dev *pdev)
+{
+       int pos;
+       u32 reg32;
+       u16 reg16;
+       int capable = 1, enabled = 1;
+       struct pci_dev *child_dev;
+       struct pcie_link_state *link_state = pdev->link_state;
+
+       /* All functions should have the same cap and state, take the worst */
+       list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+               pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+               if (!pos)
+                       return;
+               pci_read_config_dword(child_dev, pos + PCI_EXP_LNKCAP, &reg32);
+               if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) {
+                       capable = 0;
+                       enabled = 0;
+                       break;
+               }
+               pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
+               if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
+                       enabled = 0;
+       }
+       link_state->clk_pm_capable = capable;
+       link_state->clk_pm_enabled = enabled;
+       link_state->bios_clk_state = enabled;
+       pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
+}
+
+/*
+ * pcie_aspm_configure_common_clock: check if the 2 ends of a link
+ *   could use common clock. If they are, configure them to use the
+ *   common clock. That will reduce the ASPM state exit latency.
+ */
+static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
+{
+       int pos, child_pos;
+       u16 reg16 = 0;
+       struct pci_dev *child_dev;
+       int same_clock = 1;
+
+       /*
+        * all functions of a slot should have the same Slot Clock
+        * Configuration, so just check one function
+        * */
+       child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
+               bus_list);
+       BUG_ON(!child_dev->is_pcie);
+
+       /* Check downstream component if bit Slot Clock Configuration is 1 */
+       child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+       pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKSTA, &reg16);
+       if (!(reg16 & PCI_EXP_LNKSTA_SLC))
+               same_clock = 0;
+
+       /* Check upstream component if bit Slot Clock Configuration is 1 */
+       pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
+       if (!(reg16 & PCI_EXP_LNKSTA_SLC))
+               same_clock = 0;
+
+       /* Configure downstream component, all functions */
+       list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+               child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+               pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
+                       &reg16);
+               if (same_clock)
+                       reg16 |= PCI_EXP_LNKCTL_CCC;
+               else
+                       reg16 &= ~PCI_EXP_LNKCTL_CCC;
+               pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
+                       reg16);
+       }
+
+       /* Configure upstream component */
+       pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+       if (same_clock)
+               reg16 |= PCI_EXP_LNKCTL_CCC;
+       else
+               reg16 &= ~PCI_EXP_LNKCTL_CCC;
+       pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+
+       /* retrain link */
+       reg16 |= PCI_EXP_LNKCTL_RL;
+       pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+
+       /* Wait for link training end */
+       while (1) {
+               pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
+               if (!(reg16 & PCI_EXP_LNKSTA_LT))
+                       break;
+               cpu_relax();
+       }
+}
+
+/*
+ * calc_L0S_latency: Convert L0s latency encoding to ns
+ */
+static unsigned int calc_L0S_latency(unsigned int latency_encoding, int ac)
+{
+       unsigned int ns = 64;
+
+       if (latency_encoding == 0x7) {
+               if (ac)
+                       ns = -1U;
+               else
+                       ns = 5*1000; /* > 4us */
+       } else
+               ns *= (1 << latency_encoding);
+       return ns;
+}
+
+/*
+ * calc_L1_latency: Convert L1 latency encoding to ns
+ */
+static unsigned int calc_L1_latency(unsigned int latency_encoding, int ac)
+{
+       unsigned int ns = 1000;
+
+       if (latency_encoding == 0x7) {
+               if (ac)
+                       ns = -1U;
+               else
+                       ns = 65*1000; /* > 64us */
+       } else
+               ns *= (1 << latency_encoding);
+       return ns;
+}
+
+static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state,
+       unsigned int *l0s, unsigned int *l1, unsigned int *enabled)
+{
+       int pos;
+       u16 reg16;
+       u32 reg32;
+       unsigned int latency;
+
+       pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
+       *state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
+       if (*state != PCIE_LINK_STATE_L0S &&
+               *state != (PCIE_LINK_STATE_L1|PCIE_LINK_STATE_L0S))
+               * state = 0;
+       if (*state == 0)
+               return;
+
+       latency = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
+       *l0s = calc_L0S_latency(latency, 0);
+       if (*state & PCIE_LINK_STATE_L1) {
+               latency = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
+               *l1 = calc_L1_latency(latency, 0);
+       }
+       pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+       *enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1);
+}
+
+static void pcie_aspm_cap_init(struct pci_dev *pdev)
+{
+       struct pci_dev *child_dev;
+       u32 state, tmp;
+       struct pcie_link_state *link_state = pdev->link_state;
+
+       /* upstream component states */
+       pcie_aspm_get_cap_device(pdev, &link_state->support_state,
+               &link_state->l0s_upper_latency,
+               &link_state->l1_upper_latency,
+               &link_state->enabled_state);
+       /* downstream component states, all functions have the same setting */
+       child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
+               bus_list);
+       pcie_aspm_get_cap_device(child_dev, &state,
+               &link_state->l0s_down_latency,
+               &link_state->l1_down_latency,
+               &tmp);
+       link_state->support_state &= state;
+       if (!link_state->support_state)
+               return;
+       link_state->enabled_state &= link_state->support_state;
+       link_state->bios_aspm_state = link_state->enabled_state;
+
+       /* ENDPOINT states*/
+       list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+               int pos;
+               u32 reg32;
+               unsigned int latency;
+               struct endpoint_state *ep_state =
+                       &link_state->endpoints[PCI_FUNC(child_dev->devfn)];
+
+               if (child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
+                       child_dev->pcie_type != PCI_EXP_TYPE_LEG_END)
+                       continue;
+
+               pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+               pci_read_config_dword(child_dev, pos + PCI_EXP_DEVCAP, &reg32);
+               latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
+               latency = calc_L0S_latency(latency, 1);
+               ep_state->l0s_acceptable_latency = latency;
+               if (link_state->support_state & PCIE_LINK_STATE_L1) {
+                       latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9;
+                       latency = calc_L1_latency(latency, 1);
+                       ep_state->l1_acceptable_latency = latency;
+               }
+       }
+}
+
+static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev,
+       unsigned int state)
+{
+       struct pci_dev *parent_dev, *tmp_dev;
+       unsigned int latency, l1_latency = 0;
+       struct pcie_link_state *link_state;
+       struct endpoint_state *ep_state;
+
+       parent_dev = pdev->bus->self;
+       link_state = parent_dev->link_state;
+       state &= link_state->support_state;
+       if (state == 0)
+               return 0;
+       ep_state = &link_state->endpoints[PCI_FUNC(pdev->devfn)];
+
+       /*
+        * Check latency for endpoint device.
+        * TBD: The latency from the endpoint to root complex vary per
+        * switch's upstream link state above the device. Here we just do a
+        * simple check which assumes all links above the device can be in L1
+        * state, that is we just consider the worst case. If switch's upstream
+        * link can't be put into L0S/L1, then our check is too strictly.
+        */
+       tmp_dev = pdev;
+       while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
+               parent_dev = tmp_dev->bus->self;
+               link_state = parent_dev->link_state;
+               if (state & PCIE_LINK_STATE_L0S) {
+                       latency = max_t(unsigned int,
+                                       link_state->l0s_upper_latency,
+                                       link_state->l0s_down_latency);
+                       if (latency > ep_state->l0s_acceptable_latency)
+                               state &= ~PCIE_LINK_STATE_L0S;
+               }
+               if (state & PCIE_LINK_STATE_L1) {
+                       latency = max_t(unsigned int,
+                                       link_state->l1_upper_latency,
+                                       link_state->l1_down_latency);
+                       if (latency + l1_latency >
+                                       ep_state->l1_acceptable_latency)
+                               state &= ~PCIE_LINK_STATE_L1;
+               }
+               if (!parent_dev->bus->self) /* parent_dev is a root port */
+                       break;
+               else {
+                       /*
+                        * parent_dev is the downstream port of a switch, make
+                        * tmp_dev the upstream port of the switch
+                        */
+                       tmp_dev = parent_dev->bus->self;
+                       /*
+                        * every switch on the path to root complex need 1 more
+                        * microsecond for L1. Spec doesn't mention L0S.
+                        */
+                       if (state & PCIE_LINK_STATE_L1)
+                               l1_latency += 1000;
+               }
+       }
+       return state;
+}
+
+static unsigned int pcie_aspm_check_state(struct pci_dev *pdev,
+       unsigned int state)
+{
+       struct pci_dev *child_dev;
+
+       /* If no child, disable the link */
+       if (list_empty(&pdev->subordinate->devices))
+               return 0;
+       list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+               if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
+                       /*
+                        * If downstream component of a link is pci bridge, we
+                        * disable ASPM for now for the link
+                        * */
+                       state = 0;
+                       break;
+               }
+               if ((child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
+                       child_dev->pcie_type != PCI_EXP_TYPE_LEG_END))
+                       continue;
+               /* Device not in D0 doesn't need check latency */
+               if (child_dev->current_state == PCI_D1 ||
+                       child_dev->current_state == PCI_D2 ||
+                       child_dev->current_state == PCI_D3hot ||
+                       child_dev->current_state == PCI_D3cold)
+                       continue;
+               state = __pcie_aspm_check_state_one(child_dev, state);
+       }
+       return state;
+}
+
+static void __pcie_aspm_config_one_dev(struct pci_dev *pdev, unsigned int state)
+{
+       u16 reg16;
+       int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+
+       pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+       reg16 &= ~0x3;
+       reg16 |= state;
+       pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+}
+
+static void __pcie_aspm_config_link(struct pci_dev *pdev, unsigned int state)
+{
+       struct pci_dev *child_dev;
+       int valid = 1;
+       struct pcie_link_state *link_state = pdev->link_state;
+
+       /*
+        * if the downstream component has pci bridge function, don't do ASPM
+        * now
+        */
+       list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+               if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
+                       valid = 0;
+                       break;
+               }
+       }
+       if (!valid)
+               return;
+
+       /*
+        * spec 2.0 suggests all functions should be configured the same
+        * setting for ASPM. Enabling ASPM L1 should be done in upstream
+        * component first and then downstream, and vice versa for disabling
+        * ASPM L1. Spec doesn't mention L0S.
+        */
+       if (state & PCIE_LINK_STATE_L1)
+               __pcie_aspm_config_one_dev(pdev, state);
+
+       list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list)
+               __pcie_aspm_config_one_dev(child_dev, state);
+
+       if (!(state & PCIE_LINK_STATE_L1))
+               __pcie_aspm_config_one_dev(pdev, state);
+
+       link_state->enabled_state = state;
+}
+
+static void __pcie_aspm_configure_link_state(struct pci_dev *pdev,
+       unsigned int state)
+{
+       struct pcie_link_state *link_state = pdev->link_state;
+
+       if (link_state->support_state == 0)
+               return;
+       state &= PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
+
+       /* state 0 means disabling aspm */
+       state = pcie_aspm_check_state(pdev, state);
+       if (link_state->enabled_state == state)
+               return;
+       __pcie_aspm_config_link(pdev, state);
+}
+
+/*
+ * pcie_aspm_configure_link_state: enable/disable PCI express link state
+ * @pdev: the root port or switch downstream port
+ */
+static void pcie_aspm_configure_link_state(struct pci_dev *pdev,
+       unsigned int state)
+{
+       down_read(&pci_bus_sem);
+       mutex_lock(&aspm_lock);
+       __pcie_aspm_configure_link_state(pdev, state);
+       mutex_unlock(&aspm_lock);
+       up_read(&pci_bus_sem);
+}
+
+static void free_link_state(struct pci_dev *pdev)
+{
+       kfree(pdev->link_state);
+       pdev->link_state = NULL;
+}
+
+/*
+ * pcie_aspm_init_link_state: Initiate PCI express link state.
+ * It is called after the pcie and its children devices are scaned.
+ * @pdev: the root port or switch downstream port
+ */
+void pcie_aspm_init_link_state(struct pci_dev *pdev)
+{
+       unsigned int state;
+       struct pcie_link_state *link_state;
+       int error = 0;
+
+       if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
+               return;
+       if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+               pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+               return;
+       down_read(&pci_bus_sem);
+       if (list_empty(&pdev->subordinate->devices))
+               goto out;
+
+       mutex_lock(&aspm_lock);
+
+       link_state = kzalloc(sizeof(*link_state), GFP_KERNEL);
+       if (!link_state)
+               goto unlock_out;
+       pdev->link_state = link_state;
+
+       pcie_aspm_configure_common_clock(pdev);
+
+       pcie_aspm_cap_init(pdev);
+
+       /* config link state to avoid BIOS error */
+       state = pcie_aspm_check_state(pdev, policy_to_aspm_state(pdev));
+       __pcie_aspm_config_link(pdev, state);
+
+       pcie_check_clock_pm(pdev);
+
+       link_state->pdev = pdev;
+       list_add(&link_state->sibiling, &link_list);
+
+unlock_out:
+       if (error)
+               free_link_state(pdev);
+       mutex_unlock(&aspm_lock);
+out:
+       up_read(&pci_bus_sem);
+}
+
+/* @pdev: the endpoint device */
+void pcie_aspm_exit_link_state(struct pci_dev *pdev)
+{
+       struct pci_dev *parent = pdev->bus->self;
+       struct pcie_link_state *link_state = parent->link_state;
+
+       if (aspm_disabled || !pdev->is_pcie || !parent || !link_state)
+               return;
+       if (parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+               parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+               return;
+       down_read(&pci_bus_sem);
+       mutex_lock(&aspm_lock);
+
+       /*
+        * All PCIe functions are in one slot, remove one function will remove
+        * the the whole slot, so just wait
+        */
+       if (!list_empty(&parent->subordinate->devices))
+               goto out;
+
+       /* All functions are removed, so just disable ASPM for the link */
+       __pcie_aspm_config_one_dev(parent, 0);
+       list_del(&link_state->sibiling);
+       /* Clock PM is for endpoint device */
+
+       free_link_state(parent);
+out:
+       mutex_unlock(&aspm_lock);
+       up_read(&pci_bus_sem);
+}
+
+/* @pdev: the root port or switch downstream port */
+void pcie_aspm_pm_state_change(struct pci_dev *pdev)
+{
+       struct pcie_link_state *link_state = pdev->link_state;
+
+       if (aspm_disabled || !pdev->is_pcie || !pdev->link_state)
+               return;
+       if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+               pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+               return;
+       /*
+        * devices changed PM state, we should recheck if latency meets all
+        * functions' requirement
+        */
+       pcie_aspm_configure_link_state(pdev, link_state->enabled_state);
+}
+
+/*
+ * pci_disable_link_state - disable pci device's link state, so the link will
+ * never enter specific states
+ */
+void pci_disable_link_state(struct pci_dev *pdev, int state)
+{
+       struct pci_dev *parent = pdev->bus->self;
+       struct pcie_link_state *link_state;
+
+       if (aspm_disabled || !pdev->is_pcie)
+               return;
+       if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
+           pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
+               parent = pdev;
+       if (!parent)
+               return;
+
+       down_read(&pci_bus_sem);
+       mutex_lock(&aspm_lock);
+       link_state = parent->link_state;
+       link_state->support_state &=
+               ~(state & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1));
+       if (state & PCIE_LINK_STATE_CLKPM)
+               link_state->clk_pm_capable = 0;
+
+       __pcie_aspm_configure_link_state(parent, link_state->enabled_state);
+       if (!link_state->clk_pm_capable && link_state->clk_pm_enabled)
+               pcie_set_clock_pm(parent, 0);
+       mutex_unlock(&aspm_lock);
+       up_read(&pci_bus_sem);
+}
+EXPORT_SYMBOL(pci_disable_link_state);
+
+static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
+{
+       int i;
+       struct pci_dev *pdev;
+       struct pcie_link_state *link_state;
+
+       for (i = 0; i < ARRAY_SIZE(policy_str); i++)
+               if (!strncmp(val, policy_str[i], strlen(policy_str[i])))
+                       break;
+       if (i >= ARRAY_SIZE(policy_str))
+               return -EINVAL;
+       if (i == aspm_policy)
+               return 0;
+
+       down_read(&pci_bus_sem);
+       mutex_lock(&aspm_lock);
+       aspm_policy = i;
+       list_for_each_entry(link_state, &link_list, sibiling) {
+               pdev = link_state->pdev;
+               __pcie_aspm_configure_link_state(pdev,
+                       policy_to_aspm_state(pdev));
+               if (link_state->clk_pm_capable &&
+                   link_state->clk_pm_enabled != policy_to_clkpm_state(pdev))
+                       pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
+
+       }
+       mutex_unlock(&aspm_lock);
+       up_read(&pci_bus_sem);
+       return 0;
+}
+
+static int pcie_aspm_get_policy(char *buffer, struct kernel_param *kp)
+{
+       int i, cnt = 0;
+       for (i = 0; i < ARRAY_SIZE(policy_str); i++)
+               if (i == aspm_policy)
+                       cnt += sprintf(buffer + cnt, "[%s] ", policy_str[i]);
+               else
+                       cnt += sprintf(buffer + cnt, "%s ", policy_str[i]);
+       return cnt;
+}
+
+module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
+       NULL, 0644);
+
+#ifdef CONFIG_PCIEASPM_DEBUG
+static ssize_t link_state_show(struct device *dev,
+               struct device_attribute *attr,
+               char *buf)
+{
+       struct pci_dev *pci_device = to_pci_dev(dev);
+       struct pcie_link_state *link_state = pci_device->link_state;
+
+       return sprintf(buf, "%d\n", link_state->enabled_state);
+}
+
+static ssize_t link_state_store(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf,
+               size_t n)
+{
+       struct pci_dev *pci_device = to_pci_dev(dev);
+       int state;
+
+       if (n < 1)
+               return -EINVAL;
+       state = buf[0]-'0';
+       if (state >= 0 && state <= 3) {
+               /* setup link aspm state */
+               pcie_aspm_configure_link_state(pci_device, state);
+               return n;
+       }
+
+       return -EINVAL;
+}
+
+static ssize_t clk_ctl_show(struct device *dev,
+               struct device_attribute *attr,
+               char *buf)
+{
+       struct pci_dev *pci_device = to_pci_dev(dev);
+       struct pcie_link_state *link_state = pci_device->link_state;
+
+       return sprintf(buf, "%d\n", link_state->clk_pm_enabled);
+}
+
+static ssize_t clk_ctl_store(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf,
+               size_t n)
+{
+       struct pci_dev *pci_device = to_pci_dev(dev);
+       int state;
+
+       if (n < 1)
+               return -EINVAL;
+       state = buf[0]-'0';
+
+       down_read(&pci_bus_sem);
+       mutex_lock(&aspm_lock);
+       pcie_set_clock_pm(pci_device, !!state);
+       mutex_unlock(&aspm_lock);
+       up_read(&pci_bus_sem);
+
+       return n;
+}
+
+static DEVICE_ATTR(link_state, 0644, link_state_show, link_state_store);
+static DEVICE_ATTR(clk_ctl, 0644, clk_ctl_show, clk_ctl_store);
+
+static char power_group[] = "power";
+void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
+{
+       struct pcie_link_state *link_state = pdev->link_state;
+
+       if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+               pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
+               return;
+
+       if (link_state->support_state)
+               sysfs_add_file_to_group(&pdev->dev.kobj,
+                       &dev_attr_link_state.attr, power_group);
+       if (link_state->clk_pm_capable)
+               sysfs_add_file_to_group(&pdev->dev.kobj,
+                       &dev_attr_clk_ctl.attr, power_group);
+}
+
+void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
+{
+       struct pcie_link_state *link_state = pdev->link_state;
+
+       if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+               pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
+               return;
+
+       if (link_state->support_state)
+               sysfs_remove_file_from_group(&pdev->dev.kobj,
+                       &dev_attr_link_state.attr, power_group);
+       if (link_state->clk_pm_capable)
+               sysfs_remove_file_from_group(&pdev->dev.kobj,
+                       &dev_attr_clk_ctl.attr, power_group);
+}
+#endif
+
+static int __init pcie_aspm_disable(char *str)
+{
+       aspm_disabled = 1;
+       return 1;
+}
+
+__setup("pcie_noaspm", pcie_aspm_disable);
+
+static int __init pcie_aspm_init(void)
+{
+       if (aspm_disabled)
+               return 0;
+       pci_osc_support_set(OSC_ACTIVE_STATE_PWR_SUPPORT|
+               OSC_CLOCK_PWR_CAPABILITY_SUPPORT);
+       return 0;
+}
+
+fs_initcall(pcie_aspm_init);
index b20a9b81dae2df5e9cca491b4c1504def575858c..23d9eb073296dea5e974141c008ee2154b9b6257 100644 (file)
@@ -192,9 +192,8 @@ static int get_port_device_capability(struct pci_dev *dev)
                if (reg32 & SLOT_HP_CAPABLE_MASK)
                        services |= PCIE_PORT_SERVICE_HP;
        } 
-       /* PME Capable */
-       pos = pci_find_capability(dev, PCI_CAP_ID_PME);
-       if (pos) 
+       /* PME Capable - root port capability */
+       if (((reg16 >> 4) & PORT_TYPE_MASK) == PCIE_RC_PORT)
                services |= PCIE_PORT_SERVICE_PME;
        
        pos = PCI_CFG_SPACE_SIZE;
index 5fd585293e7954c777094b6331e5a5fae9c094ca..8b505bd925aa31895df3eafd4c47cb40b5d24bc3 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/cpumask.h>
+#include <linux/aspm.h>
 #include "pci.h"
 
 #define CARDBUS_LATENCY_TIMER  176     /* secondary latency timer */
@@ -53,7 +54,7 @@ static void pci_create_legacy_files(struct pci_bus *b)
                b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
                b->legacy_io->read = pci_read_legacy_io;
                b->legacy_io->write = pci_write_legacy_io;
-               class_device_create_bin_file(&b->class_dev, b->legacy_io);
+               device_create_bin_file(&b->dev, b->legacy_io);
 
                /* Allocated above after the legacy_io struct */
                b->legacy_mem = b->legacy_io + 1;
@@ -61,15 +62,15 @@ static void pci_create_legacy_files(struct pci_bus *b)
                b->legacy_mem->size = 1024*1024;
                b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
                b->legacy_mem->mmap = pci_mmap_legacy_mem;
-               class_device_create_bin_file(&b->class_dev, b->legacy_mem);
+               device_create_bin_file(&b->dev, b->legacy_mem);
        }
 }
 
 void pci_remove_legacy_files(struct pci_bus *b)
 {
        if (b->legacy_io) {
-               class_device_remove_bin_file(&b->class_dev, b->legacy_io);
-               class_device_remove_bin_file(&b->class_dev, b->legacy_mem);
+               device_remove_bin_file(&b->dev, b->legacy_io);
+               device_remove_bin_file(&b->dev, b->legacy_mem);
                kfree(b->legacy_io); /* both are allocated here */
        }
 }
@@ -81,26 +82,27 @@ void pci_remove_legacy_files(struct pci_bus *bus) { return; }
 /*
  * PCI Bus Class Devices
  */
-static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev,
+static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
+                                       struct device_attribute *attr,
                                        char *buf)
 {
        int ret;
        cpumask_t cpumask;
 
-       cpumask = pcibus_to_cpumask(to_pci_bus(class_dev));
+       cpumask = pcibus_to_cpumask(to_pci_bus(dev));
        ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask);
        if (ret < PAGE_SIZE)
                buf[ret++] = '\n';
        return ret;
 }
-CLASS_DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
+DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
 
 /*
  * PCI Bus Class
  */
-static void release_pcibus_dev(struct class_device *class_dev)
+static void release_pcibus_dev(struct device *dev)
 {
-       struct pci_bus *pci_bus = to_pci_bus(class_dev);
+       struct pci_bus *pci_bus = to_pci_bus(dev);
 
        if (pci_bus->bridge)
                put_device(pci_bus->bridge);
@@ -109,7 +111,7 @@ static void release_pcibus_dev(struct class_device *class_dev)
 
 static struct class pcibus_class = {
        .name           = "pci_bus",
-       .release        = &release_pcibus_dev,
+       .dev_release    = &release_pcibus_dev,
 };
 
 static int __init pcibus_class_init(void)
@@ -392,7 +394,6 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
 {
        struct pci_bus *child;
        int i;
-       int retval;
 
        /*
         * Allocate a new bus, and inherit stuff from the parent..
@@ -408,15 +409,12 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
        child->bus_flags = parent->bus_flags;
        child->bridge = get_device(&bridge->dev);
 
-       child->class_dev.class = &pcibus_class;
-       sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr);
-       retval = class_device_register(&child->class_dev);
-       if (retval)
-               goto error_register;
-       retval = class_device_create_file(&child->class_dev,
-                                         &class_device_attr_cpuaffinity);
-       if (retval)
-               goto error_file_create;
+       /* initialize some portions of the bus device, but don't register it
+        * now as the parent is not properly set up yet.  This device will get
+        * registered later in pci_bus_add_devices()
+        */
+       child->dev.class = &pcibus_class;
+       sprintf(child->dev.bus_id, "%04x:%02x", pci_domain_nr(child), busnr);
 
        /*
         * Set up the primary, secondary and subordinate
@@ -434,12 +432,6 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
        bridge->subordinate = child;
 
        return child;
-
-error_file_create:
-       class_device_unregister(&child->class_dev);
-error_register:
-       kfree(child);
-       return NULL;
 }
 
 struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
@@ -471,8 +463,6 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
        }
 }
 
-unsigned int pci_scan_child_bus(struct pci_bus *bus);
-
 /*
  * If it's a bridge, configure it and scan the bus behind it.
  * For CardBus bridges, we don't scan behind as the devices will
@@ -641,13 +631,13 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
                    (child->number > bus->subordinate) ||
                    (child->number < bus->number) ||
                    (child->subordinate < bus->number)) {
-                       pr_debug("PCI: Bus #%02x (-#%02x) is %s"
+                       pr_debug("PCI: Bus #%02x (-#%02x) is %s "
                                "hidden behind%s bridge #%02x (-#%02x)\n",
                                child->number, child->subordinate,
                                (bus->number > child->subordinate &&
                                 bus->subordinate < child->number) ?
-                                       "wholly " : " partially",
-                               bus->self->transparent ? " transparent" : " ",
+                                       "wholly" : "partially",
+                               bus->self->transparent ? " transparent" : "",
                                bus->number, bus->subordinate);
                }
                bus = bus->parent;
@@ -971,6 +961,7 @@ struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)
 
        return dev;
 }
+EXPORT_SYMBOL(pci_scan_single_device);
 
 /**
  * pci_scan_slot - scan a PCI slot on a bus for devices.
@@ -1011,6 +1002,10 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
                                break;
                }
        }
+
+       if (bus->self)
+               pcie_aspm_init_link_state(bus->self);
+
        return nr;
 }
 
@@ -1103,32 +1098,27 @@ struct pci_bus * pci_create_bus(struct device *parent,
                goto dev_reg_err;
        b->bridge = get_device(dev);
 
-       b->class_dev.class = &pcibus_class;
-       sprintf(b->class_dev.class_id, "%04x:%02x", pci_domain_nr(b), bus);
-       error = class_device_register(&b->class_dev);
+       b->dev.class = &pcibus_class;
+       b->dev.parent = b->bridge;
+       sprintf(b->dev.bus_id, "%04x:%02x", pci_domain_nr(b), bus);
+       error = device_register(&b->dev);
        if (error)
                goto class_dev_reg_err;
-       error = class_device_create_file(&b->class_dev, &class_device_attr_cpuaffinity);
+       error = device_create_file(&b->dev, &dev_attr_cpuaffinity);
        if (error)
-               goto class_dev_create_file_err;
+               goto dev_create_file_err;
 
        /* Create legacy_io and legacy_mem files for this bus */
        pci_create_legacy_files(b);
 
-       error = sysfs_create_link(&b->class_dev.kobj, &b->bridge->kobj, "bridge");
-       if (error)
-               goto sys_create_link_err;
-
        b->number = b->secondary = bus;
        b->resource[0] = &ioport_resource;
        b->resource[1] = &iomem_resource;
 
        return b;
 
-sys_create_link_err:
-       class_device_remove_file(&b->class_dev, &class_device_attr_cpuaffinity);
-class_dev_create_file_err:
-       class_device_unregister(&b->class_dev);
+dev_create_file_err:
+       device_unregister(&b->dev);
 class_dev_reg_err:
        device_unregister(dev);
 dev_reg_err:
@@ -1140,7 +1130,6 @@ err_out:
        kfree(b);
        return NULL;
 }
-EXPORT_SYMBOL_GPL(pci_create_bus);
 
 struct pci_bus *pci_scan_bus_parented(struct device *parent,
                int bus, struct pci_ops *ops, void *sysdata)
@@ -1159,7 +1148,6 @@ EXPORT_SYMBOL(pci_add_new_bus);
 EXPORT_SYMBOL(pci_do_scan_bus);
 EXPORT_SYMBOL(pci_scan_slot);
 EXPORT_SYMBOL(pci_scan_bridge);
-EXPORT_SYMBOL(pci_scan_single_device);
 EXPORT_SYMBOL_GPL(pci_scan_child_bus);
 #endif
 
index 716439e25dd283fcf4ecce43c9966bd33d044a27..68aeeb7206de61bfefb9d0b6e2ac8250da933a62 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/smp_lock.h>
 #include <linux/capability.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
@@ -202,15 +203,18 @@ struct pci_filp_private {
        int write_combine;
 };
 
-static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
+                              unsigned long arg)
 {
-       const struct proc_dir_entry *dp = PDE(inode);
+       const struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
        struct pci_dev *dev = dp->data;
 #ifdef HAVE_PCI_MMAP
        struct pci_filp_private *fpriv = file->private_data;
 #endif /* HAVE_PCI_MMAP */
        int ret = 0;
 
+       lock_kernel();
+
        switch (cmd) {
        case PCIIOC_CONTROLLER:
                ret = pci_domain_nr(dev->bus);
@@ -239,6 +243,7 @@ static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned i
                break;
        };
 
+       unlock_kernel();
        return ret;
 }
 
@@ -291,7 +296,7 @@ static const struct file_operations proc_bus_pci_operations = {
        .llseek         = proc_bus_pci_lseek,
        .read           = proc_bus_pci_read,
        .write          = proc_bus_pci_write,
-       .ioctl          = proc_bus_pci_ioctl,
+       .unlocked_ioctl = proc_bus_pci_ioctl,
 #ifdef HAVE_PCI_MMAP
        .open           = proc_bus_pci_open,
        .release        = proc_bus_pci_release,
@@ -370,7 +375,7 @@ static int show_device(struct seq_file *m, void *v)
        return 0;
 }
 
-static struct seq_operations proc_bus_pci_devices_op = {
+static const struct seq_operations proc_bus_pci_devices_op = {
        .start  = pci_seq_start,
        .next   = pci_seq_next,
        .stop   = pci_seq_stop,
@@ -480,7 +485,3 @@ static int __init pci_proc_init(void)
 
 __initcall(pci_proc_init);
 
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(pci_proc_detach_bus);
-#endif
-
index 72e0bd5d80aced43ef522ff52efdeebd65b86aa6..0a953d43b9a207961a6d41dbb1872d105f978982 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/acpi.h>
+#include <linux/kallsyms.h>
 #include "pci.h"
 
 /* The Mellanox Tavor device gives false positive parity errors
@@ -46,14 +47,14 @@ static void quirk_passive_release(struct pci_dev *dev)
        while ((d = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d))) {
                pci_read_config_byte(d, 0x82, &dlc);
                if (!(dlc & 1<<1)) {
-                       printk(KERN_ERR "PCI: PIIX3: Enabling Passive Release on %s\n", pci_name(d));
+                       dev_err(&d->dev, "PIIX3: Enabling Passive Release\n");
                        dlc |= 1<<1;
                        pci_write_config_byte(d, 0x82, dlc);
                }
        }
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82441,      quirk_passive_release );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_82441,      quirk_passive_release );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82441,      quirk_passive_release);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_82441,      quirk_passive_release);
 
 /*  The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround
     but VIA don't answer queries. If you happen to have good contacts at VIA
@@ -68,20 +69,20 @@ static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
 {
        if (!isa_dma_bridge_buggy) {
                isa_dma_bridge_buggy=1;
-               printk(KERN_INFO "Activating ISA DMA hang workarounds.\n");
+               dev_info(&dev->dev, "Activating ISA DMA hang workarounds\n");
        }
 }
        /*
         * Its not totally clear which chipsets are the problematic ones
         * We know 82C586 and 82C596 variants are affected.
         */
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C586_0,     quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C596,       quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82371SB_0,  quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL,      PCI_DEVICE_ID_AL_M1533,         quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,     PCI_DEVICE_ID_NEC_CBUS_1,       quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,     PCI_DEVICE_ID_NEC_CBUS_2,       quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,     PCI_DEVICE_ID_NEC_CBUS_3,       quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C586_0,     quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C596,       quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82371SB_0,  quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL,      PCI_DEVICE_ID_AL_M1533,         quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,     PCI_DEVICE_ID_NEC_CBUS_1,       quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,     PCI_DEVICE_ID_NEC_CBUS_2,       quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,     PCI_DEVICE_ID_NEC_CBUS_3,       quirk_isa_dma_hangs);
 
 int pci_pci_problems;
 EXPORT_SYMBOL(pci_pci_problems);
@@ -92,12 +93,12 @@ EXPORT_SYMBOL(pci_pci_problems);
 static void __devinit quirk_nopcipci(struct pci_dev *dev)
 {
        if ((pci_pci_problems & PCIPCI_FAIL)==0) {
-               printk(KERN_INFO "Disabling direct PCI/PCI transfers.\n");
+               dev_info(&dev->dev, "Disabling direct PCI/PCI transfers\n");
                pci_pci_problems |= PCIPCI_FAIL;
        }
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,      PCI_DEVICE_ID_SI_5597,          quirk_nopcipci );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,      PCI_DEVICE_ID_SI_496,           quirk_nopcipci );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,      PCI_DEVICE_ID_SI_5597,          quirk_nopcipci);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,      PCI_DEVICE_ID_SI_496,           quirk_nopcipci);
 
 static void __devinit quirk_nopciamd(struct pci_dev *dev)
 {
@@ -105,11 +106,11 @@ static void __devinit quirk_nopciamd(struct pci_dev *dev)
        pci_read_config_byte(dev, 0x08, &rev);
        if (rev == 0x13) {
                /* Erratum 24 */
-               printk(KERN_INFO "Chipset erratum: Disabling direct PCI/AGP transfers.\n");
+               dev_info(&dev->dev, "Chipset erratum: Disabling direct PCI/AGP transfers\n");
                pci_pci_problems |= PCIAGP_FAIL;
        }
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_8151_0,       quirk_nopciamd );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_8151_0,       quirk_nopciamd);
 
 /*
  *     Triton requires workarounds to be used by the drivers
@@ -117,14 +118,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,        PCI_DEVICE_ID_AMD_8151_0,       quirk_nopci
 static void __devinit quirk_triton(struct pci_dev *dev)
 {
        if ((pci_pci_problems&PCIPCI_TRITON)==0) {
-               printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+               dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
                pci_pci_problems |= PCIPCI_TRITON;
        }
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82437,      quirk_triton ); 
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82437VX,    quirk_triton ); 
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82439,      quirk_triton ); 
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82439TX,    quirk_triton ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82437,      quirk_triton);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82437VX,    quirk_triton);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82439,      quirk_triton);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82439TX,    quirk_triton);
 
 /*
  *     VIA Apollo KT133 needs PCI latency patch
@@ -139,25 +140,22 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,      PCI_DEVICE_ID_INTEL_82439TX,    quir
 static void quirk_vialatency(struct pci_dev *dev)
 {
        struct pci_dev *p;
-       u8 rev;
        u8 busarb;
        /* Ok we have a potential problem chipset here. Now see if we have
           a buggy southbridge */
           
        p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL);
        if (p!=NULL) {
-               pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
                /* 0x40 - 0x4f == 686B, 0x10 - 0x2f == 686A; thanks Dan Hollis */
                /* Check for buggy part revisions */
-               if (rev < 0x40 || rev > 0x42)
+               if (p->revision < 0x40 || p->revision > 0x42)
                        goto exit;
        } else {
                p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL);
                if (p==NULL)    /* No problem parts */
                        goto exit;
-               pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
                /* Check for buggy part revisions */
-               if (rev < 0x10 || rev > 0x12) 
+               if (