[ACPI] merge acpi-2.6.12 branch into latest Linux 2.6.13-rc...
authorLen Brown <len.brown@intel.com>
Tue, 12 Jul 2005 21:21:56 +0000 (17:21 -0400)
committerLen Brown <len.brown@intel.com>
Tue, 12 Jul 2005 21:21:56 +0000 (17:21 -0400)
Signed-off-by: Len Brown <len.brown@intel.com>
31 files changed:
1  2 
arch/i386/pci/irq.c
arch/ia64/kernel/acpi.c
arch/ia64/kernel/process.c
arch/ia64/kernel/setup.c
drivers/acpi/Kconfig
drivers/acpi/processor_core.c
drivers/acpi/processor_idle.c
drivers/acpi/scan.c
drivers/base/sys.c
drivers/net/b44.c
drivers/pci/pci.c
drivers/pcmcia/yenta_socket.c
include/acpi/acpi_bus.h
include/acpi/acpi_drivers.h
include/asm-alpha/pci.h
include/asm-arm/pci.h
include/asm-i386/apicdef.h
include/asm-i386/pci.h
include/asm-ia64/pci.h
include/asm-mips/pci.h
include/asm-ppc/pci.h
include/asm-ppc64/pci.h
include/asm-sh/pci.h
include/asm-sh64/pci.h
include/asm-sparc/pci.h
include/asm-sparc64/pci.h
include/asm-x86_64/pci.h
include/linux/acpi.h
include/linux/device.h
include/linux/pm.h
kernel/power/main.c

diff --combined arch/i386/pci/irq.c
@@@ -57,35 -57,6 +57,35 @@@ struct irq_router_handler 
  
  int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
  
 +/*
 + *  Check passed address for the PCI IRQ Routing Table signature
 + *  and perform checksum verification.
 + */
 +
 +static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
 +{
 +      struct irq_routing_table *rt;
 +      int i;
 +      u8 sum;
 +
 +      rt = (struct irq_routing_table *) addr;
 +      if (rt->signature != PIRQ_SIGNATURE ||
 +          rt->version != PIRQ_VERSION ||
 +          rt->size % 16 ||
 +          rt->size < sizeof(struct irq_routing_table))
 +              return NULL;
 +      sum = 0;
 +      for (i=0; i < rt->size; i++)
 +              sum += addr[i];
 +      if (!sum) {
 +              DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
 +              return rt;
 +      }
 +      return NULL;
 +}
 +
 +
 +
  /*
   *  Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
   */
@@@ -94,17 -65,23 +94,17 @@@ static struct irq_routing_table * __ini
  {
        u8 *addr;
        struct irq_routing_table *rt;
 -      int i;
 -      u8 sum;
  
 +      if (pirq_table_addr) {
 +              rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
 +              if (rt)
 +                      return rt;
 +              printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n");
 +      }
        for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
 -              rt = (struct irq_routing_table *) addr;
 -              if (rt->signature != PIRQ_SIGNATURE ||
 -                  rt->version != PIRQ_VERSION ||
 -                  rt->size % 16 ||
 -                  rt->size < sizeof(struct irq_routing_table))
 -                      continue;
 -              sum = 0;
 -              for(i=0; i<rt->size; i++)
 -                      sum += addr[i];
 -              if (!sum) {
 -                      DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
 +              rt = pirq_check_routing_table(addr);
 +              if (rt)
                        return rt;
 -              }
        }
        return NULL;
  }
@@@ -249,24 -226,6 +249,24 @@@ static int pirq_via_set(struct pci_dev 
        return 1;
  }
  
 +/*
 + * The VIA pirq rules are nibble-based, like ALI,
 + * but without the ugly irq number munging.
 + * However, for 82C586, nibble map is different .
 + */
 +static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
 +{
 +      static unsigned int pirqmap[4] = { 3, 2, 5, 1 };
 +      return read_config_nybble(router, 0x55, pirqmap[pirq-1]);
 +}
 +
 +static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
 +{
 +      static unsigned int pirqmap[4] = { 3, 2, 5, 1 };
 +      write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
 +      return 1;
 +}
 +
  /*
   * ITE 8330G pirq rules are nibble-based
   * FIXME: pirqmap may be { 1, 0, 3, 2 },
@@@ -553,10 -512,6 +553,10 @@@ static __init int via_router_probe(stru
        switch(device)
        {
                case PCI_DEVICE_ID_VIA_82C586_0:
 +                      r->name = "VIA";
 +                      r->get = pirq_via586_get;
 +                      r->set = pirq_via586_set;
 +                      return 1;
                case PCI_DEVICE_ID_VIA_82C596:
                case PCI_DEVICE_ID_VIA_82C686:
                case PCI_DEVICE_ID_VIA_8231:
@@@ -1051,24 -1006,28 +1051,28 @@@ static int __init pcibios_irq_init(void
  subsys_initcall(pcibios_irq_init);
  
  
- static void pirq_penalize_isa_irq(int irq)
+ static void pirq_penalize_isa_irq(int irq, int active)
  {
        /*
         *  If any ISAPnP device reports an IRQ in its list of possible
         *  IRQ's, we try to avoid assigning it to PCI devices.
         */
-       if (irq < 16)
-               pirq_penalty[irq] += 100;
+       if (irq < 16) {
+               if (active)
+                       pirq_penalty[irq] += 1000;
+               else
+                       pirq_penalty[irq] += 100;
+       }
  }
  
- void pcibios_penalize_isa_irq(int irq)
+ void pcibios_penalize_isa_irq(int irq, int active)
  {
  #ifdef CONFIG_ACPI_PCI
        if (!acpi_noirq)
-               acpi_penalize_isa_irq(irq);
+               acpi_penalize_isa_irq(irq, active);
        else
  #endif
-               pirq_penalize_isa_irq(irq);
+               pirq_penalize_isa_irq(irq, active);
  }
  
  static int pirq_enable_irq(struct pci_dev *dev)
diff --combined arch/ia64/kernel/acpi.c
@@@ -11,6 -11,7 +11,7 @@@
   *  Copyright (C) 2001 Jenna Hall <jenna.s.hall@intel.com>
   *  Copyright (C) 2001 Takayoshi Kochi <t-kochi@bq.jp.nec.com>
   *  Copyright (C) 2002 Erich Focht <efocht@ess.nec.de>
+  *  Copyright (C) 2004 Ashok Raj <ashok.raj@intel.com>
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   *
@@@ -67,6 -68,11 +68,11 @@@ EXPORT_SYMBOL(pm_power_off)
  unsigned char acpi_kbd_controller_present = 1;
  unsigned char acpi_legacy_devices;
  
+ static unsigned int __initdata acpi_madt_rev;
+ unsigned int acpi_cpei_override;
+ unsigned int acpi_cpei_phys_cpuid;
  #define MAX_SAPICS 256
  u16 ia64_acpiid_to_sapicid[MAX_SAPICS] =
        { [0 ... MAX_SAPICS - 1] = -1 };
@@@ -236,7 -242,9 +242,7 @@@ acpi_parse_iosapic (acpi_table_entry_he
        if (BAD_MADT_ENTRY(iosapic, end))
                return -EINVAL;
  
 -      iosapic_init(iosapic->address, iosapic->global_irq_base);
 -
 -      return 0;
 +      return iosapic_init(iosapic->address, iosapic->global_irq_base);
  }
  
  
@@@ -265,10 -273,56 +271,56 @@@ acpi_parse_plat_int_src 
                                                (plintsrc->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
  
        platform_intr_list[plintsrc->type] = vector;
+       if (acpi_madt_rev > 1) {
+               acpi_cpei_override = plintsrc->plint_flags.cpei_override_flag;
+       }
+       /*
+        * Save the physical id, so we can check when its being removed
+        */
+       acpi_cpei_phys_cpuid = ((plintsrc->id << 8) | (plintsrc->eid)) & 0xffff;
        return 0;
  }
  
  
+ unsigned int can_cpei_retarget(void)
+ {
+       extern int cpe_vector;
+       /*
+        * Only if CPEI is supported and the override flag
+        * is present, otherwise return that its re-targettable
+        * if we are in polling mode.
+        */
+       if (cpe_vector > 0 && !acpi_cpei_override)
+               return 0;
+       else
+               return 1;
+ }
+ unsigned int is_cpu_cpei_target(unsigned int cpu)
+ {
+       unsigned int logical_id;
+       logical_id = cpu_logical_id(acpi_cpei_phys_cpuid);
+       if (logical_id == cpu)
+               return 1;
+       else
+               return 0;
+ }
+ void set_cpei_target_cpu(unsigned int cpu)
+ {
+       acpi_cpei_phys_cpuid = cpu_physical_id(cpu);
+ }
+ unsigned int get_cpei_target_cpu(void)
+ {
+       return acpi_cpei_phys_cpuid;
+ }
  static int __init
  acpi_parse_int_src_ovr (
        acpi_table_entry_header *header, const unsigned long end)
@@@ -326,6 -380,8 +378,8 @@@ acpi_parse_madt (unsigned long phys_add
  
        acpi_madt = (struct acpi_table_madt *) __va(phys_addr);
  
+       acpi_madt_rev = acpi_madt->header.revision;
        /* remember the value for reference after free_initmem() */
  #ifdef CONFIG_ITANIUM
        has_8259 = 1; /* Firmware on old Itanium systems is broken */
@@@ -640,10 -696,8 +694,10 @@@ acpi_boot_init (void
                        if (smp_boot_data.cpu_phys_id[cpu] != hard_smp_processor_id())
                                node_cpuid[i++].phys_id = smp_boot_data.cpu_phys_id[cpu];
        }
 -      build_cpu_to_node_map();
  # endif
 +#endif
 +#ifdef CONFIG_ACPI_NUMA
 +      build_cpu_to_node_map();
  #endif
        /* Make boot-up look pretty */
        printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, total_cpus);
@@@ -772,7 -826,7 +826,7 @@@ EXPORT_SYMBOL(acpi_unmap_lsapic)
   
  
  #ifdef CONFIG_ACPI_NUMA
 -acpi_status __init
 +acpi_status __devinit
  acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret)
  {
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
        return AE_OK;
  }
  #endif /* CONFIG_NUMA */
 +
 +int
 +acpi_register_ioapic (acpi_handle handle, u64 phys_addr, u32 gsi_base)
 +{
 +      int err;
 +
 +      if ((err = iosapic_init(phys_addr, gsi_base)))
 +              return err;
 +
 +#if CONFIG_ACPI_NUMA
 +      acpi_map_iosapic(handle, 0, NULL, NULL);
 +#endif /* CONFIG_ACPI_NUMA */
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL(acpi_register_ioapic);
 +
 +int
 +acpi_unregister_ioapic (acpi_handle handle, u32 gsi_base)
 +{
 +      return iosapic_remove(gsi_base);
 +}
 +EXPORT_SYMBOL(acpi_unregister_ioapic);
 +
  #endif /* CONFIG_ACPI_BOOT */
@@@ -27,7 -27,6 +27,7 @@@
  #include <linux/efi.h>
  #include <linux/interrupt.h>
  #include <linux/delay.h>
 +#include <linux/kprobes.h>
  
  #include <asm/cpu.h>
  #include <asm/delay.h>
@@@ -196,6 -195,7 +196,7 @@@ update_pal_halt_status(int status
  void
  default_idle (void)
  {
+       local_irq_enable();
        while (!need_resched())
                if (can_do_pal_halt)
                        safe_halt();
@@@ -708,13 -708,6 +709,13 @@@ kernel_thread_helper (int (*fn)(void *)
  void
  flush_thread (void)
  {
 +      /*
 +       * Remove function-return probe instances associated with this task
 +       * and put them back on the free list. Do not insert an exit probe for
 +       * this function, it will be disabled by kprobe_flush_task if you do.
 +       */
 +      kprobe_flush_task(current);
 +
        /* drop floating-point and debug-register state if it exists: */
        current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID);
        ia64_drop_fpu(current);
  void
  exit_thread (void)
  {
 +
 +      /*
 +       * Remove function-return probe instances associated with this task
 +       * and put them back on the free list. Do not insert an exit probe for
 +       * this function, it will be disabled by kprobe_flush_task if you do.
 +       */
 +      kprobe_flush_task(current);
 +
        ia64_drop_fpu(current);
  #ifdef CONFIG_PERFMON
         /* if needed, stop monitoring and flush state to perfmon context */
diff --combined arch/ia64/kernel/setup.c
@@@ -40,6 -40,8 +40,8 @@@
  #include <linux/serial_core.h>
  #include <linux/efi.h>
  #include <linux/initrd.h>
+ #include <linux/platform.h>
+ #include <linux/pm.h>
  
  #include <asm/ia32.h>
  #include <asm/machvec.h>
@@@ -72,8 -74,6 +74,8 @@@ DEFINE_PER_CPU(unsigned long, ia64_phys
  unsigned long ia64_cycles_per_usec;
  struct ia64_boot_param *ia64_boot_param;
  struct screen_info screen_info;
 +unsigned long vga_console_iobase;
 +unsigned long vga_console_membase;
  
  unsigned long ia64_max_cacheline_size;
  unsigned long ia64_iobase;    /* virtual address for I/O accesses */
@@@ -275,25 -275,23 +277,25 @@@ io_port_init (void
  static inline int __init
  early_console_setup (char *cmdline)
  {
 +      int earlycons = 0;
 +
  #ifdef CONFIG_SERIAL_SGI_L1_CONSOLE
        {
                extern int sn_serial_console_early_setup(void);
                if (!sn_serial_console_early_setup())
 -                      return 0;
 +                      earlycons++;
        }
  #endif
  #ifdef CONFIG_EFI_PCDP
        if (!efi_setup_pcdp_console(cmdline))
 -              return 0;
 +              earlycons++;
  #endif
  #ifdef CONFIG_SERIAL_8250_CONSOLE
        if (!early_serial_console_init(cmdline))
 -              return 0;
 +              earlycons++;
  #endif
  
 -      return -1;
 +      return (earlycons) ? 0 : -1;
  }
  
  static inline void
@@@ -783,6 -781,7 +785,7 @@@ cpu_init (void
        /* size of physical stacked register partition plus 8 bytes: */
        __get_cpu_var(ia64_phys_stacked_size_p8) = num_phys_stacked*8 + 8;
        platform_cpu_init();
+       pm_idle = default_idle;
  }
  
  void
diff --combined drivers/acpi/Kconfig
@@@ -3,6 -3,7 +3,7 @@@
  #
  
  menu "ACPI (Advanced Configuration and Power Interface) Support"
+       depends on PM
        depends on !X86_VISWS
        depends on !IA64_HP_SIM
        depends on IA64 || X86
@@@ -48,15 -49,14 +49,14 @@@ config ACPI_BOO
  
  config ACPI_INTERPRETER
        bool
-       depends on !IA64_SGI_SN
        default y
  
  if ACPI_INTERPRETER
  
  config ACPI_SLEEP
        bool "Sleep States (EXPERIMENTAL)"
 -      depends on X86
 -      depends on EXPERIMENTAL
 +      depends on X86 && (!SMP || SUSPEND_SMP)
 +      depends on EXPERIMENTAL && PM
        default y
        ---help---
          This option adds support for ACPI suspend states. 
@@@ -79,6 -79,14 +79,14 @@@ config ACPI_SLEEP_PROC_F
        depends on ACPI_SLEEP && PROC_FS
        default y
  
+ config ACPI_SLEEP_PROC_SLEEP
+       bool "/proc/acpi/sleep (deprecated)"
+       depends on ACPI_SLEEP_PROC_FS
+       default n
+       ---help---
+         Create /proc/acpi/sleep
+         Deprecated by /sys/power/state
  config ACPI_AC
        tristate "AC Adapter"
        depends on X86
@@@ -99,7 -107,6 +107,6 @@@ config ACPI_BATTER
  
  config ACPI_BUTTON
        tristate "Button"
-       depends on !IA64_SGI_SN
        default m
        help
          This driver registers for events based on buttons, such as the
  config ACPI_VIDEO
        tristate "Video"
        depends on EXPERIMENTAL
-       depends on !IA64_SGI_SN
        default m
        help
          This driver implement the ACPI Extensions For Display Adapters
          Note that this is an ref. implementation only.  It may or may not work
          for your integrated video device.
  
+ config ACPI_HOTKEY
+       tristate "Generic Hotkey"
+       depends on ACPI_INTERPRETER
+       depends on EXPERIMENTAL
+       depends on !IA64_SGI_SN
+       default m
+       help
+       ACPI generic hotkey
  config ACPI_FAN
        tristate "Fan"
-       depends on !IA64_SGI_SN
        default m
        help
          This driver adds support for ACPI fan devices, allowing user-mode 
  
  config ACPI_PROCESSOR
        tristate "Processor"
-       depends on !IA64_SGI_SN
        default m
        help
          This driver installs ACPI as the idle handler for Linux, and uses
  config ACPI_HOTPLUG_CPU
        bool "Processor Hotplug (EXPERIMENTAL)"
        depends on ACPI_PROCESSOR && HOTPLUG_CPU && EXPERIMENTAL
-       depends on !IA64_SGI_SN
        select ACPI_CONTAINER
        default n
         ---help---
@@@ -262,7 -274,6 +274,6 @@@ config ACPI_BLACKLIST_YEA
  
  config ACPI_DEBUG
        bool "Debug Statements"
-       depends on !IA64_SGI_SN
        default n
        help
          The ACPI driver can optionally report errors with a great deal
  
  config ACPI_BUS
        bool
-       depends on !IA64_SGI_SN
        default y
  
  config ACPI_EC
  
  config ACPI_POWER
        bool
-       depends on !IA64_SGI_SN
        default y
  
  config ACPI_PCI
        bool
-       depends on !IA64_SGI_SN
        default PCI
  
  config ACPI_SYSTEM
        bool
-       depends on !IA64_SGI_SN
        default y
        help
          This driver will enable your system to shut down using ACPI, and
@@@ -327,8 -334,13 +334,13 @@@ config ACPI_CONTAINE
        depends on EXPERIMENTAL
        default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
         ---help---
-               This is the ACPI generic container driver which supports
-               ACPI0004, PNP0A05 and PNP0A06 devices
+         This allows _physical_ insertion and removal of CPUs and memory.
+         This can be useful, for example, on NUMA machines that support
+         ACPI based physical hotplug of nodes, or non-NUMA machines that
+         support physical cpu/memory hot-plug.
+         If one selects "m", this driver can be loaded with
+         "modprobe acpi_container".
  
  config ACPI_HOTPLUG_MEMORY
        tristate "Memory Hotplug"
@@@ -255,6 -255,43 +255,43 @@@ acpi_processor_errata 
  }
  
  
+ /* --------------------------------------------------------------------------
+                               Common ACPI processor fucntions
+    -------------------------------------------------------------------------- */
+ /*
+  * _PDC is required for a BIOS-OS handshake for most of the newer
+  * ACPI processor features.
+  */
+ int acpi_processor_set_pdc(struct acpi_processor *pr,
+                               struct acpi_object_list *pdc_in)
+ {
+       acpi_status             status = AE_OK;
+       u32                     arg0_buf[3];
+       union acpi_object       arg0 = {ACPI_TYPE_BUFFER};
+       struct acpi_object_list no_object = {1, &arg0};
+       struct acpi_object_list *pdc;
+       ACPI_FUNCTION_TRACE("acpi_processor_set_pdc");
+       arg0.buffer.length = 12;
+       arg0.buffer.pointer = (u8 *) arg0_buf;
+       arg0_buf[0] = ACPI_PDC_REVISION_ID;
+       arg0_buf[1] = 0;
+       arg0_buf[2] = 0;
+       pdc = (pdc_in) ? pdc_in : &no_object;
+       status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL);
+       if ((ACPI_FAILURE(status)) && (pdc_in))
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating _PDC, using legacy perf. control...\n"));
+       return_VALUE(status);
+ }
  /* --------------------------------------------------------------------------
                                FS Interface (/proc)
     -------------------------------------------------------------------------- */
@@@ -723,7 -760,7 +760,7 @@@ int acpi_processor_device_add
                return_VALUE(-ENODEV);
        }
  
 -      acpi_bus_scan(*device);
 +      acpi_bus_start(*device);
  
        pr = acpi_driver_data(*device);
        if (!pr)
@@@ -6,6 -6,8 +6,8 @@@
   *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
   *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
   *                    - Added processor hotplug support
+  *  Copyright (C) 2005  Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+  *                    - Added support for C3 on SMP
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   *
@@@ -142,7 -144,7 +144,7 @@@ acpi_processor_power_activate 
                switch (old->type) {
                case ACPI_STATE_C3:
                        /* Disable bus master reload */
-                       if (new->type != ACPI_STATE_C3)
+                       if (new->type != ACPI_STATE_C3 && pr->flags.bm_check)
                                acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, ACPI_MTX_DO_NOT_LOCK);
                        break;
                }
        switch (new->type) {
        case ACPI_STATE_C3:
                /* Enable bus master reload */
-               if (old->type != ACPI_STATE_C3)
+               if (old->type != ACPI_STATE_C3 && pr->flags.bm_check)
                        acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1, ACPI_MTX_DO_NOT_LOCK);
                break;
        }
  }
  
  
+ static atomic_t       c3_cpu_count;
  static void acpi_processor_idle (void)
  {
        struct acpi_processor   *pr = NULL;
        int                     sleep_ticks = 0;
        u32                     t1, t2 = 0;
  
 -      pr = processors[_smp_processor_id()];
 +      pr = processors[raw_smp_processor_id()];
        if (!pr)
                return;
  
                break;
  
        case ACPI_STATE_C3:
-               /* Disable bus master arbitration */
-               acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
+               
+               if (pr->flags.bm_check) {
+                       if (atomic_inc_return(&c3_cpu_count) ==
+                                       num_online_cpus()) {
+                               /*
+                                * All CPUs are trying to go to C3
+                                * Disable bus master arbitration
+                                */
+                               acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
+                                       ACPI_MTX_DO_NOT_LOCK);
+                       }
+               } else {
+                       /* SMP with no shared cache... Invalidate cache  */
+                       ACPI_FLUSH_CPU_CACHE();
+               }
+               
                /* Get start time (ticks) */
                t1 = inl(acpi_fadt.xpm_tmr_blk.address);
                /* Invoke C3 */
                t2 = inl(acpi_fadt.xpm_tmr_blk.address);
                /* Get end time (ticks) */
                t2 = inl(acpi_fadt.xpm_tmr_blk.address);
-               /* Enable bus master arbitration */
-               acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_DO_NOT_LOCK);
+               if (pr->flags.bm_check) {
+                       /* Enable bus master arbitration */
+                       atomic_dec(&c3_cpu_count);
+                       acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_DO_NOT_LOCK);
+               }
                /* Re-enable interrupts */
                local_irq_enable();
                /* Compute time (ticks) that we were actually asleep */
@@@ -519,6 -542,29 +542,29 @@@ static int acpi_processor_get_power_inf
  }
  
  
+ static int acpi_processor_get_power_info_default_c1 (struct acpi_processor *pr)
+ {
+       int i;
+       ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1");
+       for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++)
+               memset(pr->power.states, 0, sizeof(struct acpi_processor_cx));
+       /* if info is obtained from pblk/fadt, type equals state */
+       pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
+       pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2;
+       pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3;
+       /* the C0 state only exists as a filler in our array,
+        * and all processors need to support C1 */
+       pr->power.states[ACPI_STATE_C0].valid = 1;
+       pr->power.states[ACPI_STATE_C1].valid = 1;
+       return_VALUE(0);
+ }
  static int acpi_processor_get_power_info_cst (struct acpi_processor *pr)
  {
        acpi_status             status = 0;
  
        ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_cst");
  
-       if (errata.smp)
-               return_VALUE(-ENODEV);
        if (nocst)
                return_VALUE(-ENODEV);
  
@@@ -664,13 -707,6 +707,6 @@@ static void acpi_processor_power_verify
                return_VOID;
        }
  
-       /* We're (currently) only supporting C2 on UP */
-       else if (errata.smp) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "C2 not supported in SMP mode\n"));
-               return_VOID;
-       }
        /*
         * Otherwise we've met all of our C2 requirements.
         * Normalize the C2 latency to expidite policy
@@@ -686,6 -722,8 +722,8 @@@ static void acpi_processor_power_verify
        struct acpi_processor *pr,
        struct acpi_processor_cx *cx)
  {
+       static int bm_check_flag;
        ACPI_FUNCTION_TRACE("acpi_processor_get_power_verify_c3");
  
        if (!cx->address)
                return_VOID;
        }
  
-       /* bus mastering control is necessary */
-       else if (!pr->flags.bm_control) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "C3 support requires bus mastering control\n"));
-               return_VOID;
-       }
-       /* We're (currently) only supporting C2 on UP */
-       else if (errata.smp) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "C3 not supported in SMP mode\n"));
-               return_VOID;
-       }
        /*
         * PIIX4 Erratum #18: We don't support C3 when Type-F (fast)
         * DMA transfers are used by any ISA device to avoid livelock.
                return_VOID;
        }
  
+       /* All the logic here assumes flags.bm_check is same across all CPUs */
+       if (!bm_check_flag) {
+               /* Determine whether bm_check is needed based on CPU  */
+               acpi_processor_power_init_bm_check(&(pr->flags), pr->id);
+               bm_check_flag = pr->flags.bm_check;
+       } else {
+               pr->flags.bm_check = bm_check_flag;
+       }
+       if (pr->flags.bm_check) {
+               printk("Disabling BM access before entering C3\n");
+               /* bus mastering control is necessary */
+               if (!pr->flags.bm_control) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                         "C3 support requires bus mastering control\n"));
+                       return_VOID;
+               }
+       } else {
+               printk("Invalidating cache before entering C3\n");
+               /*
+                * WBINVD should be set in fadt, for C3 state to be
+                * supported on when bm_check is not required.
+                */
+               if (acpi_fadt.wb_invd != 1) {
+                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                         "Cache invalidation should work properly"
+                         " for C3 to be enabled on SMP systems\n"));
+                       return_VOID;
+               }
+               acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD,
+                               0, ACPI_MTX_DO_NOT_LOCK);
+       }
        /*
         * Otherwise we've met all of our C3 requirements.
         * Normalize the C3 latency to expidite policy.  Enable
         */
        cx->valid = 1;
        cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
-       pr->flags.bm_check = 1;
  
        return_VOID;
  }
@@@ -787,10 -843,7 +843,7 @@@ static int acpi_processor_get_power_inf
        if ((result) || (acpi_processor_power_verify(pr) < 2)) {
                result = acpi_processor_get_power_info_fadt(pr);
                if (result)
-                       return_VALUE(result);
-               if (acpi_processor_power_verify(pr) < 2)
-                       return_VALUE(-ENODEV);
+                       result = acpi_processor_get_power_info_default_c1(pr);
        }
  
        /*
         * CPU as being "idle manageable"
         */
        for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
-               if (pr->power.states[i].valid)
+               if (pr->power.states[i].valid) {
                        pr->power.count = i;
-               if ((pr->power.states[i].valid) &&
-                   (pr->power.states[i].type >= ACPI_STATE_C2))
                        pr->flags.power = 1;
+               }
        }
  
        return_VALUE(0);
@@@ -829,7 -881,7 +881,7 @@@ int acpi_processor_cst_has_changed (str
        if (!pr)
                return_VALUE(-EINVAL);
  
-       if (errata.smp || nocst) {
+       if ( nocst) {
                return_VALUE(-ENODEV);
        }
  
@@@ -929,7 -981,6 +981,6 @@@ static struct file_operations acpi_proc
        .release        = single_release,
  };
  
  int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device)
  {
        acpi_status             status = 0;
                first_run++;
        }
  
-       if (!errata.smp && (pr->id == 0) && acpi_fadt.cst_cnt && !nocst) {
+       if (!pr)
+               return_VALUE(-EINVAL);
+       if (acpi_fadt.cst_cnt && !nocst) {
                status = acpi_os_write_port(acpi_fadt.smi_cmd, acpi_fadt.cst_cnt, 8);
                if (ACPI_FAILURE(status)) {
                        ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                }
        }
  
+       acpi_processor_power_init_pdc(&(pr->power), pr->id);
+       acpi_processor_set_pdc(pr, pr->power.pdc);
        acpi_processor_get_power_info(pr);
  
        /*
diff --combined drivers/acpi/scan.c
@@@ -65,14 -65,14 +65,14 @@@ static ssize_t acpi_device_attr_show(st
  {
        struct acpi_device *device = to_acpi_device(kobj);
        struct acpi_device_attribute *attribute = to_handle_attr(attr);
 -      return attribute->show ? attribute->show(device, buf) : 0;
 +      return attribute->show ? attribute->show(device, buf) : -EIO;
  }
  static ssize_t acpi_device_attr_store(struct kobject *kobj,
                struct attribute *attr, const char *buf, size_t len)
  {
        struct acpi_device *device = to_acpi_device(kobj);
        struct acpi_device_attribute *attribute = to_handle_attr(attr);
 -      return attribute->store ? attribute->store(device, buf, len) : len;
 +      return attribute->store ? attribute->store(device, buf, len) : -EIO;
  }
  
  static struct sysfs_ops acpi_device_sysfs_ops = {
@@@ -553,29 -553,20 +553,29 @@@ acpi_bus_driver_init 
         * upon possible configuration and currently allocated resources.
         */
  
 +      ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));
 +      return_VALUE(0);
 +}
 +
 +int
 +acpi_start_single_object (
 +              struct acpi_device *device)
 +{
 +      int result = 0;
 +      struct acpi_driver *driver;
 +
 +      ACPI_FUNCTION_TRACE("acpi_start_single_object");
 +
 +      if (!(driver = device->driver))
 +              return_VALUE(0);
 +
        if (driver->ops.start) {
                result = driver->ops.start(device);
                if (result && driver->ops.remove)
                        driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);
 -              return_VALUE(result);
        }
  
 -      ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));
 -
 -      if (driver->ops.scan) {
 -              driver->ops.scan(device);
 -      }
 -
 -      return_VALUE(0);
 +      return_VALUE(result);
  }
  
  static int acpi_driver_attach(struct acpi_driver * drv)
  
                if (!acpi_bus_match(dev, drv)) {
                        if (!acpi_bus_driver_init(dev, drv)) {
 +                              acpi_start_single_object(dev);
                                atomic_inc(&drv->references);
                                count++;
                                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
@@@ -1019,8 -1009,8 +1019,8 @@@ acpi_bus_remove 
  }
  
  
 -int
 -acpi_bus_add (
 +static int
 +acpi_add_single_object (
        struct acpi_device      **child,
        struct acpi_device      *parent,
        acpi_handle             handle,
        int                     result = 0;
        struct acpi_device      *device = NULL;
  
 -      ACPI_FUNCTION_TRACE("acpi_bus_add");
 +      ACPI_FUNCTION_TRACE("acpi_add_single_object");
  
        if (!child)
                return_VALUE(-EINVAL);
        /*
         * Status
         * ------
-        * See if the device is present.  We always assume that non-Device()
-        * objects (e.g. thermal zones, power resources, processors, etc.) are
-        * present, functioning, etc. (at least when parent object is present).
-        * Note that _STA has a different meaning for some objects (e.g.
-        * power resources) so we need to be careful how we use it.
+        * See if the device is present.  We always assume that non-Device
+        * and non-Processor objects (e.g. thermal zones, power resources,
+        * etc.) are present, functioning, etc. (at least when parent object
+        * is present).  Note that _STA has a different meaning for some
+        * objects (e.g. power resources) so we need to be careful how we use
+        * it.
         */
        switch (type) {
+       case ACPI_BUS_TYPE_PROCESSOR:
        case ACPI_BUS_TYPE_DEVICE:
                result = acpi_bus_get_status(device);
                if (ACPI_FAILURE(result) || !device->status.present) {
         *
         * TBD: Assumes LDM provides driver hot-plug capability.
         */
 -      acpi_bus_find_driver(device);
 +      result = acpi_bus_find_driver(device);
  
  end:
        if (!result)
  
        return_VALUE(result);
  }
 -EXPORT_SYMBOL(acpi_bus_add);
  
  
 -int acpi_bus_scan (struct acpi_device *start)
 +static int acpi_bus_scan (struct acpi_device  *start,
 +              struct acpi_bus_ops *ops)
  {
        acpi_status             status = AE_OK;
        struct acpi_device      *parent = NULL;
                        continue;
                }
  
 -              status = acpi_bus_add(&child, parent, chandle, type);
 -              if (ACPI_FAILURE(status))
 -                      continue;
 +              if (ops->acpi_op_add)
 +                      status = acpi_add_single_object(&child, parent,
 +                                      chandle, type);
 +               else
 +                      status = acpi_bus_get_device(chandle, &child);
 +
 +               if (ACPI_FAILURE(status))
 +                       continue;
 +
 +              if (ops->acpi_op_start) {
 +                      status = acpi_start_single_object(child);
 +                      if (ACPI_FAILURE(status))
 +                              continue;
 +              }
  
                /*
                 * If the device is present, enabled, and functioning then
  
        return_VALUE(0);
  }
 -EXPORT_SYMBOL(acpi_bus_scan);
  
 +int
 +acpi_bus_add (
 +      struct acpi_device      **child,
 +      struct acpi_device      *parent,
 +      acpi_handle             handle,
 +      int                     type)
 +{
 +      int result;
 +      struct acpi_bus_ops ops;
 +
 +      ACPI_FUNCTION_TRACE("acpi_bus_add");
 +
 +      result = acpi_add_single_object(child, parent, handle, type);
 +      if (!result) {
 +              memset(&ops, 0, sizeof(ops));
 +              ops.acpi_op_add = 1;
 +              result = acpi_bus_scan(*child, &ops);
 +      }
 +      return_VALUE(result);
 +}
 +EXPORT_SYMBOL(acpi_bus_add);
 +
 +int
 +acpi_bus_start (
 +      struct acpi_device *device)
 +{
 +      int result;
 +      struct acpi_bus_ops ops;
 +
 +      ACPI_FUNCTION_TRACE("acpi_bus_start");
 +
 +      if (!device)
 +              return_VALUE(-EINVAL);
 +
 +      result = acpi_start_single_object(device);
 +      if (!result) {
 +              memset(&ops, 0, sizeof(ops));
 +              ops.acpi_op_start = 1;
 +              result = acpi_bus_scan(device, &ops);
 +      }
 +      return_VALUE(result);
 +}
 +EXPORT_SYMBOL(acpi_bus_start);
  
  static int
  acpi_bus_trim(struct acpi_device      *start,
@@@ -1394,19 -1333,13 +1396,19 @@@ acpi_bus_scan_fixed 
        /*
         * Enumerate all fixed-feature devices.
         */
 -      if (acpi_fadt.pwr_button == 0)
 -              result = acpi_bus_add(&device, acpi_root, 
 +      if (acpi_fadt.pwr_button == 0) {
 +              result = acpi_add_single_object(&device, acpi_root,
                        NULL, ACPI_BUS_TYPE_POWER_BUTTON);
 +              if (!result)
 +                      result = acpi_start_single_object(device);
 +      }
  
 -      if (acpi_fadt.sleep_button == 0)
 -              result = acpi_bus_add(&device, acpi_root, 
 +      if (acpi_fadt.sleep_button == 0) {
 +              result = acpi_add_single_object(&device, acpi_root,
                        NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);
 +              if (!result)
 +                      result = acpi_start_single_object(device);
 +      }
  
        return_VALUE(result);
  }
  static int __init acpi_scan_init(void)
  {
        int result;
 +      struct acpi_bus_ops ops;
  
        ACPI_FUNCTION_TRACE("acpi_scan_init");
  
        /*
         * Create the root device in the bus's device tree
         */
 -      result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, 
 +      result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT,
                ACPI_BUS_TYPE_SYSTEM);
        if (result)
                goto Done;
  
 +      result = acpi_start_single_object(acpi_root);
 +
        /*
         * Enumerate devices in the ACPI namespace.
         */
        result = acpi_bus_scan_fixed(acpi_root);
 -      if (!result) 
 -              result = acpi_bus_scan(acpi_root);
 +      if (!result) {
 +              memset(&ops, 0, sizeof(ops));
 +              ops.acpi_op_add = 1;
 +              ops.acpi_op_start = 1;
 +              result = acpi_bus_scan(acpi_root, &ops);
 +      }
  
        if (result)
                acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
diff --combined drivers/base/sys.c
@@@ -22,7 -22,6 +22,6 @@@
  #include <linux/string.h>
  #include <linux/pm.h>
  
  extern struct subsystem devices_subsys;
  
  #define to_sysdev(k) container_of(k, struct sys_device, kobj)
@@@ -37,7 -36,7 +36,7 @@@ sysdev_show(struct kobject * kobj, stru
  
        if (sysdev_attr->show)
                return sysdev_attr->show(sysdev, buffer);
 -      return 0;
 +      return -EIO;
  }
  
  
@@@ -50,7 -49,7 +49,7 @@@ sysdev_store(struct kobject * kobj, str
  
        if (sysdev_attr->store)
                return sysdev_attr->store(sysdev, buffer, count);
 -      return 0;
 +      return -EIO;
  }
  
  static struct sysfs_ops sysfs_ops = {
diff --combined drivers/net/b44.c
@@@ -1285,9 -1285,6 +1285,9 @@@ static int b44_open(struct net_device *
        b44_init_hw(bp);
        bp->flags |= B44_FLAG_INIT_COMPLETE;
  
 +      netif_carrier_off(dev);
 +      b44_check_phy(bp);
 +
        spin_unlock_irq(&bp->lock);
  
        init_timer(&bp->timer);
@@@ -1930,6 -1927,7 +1930,7 @@@ static int b44_suspend(struct pci_dev *
        b44_free_rings(bp);
  
        spin_unlock_irq(&bp->lock);
+       pci_disable_device(pdev);
        return 0;
  }
  
@@@ -1939,6 -1937,8 +1940,8 @@@ static int b44_resume(struct pci_dev *p
        struct b44 *bp = netdev_priv(dev);
  
        pci_restore_state(pdev);
+       pci_enable_device(pdev);
+       pci_set_master(pdev);
  
        if (!netif_running(dev))
                return 0;
diff --combined drivers/pci/pci.c
@@@ -235,7 -235,7 +235,7 @@@ pci_find_parent_resource(const struct p
   * -EIO if device does not support PCI PM.
   * 0 if we can successfully change the power state.
   */
+ int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t t);
  int
  pci_set_power_state(struct pci_dev *dev, pci_power_t state)
  {
                msleep(10);
        else if (state == PCI_D2 || dev->current_state == PCI_D2)
                udelay(200);
-       dev->current_state = state;
  
+       /*
+        * Give firmware a chance to be called, such as ACPI _PRx, _PSx
+        * Firmware method after natice method ?
+        */
+       if (platform_pci_set_power_state)
+               platform_pci_set_power_state(dev, state);
+       dev->current_state = state;
        return 0;
  }
  
+ int (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
+  
  /**
   * pci_choose_state - Choose the power state of a PCI device
   * @dev: PCI device to be suspended
  
  pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
  {
+       int ret;
        if (!pci_find_capability(dev, PCI_CAP_ID_PM))
                return PCI_D0;
  
-       switch (state) {
+       if (platform_pci_choose_state) {
+               ret = platform_pci_choose_state(dev, state);
+               if (ret >= 0)
+                       state = ret;
+       }
+       switch (state) {
        case 0: return PCI_D0;
        case 3: return PCI_D3hot;
        default:
@@@ -334,6 -350,10 +350,6 @@@ EXPORT_SYMBOL(pci_choose_state)
  /**
   * pci_save_state - save the PCI configuration space of a device before suspending
   * @dev: - PCI device that we're dealing with
 - * @buffer: - buffer to hold config space context
 - *
 - * @buffer must be large enough to hold the entire PCI 2.2 config space 
 - * (>= 64 bytes).
   */
  int
  pci_save_state(struct pci_dev *dev)
  /** 
   * pci_restore_state - Restore the saved state of a PCI device
   * @dev: - PCI device that we're dealing with
 - * @buffer: - saved PCI config space
 - *
   */
  int 
  pci_restore_state(struct pci_dev *dev)
@@@ -18,6 -18,7 +18,6 @@@
  #include <linux/delay.h>
  #include <linux/module.h>
  
 -#include <pcmcia/version.h>
  #include <pcmcia/cs_types.h>
  #include <pcmcia/ss.h>
  #include <pcmcia/cs.h>
@@@ -31,14 -32,6 +31,14 @@@ static int disable_clkrun
  module_param(disable_clkrun, bool, 0444);
  MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option");
  
 +static int isa_probe = 1;
 +module_param(isa_probe, bool, 0444);
 +MODULE_PARM_DESC(isa_probe, "If set ISA interrupts are probed (default). Set to N to disable probing");
 +
 +static int pwr_irqs_off;
 +module_param(pwr_irqs_off, bool, 0644);
 +MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only when seeing IRQ storms!");
 +
  #if 0
  #define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args)
  #else
@@@ -157,16 -150,15 +157,16 @@@ static int yenta_get_status(struct pcmc
  
        val  = (state & CB_3VCARD) ? SS_3VCARD : 0;
        val |= (state & CB_XVCARD) ? SS_XVCARD : 0;
 -      val |= (state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD | CB_3VCARD
 -                       | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING;
 +      val |= (state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING;
 +      val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? SS_PENDING : 0;
 +
  
        if (state & CB_CBCARD) {
                val |= SS_CARDBUS;      
                val |= (state & CB_CARDSTS) ? SS_STSCHG : 0;
                val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT;
                val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0;
 -      } else {
 +      } else if (state & CB_16BITCARD) {
                u8 status = exca_readb(socket, I365_STATUS);
                val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0;
                if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) {
@@@ -413,13 -405,11 +413,13 @@@ static int yenta_set_mem_map(struct pcm
  }
  
  
 -static unsigned int yenta_events(struct yenta_socket *socket)
 +
 +static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  {
 +      unsigned int events;
 +      struct yenta_socket *socket = (struct yenta_socket *) dev_id;
        u8 csc;
        u32 cb_event;
 -      unsigned int events;
  
        /* Clear interrupt status for the event */
        cb_event = cb_readl(socket, CB_SOCKET_EVENT);
                events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
                events |= (csc & I365_CSC_READY) ? SS_READY : 0;
        }
 -      return events;
 -}
  
 -
 -static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 -{
 -      unsigned int events;
 -      struct yenta_socket *socket = (struct yenta_socket *) dev_id;
 -
 -      events = yenta_events(socket);
 -      if (events) {
 +      if (events)
                pcmcia_parse_events(&socket->socket, events);
 +
 +      if (cb_event || csc)
                return IRQ_HANDLED;
 -      }
 +
        return IRQ_NONE;
  }
  
@@@ -473,22 -470,11 +473,22 @@@ static void yenta_clear_maps(struct yen
        }
  }
  
 +/* redoes voltage interrogation if required */
 +static void yenta_interrogate(struct yenta_socket *socket)
 +{
 +      u32 state;
 +
 +      state = cb_readl(socket, CB_SOCKET_STATE);
 +      if (!(state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) ||
 +          (state & (CB_CDETECT1 | CB_CDETECT2 | CB_NOTACARD | CB_BADVCCREQ)) ||
 +          ((state & (CB_16BITCARD | CB_CBCARD)) == (CB_16BITCARD | CB_CBCARD)))
 +              cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST);
 +}
 +
  /* Called at resume and initialization events */
  static int yenta_sock_init(struct pcmcia_socket *sock)
  {
        struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 -      u32 state;
        u16 bridge;
  
        bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_INTR;
        exca_writeb(socket, I365_GENCTL, 0x00);
  
        /* Redo card voltage interrogation */
 -      state = cb_readl(socket, CB_SOCKET_STATE);
 -      if (!(state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD |
 -                     CB_3VCARD | CB_XVCARD | CB_YVCARD)))
 -              cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST);
 +      yenta_interrogate(socket);
  
        yenta_clear_maps(socket);
  
@@@ -548,11 -537,6 +548,11 @@@ static void yenta_allocate_res(struct y
        unsigned offset;
        unsigned mask;
  
 +      res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
 +      /* Already allocated? */
 +      if (res->parent)
 +              return 0;
 +
        /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */
        mask = ~0xfff;
        if (type & IORESOURCE_IO)
  
        offset = 0x1c + 8*nr;
        bus = socket->dev->subordinate;
 -      res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
        res->name = bus->name;
        res->flags = type;
        res->start = 0;
@@@ -868,11 -853,11 +868,11 @@@ static int yenta_probe_cb_irq(struct ye
   */
  static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_irq_mask)
  {
 -      socket->socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS;
 -      socket->socket.map_size = 0x1000;
        socket->socket.pci_irq = socket->cb_irq;
 -      socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask);
 -      socket->socket.cb_dev = socket->dev;
 +      if (isa_probe)
 +              socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask);
 +      else
 +              socket->socket.irq_mask = 0;
  
        printk(KERN_INFO "Yenta: ISA IRQ mask 0x%04x, PCI irq %d\n",
               socket->socket.irq_mask, socket->cb_irq);
@@@ -938,9 -923,6 +938,9 @@@ static int __devinit yenta_probe (struc
        socket->socket.dev.dev = &dev->dev;
        socket->socket.driver_data = socket;
        socket->socket.owner = THIS_MODULE;
 +      socket->socket.features = SS_CAP_PAGE_REGS | SS_CAP_PCCARD;
 +      socket->socket.map_size = 0x1000;
 +      socket->socket.cb_dev = dev;
  
        /* prepare struct yenta_socket */
        socket->dev = dev;
                socket->poll_timer.data = (unsigned long)socket;
                socket->poll_timer.expires = jiffies + HZ;
                add_timer(&socket->poll_timer);
 +              printk(KERN_INFO "Yenta: no PCI IRQ, CardBus support disabled for this socket.\n"
 +                     KERN_INFO "Yenta: check your BIOS CardBus, BIOS IRQ or ACPI settings.\n");
 +      } else {
 +              socket->socket.features |= SS_CAP_CARDBUS;
        }
  
        /* Figure out what the dang thing can do for the PCMCIA layer... */
 +      yenta_interrogate(socket);
        yenta_get_socket_capabilities(socket, isa_interrupts);
        printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
  
@@@ -1055,6 -1032,7 +1055,7 @@@ static int yenta_dev_suspend (struct pc
                pci_save_state(dev);
                pci_read_config_dword(dev, 16*4, &socket->saved_state[0]);
                pci_read_config_dword(dev, 17*4, &socket->saved_state[1]);
+               pci_disable_device(dev);
  
                /*
                 * Some laptops (IBM T22) do not like us putting the Cardbus
@@@ -1078,6 -1056,8 +1079,8 @@@ static int yenta_dev_resume (struct pci
                pci_restore_state(dev);
                pci_write_config_dword(dev, 16*4, socket->saved_state[0]);
                pci_write_config_dword(dev, 17*4, socket->saved_state[1]);
+               pci_enable_device(dev);
+               pci_set_master(dev);
  
                if (socket->type && socket->type->restore_state)
                        socket->type->restore_state(socket);
diff --combined include/acpi/acpi_bus.h
@@@ -108,21 -108,6 +108,21 @@@ typedef int (*acpi_op_unbind)    (struct a
  typedef int (*acpi_op_match)  (struct acpi_device *device,
                                 struct acpi_driver *driver);
  
 +struct acpi_bus_ops {
 +      u32                     acpi_op_add:1;
 +      u32                     acpi_op_remove:1;
 +      u32                     acpi_op_lock:1;
 +      u32                     acpi_op_start:1;
 +      u32                     acpi_op_stop:1;
 +      u32                     acpi_op_suspend:1;
 +      u32                     acpi_op_resume:1;
 +      u32                     acpi_op_scan:1;
 +      u32                     acpi_op_bind:1;
 +      u32                     acpi_op_unbind:1;
 +      u32                     acpi_op_match:1;
 +      u32                     reserved:21;
 +};
 +
  struct acpi_device_ops {
        acpi_op_add             add;
        acpi_op_remove          remove;
@@@ -342,15 -327,36 +342,36 @@@ int acpi_bus_generate_event (struct acp
  int acpi_bus_receive_event (struct acpi_bus_event *event);
  int acpi_bus_register_driver (struct acpi_driver *driver);
  int acpi_bus_unregister_driver (struct acpi_driver *driver);
 -int acpi_bus_scan (struct acpi_device *start);
  int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent,
                acpi_handle handle, int type);
 +int acpi_bus_start (struct acpi_device *device);
  
  
  int acpi_match_ids (struct acpi_device        *device, char   *ids);
  int acpi_create_dir(struct acpi_device *);
  void acpi_remove_dir(struct acpi_device *);
  
+ /*
+  * Bind physical devices with ACPI devices
+  */
+ #include <linux/device.h>
+ struct acpi_bus_type {
+       struct list_head        list;
+       struct bus_type         *bus;
+       /* For general devices under the bus*/
+       int (*find_device)(struct device *, acpi_handle*);
+       /* For bridges, such as PCI root bridge, IDE controller */
+       int (*find_bridge)(struct device *, acpi_handle *);
+ };
+ int register_acpi_bus_type(struct acpi_bus_type *);
+ int unregister_acpi_bus_type(struct acpi_bus_type *);
+ struct device *acpi_get_physical_device(acpi_handle);
+ /* helper */
+ acpi_handle acpi_get_child(acpi_handle, acpi_integer);
+ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
+ #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->firmware_data))
  #endif /*CONFIG_ACPI_BUS*/
  
  #endif /*__ACPI_BUS_H__*/
@@@ -68,7 -68,6 +68,7 @@@ void acpi_pci_irq_del_prt (int segment
  
  struct pci_bus;
  
 +acpi_status acpi_get_pci_id (acpi_handle handle, struct acpi_pci_id *id);
  int acpi_pci_bind (struct acpi_device *device);
  int acpi_pci_unbind (struct acpi_device *device);
  int acpi_pci_bind_root (struct acpi_device *device, struct acpi_pci_id *id, struct pci_bus *bus);
@@@ -109,5 -108,10 +109,10 @@@ int acpi_ec_ecdt_probe (void)
  
  int acpi_processor_set_thermal_limit(acpi_handle handle, int type);
  
+ /* --------------------------------------------------------------------------
+                                     Hot Keys
+    -------------------------------------------------------------------------- */
+ extern int acpi_specific_hotkey_enabled;
  
  #endif /*__ACPI_DRIVERS_H__*/
diff --combined include/asm-alpha/pci.h
@@@ -58,7 -58,7 +58,7 @@@ struct pci_controller 
  
  extern void pcibios_set_master(struct pci_dev *dev);
  
- extern inline void pcibios_penalize_isa_irq(int irq)
+ extern inline void pcibios_penalize_isa_irq(int irq, int active)
  {
        /* We don't do dynamic PCI IRQ allocation */
  }
@@@ -223,25 -223,6 +223,25 @@@ pci_dac_dma_sync_single_for_device(stru
        /* Nothing to do. */
  }
  
 +#ifdef CONFIG_PCI
 +static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 +                                      enum pci_dma_burst_strategy *strat,
 +                                      unsigned long *strategy_parameter)
 +{
 +      unsigned long cacheline_size;
 +      u8 byte;
 +
 +      pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
 +      if (byte == 0)
 +              cacheline_size = 1024;
 +      else
 +              cacheline_size = (int) byte * 4;
 +
 +      *strat = PCI_DMA_BURST_BOUNDARY;
 +      *strategy_parameter = cacheline_size;
 +}
 +#endif
 +
  /* TODO: integrate with include/asm-generic/pci.h ? */
  static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
  {
diff --combined include/asm-arm/pci.h
@@@ -14,7 -14,7 +14,7 @@@ static inline void pcibios_set_master(s
        /* No special bus mastering setup handling */
  }
  
- static inline void pcibios_penalize_isa_irq(int irq)
+ static inline void pcibios_penalize_isa_irq(int irq, int active)
  {
        /* We don't do dynamic PCI IRQ allocation */
  }
  #define pci_unmap_len(PTR, LEN_NAME)          ((PTR)->LEN_NAME)
  #define pci_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL))
  
 +#ifdef CONFIG_PCI
 +static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 +                                      enum pci_dma_burst_strategy *strat,
 +                                      unsigned long *strategy_parameter)
 +{
 +      *strat = PCI_DMA_BURST_INFINITY;
 +      *strategy_parameter = ~0UL;
 +}
 +#endif
 +
  #define HAVE_PCI_MMAP
  extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                                 enum pci_mmap_state mmap_state, int write_combine);
  #define                       APIC_LVT_REMOTE_IRR             (1<<14)
  #define                       APIC_INPUT_POLARITY             (1<<13)
  #define                       APIC_SEND_PENDING               (1<<12)
 +#define                       APIC_MODE_MASK                  0x700
  #define                       GET_APIC_DELIVERY_MODE(x)       (((x)>>8)&0x7)
  #define                       SET_APIC_DELIVERY_MODE(x,y)     (((x)&~0x700)|((y)<<8))
  #define                               APIC_MODE_FIXED         0x0
  #define                               APIC_MODE_NMI           0x4
 -#define                               APIC_MODE_EXINT         0x7
 +#define                               APIC_MODE_EXTINT        0x7
  #define       APIC_LVT1       0x360
  #define               APIC_LVTERR     0x370
  #define               APIC_TMICT      0x380
  
  #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
  
- #ifdef CONFIG_NUMA
-  #define MAX_IO_APICS 32
- #else
-  #define MAX_IO_APICS 8
- #endif
+ #define MAX_IO_APICS 64
  
  /*
   * the local APIC register structure, memory mapped. Not terribly well
diff --combined include/asm-i386/pci.h
@@@ -27,7 -27,7 +27,7 @@@ void pcibios_config_init(void)
  struct pci_bus * pcibios_scan_root(int bus);
  
  void pcibios_set_master(struct pci_dev *dev);
- void pcibios_penalize_isa_irq(int irq);
+ void pcibios_penalize_isa_irq(int irq, int active);
  struct irq_routing_table *pcibios_get_irq_routing_table(void);
  int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
  
@@@ -99,16 -99,6 +99,16 @@@ static inline void pcibios_add_platform
  {
  }
  
 +#ifdef CONFIG_PCI
 +static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 +                                      enum pci_dma_burst_strategy *strat,
 +                                      unsigned long *strategy_parameter)
 +{
 +      *strat = PCI_DMA_BURST_INFINITY;
 +      *strategy_parameter = ~0UL;
 +}
 +#endif
 +
  #endif /* __KERNEL__ */
  
  /* implement the pci_ DMA API in terms of the generic device dma_ one */
diff --combined include/asm-ia64/pci.h
@@@ -47,7 -47,7 +47,7 @@@ pcibios_set_master (struct pci_dev *dev
  }
  
  static inline void
- pcibios_penalize_isa_irq (int irq)
+ pcibios_penalize_isa_irq (int irq, int active)
  {
        /* We don't do dynamic PCI IRQ allocation */
  }
@@@ -82,25 -82,6 +82,25 @@@ extern int pcibios_prep_mwi (struct pci
  #define sg_dma_len(sg)                ((sg)->dma_length)
  #define sg_dma_address(sg)    ((sg)->dma_address)
  
 +#ifdef CONFIG_PCI
 +static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 +                                      enum pci_dma_burst_strategy *strat,
 +                                      unsigned long *strategy_parameter)
 +{
 +      unsigned long cacheline_size;
 +      u8 byte;
 +
 +      pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
 +      if (byte == 0)
 +              cacheline_size = 1024;
 +      else
 +              cacheline_size = (int) byte * 4;
 +
 +      *strat = PCI_DMA_BURST_MULTIPLE;
 +      *strategy_parameter = cacheline_size;
 +}
 +#endif
 +
  #define HAVE_PCI_MMAP
  extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
                                enum pci_mmap_state mmap_state, int write_combine);
diff --combined include/asm-mips/pci.h
@@@ -69,7 -69,7 +69,7 @@@ extern unsigned long PCIBIOS_MIN_MEM
  
  extern void pcibios_set_master(struct pci_dev *dev);
  
- static inline void pcibios_penalize_isa_irq(int irq)
+ static inline void pcibios_penalize_isa_irq(int irq, int active)
  {
        /* We don't do dynamic PCI IRQ allocation */
  }
@@@ -130,16 -130,6 +130,16 @@@ extern void pci_dac_dma_sync_single_for
  extern void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
        dma64_addr_t dma_addr, size_t len, int direction);
  
 +#ifdef CONFIG_PCI
 +static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 +                                      enum pci_dma_burst_strategy *strat,
 +                                      unsigned long *strategy_parameter)
 +{
 +      *strat = PCI_DMA_BURST_INFINITY;
 +      *strategy_parameter = ~0UL;
 +}
 +#endif
 +
  extern void pcibios_resource_to_bus(struct pci_dev *dev,
        struct pci_bus_region *region, struct resource *res);
  
diff --combined include/asm-ppc/pci.h
@@@ -37,7 -37,7 +37,7 @@@ extern inline void pcibios_set_master(s
        /* No special bus mastering setup handling */
  }
  
- extern inline void pcibios_penalize_isa_irq(int irq)
+ extern inline void pcibios_penalize_isa_irq(int irq, int active)
  {
        /* We don't do dynamic PCI IRQ allocation */
  }
@@@ -69,16 -69,6 +69,16 @@@ extern unsigned long pci_bus_to_phys(un
  #define pci_unmap_len(PTR, LEN_NAME)          (0)
  #define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
  
 +#ifdef CONFIG_PCI
 +static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 +                                      enum pci_dma_burst_strategy *strat,
 +                                      unsigned long *strategy_parameter)
 +{
 +      *strat = PCI_DMA_BURST_INFINITY;
 +      *strategy_parameter = ~0UL;
 +}
 +#endif
 +
  /*
   * At present there are very few 32-bit PPC machines that can have
   * memory above the 4GB point, and we don't support that.
@@@ -113,12 -103,6 +113,12 @@@ extern pgprot_t  pci_phys_mem_access_pro
                                         unsigned long size,
                                         pgprot_t prot);
  
 +#define HAVE_ARCH_PCI_RESOURCE_TO_USER
 +extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
 +                               const struct resource *rsrc,
 +                               u64 *start, u64 *end);
 +
 +
  #endif        /* __KERNEL__ */
  
  #endif /* __PPC_PCI_H */
diff --combined include/asm-ppc64/pci.h
@@@ -37,7 -37,7 +37,7 @@@ static inline void pcibios_set_master(s
        /* No special bus mastering setup handling */
  }
  
- static inline void pcibios_penalize_isa_irq(int irq)
+ static inline void pcibios_penalize_isa_irq(int irq, int active)
  {
        /* We don't do dynamic PCI IRQ allocation */
  }
@@@ -78,25 -78,6 +78,25 @@@ static inline int pci_dac_dma_supported
        return 0;
  }
  
 +#ifdef CONFIG_PCI
 +static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 +                                      enum pci_dma_burst_strategy *strat,
 +                                      unsigned long *strategy_parameter)
 +{
 +      unsigned long cacheline_size;
 +      u8 byte;
 +
 +      pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
 +      if (byte == 0)
 +              cacheline_size = 1024;
 +      else
 +              cacheline_size = (int) byte * 4;
 +
 +      *strat = PCI_DMA_BURST_MULTIPLE;
 +      *strategy_parameter = cacheline_size;
 +}
 +#endif
 +
  extern int pci_domain_nr(struct pci_bus *bus);
  
  /* Decide whether to display the domain number in /proc */
@@@ -155,13 -136,6 +155,13 @@@ extern pgprot_t  pci_phys_mem_access_pro
                                         unsigned long size,
                                         pgprot_t prot);
  
 +#ifdef CONFIG_PPC_MULTIPLATFORM
 +#define HAVE_ARCH_PCI_RESOURCE_TO_USER
 +extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
 +                               const struct resource *rsrc,
 +                               u64 *start, u64 *end);
 +#endif /* CONFIG_PPC_MULTIPLATFORM */
 +
  
  #endif        /* __KERNEL__ */
  
diff --combined include/asm-sh/pci.h
@@@ -36,7 -36,7 +36,7 @@@ struct pci_dev
  
  extern void pcibios_set_master(struct pci_dev *dev);
  
- static inline void pcibios_penalize_isa_irq(int irq)
+ static inline void pcibios_penalize_isa_irq(int irq, int active)
  {
        /* We don't do dynamic PCI IRQ allocation */
  }
  #define sg_dma_address(sg)    (virt_to_bus((sg)->dma_address))
  #define sg_dma_len(sg)                ((sg)->length)
  
 +#ifdef CONFIG_PCI
 +static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 +                                      enum pci_dma_burst_strategy *strat,
 +                                      unsigned long *strategy_parameter)
 +{
 +      *strat = PCI_DMA_BURST_INFINITY;
 +      *strategy_parameter = ~0UL;
 +}
 +#endif
 +
  /* Board-specific fixup routines. */
  extern void pcibios_fixup(void);
  extern void pcibios_fixup_irqs(void);
diff --combined include/asm-sh64/pci.h
@@@ -26,7 -26,7 +26,7 @@@ extern void pcibios_set_master(struct p
  /*
   * Set penalize isa irq function
   */
- static inline void pcibios_penalize_isa_irq(int irq)
+ static inline void pcibios_penalize_isa_irq(int irq, int active)
  {
        /* We don't do dynamic PCI IRQ allocation */
  }
  #define sg_dma_address(sg)    ((sg)->dma_address)
  #define sg_dma_len(sg)                ((sg)->length)
  
 +#ifdef CONFIG_PCI
 +static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 +                                      enum pci_dma_burst_strategy *strat,
 +                                      unsigned long *strategy_parameter)
 +{
 +      *strat = PCI_DMA_BURST_INFINITY;
 +      *strategy_parameter = ~0UL;
 +}
 +#endif
 +
  /* Board-specific fixup routines. */
  extern void pcibios_fixup(void);
  extern void pcibios_fixup_irqs(void);
diff --combined include/asm-sparc/pci.h
@@@ -20,7 -20,7 +20,7 @@@ extern inline void pcibios_set_master(s
        /* No special bus mastering setup handling */
  }
  
- extern inline void pcibios_penalize_isa_irq(int irq)
+ extern inline void pcibios_penalize_isa_irq(int irq, int active)
  {
        /* We don't do dynamic PCI IRQ allocation */
  }
@@@ -144,16 -144,6 +144,16 @@@ extern inline int pci_dma_supported(str
  
  #define pci_dac_dma_supported(dev, mask)      (0)
  
 +#ifdef CONFIG_PCI
 +static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 +                                      enum pci_dma_burst_strategy *strat,
 +                                      unsigned long *strategy_parameter)
 +{
 +      *strat = PCI_DMA_BURST_INFINITY;
 +      *strategy_parameter = ~0UL;
 +}
 +#endif
 +
  static inline void pcibios_add_platform_entries(struct pci_dev *dev)
  {
  }
@@@ -23,7 -23,7 +23,7 @@@ static inline void pcibios_set_master(s
        /* No special bus mastering setup handling */
  }
  
- static inline void pcibios_penalize_isa_irq(int irq)
+ static inline void pcibios_penalize_isa_irq(int irq, int active)
  {
        /* We don't do dynamic PCI IRQ allocation */
  }
@@@ -220,25 -220,6 +220,25 @@@ static inline int pci_dma_mapping_error
        return (dma_addr == PCI_DMA_ERROR_CODE);
  }
  
 +#ifdef CONFIG_PCI
 +static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 +                                      enum pci_dma_burst_strategy *strat,
 +                                      unsigned long *strategy_parameter)
 +{
 +      unsigned long cacheline_size;
 +      u8 byte;
 +
 +      pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
 +      if (byte == 0)
 +              cacheline_size = 1024;
 +      else
 +              cacheline_size = (int) byte * 4;
 +
 +      *strat = PCI_DMA_BURST_BOUNDARY;
 +      *strategy_parameter = cacheline_size;
 +}
 +#endif
 +
  /* Return the index of the PCI controller for device PDEV. */
  
  extern int pci_domain_nr(struct pci_bus *bus);
diff --combined include/asm-x86_64/pci.h
@@@ -33,7 -33,7 +33,7 @@@ extern int (*pci_config_read)(int seg, 
  extern int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value);
  
  void pcibios_set_master(struct pci_dev *dev);
- void pcibios_penalize_isa_irq(int irq);
+ void pcibios_penalize_isa_irq(int irq, int active);
  struct irq_routing_table *pcibios_get_irq_routing_table(void);
  int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
  
@@@ -123,16 -123,6 +123,16 @@@ pci_dac_dma_sync_single_for_device(stru
        flush_write_buffers();
  }
  
 +#ifdef CONFIG_PCI
 +static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 +                                      enum pci_dma_burst_strategy *strat,
 +                                      unsigned long *strategy_parameter)
 +{
 +      *strat = PCI_DMA_BURST_INFINITY;
 +      *strategy_parameter = ~0UL;
 +}
 +#endif
 +
  #define HAVE_PCI_MMAP
  extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                               enum pci_mmap_state mmap_state, int write_combine);
diff --combined include/linux/acpi.h
@@@ -206,7 -206,10 +206,10 @@@ struct acpi_table_plat_int_src 
        u8                      eid;
        u8                      iosapic_vector;
        u32                     global_irq;
-       u32                     reserved;
+       struct {
+               u32                     cpei_override_flag:1;
+               u32                     reserved:31;
+       }                       plint_flags;
  } __attribute__ ((packed));
  
  enum acpi_interrupt_id {
@@@ -342,19 -345,11 +345,19 @@@ struct acpi_table_ecdt 
  
  /* PCI MMCONFIG */
  
 +/* Defined in PCI Firmware Specification 3.0 */
 +struct acpi_table_mcfg_config {
 +      u32                             base_address;
 +      u32                             base_reserved;
 +      u16                             pci_segment_group_number;
 +      u8                              start_bus_number;
 +      u8                              end_bus_number;
 +      u8                              reserved[4];
 +} __attribute__ ((packed));
  struct acpi_table_mcfg {
        struct acpi_table_header        header;
        u8                              reserved[8];
 -      u32                             base_address;
 -      u32                             base_reserved;
 +      struct acpi_table_mcfg_config   config[0];
  } __attribute__ ((packed));
  
  /* Table Handlers */
@@@ -399,7 -394,6 +402,7 @@@ int acpi_table_parse (enum acpi_table_i
  int acpi_get_table_header_early (enum acpi_table_id id, struct acpi_table_header **header);
  int acpi_table_parse_madt (enum acpi_madt_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries);
  int acpi_table_parse_srat (enum acpi_srat_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries);
 +int acpi_parse_mcfg (unsigned long phys_addr, unsigned long size);
  void acpi_table_print (struct acpi_table_header *header, unsigned long phys_addr);
  void acpi_table_print_madt_entry (acpi_table_entry_header *madt);
  void acpi_table_print_srat_entry (acpi_table_entry_header *srat);
@@@ -416,13 -410,9 +419,13 @@@ int acpi_map_lsapic(acpi_handle handle
  int acpi_unmap_lsapic(int cpu);
  #endif /* CONFIG_ACPI_HOTPLUG_CPU */
  
 +int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base);
 +int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);
 +
  extern int acpi_mp_config;
  
 -extern u32 pci_mmcfg_base_addr;
 +extern struct acpi_table_mcfg_config *pci_mmcfg_config;
 +extern int pci_mmcfg_config_num;
  
  extern int sbf_port ;
  
@@@ -475,7 -465,7 +478,7 @@@ struct acpi_prt_list 
  struct pci_dev;
  
  int acpi_pci_irq_enable (struct pci_dev *dev);
- void acpi_penalize_isa_irq(int irq);
+ void acpi_penalize_isa_irq(int irq, int active);
  
  #ifdef CONFIG_ACPI_DEALLOCATE_IRQ
  void acpi_pci_irq_disable (struct pci_dev *dev);
diff --combined include/linux/device.h
@@@ -14,7 -14,6 +14,7 @@@
  #include <linux/config.h>
  #include <linux/ioport.h>
  #include <linux/kobject.h>
 +#include <linux/klist.h>
  #include <linux/list.h>
  #include <linux/types.h>
  #include <linux/module.h>
@@@ -45,15 -44,14 +45,15 @@@ struct device
  struct device_driver;
  struct class;
  struct class_device;
 -struct class_simple;
  
  struct bus_type {
 -      char                    * name;
 +      const char              * name;
  
        struct subsystem        subsys;
        struct kset             drivers;
        struct kset             devices;
 +      struct klist            klist_devices;
 +      struct klist            klist_drivers;
  
        struct bus_attribute    * bus_attrs;
        struct device_attribute * dev_attrs;
@@@ -69,7 -67,7 +69,7 @@@
  extern int bus_register(struct bus_type * bus);
  extern void bus_unregister(struct bus_type * bus);
  
 -extern int bus_rescan_devices(struct bus_type * bus);
 +extern void bus_rescan_devices(struct bus_type * bus);
  
  extern struct bus_type * get_bus(struct bus_type * bus);
  extern void put_bus(struct bus_type * bus);
@@@ -80,8 -78,6 +80,8 @@@ extern struct bus_type * find_bus(char 
  
  int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data,
                     int (*fn)(struct device *, void *));
 +struct device * bus_find_device(struct bus_type *bus, struct device *start,
 +                              void *data, int (*match)(struct device *, void *));
  
  int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, 
                     void * data, int (*fn)(struct device_driver *, void *));
@@@ -102,18 -98,17 +102,18 @@@ extern int bus_create_file(struct bus_t
  extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
  
  struct device_driver {
 -      char                    * name;
 +      const char              * name;
        struct bus_type         * bus;
  
        struct completion       unloaded;
        struct kobject          kobj;
 -      struct list_head        devices;
 +      struct klist            klist_devices;
 +      struct klist_node       knode_bus;
  
 -      struct module           * owner;
 +      struct module           * owner;
  
        int     (*probe)        (struct device * dev);
 -      int     (*remove)       (struct device * dev);
 +      int     (*remove)       (struct device * dev);
        void    (*shutdown)     (struct device * dev);
        int     (*suspend)      (struct device * dev, pm_message_t state, u32 level);
        int     (*resume)       (struct device * dev, u32 level);
@@@ -142,19 -137,12 +142,19 @@@ struct driver_attribute driver_attr_##_
  extern int driver_create_file(struct device_driver *, struct driver_attribute *);
  extern void driver_remove_file(struct device_driver *, struct driver_attribute *);
  
 +extern int driver_for_each_device(struct device_driver * drv, struct device * start,
 +                                void * data, int (*fn)(struct device *, void *));
 +struct device * driver_find_device(struct device_driver *drv,
 +                                 struct device *start, void *data,
 +                                 int (*match)(struct device *, void *));
 +
  
  /*
   * device classes
   */
  struct class {
 -      char                    * name;
 +      const char              * name;
 +      struct module           * owner;
  
        struct subsystem        subsys;
        struct list_head        children;
@@@ -197,7 -185,6 +197,7 @@@ struct class_device 
        struct kobject          kobj;
        struct class            * class;        /* required */
        dev_t                   devt;           /* dev_t, creates the sysfs "dev" */
 +      struct class_device_attribute *devt_attr;
        struct device           * dev;          /* not necessary, but nice to have */
        void                    * class_data;   /* class-specific data */
  
@@@ -258,34 -245,34 +258,36 @@@ struct class_interface 
  extern int class_interface_register(struct class_interface *);
  extern void class_interface_unregister(struct class_interface *);
  
 -/* interface for class simple stuff */
 -extern struct class_simple *class_simple_create(struct module *owner, char *name);
 -extern void class_simple_destroy(struct class_simple *cs);
 -extern struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, struct device *device, const char *fmt, ...)
 -      __attribute__((format(printf,4,5)));
 -extern int class_simple_set_hotplug(struct class_simple *, 
 -      int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size));
 -extern void class_simple_device_remove(dev_t dev);
 +extern struct class *class_create(struct module *owner, char *name);
 +extern void class_destroy(struct class *cls);
 +extern struct class_device *class_device_create(struct class *cls, dev_t devt,
 +                                              struct device *device, char *fmt, ...)
 +                                      __attribute__((format(printf,4,5)));
 +extern void class_device_destroy(struct class *cls, dev_t devt);
  
  
  struct device {
 -      struct list_head node;          /* node in sibling list */
 -      struct list_head bus_list;      /* node in bus's list */
 -      struct list_head driver_list;
 -      struct list_head children;
 +      struct klist            klist_children;
 +      struct klist_node       knode_parent;           /* node in sibling list */
 +      struct klist_node       knode_driver;
 +      struct klist_node       knode_bus;
        struct device   * parent;
  
        struct kobject kobj;
        char    bus_id[BUS_ID_SIZE];    /* position on parent bus */
  
 +      struct semaphore        sem;    /* semaphore to synchronize calls to
 +                                       * its driver.
 +                                       */
 +
        struct bus_type * bus;          /* type of bus device is on */
        struct device_driver *driver;   /* which driver has allocated this
                                           device */
        void            *driver_data;   /* data private to the driver */
-       void            *platform_data; /* Platform specific data (e.g. ACPI,
-                                          BIOS data relevant to device) */
+       void            *platform_data; /* Platform specific data, device
+                                          core doesn't touch it */
+       void            *firmware_data; /* Firmware specific data (e.g. ACPI,
+                                          BIOS data),reserved for device core*/
        struct dev_pm_info      power;
  
        u64             *dma_mask;      /* dma mask (if dma'able device) */
        void    (*release)(struct device * dev);
  };
  
 -static inline struct device *
 -list_to_dev(struct list_head *node)
 -{
 -      return list_entry(node, struct device, node);
 -}
 -
  static inline void *
  dev_get_drvdata (struct device *dev)
  {
@@@ -330,6 -323,7 +332,6 @@@ extern int device_for_each_child(struc
   * Manual binding of a device to driver. See drivers/base/bus.c
   * for information on use.
   */
 -extern int  driver_probe_device(struct device_driver * drv, struct device * dev);
  extern void device_bind_driver(struct device * dev);
  extern void device_release_driver(struct device * dev);
  extern int  device_attach(struct device * dev);
@@@ -340,10 -334,8 +342,10 @@@ extern void driver_attach(struct device
  
  struct device_attribute {
        struct attribute        attr;
 -      ssize_t (*show)(struct device * dev, char * buf);
 -      ssize_t (*store)(struct device * dev, const char * buf, size_t count);
 +      ssize_t (*show)(struct device *dev, struct device_attribute *attr,
 +                      char *buf);
 +      ssize_t (*store)(struct device *dev, struct device_attribute *attr,
 +                       const char *buf, size_t count);
  };
  
  #define DEVICE_ATTR(_name,_mode,_show,_store) \
@@@ -370,12 -362,13 +372,12 @@@ extern int (*platform_notify_remove)(st
   */
  extern struct device * get_device(struct device * dev);
  extern void put_device(struct device * dev);
 -extern struct device *device_find(const char *name, struct bus_type *bus);
  
  
  /* drivers/base/platform.c */
  
  struct platform_device {
 -      char            * name;
 +      const char      * name;
        u32             id;
        struct device   dev;
        u32             num_resources;
diff --combined include/linux/pm.h
@@@ -103,8 -103,7 +103,8 @@@ extern int pm_active
  /*
   * Register a device with power management
   */
 -struct pm_dev __deprecated *pm_register(pm_dev_t type, unsigned long id, pm_callback callback);
 +struct pm_dev __deprecated *
 +pm_register(pm_dev_t type, unsigned long id, pm_callback callback);
  
  /*
   * Unregister a device with power management
@@@ -176,7 -175,7 +176,7 @@@ struct pm_ops 
  };
  
  extern void pm_set_ops(struct pm_ops *);
+ extern struct pm_ops *pm_ops;
  extern int pm_suspend(suspend_state_t state);
  
  
@@@ -191,18 -190,17 +191,18 @@@ typedef u32 __bitwise pm_message_t
  /*
   * There are 4 important states driver can be in:
   * ON     -- driver is working
 - * FREEZE -- stop operations and apply whatever policy is applicable to a suspended driver
 - *           of that class, freeze queues for block like IDE does, drop packets for
 - *           ethernet, etc... stop DMA engine too etc... so a consistent image can be
 - *           saved; but do not power any hardware down.
 - * SUSPEND - like FREEZE, but hardware is doing as much powersaving as possible. Roughly
 - *           pci D3.
 + * FREEZE -- stop operations and apply whatever policy is applicable to a
 + *           suspended driver of that class, freeze queues for block like IDE
 + *           does, drop packets for ethernet, etc... stop DMA engine too etc...
 + *           so a consistent image can be saved; but do not power any hardware
 + *           down.
 + * SUSPEND - like FREEZE, but hardware is doing as much powersaving as
 + *           possible. Roughly pci D3.
   *
 - * Unfortunately, current drivers only recognize numeric values 0 (ON) and 3 (SUSPEND).
 - * We'll need to fix the drivers. So yes, putting 3 to all diferent defines is intentional,
 - * and will go away as soon as drivers are fixed. Also note that typedef is neccessary,
 - * we'll probably want to switch to
 + * Unfortunately, current drivers only recognize numeric values 0 (ON) and 3
 + * (SUSPEND).  We'll need to fix the drivers. So yes, putting 3 to all different
 + * defines is intentional, and will go away as soon as drivers are fixed.  Also
 + * note that typedef is neccessary, we'll probably want to switch to
   *   typedef struct pm_message_t { int event; int flags; } pm_message_t
   * or something similar soon.
   */
@@@ -224,18 -222,11 +224,18 @@@ struct dev_pm_info 
  
  extern void device_pm_set_parent(struct device * dev, struct device * parent);
  
 -extern int device_suspend(pm_message_t state);
  extern int device_power_down(pm_message_t state);
  extern void device_power_up(void);
  extern void device_resume(void);
  
 +#ifdef CONFIG_PM
 +extern int device_suspend(pm_message_t state);
 +#else
 +static inline int device_suspend(pm_message_t state)
 +{
 +      return 0;
 +}
 +#endif
  
  #endif /* __KERNEL__ */
  
diff --combined kernel/power/main.c
@@@ -19,6 -19,9 +19,9 @@@
  
  #include "power.h"
  
+ /*This is just an arbitrary number */
+ #define FREE_PAGE_NUMBER (100)
  DECLARE_MUTEX(pm_sem);
  
  struct pm_ops * pm_ops = NULL;
@@@ -49,24 -52,28 +52,35 @@@ void pm_set_ops(struct pm_ops * ops
  static int suspend_prepare(suspend_state_t state)
  {
        int error = 0;
+       unsigned int free_pages;
  
        if (!pm_ops || !pm_ops->enter)
                return -EPERM;
  
        pm_prepare_console();
  
 +      disable_nonboot_cpus();
 +
 +      if (num_online_cpus() != 1) {
 +              error = -EPERM;
 +              goto Enable_cpu;
 +      }
 +
        if (freeze_processes()) {
                error = -EAGAIN;
                goto Thaw;
        }
  
+       if ((free_pages = nr_free_pages()) < FREE_PAGE_NUMBER) {
+               pr_debug("PM: free some memory\n");
+               shrink_all_memory(FREE_PAGE_NUMBER - free_pages);
+               if (nr_free_pages() < FREE_PAGE_NUMBER) {
+                       error = -ENOMEM;
+                       printk(KERN_ERR "PM: No enough memory\n");
+                       goto Thaw;
+               }
+       }
        if (pm_ops->prepare) {
                if ((error = pm_ops->prepare(state)))
                        goto Thaw;
@@@ -82,8 -89,6 +96,8 @@@
                pm_ops->finish(state);
   Thaw:
        thaw_processes();
 + Enable_cpu:
 +      enable_nonboot_cpus();
        pm_restore_console();
        return error;
  }
@@@ -122,7 -127,6 +136,7 @@@ static void suspend_finish(suspend_stat
        if (pm_ops && pm_ops->finish)
                pm_ops->finish(state);
        thaw_processes();
 +      enable_nonboot_cpus();
        pm_restore_console();
  }
  
@@@ -160,6 -164,12 +174,6 @@@ static int enter_state(suspend_state_t 
                goto Unlock;
        }
  
 -      /* Suspend is hard to get right on SMP. */
 -      if (num_online_cpus() != 1) {
 -              error = -EPERM;
 -              goto Unlock;
 -      }
 -
        pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
        if ((error = suspend_prepare(state)))
                goto Unlock;
@@@ -194,7 -204,7 +208,7 @@@ int software_suspend(void
  
  int pm_suspend(suspend_state_t state)
  {
-       if (state > PM_SUSPEND_ON && state < PM_SUSPEND_MAX)
+       if (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX)
                return enter_state(state);
        return -EINVAL;
  }