]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'x86-mrst-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 7 Mar 2010 23:59:39 +0000 (15:59 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 7 Mar 2010 23:59:39 +0000 (15:59 -0800)
* 'x86-mrst-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (30 commits)
  x86, mrst: Fix whitespace breakage in apb_timer.c
  x86, mrst: Fix APB timer per cpu clockevent
  x86, mrst: Remove X86_MRST dependency on PCI_IOAPIC
  x86, olpc: Use pci subarch init for OLPC
  x86, pci: Add arch_init to x86_init abstraction
  x86, mrst: Add Kconfig dependencies for Moorestown
  x86, pci: Exclude Moorestown PCI code if CONFIG_X86_MRST=n
  x86, numaq: Make CONFIG_X86_NUMAQ depend on CONFIG_PCI
  x86, pci: Add sanity check for PCI fixed bar probing
  x86, legacy_irq: Remove duplicate vector assigment
  x86, legacy_irq: Remove left over nr_legacy_irqs
  x86, mrst: Platform clock setup code
  x86, apbt: Moorestown APB system timer driver
  x86, mrst: Add vrtc platform data setup code
  x86, mrst: Add platform timer info parsing code
  x86, mrst: Fill in PCI functions in x86_init layer
  x86, mrst: Add dummy legacy pic to platform setup
  x86/PCI: Moorestown PCI support
  x86, ioapic: Add dummy ioapic functions
  x86, ioapic: Early enable ioapic for timer irq
  ...

Fixed up semantic conflict of new clocksources due to commit
17622339af25 ("clocksource: add argument to resume callback").

21 files changed:
1  2 
Documentation/kernel-parameters.txt
arch/x86/Kconfig
arch/x86/include/asm/numaq.h
arch/x86/include/asm/pci.h
arch/x86/include/asm/pci_x86.h
arch/x86/include/asm/x86_init.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/apb_timer.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/nmi.c
arch/x86/kernel/apic/numaq_32.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/x86_init.c
arch/x86/pci/Makefile
arch/x86/pci/acpi.c
arch/x86/pci/common.c
arch/x86/pci/irq.c
arch/x86/pci/numaq_32.c
drivers/pci/pci.c
include/linux/pci.h

index d80930d58daeb4a479e3ab6592b156faaf5d3e69,917220459e2a6917a53a3943bcb73ea894e9be73..3bc48b0bd3a979e857287115d2893b068abb8b58
@@@ -54,7 -54,6 +54,7 @@@ parameter is applicable
        IMA     Integrity measurement architecture is enabled.
        IOSCHED More than one I/O scheduler is enabled.
        IP_PNP  IP DHCP, BOOTP, or RARP is enabled.
 +      IPV6    IPv6 support is enabled.
        ISAPNP  ISA PnP code is enabled.
        ISDN    Appropriate ISDN support is enabled.
        JOY     Appropriate joystick support is enabled.
@@@ -200,10 -199,6 +200,10 @@@ and is between 256 and 4096 characters
                        acpi_display_output=video
                        See above.
  
 +      acpi_early_pdc_eval     [HW,ACPI] Evaluate processor _PDC methods
 +                              early. Needed on some platforms to properly
 +                              initialize the EC.
 +
        acpi_irq_balance [HW,ACPI]
                        ACPI will balance active IRQs
                        default in APIC mode
        aic79xx=        [HW,SCSI]
                        See Documentation/scsi/aic79xx.txt.
  
 +      alignment=      [KNL,ARM]
 +                      Allow the default userspace alignment fault handler
 +                      behaviour to be specified.  Bit 0 enables warnings,
 +                      bit 1 enables fixups, and bit 2 sends a segfault.
 +
        amd_iommu=      [HW,X86-84]
                        Pass parameters to the AMD IOMMU driver in the system.
                        Possible values are:
                        Change the amount of debugging information output
                        when initialising the APIC and IO-APIC components.
  
 +      autoconf=       [IPV6]
 +                      See Documentation/networking/ipv6.txt.
 +
        show_lapic=     [APIC,X86] Advanced Programmable Interrupt Controller
                        Limit apic dumping. The parameter defines the maximal
                        number of local apics being dumped. Also it is possible
                        See drivers/char/README.epca and
                        Documentation/serial/digiepca.txt.
  
 +      disable=        [IPV6]
 +                      See Documentation/networking/ipv6.txt.
 +
 +      disable_ipv6=   [IPV6]
 +                      See Documentation/networking/ipv6.txt.
 +
        disable_mtrr_cleanup [X86]
                        The kernel tries to adjust MTRR layout from continuous
                        to discrete, to make X server driver able to add WB
        nomfgpt         [X86-32] Disable Multi-Function General Purpose
                        Timer usage (for AMD Geode machines).
  
 +      nopat           [X86] Disable PAT (page attribute table extension of
 +                      pagetables) support.
 +
        norandmaps      Don't use address space randomization.  Equivalent to
                        echo 0 > /proc/sys/kernel/randomize_va_space
  
                                IRQ routing is enabled.
                noacpi          [X86] Do not use ACPI for IRQ routing
                                or for PCI scanning.
 -              use_crs         [X86] Use _CRS for PCI resource
 -                              allocation.
 +              use_crs         [X86] Use PCI host bridge window information
 +                              from ACPI.  On BIOSes from 2008 or later, this
 +                              is enabled by default.  If you need to use this,
 +                              please report a bug.
 +              nocrs           [X86] Ignore PCI host bridge windows from ACPI.
 +                              If you need to use this, please report a bug.
                routeirq        Do IRQ routing for all PCI devices.
                                This is normally done in pci_enable_device(),
                                so this option is a temporary workaround
                force   Enable ASPM even on devices that claim not to support it.
                        WARNING: Forcing ASPM on may cause system lockups.
  
 +      pcie_pme=       [PCIE,PM] Native PCIe PME signaling options:
 +              off     Do not use native PCIe PME signaling.
 +              force   Use native PCIe PME signaling even if the BIOS refuses
 +                      to allow the kernel to control the relevant PCIe config
 +                      registers.
 +              nomsi   Do not use MSI for native PCIe PME signaling (this makes
 +                      all PCIe root ports use INTx for everything).
 +
        pcmv=           [HW,PCMCIA] BadgePAD 4
  
        pd.             [PARIDE]
                                        medium is write-protected).
                        Example: quirks=0419:aaf5:rl,0421:0433:rc
  
 +      userpte=
 +                      [X86] Flags controlling user PTE allocations.
 +
 +                              nohigh = do not allocate PTE pages in
 +                                      HIGHMEM regardless of setting
 +                                      of CONFIG_HIGHPTE.
 +
        vdso=           [X86,SH]
                        vdso=2: enable compat VDSO (default with COMPAT_VDSO)
                        vdso=1: enable VDSO (default)
                        default x2apic cluster mode on platforms
                        supporting x2apic.
  
+       x86_mrst_timer= [X86-32,APBT]
+                       Choose timer option for x86 Moorestown MID platform.
+                       Two valid options are apbt timer only and lapic timer
+                       plus one apbt timer for broadcast timer.
+                       x86_mrst_timer=apbt_only | lapic_and_apbt
        xd=             [HW,XT] Original XT pre-IDE (RLL encoded) disks.
        xd_geo=         See header of drivers/block/xd.c.
  
diff --combined arch/x86/Kconfig
index f15f37bfbd62b8f7a9ebc0ebb4e391cb1ea4df37,d22686f69de8d280366aff5060d161258e700951..e98440371525a968c1afa04cc69350401c497ec0
@@@ -31,7 -31,6 +31,7 @@@ config X8
        select ARCH_WANT_FRAME_POINTERS
        select HAVE_DMA_ATTRS
        select HAVE_KRETPROBES
 +      select HAVE_OPTPROBES
        select HAVE_FTRACE_MCOUNT_RECORD
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FUNCTION_TRACER
@@@ -46,7 -45,6 +46,7 @@@
        select HAVE_GENERIC_DMA_COHERENT if X86_32
        select HAVE_EFFICIENT_UNALIGNED_ACCESS
        select USER_STACKTRACE_SUPPORT
 +      select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_DMA_API_DEBUG
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_BZIP2
@@@ -185,9 -183,6 +185,9 @@@ config ARCH_SUPPORTS_OPTIMIZED_INLININ
  config ARCH_SUPPORTS_DEBUG_PAGEALLOC
        def_bool y
  
 +config HAVE_EARLY_RES
 +      def_bool y
 +
  config HAVE_INTEL_TXT
        def_bool y
        depends on EXPERIMENTAL && DMAR && ACPI
@@@ -393,8 -388,12 +393,12 @@@ config X86_ELA
  
  config X86_MRST
         bool "Moorestown MID platform"
+       depends on PCI
+       depends on PCI_GOANY
        depends on X86_32
        depends on X86_EXTENDED_PLATFORM
+       depends on X86_IO_APIC
+       select APB_TIMER
        ---help---
          Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin
          Internet Device(MID) platform. Moorestown consists of two chips:
@@@ -429,6 -428,7 +433,7 @@@ config X86_32_NON_STANDAR
  config X86_NUMAQ
        bool "NUMAQ (IBM/Sequent)"
        depends on X86_32_NON_STANDARD
+       depends on PCI
        select NUMA
        select X86_MPPARSE
        ---help---
@@@ -573,18 -573,6 +578,18 @@@ config PARAVIRT_DEBU
          Enable to debug paravirt_ops internals.  Specifically, BUG if
          a paravirt_op is missing when it is called.
  
 +config NO_BOOTMEM
 +      default y
 +      bool "Disable Bootmem code"
 +      ---help---
 +        Use early_res directly instead of bootmem before slab is ready.
 +              - allocator (buddy) [generic]
 +              - early allocator (bootmem) [generic]
 +              - very early allocator (reserve_early*()) [x86]
 +              - very very early allocator (early brk model) [x86]
 +        So reduce one layer between early allocator to final allocator
 +
 +
  config MEMTEST
        bool "Memtest"
        ---help---
@@@ -629,6 -617,16 +634,16 @@@ config HPET_EMULATE_RT
        def_bool y
        depends on HPET_TIMER && (RTC=y || RTC=m || RTC_DRV_CMOS=m || RTC_DRV_CMOS=y)
  
+ config APB_TIMER
+        def_bool y if MRST
+        prompt "Langwell APB Timer Support" if X86_MRST
+        help
+          APB timer is the replacement for 8254, HPET on X86 MID platforms.
+          The APBT provides a stable time base on SMP
+          systems, unlike the TSC, but it is more expensive to access,
+          as it is off-chip. APB timers are always running regardless of CPU
+          C states, they are used as per CPU clockevent device when possible.
  # Mark as embedded because too many people got it wrong.
  # The code disables itself when not needed.
  config DMI
index 13370b95ea9481c32132961d2b804fd3d7ebea6b,ef6bf81f846050feb948d6d33a6d348eaa8ccacd..37c516545ec8c7a8b73b13e84c37756d1a6ac6e2
  
  extern int found_numaq;
  extern int get_memcfg_numaq(void);
+ extern int pci_numaq_init(void);
  
  extern void *xquad_portio;
  
 +#define XQUAD_PORTIO_BASE 0xfe400000
 +#define XQUAD_PORTIO_QUAD 0x40000  /* 256k per quad. */
 +#define XQUAD_PORT_ADDR(port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port)
 +
  /*
   * SYS_CFG_DATA_PRIV_ADDR, struct eachquadmem, and struct sys_cfg_data are the
   */
index b4a00dd4eed586da6c864187521bf748b2dbd09f,8bd433ccc242627443edaa24f0a98da8dce8706f..3e002ca5a287d281d190f6401eb146d864f8903d
@@@ -45,8 -45,15 +45,15 @@@ static inline int pci_proc_domain(struc
  
  #ifdef CONFIG_PCI
  extern unsigned int pcibios_assign_all_busses(void);
+ extern int pci_legacy_init(void);
+ # ifdef CONFIG_ACPI
+ #  define x86_default_pci_init pci_acpi_init
+ # else
+ #  define x86_default_pci_init pci_legacy_init
+ # endif
  #else
- #define pcibios_assign_all_busses()   0
+ # define pcibios_assign_all_busses()  0
+ # define x86_default_pci_init         NULL
  #endif
  
  extern unsigned long pci_mem_start;
@@@ -124,8 -131,6 +131,8 @@@ extern void pci_iommu_alloc(void)
  #include "pci_64.h"
  #endif
  
 +void dma32_reserve_bootmem(void);
 +
  /* implement the pci_ DMA API in terms of the generic device dma_ one */
  #include <asm-generic/pci-dma-compat.h>
  
index 05b58ccb2e826521e627e439e466412e3e42027a,36085518badb1911f7c150abaad290fa2e527065..1a0422348d6d3f5aae451824c14f65fc0631bfc2
@@@ -29,7 -29,6 +29,7 @@@
  #define PCI_CHECK_ENABLE_AMD_MMCONF   0x20000
  #define PCI_HAS_IO_ECS                0x40000
  #define PCI_NOASSIGN_ROMS     0x80000
 +#define PCI_ROOT_NO_CRS               0x100000
  
  extern unsigned int pci_probe;
  extern unsigned long pirq_table_addr;
@@@ -83,7 -82,6 +83,6 @@@ struct irq_routing_table 
  
  extern unsigned int pcibios_irq_mask;
  
- extern int pcibios_scanned;
  extern spinlock_t pci_config_lock;
  
  extern int (*pcibios_enable_irq)(struct pci_dev *dev);
@@@ -106,16 -104,15 +105,15 @@@ extern bool port_cf9_safe
  extern int pci_direct_probe(void);
  extern void pci_direct_init(int type);
  extern void pci_pcbios_init(void);
- extern int pci_olpc_init(void);
  extern void __init dmi_check_pciprobe(void);
  extern void __init dmi_check_skip_isa_align(void);
  
  /* some common used subsys_initcalls */
  extern int __init pci_acpi_init(void);
- extern int __init pcibios_irq_init(void);
- extern int __init pci_visws_init(void);
- extern int __init pci_numaq_init(void);
+ extern void __init pcibios_irq_init(void);
  extern int __init pcibios_init(void);
+ extern int pci_legacy_init(void);
+ extern void pcibios_fixup_irqs(void);
  
  /* pci-mmconfig.c */
  
@@@ -183,3 -180,17 +181,17 @@@ static inline void mmio_config_writel(v
  {
        asm volatile("movl %%eax,(%1)" : : "a" (val), "r" (pos) : "memory");
  }
+ #ifdef CONFIG_PCI
+ # ifdef CONFIG_ACPI
+ #  define x86_default_pci_init                pci_acpi_init
+ # else
+ #  define x86_default_pci_init                pci_legacy_init
+ # endif
+ # define x86_default_pci_init_irq     pcibios_irq_init
+ # define x86_default_pci_fixup_irqs   pcibios_fixup_irqs
+ #else
+ # define x86_default_pci_init         NULL
+ # define x86_default_pci_init_irq     NULL
+ # define x86_default_pci_fixup_irqs   NULL
+ #endif
index 60cc3526908377d98fe787f5956cf34c1f2346eb,b1d62bbcae3dbe3225cfdb95940f4176a5c8710b..519b54327d750f5e3580ed45cc68e78272c1ba81
@@@ -98,6 -98,20 +98,20 @@@ struct x86_init_iommu 
        int (*iommu_init)(void);
  };
  
+ /**
+  * struct x86_init_pci - platform specific pci init functions
+  * @arch_init:                        platform specific pci arch init call
+  * @init:                     platform specific pci subsystem init
+  * @init_irq:                 platform specific pci irq init
+  * @fixup_irqs:                       platform specific pci irq fixup
+  */
+ struct x86_init_pci {
+       int (*arch_init)(void);
+       int (*init)(void);
+       void (*init_irq)(void);
+       void (*fixup_irqs)(void);
+ };
  /**
   * struct x86_init_ops - functions for platform specific setup
   *
@@@ -110,6 -124,7 +124,7 @@@ struct x86_init_ops 
        struct x86_init_paging          paging;
        struct x86_init_timers          timers;
        struct x86_init_iommu           iommu;
+       struct x86_init_pci             pci;
  };
  
  /**
@@@ -126,7 -141,6 +141,7 @@@ struct x86_cpuinit_ops 
   * @get_wallclock:            get time from HW clock like RTC etc.
   * @set_wallclock:            set time back to HW clock
   * @is_untracked_pat_range    exclude from PAT logic
 + * @nmi_init                  enable NMI on cpus
   */
  struct x86_platform_ops {
        unsigned long (*calibrate_tsc)(void);
        int (*set_wallclock)(unsigned long nowtime);
        void (*iommu_shutdown)(void);
        bool (*is_untracked_pat_range)(u64 start, u64 end);
 +      void (*nmi_init)(void);
  };
  
  extern struct x86_init_ops x86_init;
index 738fcb60e7086ccca4096fa82bc818b2d0d7b35a,db2773c6defd7dc03ba36e729a3095121abb373e..a54d714545ff826fba14badabf1af6401809b712
@@@ -35,6 -35,7 +35,7 @@@
  #include <linux/ioport.h>
  #include <linux/pci.h>
  
+ #include <asm/pci_x86.h>
  #include <asm/pgtable.h>
  #include <asm/io_apic.h>
  #include <asm/apic.h>
@@@ -49,7 -50,6 +50,7 @@@ EXPORT_SYMBOL(acpi_disabled)
  
  #ifdef        CONFIG_X86_64
  # include <asm/proto.h>
 +# include <asm/numa_64.h>
  #endif                                /* X86 */
  
  #define BAD_MADT_ENTRY(entry, end) (                                      \
@@@ -490,25 -490,6 +491,25 @@@ int acpi_register_gsi(struct device *de
   */
  #ifdef CONFIG_ACPI_HOTPLUG_CPU
  
 +static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 +{
 +#ifdef CONFIG_ACPI_NUMA
 +      int nid;
 +
 +      nid = acpi_get_node(handle);
 +      if (nid == -1 || !node_online(nid))
 +              return;
 +#ifdef CONFIG_X86_64
 +      apicid_to_node[physid] = nid;
 +      numa_set_node(cpu, nid);
 +#else /* CONFIG_X86_32 */
 +      apicid_2_node[physid] = nid;
 +      cpu_to_node_map[cpu] = nid;
 +#endif
 +
 +#endif
 +}
 +
  static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
  {
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        }
  
        cpu = cpumask_first(new_map);
 +      acpi_map_cpu2node(handle, cpu, physid);
  
        *pcpu = cpu;
        retval = 0;
@@@ -1370,6 -1350,14 +1371,6 @@@ static struct dmi_system_id __initdata 
                     DMI_MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
                     },
         },
 -      {
 -       .callback = force_acpi_ht,
 -       .ident = "ASUS P2B-DS",
 -       .matches = {
 -                   DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
 -                   DMI_MATCH(DMI_BOARD_NAME, "P2B-DS"),
 -                   },
 -       },
        {
         .callback = force_acpi_ht,
         .ident = "ASUS CUR-DLS",
@@@ -1624,6 -1612,9 +1625,9 @@@ int __init acpi_boot_init(void
  
        acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet);
  
+       if (!acpi_noirq)
+               x86_init.pci.init = pci_acpi_init;
        return 0;
  }
  
index 0000000000000000000000000000000000000000,2afa27d01297c23a274341c8e4eca6c47898e50f..4b7099526d2c1c8c6c496f4ce0f8e028fbac9eab
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,784 +1,784 @@@
 -static void apbt_restart_clocksource(void);
+ /*
+  * apb_timer.c: Driver for Langwell APB timers
+  *
+  * (C) Copyright 2009 Intel Corporation
+  * Author: Jacob Pan (jacob.jun.pan@intel.com)
+  *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
+  * as published by the Free Software Foundation; version 2
+  * of the License.
+  *
+  * Note:
+  * Langwell is the south complex of Intel Moorestown MID platform. There are
+  * eight external timers in total that can be used by the operating system.
+  * The timer information, such as frequency and addresses, is provided to the
+  * OS via SFI tables.
+  * Timer interrupts are routed via FW/HW emulated IOAPIC independently via
+  * individual redirection table entries (RTE).
+  * Unlike HPET, there is no master counter, therefore one of the timers are
+  * used as clocksource. The overall allocation looks like:
+  *  - timer 0 - NR_CPUs for per cpu timer
+  *  - one timer for clocksource
+  *  - one timer for watchdog driver.
+  * It is also worth notice that APB timer does not support true one-shot mode,
+  * free-running mode will be used here to emulate one-shot mode.
+  * APB timer can also be used as broadcast timer along with per cpu local APIC
+  * timer, but by default APB timer has higher rating than local APIC timers.
+  */
+ #include <linux/clocksource.h>
+ #include <linux/clockchips.h>
+ #include <linux/delay.h>
+ #include <linux/errno.h>
+ #include <linux/init.h>
+ #include <linux/sysdev.h>
+ #include <linux/pm.h>
+ #include <linux/pci.h>
+ #include <linux/sfi.h>
+ #include <linux/interrupt.h>
+ #include <linux/cpu.h>
+ #include <linux/irq.h>
+ #include <asm/fixmap.h>
+ #include <asm/apb_timer.h>
+ #define APBT_MASK                     CLOCKSOURCE_MASK(32)
+ #define APBT_SHIFT                    22
+ #define APBT_CLOCKEVENT_RATING                150
+ #define APBT_CLOCKSOURCE_RATING               250
+ #define APBT_MIN_DELTA_USEC           200
+ #define EVT_TO_APBT_DEV(evt) container_of(evt, struct apbt_dev, evt)
+ #define APBT_CLOCKEVENT0_NUM   (0)
+ #define APBT_CLOCKEVENT1_NUM   (1)
+ #define APBT_CLOCKSOURCE_NUM   (2)
+ static unsigned long apbt_address;
+ static int apb_timer_block_enabled;
+ static void __iomem *apbt_virt_address;
+ static int phy_cs_timer_id;
+ /*
+  * Common DW APB timer info
+  */
+ static uint64_t apbt_freq;
+ static void apbt_set_mode(enum clock_event_mode mode,
+                         struct clock_event_device *evt);
+ static int apbt_next_event(unsigned long delta,
+                          struct clock_event_device *evt);
+ static cycle_t apbt_read_clocksource(struct clocksource *cs);
 -static void apbt_restart_clocksource(void)
++static void apbt_restart_clocksource(struct clocksource *cs);
+ struct apbt_dev {
+       struct clock_event_device evt;
+       unsigned int num;
+       int cpu;
+       unsigned int irq;
+       unsigned int tick;
+       unsigned int count;
+       unsigned int flags;
+       char name[10];
+ };
+ int disable_apbt_percpu __cpuinitdata;
+ static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev);
+ #ifdef CONFIG_SMP
+ static unsigned int apbt_num_timers_used;
+ static struct apbt_dev *apbt_devs;
+ #endif
+ static        inline unsigned long apbt_readl_reg(unsigned long a)
+ {
+       return readl(apbt_virt_address + a);
+ }
+ static inline void apbt_writel_reg(unsigned long d, unsigned long a)
+ {
+       writel(d, apbt_virt_address + a);
+ }
+ static inline unsigned long apbt_readl(int n, unsigned long a)
+ {
+       return readl(apbt_virt_address + a + n * APBTMRS_REG_SIZE);
+ }
+ static inline void apbt_writel(int n, unsigned long d, unsigned long a)
+ {
+       writel(d, apbt_virt_address + a + n * APBTMRS_REG_SIZE);
+ }
+ static inline void apbt_set_mapping(void)
+ {
+       struct sfi_timer_table_entry *mtmr;
+       if (apbt_virt_address) {
+               pr_debug("APBT base already mapped\n");
+               return;
+       }
+       mtmr = sfi_get_mtmr(APBT_CLOCKEVENT0_NUM);
+       if (mtmr == NULL) {
+               printk(KERN_ERR "Failed to get MTMR %d from SFI\n",
+                      APBT_CLOCKEVENT0_NUM);
+               return;
+       }
+       apbt_address = (unsigned long)mtmr->phys_addr;
+       if (!apbt_address) {
+               printk(KERN_WARNING "No timer base from SFI, use default\n");
+               apbt_address = APBT_DEFAULT_BASE;
+       }
+       apbt_virt_address = ioremap_nocache(apbt_address, APBT_MMAP_SIZE);
+       if (apbt_virt_address) {
+               pr_debug("Mapped APBT physical addr %p at virtual addr %p\n",\
+                        (void *)apbt_address, (void *)apbt_virt_address);
+       } else {
+               pr_debug("Failed mapping APBT phy address at %p\n",\
+                        (void *)apbt_address);
+               goto panic_noapbt;
+       }
+       apbt_freq = mtmr->freq_hz / USEC_PER_SEC;
+       sfi_free_mtmr(mtmr);
+       /* Now figure out the physical timer id for clocksource device */
+       mtmr = sfi_get_mtmr(APBT_CLOCKSOURCE_NUM);
+       if (mtmr == NULL)
+               goto panic_noapbt;
+       /* Now figure out the physical timer id */
+       phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff)
+               / APBTMRS_REG_SIZE;
+       pr_debug("Use timer %d for clocksource\n", phy_cs_timer_id);
+       return;
+ panic_noapbt:
+       panic("Failed to setup APB system timer\n");
+ }
+ static inline void apbt_clear_mapping(void)
+ {
+       iounmap(apbt_virt_address);
+       apbt_virt_address = NULL;
+ }
+ /*
+  * APBT timer interrupt enable / disable
+  */
+ static inline int is_apbt_capable(void)
+ {
+       return apbt_virt_address ? 1 : 0;
+ }
+ static struct clocksource clocksource_apbt = {
+       .name           = "apbt",
+       .rating         = APBT_CLOCKSOURCE_RATING,
+       .read           = apbt_read_clocksource,
+       .mask           = APBT_MASK,
+       .shift          = APBT_SHIFT,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+       .resume         = apbt_restart_clocksource,
+ };
+ /* boot APB clock event device */
+ static struct clock_event_device apbt_clockevent = {
+       .name           = "apbt0",
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .set_mode       = apbt_set_mode,
+       .set_next_event = apbt_next_event,
+       .shift          = APBT_SHIFT,
+       .irq            = 0,
+       .rating         = APBT_CLOCKEVENT_RATING,
+ };
+ /*
+  * if user does not want to use per CPU apb timer, just give it a lower rating
+  * than local apic timer and skip the late per cpu timer init.
+  */
+ static inline int __init setup_x86_mrst_timer(char *arg)
+ {
+       if (!arg)
+               return -EINVAL;
+       if (strcmp("apbt_only", arg) == 0)
+               disable_apbt_percpu = 0;
+       else if (strcmp("lapic_and_apbt", arg) == 0)
+               disable_apbt_percpu = 1;
+       else {
+               pr_warning("X86 MRST timer option %s not recognised"
+                          " use x86_mrst_timer=apbt_only or lapic_and_apbt\n",
+                          arg);
+               return -EINVAL;
+       }
+       return 0;
+ }
+ __setup("x86_mrst_timer=", setup_x86_mrst_timer);
+ /*
+  * start count down from 0xffff_ffff. this is done by toggling the enable bit
+  * then load initial load count to ~0.
+  */
+ static void apbt_start_counter(int n)
+ {
+       unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
+       ctrl &= ~APBTMR_CONTROL_ENABLE;
+       apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+       apbt_writel(n, ~0, APBTMR_N_LOAD_COUNT);
+       /* enable, mask interrupt */
+       ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
+       ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT);
+       apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+       /* read it once to get cached counter value initialized */
+       apbt_read_clocksource(&clocksource_apbt);
+ }
+ static irqreturn_t apbt_interrupt_handler(int irq, void *data)
+ {
+       struct apbt_dev *dev = (struct apbt_dev *)data;
+       struct clock_event_device *aevt = &dev->evt;
+       if (!aevt->event_handler) {
+               printk(KERN_INFO "Spurious APBT timer interrupt on %d\n",
+                      dev->num);
+               return IRQ_NONE;
+       }
+       aevt->event_handler(aevt);
+       return IRQ_HANDLED;
+ }
++static void apbt_restart_clocksource(struct clocksource *cs)
+ {
+       apbt_start_counter(phy_cs_timer_id);
+ }
+ /* Setup IRQ routing via IOAPIC */
+ #ifdef CONFIG_SMP
+ static void apbt_setup_irq(struct apbt_dev *adev)
+ {
+       struct irq_chip *chip;
+       struct irq_desc *desc;
+       /* timer0 irq has been setup early */
+       if (adev->irq == 0)
+               return;
+       desc = irq_to_desc(adev->irq);
+       chip = get_irq_chip(adev->irq);
+       disable_irq(adev->irq);
+       desc->status |= IRQ_MOVE_PCNTXT;
+       irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
+       /* APB timer irqs are set up as mp_irqs, timer is edge triggerred */
+       set_irq_chip_and_handler_name(adev->irq, chip, handle_edge_irq, "edge");
+       enable_irq(adev->irq);
+       if (system_state == SYSTEM_BOOTING)
+               if (request_irq(adev->irq, apbt_interrupt_handler,
+                               IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
+                               adev->name, adev)) {
+                       printk(KERN_ERR "Failed request IRQ for APBT%d\n",
+                              adev->num);
+               }
+ }
+ #endif
+ static void apbt_enable_int(int n)
+ {
+       unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
+       /* clear pending intr */
+       apbt_readl(n, APBTMR_N_EOI);
+       ctrl &= ~APBTMR_CONTROL_INT;
+       apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+ }
+ static void apbt_disable_int(int n)
+ {
+       unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
+       ctrl |= APBTMR_CONTROL_INT;
+       apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+ }
+ static int __init apbt_clockevent_register(void)
+ {
+       struct sfi_timer_table_entry *mtmr;
+       struct apbt_dev *adev = &__get_cpu_var(cpu_apbt_dev);
+       mtmr = sfi_get_mtmr(APBT_CLOCKEVENT0_NUM);
+       if (mtmr == NULL) {
+               printk(KERN_ERR "Failed to get MTMR %d from SFI\n",
+                      APBT_CLOCKEVENT0_NUM);
+               return -ENODEV;
+       }
+       /*
+        * We need to calculate the scaled math multiplication factor for
+        * nanosecond to apbt tick conversion.
+        * mult = (nsec/cycle)*2^APBT_SHIFT
+        */
+       apbt_clockevent.mult = div_sc((unsigned long) mtmr->freq_hz
+                                     , NSEC_PER_SEC, APBT_SHIFT);
+       /* Calculate the min / max delta */
+       apbt_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
+                                                          &apbt_clockevent);
+       apbt_clockevent.min_delta_ns = clockevent_delta2ns(
+               APBT_MIN_DELTA_USEC*apbt_freq,
+               &apbt_clockevent);
+       /*
+        * Start apbt with the boot cpu mask and make it
+        * global if not used for per cpu timer.
+        */
+       apbt_clockevent.cpumask = cpumask_of(smp_processor_id());
+       adev->num = smp_processor_id();
+       memcpy(&adev->evt, &apbt_clockevent, sizeof(struct clock_event_device));
+       if (disable_apbt_percpu) {
+               apbt_clockevent.rating = APBT_CLOCKEVENT_RATING - 100;
+               global_clock_event = &adev->evt;
+               printk(KERN_DEBUG "%s clockevent registered as global\n",
+                      global_clock_event->name);
+       }
+       if (request_irq(apbt_clockevent.irq, apbt_interrupt_handler,
+                       IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
+                       apbt_clockevent.name, adev)) {
+               printk(KERN_ERR "Failed request IRQ for APBT%d\n",
+                      apbt_clockevent.irq);
+       }
+       clockevents_register_device(&adev->evt);
+       /* Start APBT 0 interrupts */
+       apbt_enable_int(APBT_CLOCKEVENT0_NUM);
+       sfi_free_mtmr(mtmr);
+       return 0;
+ }
+ #ifdef CONFIG_SMP
+ /* Should be called with per cpu */
+ void apbt_setup_secondary_clock(void)
+ {
+       struct apbt_dev *adev;
+       struct clock_event_device *aevt;
+       int cpu;
+       /* Don't register boot CPU clockevent */
+       cpu = smp_processor_id();
+       if (cpu == boot_cpu_id)
+               return;
+       /*
+        * We need to calculate the scaled math multiplication factor for
+        * nanosecond to apbt tick conversion.
+        * mult = (nsec/cycle)*2^APBT_SHIFT
+        */
+       printk(KERN_INFO "Init per CPU clockevent %d\n", cpu);
+       adev = &per_cpu(cpu_apbt_dev, cpu);
+       aevt = &adev->evt;
+       memcpy(aevt, &apbt_clockevent, sizeof(*aevt));
+       aevt->cpumask = cpumask_of(cpu);
+       aevt->name = adev->name;
+       aevt->mode = CLOCK_EVT_MODE_UNUSED;
+       printk(KERN_INFO "Registering CPU %d clockevent device %s, mask %08x\n",
+              cpu, aevt->name, *(u32 *)aevt->cpumask);
+       apbt_setup_irq(adev);
+       clockevents_register_device(aevt);
+       apbt_enable_int(cpu);
+       return;
+ }
+ /*
+  * this notify handler process CPU hotplug events. in case of S0i3, nonboot
+  * cpus are disabled/enabled frequently, for performance reasons, we keep the
+  * per cpu timer irq registered so that we do need to do free_irq/request_irq.
+  *
+  * TODO: it might be more reliable to directly disable percpu clockevent device
+  * without the notifier chain. currently, cpu 0 may get interrupts from other
+  * cpu timers during the offline process due to the ordering of notification.
+  * the extra interrupt is harmless.
+  */
+ static int apbt_cpuhp_notify(struct notifier_block *n,
+                            unsigned long action, void *hcpu)
+ {
+       unsigned long cpu = (unsigned long)hcpu;
+       struct apbt_dev *adev = &per_cpu(cpu_apbt_dev, cpu);
+       switch (action & 0xf) {
+       case CPU_DEAD:
+               apbt_disable_int(cpu);
+               if (system_state == SYSTEM_RUNNING)
+                       pr_debug("skipping APBT CPU %lu offline\n", cpu);
+               else if (adev) {
+                       pr_debug("APBT clockevent for cpu %lu offline\n", cpu);
+                       free_irq(adev->irq, adev);
+               }
+               break;
+       default:
+               pr_debug(KERN_INFO "APBT notified %lu, no action\n", action);
+       }
+       return NOTIFY_OK;
+ }
+ static __init int apbt_late_init(void)
+ {
+       if (disable_apbt_percpu)
+               return 0;
+       /* This notifier should be called after workqueue is ready */
+       hotcpu_notifier(apbt_cpuhp_notify, -20);
+       return 0;
+ }
+ fs_initcall(apbt_late_init);
+ #else
+ void apbt_setup_secondary_clock(void) {}
+ #endif /* CONFIG_SMP */
+ static void apbt_set_mode(enum clock_event_mode mode,
+                         struct clock_event_device *evt)
+ {
+       unsigned long ctrl;
+       uint64_t delta;
+       int timer_num;
+       struct apbt_dev *adev = EVT_TO_APBT_DEV(evt);
+       timer_num = adev->num;
+       pr_debug("%s CPU %d timer %d mode=%d\n",
+                __func__, first_cpu(*evt->cpumask), timer_num, mode);
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * apbt_clockevent.mult;
+               delta >>= apbt_clockevent.shift;
+               ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
+               ctrl |= APBTMR_CONTROL_MODE_PERIODIC;
+               apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+               /*
+                * DW APB p. 46, have to disable timer before load counter,
+                * may cause sync problem.
+                */
+               ctrl &= ~APBTMR_CONTROL_ENABLE;
+               apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+               udelay(1);
+               pr_debug("Setting clock period %d for HZ %d\n", (int)delta, HZ);
+               apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT);
+               ctrl |= APBTMR_CONTROL_ENABLE;
+               apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+               break;
+               /* APB timer does not have one-shot mode, use free running mode */
+       case CLOCK_EVT_MODE_ONESHOT:
+               ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
+               /*
+                * set free running mode, this mode will let timer reload max
+                * timeout which will give time (3min on 25MHz clock) to rearm
+                * the next event, therefore emulate the one-shot mode.
+                */
+               ctrl &= ~APBTMR_CONTROL_ENABLE;
+               ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
+               apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+               /* write again to set free running mode */
+               apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+               /*
+                * DW APB p. 46, load counter with all 1s before starting free
+                * running mode.
+                */
+               apbt_writel(timer_num, ~0, APBTMR_N_LOAD_COUNT);
+               ctrl &= ~APBTMR_CONTROL_INT;
+               ctrl |= APBTMR_CONTROL_ENABLE;
+               apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               apbt_disable_int(timer_num);
+               ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
+               ctrl &= ~APBTMR_CONTROL_ENABLE;
+               apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+               break;
+       case CLOCK_EVT_MODE_RESUME:
+               apbt_enable_int(timer_num);
+               break;
+       }
+ }
+ static int apbt_next_event(unsigned long delta,
+                          struct clock_event_device *evt)
+ {
+       unsigned long ctrl;
+       int timer_num;
+       struct apbt_dev *adev = EVT_TO_APBT_DEV(evt);
+       timer_num = adev->num;
+       /* Disable timer */
+       ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
+       ctrl &= ~APBTMR_CONTROL_ENABLE;
+       apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+       /* write new count */
+       apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT);
+       ctrl |= APBTMR_CONTROL_ENABLE;
+       apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+       return 0;
+ }
+ /*
+  * APB timer clock is not in sync with pclk on Langwell, which translates to
+  * unreliable read value caused by sampling error. the error does not add up
+  * overtime and only happens when sampling a 0 as a 1 by mistake. so the time
+  * would go backwards. the following code is trying to prevent time traveling
+  * backwards. little bit paranoid.
+  */
+ static cycle_t apbt_read_clocksource(struct clocksource *cs)
+ {
+       unsigned long t0, t1, t2;
+       static unsigned long last_read;
+ bad_count:
+       t1 = apbt_readl(phy_cs_timer_id,
+                       APBTMR_N_CURRENT_VALUE);
+       t2 = apbt_readl(phy_cs_timer_id,
+                       APBTMR_N_CURRENT_VALUE);
+       if (unlikely(t1 < t2)) {
+               pr_debug("APBT: read current count error %lx:%lx:%lx\n",
+                        t1, t2, t2 - t1);
+               goto bad_count;
+       }
+       /*
+        * check against cached last read, makes sure time does not go back.
+        * it could be a normal rollover but we will do tripple check anyway
+        */
+       if (unlikely(t2 > last_read)) {
+               /* check if we have a normal rollover */
+               unsigned long raw_intr_status =
+                       apbt_readl_reg(APBTMRS_RAW_INT_STATUS);
+               /*
+                * cs timer interrupt is masked but raw intr bit is set if
+                * rollover occurs. then we read EOI reg to clear it.
+                */
+               if (raw_intr_status & (1 << phy_cs_timer_id)) {
+                       apbt_readl(phy_cs_timer_id, APBTMR_N_EOI);
+                       goto out;
+               }
+               pr_debug("APB CS going back %lx:%lx:%lx ",
+                        t2, last_read, t2 - last_read);
+ bad_count_x3:
+               pr_debug(KERN_INFO "tripple check enforced\n");
+               t0 = apbt_readl(phy_cs_timer_id,
+                               APBTMR_N_CURRENT_VALUE);
+               udelay(1);
+               t1 = apbt_readl(phy_cs_timer_id,
+                               APBTMR_N_CURRENT_VALUE);
+               udelay(1);
+               t2 = apbt_readl(phy_cs_timer_id,
+                               APBTMR_N_CURRENT_VALUE);
+               if ((t2 > t1) || (t1 > t0)) {
+                       printk(KERN_ERR "Error: APB CS tripple check failed\n");
+                       goto bad_count_x3;
+               }
+       }
+ out:
+       last_read = t2;
+       return (cycle_t)~t2;
+ }
+ static int apbt_clocksource_register(void)
+ {
+       u64 start, now;
+       cycle_t t1;
+       /* Start the counter, use timer 2 as source, timer 0/1 for event */
+       apbt_start_counter(phy_cs_timer_id);
+       /* Verify whether apbt counter works */
+       t1 = apbt_read_clocksource(&clocksource_apbt);
+       rdtscll(start);
+       /*
+        * We don't know the TSC frequency yet, but waiting for
+        * 200000 TSC cycles is safe:
+        * 4 GHz == 50us
+        * 1 GHz == 200us
+        */
+       do {
+               rep_nop();
+               rdtscll(now);
+       } while ((now - start) < 200000UL);
+       /* APBT is the only always on clocksource, it has to work! */
+       if (t1 == apbt_read_clocksource(&clocksource_apbt))
+               panic("APBT counter not counting. APBT disabled\n");
+       /*
+        * initialize and register APBT clocksource
+        * convert that to ns/clock cycle
+        * mult = (ns/c) * 2^APBT_SHIFT
+        */
+       clocksource_apbt.mult = div_sc(MSEC_PER_SEC,
+                                      (unsigned long) apbt_freq, APBT_SHIFT);
+       clocksource_register(&clocksource_apbt);
+       return 0;
+ }
+ /*
+  * Early setup the APBT timer, only use timer 0 for booting then switch to
+  * per CPU timer if possible.
+  * returns 1 if per cpu apbt is setup
+  * returns 0 if no per cpu apbt is chosen
+  * panic if set up failed, this is the only platform timer on Moorestown.
+  */
+ void __init apbt_time_init(void)
+ {
+ #ifdef CONFIG_SMP
+       int i;
+       struct sfi_timer_table_entry *p_mtmr;
+       unsigned int percpu_timer;
+       struct apbt_dev *adev;
+ #endif
+       if (apb_timer_block_enabled)
+               return;
+       apbt_set_mapping();
+       if (apbt_virt_address) {
+               pr_debug("Found APBT version 0x%lx\n",\
+                        apbt_readl_reg(APBTMRS_COMP_VERSION));
+       } else
+               goto out_noapbt;
+       /*
+        * Read the frequency and check for a sane value, for ESL model
+        * we extend the possible clock range to allow time scaling.
+        */
+       if (apbt_freq < APBT_MIN_FREQ || apbt_freq > APBT_MAX_FREQ) {
+               pr_debug("APBT has invalid freq 0x%llx\n", apbt_freq);
+               goto out_noapbt;
+       }
+       if (apbt_clocksource_register()) {
+               pr_debug("APBT has failed to register clocksource\n");
+               goto out_noapbt;
+       }
+       if (!apbt_clockevent_register())
+               apb_timer_block_enabled = 1;
+       else {
+               pr_debug("APBT has failed to register clockevent\n");
+               goto out_noapbt;
+       }
+ #ifdef CONFIG_SMP
+       /* kernel cmdline disable apb timer, so we will use lapic timers */
+       if (disable_apbt_percpu) {
+               printk(KERN_INFO "apbt: disabled per cpu timer\n");
+               return;
+       }
+       pr_debug("%s: %d CPUs online\n", __func__, num_online_cpus());
+       if (num_possible_cpus() <= sfi_mtimer_num) {
+               percpu_timer = 1;
+               apbt_num_timers_used = num_possible_cpus();
+       } else {
+               percpu_timer = 0;
+               apbt_num_timers_used = 1;
+               adev = &per_cpu(cpu_apbt_dev, 0);
+               adev->flags &= ~APBT_DEV_USED;
+       }
+       pr_debug("%s: %d APB timers used\n", __func__, apbt_num_timers_used);
+       /* here we set up per CPU timer data structure */
+       apbt_devs = kzalloc(sizeof(struct apbt_dev) * apbt_num_timers_used,
+                           GFP_KERNEL);
+       if (!apbt_devs) {
+               printk(KERN_ERR "Failed to allocate APB timer devices\n");
+               return;
+       }
+       for (i = 0; i < apbt_num_timers_used; i++) {
+               adev = &per_cpu(cpu_apbt_dev, i);
+               adev->num = i;
+               adev->cpu = i;
+               p_mtmr = sfi_get_mtmr(i);
+               if (p_mtmr) {
+                       adev->tick = p_mtmr->freq_hz;
+                       adev->irq = p_mtmr->irq;
+               } else
+                       printk(KERN_ERR "Failed to get timer for cpu %d\n", i);
+               adev->count = 0;
+               sprintf(adev->name, "apbt%d", i);
+       }
+ #endif
+       return;
+ out_noapbt:
+       apbt_clear_mapping();
+       apb_timer_block_enabled = 0;
+       panic("failed to enable APB timer\n");
+ }
+ static inline void apbt_disable(int n)
+ {
+       if (is_apbt_capable()) {
+               unsigned long ctrl =  apbt_readl(n, APBTMR_N_CONTROL);
+               ctrl &= ~APBTMR_CONTROL_ENABLE;
+               apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+       }
+ }
+ /* called before apb_timer_enable, use early map */
+ unsigned long apbt_quick_calibrate()
+ {
+       int i, scale;
+       u64 old, new;
+       cycle_t t1, t2;
+       unsigned long khz = 0;
+       u32 loop, shift;
+       apbt_set_mapping();
+       apbt_start_counter(phy_cs_timer_id);
+       /* check if the timer can count down, otherwise return */
+       old = apbt_read_clocksource(&clocksource_apbt);
+       i = 10000;
+       while (--i) {
+               if (old != apbt_read_clocksource(&clocksource_apbt))
+                       break;
+       }
+       if (!i)
+               goto failed;
+       /* count 16 ms */
+       loop = (apbt_freq * 1000) << 4;
+       /* restart the timer to ensure it won't get to 0 in the calibration */
+       apbt_start_counter(phy_cs_timer_id);
+       old = apbt_read_clocksource(&clocksource_apbt);
+       old += loop;
+       t1 = __native_read_tsc();
+       do {
+               new = apbt_read_clocksource(&clocksource_apbt);
+       } while (new < old);
+       t2 = __native_read_tsc();
+       shift = 5;
+       if (unlikely(loop >> shift == 0)) {
+               printk(KERN_INFO
+                      "APBT TSC calibration failed, not enough resolution\n");
+               return 0;
+       }
+       scale = (int)div_u64((t2 - t1), loop >> shift);
+       khz = (scale * apbt_freq * 1000) >> shift;
+       printk(KERN_INFO "TSC freq calculated by APB timer is %lu khz\n", khz);
+       return khz;
+ failed:
+       return 0;
+ }
index 6e29b2a77aa89e113e3605136cf74770317e99aa,94f22b12858d3d2702068c6ff52aedb58f4bdcdb..00187f1fcfb7f75602f845f4f01bf6dc6d3bfdf2
@@@ -581,7 -581,7 +581,7 @@@ calibrate_by_pmtimer(long deltapm, lon
                res = (((u64)(*deltatsc)) * pm_100ms);
                do_div(res, deltapm);
                apic_printk(APIC_VERBOSE, "TSC delta adjusted to "
 -                                        "PM-Timer: %lu (%ld) \n",
 +                                        "PM-Timer: %lu (%ld)\n",
                                        (unsigned long)res, *deltatsc);
                *deltatsc = (long)res;
        }
@@@ -1390,7 -1390,7 +1390,7 @@@ void __init enable_IR_x2apic(void
        }
  
        local_irq_save(flags);
-       mask_8259A();
+       legacy_pic->mask_all();
        mask_IO_APIC_setup(ioapic_entries);
  
        if (dmar_table_init_ret)
  nox2apic:
        if (!ret) /* IR enabling failed */
                restore_IO_APIC_setup(ioapic_entries);
-       unmask_8259A();
+       legacy_pic->restore_mask();
        local_irq_restore(flags);
  
  out:
@@@ -2018,7 -2018,7 +2018,7 @@@ static int lapic_resume(struct sys_devi
                }
  
                mask_IO_APIC_setup(ioapic_entries);
-               mask_8259A();
+               legacy_pic->mask_all();
        }
  
        if (x2apic_mode)
  
        if (intr_remapping_enabled) {
                reenable_intr_remapping(x2apic_mode);
-               unmask_8259A();
+               legacy_pic->restore_mask();
                restore_IO_APIC_setup(ioapic_entries);
                free_ioapic_entries(ioapic_entries);
        }
index 14862f11cc4ad68a1b8ef7761ec3f2c37f82b532,b758d49b811ce6e7b3ba00059aad62a0b8b914ff..e4e0ddcb1546bde04f0d01675756622b9d2434bd
@@@ -143,12 -143,6 +143,6 @@@ static struct irq_cfg irq_cfgx[NR_IRQS_
  static struct irq_cfg irq_cfgx[NR_IRQS];
  #endif
  
- void __init io_apic_disable_legacy(void)
- {
-       nr_legacy_irqs = 0;
-       nr_irqs_gsi = 0;
- }
  int __init arch_early_irq_init(void)
  {
        struct irq_cfg *cfg;
        int node;
        int i;
  
+       if (!legacy_pic->nr_legacy_irqs) {
+               nr_irqs_gsi = 0;
+               io_apic_irqs = ~0UL;
+       }
        cfg = irq_cfgx;
        count = ARRAY_SIZE(irq_cfgx);
        node= cpu_to_node(boot_cpu_id);
                 * For legacy IRQ's, start with assigning irq0 to irq15 to
                 * IRQ0_VECTOR to IRQ15_VECTOR on cpu 0.
                 */
-               if (i < nr_legacy_irqs) {
+               if (i < legacy_pic->nr_legacy_irqs) {
                        cfg[i].vector = IRQ0_VECTOR + i;
                        cpumask_set_cpu(0, cfg[i].domain);
                }
@@@ -852,7 -851,7 +851,7 @@@ static int __init find_isa_irq_apic(in
   */
  static int EISA_ELCR(unsigned int irq)
  {
-       if (irq < nr_legacy_irqs) {
+       if (irq < legacy_pic->nr_legacy_irqs) {
                unsigned int port = 0x4d0 + (irq >> 3);
                return (inb(port) >> (irq & 7)) & 1;
        }
@@@ -1439,7 -1438,7 +1438,7 @@@ static void setup_IO_APIC_irq(int apic_
         * controllers like 8259. Now that IO-APIC can handle this irq, update
         * the cfg->domain.
         */
-       if (irq < nr_legacy_irqs && cpumask_test_cpu(0, cfg->domain))
+       if (irq < legacy_pic->nr_legacy_irqs && cpumask_test_cpu(0, cfg->domain))
                apic->vector_allocation_domain(0, cfg->domain);
  
        if (assign_irq_vector(irq, cfg, apic->target_cpus()))
        }
  
        ioapic_register_intr(irq, desc, trigger);
-       if (irq < nr_legacy_irqs)
-               disable_8259A_irq(irq);
+       if (irq < legacy_pic->nr_legacy_irqs)
+               legacy_pic->chip->mask(irq);
  
        ioapic_write_entry(apic_id, pin, entry);
  }
@@@ -1475,7 -1474,7 +1474,7 @@@ static struct 
  
  static void __init setup_IO_APIC_irqs(void)
  {
 -      int apic_id = 0, pin, idx, irq;
 +      int apic_id, pin, idx, irq;
        int notcon = 0;
        struct irq_desc *desc;
        struct irq_cfg *cfg;
  
        apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
  
 -#ifdef CONFIG_ACPI
 -      if (!acpi_disabled && acpi_ioapic) {
 -              apic_id = mp_find_ioapic(0);
 -              if (apic_id < 0)
 -                      apic_id = 0;
 -      }
 -#endif
 -
 +      for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
        for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
                idx = find_irq_entry(apic_id, pin, mp_INT);
                if (idx == -1) {
  
                irq = pin_2_irq(idx, apic_id, pin);
  
 +              if ((apic_id > 0) && (irq > 16))
 +                      continue;
 +
                /*
                 * Skip the timer IRQ if there's a quirk handler
                 * installed and if it returns 1:
@@@ -1695,7 -1698,7 +1694,7 @@@ __apicdebuginit(void) print_IO_APIC(voi
        printk(KERN_DEBUG ".... IRQ redirection table:\n");
  
        printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
 -                        " Stat Dmod Deli Vect:   \n");
 +                        " Stat Dmod Deli Vect:\n");
  
        for (i = 0; i <= reg_01.bits.entries; i++) {
                struct IO_APIC_route_entry entry;
@@@ -1873,7 -1876,7 +1872,7 @@@ __apicdebuginit(void) print_PIC(void
        unsigned int v;
        unsigned long flags;
  
-       if (!nr_legacy_irqs)
+       if (!legacy_pic->nr_legacy_irqs)
                return;
  
        printk(KERN_DEBUG "\nprinting PIC contents\n");
@@@ -1957,7 -1960,7 +1956,7 @@@ void __init enable_IO_APIC(void
                nr_ioapic_registers[apic] = reg_01.bits.entries+1;
        }
  
-       if (!nr_legacy_irqs)
+       if (!legacy_pic->nr_legacy_irqs)
                return;
  
        for(apic = 0; apic < nr_ioapics; apic++) {
@@@ -2014,7 -2017,7 +2013,7 @@@ void disable_IO_APIC(void
         */
        clear_IO_APIC();
  
-       if (!nr_legacy_irqs)
+       if (!legacy_pic->nr_legacy_irqs)
                return;
  
        /*
@@@ -2247,9 -2250,9 +2246,9 @@@ static unsigned int startup_ioapic_irq(
        struct irq_cfg *cfg;
  
        raw_spin_lock_irqsave(&ioapic_lock, flags);
-       if (irq < nr_legacy_irqs) {
-               disable_8259A_irq(irq);
-               if (i8259A_irq_pending(irq))
+       if (irq < legacy_pic->nr_legacy_irqs) {
+               legacy_pic->chip->mask(irq);
+               if (legacy_pic->irq_pending(irq))
                        was_pending = 1;
        }
        cfg = irq_cfg(irq);
@@@ -2782,8 -2785,8 +2781,8 @@@ static inline void init_IO_APIC_traps(v
                         * so default to an old-fashioned 8259
                         * interrupt if we can..
                         */
-                       if (irq < nr_legacy_irqs)
-                               make_8259A_irq(irq);
+                       if (irq < legacy_pic->nr_legacy_irqs)
+                               legacy_pic->make_irq(irq);
                        else
                                /* Strange. Oh, well.. */
                                desc->chip = &no_irq_chip;
@@@ -2940,7 -2943,7 +2939,7 @@@ static inline void __init check_timer(v
        /*
         * get/set the timer IRQ vector:
         */
-       disable_8259A_irq(0);
+       legacy_pic->chip->mask(0);
        assign_irq_vector(0, cfg, apic->target_cpus());
  
        /*
         * automatically.
         */
        apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
-       init_8259A(1);
+       legacy_pic->init(1);
  #ifdef CONFIG_X86_32
        {
                unsigned int ver;
                if (timer_irq_works()) {
                        if (nmi_watchdog == NMI_IO_APIC) {
                                setup_nmi();
-                               enable_8259A_irq(0);
+                               legacy_pic->chip->unmask(0);
                        }
                        if (disable_timer_pin_1 > 0)
                                clear_IO_APIC_pin(0, pin1);
                 */
                replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2);
                setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
-               enable_8259A_irq(0);
+               legacy_pic->chip->unmask(0);
                if (timer_irq_works()) {
                        apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
                        timer_through_8259 = 1;
                        if (nmi_watchdog == NMI_IO_APIC) {
-                               disable_8259A_irq(0);
+                               legacy_pic->chip->mask(0);
                                setup_nmi();
-                               enable_8259A_irq(0);
+                               legacy_pic->chip->unmask(0);
                        }
                        goto out;
                }
                 * Cleanup, just in case ...
                 */
                local_irq_disable();
-               disable_8259A_irq(0);
+               legacy_pic->chip->mask(0);
                clear_IO_APIC_pin(apic2, pin2);
                apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
        }
  
        lapic_register_intr(0, desc);
        apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);     /* Fixed mode */
-       enable_8259A_irq(0);
+       legacy_pic->chip->unmask(0);
  
        if (timer_irq_works()) {
                apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
                goto out;
        }
        local_irq_disable();
-       disable_8259A_irq(0);
+       legacy_pic->chip->mask(0);
        apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
        apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
  
        apic_printk(APIC_QUIET, KERN_INFO
                    "...trying to set up timer as ExtINT IRQ...\n");
  
-       init_8259A(0);
-       make_8259A_irq(0);
+       legacy_pic->init(0);
+       legacy_pic->make_irq(0);
        apic_write(APIC_LVT0, APIC_DM_EXTINT);
  
        unlock_ExtINT_logic();
@@@ -3126,7 -3129,7 +3125,7 @@@ void __init setup_IO_APIC(void
        /*
         * calling enable_IO_APIC() is moved to setup_local_APIC for BP
         */
-       io_apic_irqs = nr_legacy_irqs ? ~PIC_IRQS : ~0UL;
+       io_apic_irqs = legacy_pic->nr_legacy_irqs ? ~PIC_IRQS : ~0UL;
  
        apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
        /*
        sync_Arb_IDs();
        setup_IO_APIC_irqs();
        init_IO_APIC_traps();
-       if (nr_legacy_irqs)
+       if (legacy_pic->nr_legacy_irqs)
                check_timer();
  }
  
@@@ -3872,28 -3875,6 +3871,28 @@@ void __init probe_nr_irqs_gsi(void
        printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi);
  }
  
 +#ifdef CONFIG_SPARSE_IRQ
 +int __init arch_probe_nr_irqs(void)
 +{
 +      int nr;
 +
 +      if (nr_irqs > (NR_VECTORS * nr_cpu_ids))
 +              nr_irqs = NR_VECTORS * nr_cpu_ids;
 +
 +      nr = nr_irqs_gsi + 8 * nr_cpu_ids;
 +#if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ)
 +      /*
 +       * for MSI and HT dyn irq
 +       */
 +      nr += nr_irqs_gsi * 16;
 +#endif
 +      if (nr < nr_irqs)
 +              nr_irqs = nr;
 +
 +      return 0;
 +}
 +#endif
 +
  static int __io_apic_set_pci_routing(struct device *dev, int irq,
                                struct io_apic_irq_attr *irq_attr)
  {
        /*
         * IRQs < 16 are already in the irq_2_pin[] map
         */
-       if (irq >= nr_legacy_irqs) {
+       if (irq >= legacy_pic->nr_legacy_irqs) {
                cfg = desc->chip_data;
                if (add_pin_to_irq_node_nopanic(cfg, node, ioapic, pin)) {
                        printk(KERN_INFO "can not add pin %d for irq %d\n",
@@@ -4101,23 -4082,27 +4100,23 @@@ int acpi_get_override_irq(int bus_irq, 
  #ifdef CONFIG_SMP
  void __init setup_ioapic_dest(void)
  {
 -      int pin, ioapic = 0, irq, irq_entry;
 +      int pin, ioapic, irq, irq_entry;
        struct irq_desc *desc;
        const struct cpumask *mask;
  
        if (skip_ioapic_setup == 1)
                return;
  
 -#ifdef CONFIG_ACPI
 -      if (!acpi_disabled && acpi_ioapic) {
 -              ioapic = mp_find_ioapic(0);
 -              if (ioapic < 0)
 -                      ioapic = 0;
 -      }
 -#endif
 -
 +      for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
        for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
                irq_entry = find_irq_entry(ioapic, pin, mp_INT);
                if (irq_entry == -1)
                        continue;
                irq = pin_2_irq(irq_entry, ioapic, pin);
  
 +              if ((ioapic > 0) && (irq > 16))
 +                      continue;
 +
                desc = irq_to_desc(irq);
  
                /*
@@@ -4302,3 -4287,24 +4301,24 @@@ void __init mp_register_ioapic(int id, 
  
        nr_ioapics++;
  }
+ /* Enable IOAPIC early just for system timer */
+ void __init pre_init_apic_IRQ0(void)
+ {
+       struct irq_cfg *cfg;
+       struct irq_desc *desc;
+       printk(KERN_INFO "Early APIC setup for system timer0\n");
+ #ifndef CONFIG_SMP
+       phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
+ #endif
+       desc = irq_to_desc_alloc_node(0, 0);
+       setup_local_APIC();
+       cfg = irq_cfg(0);
+       add_pin_to_irq_node(cfg, 0, 0, 0);
+       set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
+       setup_IO_APIC_irq(0, 0, 0, desc, 0, 0);
+ }
index bd7c96b5e8d8fd2f26f85c3e5e03cd5977682c68,f72b5f0f388ecc945413d77a190263e3737a5982..8aa65adbd25d75340fe2d73434528207921f4a83
@@@ -177,7 -177,7 +177,7 @@@ int __init check_nmi_watchdog(void
  error:
        if (nmi_watchdog == NMI_IO_APIC) {
                if (!timer_through_8259)
-                       disable_8259A_irq(0);
+                       legacy_pic->chip->mask(0);
                on_each_cpu(__acpi_nmi_disable, NULL, 1);
        }
  
@@@ -438,8 -438,8 +438,8 @@@ nmi_watchdog_tick(struct pt_regs *regs
                 * Ayiee, looks like this CPU is stuck ...
                 * wait a few IRQs (5 seconds) before doing the oops ...
                 */
 -              __this_cpu_inc(per_cpu_var(alert_counter));
 -              if (__this_cpu_read(per_cpu_var(alert_counter)) == 5 * nmi_hz)
 +              __this_cpu_inc(alert_counter);
 +              if (__this_cpu_read(alert_counter) == 5 * nmi_hz)
                        /*
                         * die_nmi will return ONLY if NOTIFY_STOP happens..
                         */
                                regs, panic_on_timeout);
        } else {
                __get_cpu_var(last_irq_sum) = sum;
 -              __this_cpu_write(per_cpu_var(alert_counter), 0);
 +              __this_cpu_write(alert_counter, 0);
        }
  
        /* see if the nmi watchdog went off */
index 47dd856708e5c160789253d30dd3f105061bc4b5,be5c4fd477785764550961ede675c1633aac9d6f..3e28401f161c768193e784cc013814cadf190078
@@@ -225,7 -225,7 +225,7 @@@ static void __init smp_read_mpc_oem(str
  
        mpc_record = 0;
        printk(KERN_INFO
 -              "Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
 +              "Found an OEM MPC table at %8p - parsing it...\n", oemtable);
  
        if (memcmp(oemtable->signature, MPC_OEM_SIGNATURE, 4)) {
                printk(KERN_WARNING
@@@ -277,6 -277,7 +277,7 @@@ static __init void early_check_numaq(vo
                x86_init.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus;
                x86_init.mpparse.mpc_oem_bus_info = mpc_oem_bus_info;
                x86_init.timers.tsc_pre_init = numaq_tsc_init;
+               x86_init.pci.init = pci_numaq_init;
        }
  }
  
index a435c76d714ebd81eef9d0fa9c293087ed92a7bc,86f7edcd0438d23e8145da3a7688f47e13c01e38..a02e80c3c54bedbfdcb05d8741461d0abdc6fe9d
@@@ -48,6 -48,7 +48,7 @@@
  #include <linux/err.h>
  #include <linux/nmi.h>
  #include <linux/tboot.h>
+ #include <linux/stackprotector.h>
  
  #include <asm/acpi.h>
  #include <asm/desc.h>
@@@ -67,6 -68,7 +68,7 @@@
  #include <linux/mc146818rtc.h>
  
  #include <asm/smpboot_hooks.h>
+ #include <asm/i8259.h>
  
  #ifdef CONFIG_X86_32
  u8 apicid_2_node[MAX_APICID];
@@@ -291,9 -293,9 +293,9 @@@ notrace static void __cpuinit start_sec
        check_tsc_sync_target();
  
        if (nmi_watchdog == NMI_IO_APIC) {
-               disable_8259A_irq(0);
+               legacy_pic->chip->mask(0);
                enable_NMI_through_LVT0();
-               enable_8259A_irq(0);
+               legacy_pic->chip->unmask(0);
        }
  
  #ifdef CONFIG_X86_32
        unlock_vector_lock();
        ipi_call_unlock();
        per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
 +      x86_platform.nmi_init();
  
        /* enable local interrupts */
        local_irq_enable();
  
+       /* to prevent fake stack check failure in clock setup */
+       boot_init_stack_canary();
        x86_cpuinit.setup_percpu_clockev();
  
        wmb();
index ee5746c946283284db77d153354ffa962b028c9f,1817cd7a03fa49b1e3af618c08f217826dd5a107..61a1e8c7e19f8169e736bd329e9b2b72c87c3cce
@@@ -4,9 -4,11 +4,11 @@@
   *  For licencing details see kernel-base/COPYING
   */
  #include <linux/init.h>
+ #include <linux/ioport.h>
  
  #include <asm/bios_ebda.h>
  #include <asm/paravirt.h>
+ #include <asm/pci_x86.h>
  #include <asm/mpspec.h>
  #include <asm/setup.h>
  #include <asm/apic.h>
@@@ -70,19 -72,22 +72,25 @@@ struct x86_init_ops x86_init __initdat
        .iommu = {
                .iommu_init             = iommu_init_noop,
        },
+       .pci = {
+               .init                   = x86_default_pci_init,
+               .init_irq               = x86_default_pci_init_irq,
+               .fixup_irqs             = x86_default_pci_fixup_irqs,
+       },
  };
  
  struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = {
        .setup_percpu_clockev           = setup_secondary_APIC_clock,
  };
  
 +static void default_nmi_init(void) { };
 +
  struct x86_platform_ops x86_platform = {
        .calibrate_tsc                  = native_calibrate_tsc,
        .get_wallclock                  = mach_get_cmos_time,
        .set_wallclock                  = mach_set_rtc_mmss,
        .iommu_shutdown                 = iommu_shutdown_noop,
        .is_untracked_pat_range         = is_ISA_range,
 +      .nmi_init                       = default_nmi_init
  };
diff --combined arch/x86/pci/Makefile
index 0b7d3e9593e157cb328db23c922f5c3c6cde8d20,56caf2a18baa61757fb22aea7a44341727b1d4e9..b110d97fb9254b564d46b423ab2378bc547a197d
@@@ -13,8 -13,11 +13,10 @@@ obj-$(CONFIG_X86_VISWS)             += visws.
  
  obj-$(CONFIG_X86_NUMAQ)               += numaq_32.o
  
+ obj-$(CONFIG_X86_MRST)                += mrst.o
  obj-y                         += common.o early.o
 -obj-y                         += amd_bus.o
 -obj-$(CONFIG_X86_64)          += bus_numa.o
 +obj-y                         += amd_bus.o bus_numa.o
  
  ifeq ($(CONFIG_PCI_DEBUG),y)
  EXTRA_CFLAGS += -DDEBUG
diff --combined arch/x86/pci/acpi.c
index 5f11ff6f5389bd45c6279b98c347c7754b164a8a,b53f0487e2d3ed8dd5554a2c340e31205e2b594a..6e22454bfaa6d51e4f22ce9eb5c379e1770319d6
@@@ -15,51 -15,6 +15,51 @@@ struct pci_root_info 
        int busnum;
  };
  
 +static bool pci_use_crs = true;
 +
 +static int __init set_use_crs(const struct dmi_system_id *id)
 +{
 +      pci_use_crs = true;
 +      return 0;
 +}
 +
 +static const struct dmi_system_id pci_use_crs_table[] __initconst = {
 +      /* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */
 +      {
 +              .callback = set_use_crs,
 +              .ident = "IBM System x3800",
 +              .matches = {
 +                      DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
 +                      DMI_MATCH(DMI_PRODUCT_NAME, "x3800"),
 +              },
 +      },
 +      {}
 +};
 +
 +void __init pci_acpi_crs_quirks(void)
 +{
 +      int year;
 +
 +      if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008)
 +              pci_use_crs = false;
 +
 +      dmi_check_system(pci_use_crs_table);
 +
 +      /*
 +       * If the user specifies "pci=use_crs" or "pci=nocrs" explicitly, that
 +       * takes precedence over anything we figured out above.
 +       */
 +      if (pci_probe & PCI_ROOT_NO_CRS)
 +              pci_use_crs = false;
 +      else if (pci_probe & PCI_USE__CRS)
 +              pci_use_crs = true;
 +
 +      printk(KERN_INFO "PCI: %s host bridge windows from ACPI; "
 +             "if necessary, use \"pci=%s\" and report a bug\n",
 +             pci_use_crs ? "Using" : "Ignoring",
 +             pci_use_crs ? "nocrs" : "use_crs");
 +}
 +
  static acpi_status
  resource_to_addr(struct acpi_resource *resource,
                        struct acpi_resource_address64 *addr)
@@@ -90,6 -45,20 +90,6 @@@ count_resource(struct acpi_resource *ac
        return AE_OK;
  }
  
 -static int
 -bus_has_transparent_bridge(struct pci_bus *bus)
 -{
 -      struct pci_dev *dev;
 -
 -      list_for_each_entry(dev, &bus->devices, bus_list) {
 -              u16 class = dev->class >> 8;
 -
 -              if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent)
 -                      return true;
 -      }
 -      return false;
 -}
 -
  static void
  align_resource(struct acpi_device *bridge, struct resource *res)
  {
@@@ -123,8 -92,12 +123,8 @@@ setup_resource(struct acpi_resource *ac
        acpi_status status;
        unsigned long flags;
        struct resource *root;
 -      int max_root_bus_resources = PCI_BUS_NUM_RESOURCES;
        u64 start, end;
  
 -      if (bus_has_transparent_bridge(info->bus))
 -              max_root_bus_resources -= 3;
 -
        status = resource_to_addr(acpi_res, &addr);
        if (!ACPI_SUCCESS(status))
                return AE_OK;
  
        start = addr.minimum + addr.translation_offset;
        end = start + addr.address_length - 1;
 -      if (info->res_num >= max_root_bus_resources) {
 -              if (pci_probe & PCI_USE__CRS)
 -                      printk(KERN_WARNING "PCI: Failed to allocate "
 -                             "0x%lx-0x%lx from %s for %s due to _CRS "
 -                             "returning more than %d resource descriptors\n",
 -                             (unsigned long) start, (unsigned long) end,
 -                             root->name, info->name, max_root_bus_resources);
 -              return AE_OK;
 -      }
  
        res = &info->res[info->res_num];
        res->name = info->name;
        res->child = NULL;
        align_resource(info->bridge, res);
  
 -      if (!(pci_probe & PCI_USE__CRS)) {
 +      if (!pci_use_crs) {
                dev_printk(KERN_DEBUG, &info->bridge->dev,
                           "host bridge window %pR (ignored)\n", res);
                return AE_OK;
                dev_err(&info->bridge->dev,
                        "can't allocate host bridge window %pR\n", res);
        } else {
 -              info->bus->resource[info->res_num] = res;
 +              pci_bus_add_resource(info->bus, res, 0);
                info->res_num++;
                if (addr.translation_offset)
                        dev_info(&info->bridge->dev, "host bridge window %pR "
@@@ -182,8 -164,10 +182,8 @@@ get_current_resources(struct acpi_devic
        struct pci_root_info info;
        size_t size;
  
 -      if (!(pci_probe & PCI_USE__CRS))
 -              dev_info(&device->dev,
 -                       "ignoring host bridge windows from ACPI; "
 -                       "boot with \"pci=use_crs\" to use them\n");
 +      if (pci_use_crs)
 +              pci_bus_remove_resources(bus);
  
        info.bridge = device;
        info.bus = bus;
@@@ -298,17 -282,14 +298,14 @@@ int __init pci_acpi_init(void
  {
        struct pci_dev *dev = NULL;
  
-       if (pcibios_scanned)
-               return 0;
        if (acpi_noirq)
-               return 0;
+               return -ENODEV;
  
        printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
        acpi_irq_penalty_init();
-       pcibios_scanned++;
        pcibios_enable_irq = acpi_pci_irq_enable;
        pcibios_disable_irq = acpi_pci_irq_disable;
+       x86_init.pci.init_irq = x86_init_noop;
  
        if (pci_routeirq) {
                /*
diff --combined arch/x86/pci/common.c
index 3736176acaab6a362f4e97a889af6d07591b6ce3,f5770b5846a60e4b802df3d4e82c2c81b6bffb8e..294e10cb11e108a82ce6140b44a67049d12dc3e6
@@@ -71,12 -71,6 +71,6 @@@ struct pci_ops pci_root_ops = 
        .write = pci_write,
  };
  
- /*
-  * legacy, numa, and acpi all want to call pcibios_scan_root
-  * from their initcalls. This flag prevents that.
-  */
- int pcibios_scanned;
  /*
   * This interrupt-safe spinlock protects all accesses to PCI
   * configuration space.
@@@ -520,9 -514,6 +514,9 @@@ char * __devinit  pcibios_setup(char *s
        } else if (!strcmp(str, "use_crs")) {
                pci_probe |= PCI_USE__CRS;
                return NULL;
 +      } else if (!strcmp(str, "nocrs")) {
 +              pci_probe |= PCI_ROOT_NO_CRS;
 +              return NULL;
        } else if (!strcmp(str, "earlydump")) {
                pci_early_dump_regs = 1;
                return NULL;
diff --combined arch/x86/pci/irq.c
index b02f6d8ac922f171b5b31be1923aa9e358e73bca,a60deb6e6696b6bbcbda159977c3a19b3aede20e..8b107521d24e63f235cdd86ddf4ee86826e36ded
@@@ -53,7 -53,7 +53,7 @@@ struct irq_router_handler 
        int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device);
  };
  
- int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
+ int (*pcibios_enable_irq)(struct pci_dev *dev) = pirq_enable_irq;
  void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
  
  /*
@@@ -590,8 -590,6 +590,8 @@@ static __init int intel_router_probe(st
        case PCI_DEVICE_ID_INTEL_ICH10_1:
        case PCI_DEVICE_ID_INTEL_ICH10_2:
        case PCI_DEVICE_ID_INTEL_ICH10_3:
 +      case PCI_DEVICE_ID_INTEL_CPT_LPC1:
 +      case PCI_DEVICE_ID_INTEL_CPT_LPC2:
                r->name = "PIIX/ICH";
                r->get = pirq_piix_get;
                r->set = pirq_piix_set;
@@@ -1018,7 -1016,7 +1018,7 @@@ static int pcibios_lookup_irq(struct pc
        return 1;
  }
  
static void __init pcibios_fixup_irqs(void)
+ void __init pcibios_fixup_irqs(void)
  {
        struct pci_dev *dev = NULL;
        u8 pin;
@@@ -1112,12 -1110,12 +1112,12 @@@ static struct dmi_system_id __initdata 
        { }
  };
  
int __init pcibios_irq_init(void)
void __init pcibios_irq_init(void)
  {
        DBG(KERN_DEBUG "PCI: IRQ init\n");
  
-       if (pcibios_enable_irq || raw_pci_ops == NULL)
-               return 0;
+       if (raw_pci_ops == NULL)
+               return;
  
        dmi_check_system(pciirq_dmi_table);
  
                        pirq_table = NULL;
        }
  
-       pcibios_enable_irq = pirq_enable_irq;
-       pcibios_fixup_irqs();
+       x86_init.pci.fixup_irqs();
  
        if (io_apic_assign_pci_irqs && pci_routeirq) {
                struct pci_dev *dev = NULL;
                for_each_pci_dev(dev)
                        pirq_enable_irq(dev);
        }
-       return 0;
  }
  
  static void pirq_penalize_isa_irq(int irq, int active)
diff --combined arch/x86/pci/numaq_32.c
index 8884a1c1ada63c2150585a681334383d7ee4f0d5,45c0c9e45903fec1432fec4146650f5199a24c98..8223738ad806a29db68ec20e4d45530852fa4bfd
@@@ -8,7 -8,9 +8,7 @@@
  #include <asm/apic.h>
  #include <asm/mpspec.h>
  #include <asm/pci_x86.h>
 -
 -#define XQUAD_PORTIO_BASE 0xfe400000
 -#define XQUAD_PORTIO_QUAD 0x40000  /* 256k per quad. */
 +#include <asm/numaq.h>
  
  #define BUS2QUAD(global) (mp_bus_id_to_node[global])
  
@@@ -16,6 -18,8 +16,6 @@@
  
  #define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local])
  
 -#define XQUAD_PORT_ADDR(port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port)
 -
  #define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \
        (0x80000000 | (BUS2LOCAL(bus) << 16) | (devfn << 8) | (reg & ~3))
  
@@@ -148,14 -152,8 +148,8 @@@ int __init pci_numaq_init(void
  {
        int quad;
  
-       if (!found_numaq)
-               return 0;
        raw_pci_ops = &pci_direct_conf1_mq;
  
-       if (pcibios_scanned++)
-               return 0;
        pci_root_bus = pcibios_scan_root(0);
        if (pci_root_bus)
                pci_bus_add_devices(pci_root_bus);
diff --combined drivers/pci/pci.c
index 5b548aee9cbc43f30a0e0bb0d850ceed3d606e08,aad62af2b4c6625eb9100f4accf3104abc5657a0..77b493b3d97b12de09bc4796711407648aa99aab
@@@ -19,8 -19,8 +19,8 @@@
  #include <linux/pci-aspm.h>
  #include <linux/pm_wakeup.h>
  #include <linux/interrupt.h>
 -#include <asm/dma.h>  /* isa_dma_bridge_buggy */
  #include <linux/device.h>
 +#include <linux/pm_runtime.h>
  #include <asm/setup.h>
  #include "pci.h"
  
@@@ -29,12 -29,6 +29,12 @@@ const char *pci_power_names[] = 
  };
  EXPORT_SYMBOL_GPL(pci_power_names);
  
 +int isa_dma_bridge_buggy;
 +EXPORT_SYMBOL(isa_dma_bridge_buggy);
 +
 +int pci_pci_problems;
 +EXPORT_SYMBOL(pci_pci_problems);
 +
  unsigned int pci_pm_d3_delay;
  
  static void pci_dev_d3_sleep(struct pci_dev *dev)
@@@ -303,6 -297,49 +303,49 @@@ int pci_find_ext_capability(struct pci_
  }
  EXPORT_SYMBOL_GPL(pci_find_ext_capability);
  
+ /**
+  * pci_bus_find_ext_capability - find an extended capability
+  * @bus:   the PCI bus to query
+  * @devfn: PCI device to query
+  * @cap:   capability code
+  *
+  * Like pci_find_ext_capability() but works for pci devices that do not have a
+  * pci_dev structure set up yet.
+  *
+  * Returns the address of the requested capability structure within the
+  * device's PCI configuration space or 0 in case the device does not
+  * support it.
+  */
+ int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn,
+                               int cap)
+ {
+       u32 header;
+       int ttl;
+       int pos = PCI_CFG_SPACE_SIZE;
+       /* minimum 8 bytes per capability */
+       ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
+       if (!pci_bus_read_config_dword(bus, devfn, pos, &header))
+               return 0;
+       if (header == 0xffffffff || header == 0)
+               return 0;
+       while (ttl-- > 0) {
+               if (PCI_EXT_CAP_ID(header) == cap)
+                       return pos;
+               pos = PCI_EXT_CAP_NEXT(header);
+               if (pos < PCI_CFG_SPACE_SIZE)
+                       break;
+               if (!pci_bus_read_config_dword(bus, devfn, pos, &header))
+                       break;
+       }
+       return 0;
+ }
  static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap)
  {
        int rc, ttl = PCI_FIND_CAP_TTL;
@@@ -386,9 -423,10 +429,9 @@@ pci_find_parent_resource(const struct p
  {
        const struct pci_bus *bus = dev->bus;
        int i;
 -      struct resource *best = NULL;
 +      struct resource *best = NULL, *r;
  
 -      for(i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
 -              struct resource *r = bus->resource[i];
 +      pci_bus_for_each_resource(bus, r, i) {
                if (!r)
                        continue;
                if (res->start && !(res->start >= r->start && res->end <= r->end))
@@@ -462,12 -500,6 +505,12 @@@ static inline int platform_pci_sleep_wa
                        pci_platform_pm->sleep_wake(dev, enable) : -ENODEV;
  }
  
 +static inline int platform_pci_run_wake(struct pci_dev *dev, bool enable)
 +{
 +      return pci_platform_pm ?
 +                      pci_platform_pm->run_wake(dev, enable) : -ENODEV;
 +}
 +
  /**
   * pci_raw_set_power_state - Use PCI PM registers to set the power state of
   *                           given PCI device
@@@ -1200,66 -1232,6 +1243,66 @@@ int pci_set_pcie_reset_state(struct pci
        return pcibios_set_pcie_reset_state(dev, state);
  }
  
 +/**
 + * pci_check_pme_status - Check if given device has generated PME.
 + * @dev: Device to check.
 + *
 + * Check the PME status of the device and if set, clear it and clear PME enable
 + * (if set).  Return 'true' if PME status and PME enable were both set or
 + * 'false' otherwise.
 + */
 +bool pci_check_pme_status(struct pci_dev *dev)
 +{
 +      int pmcsr_pos;
 +      u16 pmcsr;
 +      bool ret = false;
 +
 +      if (!dev->pm_cap)
 +              return false;
 +
 +      pmcsr_pos = dev->pm_cap + PCI_PM_CTRL;
 +      pci_read_config_word(dev, pmcsr_pos, &pmcsr);
 +      if (!(pmcsr & PCI_PM_CTRL_PME_STATUS))
 +              return false;
 +
 +      /* Clear PME status. */
 +      pmcsr |= PCI_PM_CTRL_PME_STATUS;
 +      if (pmcsr & PCI_PM_CTRL_PME_ENABLE) {
 +              /* Disable PME to avoid interrupt flood. */
 +              pmcsr &= ~PCI_PM_CTRL_PME_ENABLE;
 +              ret = true;
 +      }
 +
 +      pci_write_config_word(dev, pmcsr_pos, pmcsr);
 +
 +      return ret;
 +}
 +
 +/**
 + * pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set.
 + * @dev: Device to handle.
 + * @ign: Ignored.
 + *
 + * Check if @dev has generated PME and queue a resume request for it in that
 + * case.
 + */
 +static int pci_pme_wakeup(struct pci_dev *dev, void *ign)
 +{
 +      if (pci_check_pme_status(dev))
 +              pm_request_resume(&dev->dev);
 +      return 0;
 +}
 +
 +/**
 + * pci_pme_wakeup_bus - Walk given bus and wake up devices on it, if necessary.
 + * @bus: Top bus of the subtree to walk.
 + */
 +void pci_pme_wakeup_bus(struct pci_bus *bus)
 +{
 +      if (bus)
 +              pci_walk_bus(bus, pci_pme_wakeup, NULL);
 +}
 +
  /**
   * pci_pme_capable - check the capability of PCI device to generate PME#
   * @dev: PCI device to handle.
@@@ -1301,10 -1273,9 +1344,10 @@@ void pci_pme_active(struct pci_dev *dev
  }
  
  /**
 - * pci_enable_wake - enable PCI device as wakeup event source
 + * __pci_enable_wake - enable PCI device as wakeup event source
   * @dev: PCI device affected
   * @state: PCI state from which device will issue wakeup events
 + * @runtime: True if the events are to be generated at run time
   * @enable: True to enable event generation; false to disable
   *
   * This enables the device as a wakeup event source, or disables it.
   * Error code depending on the platform is returned if both the platform and
   * the native mechanism fail to enable the generation of wake-up events
   */
 -int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
 +int __pci_enable_wake(struct pci_dev *dev, pci_power_t state,
 +                    bool runtime, bool enable)
  {
        int ret = 0;
  
 -      if (enable && !device_may_wakeup(&dev->dev))
 +      if (enable && !runtime && !device_may_wakeup(&dev->dev))
                return -EINVAL;
  
        /* Don't do the same thing twice in a row for one device. */
                        pci_pme_active(dev, true);
                else
                        ret = 1;
 -              error = platform_pci_sleep_wake(dev, true);
 +              error = runtime ? platform_pci_run_wake(dev, true) :
 +                                      platform_pci_sleep_wake(dev, true);
                if (ret)
                        ret = error;
                if (!ret)
                        dev->wakeup_prepared = true;
        } else {
 -              platform_pci_sleep_wake(dev, false);
 +              if (runtime)
 +                      platform_pci_run_wake(dev, false);
 +              else
 +                      platform_pci_sleep_wake(dev, false);
                pci_pme_active(dev, false);
                dev->wakeup_prepared = false;
        }
  
        return ret;
  }
 +EXPORT_SYMBOL(__pci_enable_wake);
  
  /**
   * pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold
@@@ -1471,66 -1436,6 +1514,66 @@@ int pci_back_from_sleep(struct pci_dev 
        return pci_set_power_state(dev, PCI_D0);
  }
  
 +/**
 + * pci_finish_runtime_suspend - Carry out PCI-specific part of runtime suspend.
 + * @dev: PCI device being suspended.
 + *
 + * Prepare @dev to generate wake-up events at run time and put it into a low
 + * power state.
 + */
 +int pci_finish_runtime_suspend(struct pci_dev *dev)
 +{
 +      pci_power_t target_state = pci_target_state(dev);
 +      int error;
 +
 +      if (target_state == PCI_POWER_ERROR)
 +              return -EIO;
 +
 +      __pci_enable_wake(dev, target_state, true, pci_dev_run_wake(dev));
 +
 +      error = pci_set_power_state(dev, target_state);
 +
 +      if (error)
 +              __pci_enable_wake(dev, target_state, true, false);
 +
 +      return error;
 +}
 +
 +/**
 + * pci_dev_run_wake - Check if device can generate run-time wake-up events.
 + * @dev: Device to check.
 + *
 + * Return true if the device itself is cabable of generating wake-up events
 + * (through the platform or using the native PCIe PME) or if the device supports
 + * PME and one of its upstream bridges can generate wake-up events.
 + */
 +bool pci_dev_run_wake(struct pci_dev *dev)
 +{
 +      struct pci_bus *bus = dev->bus;
 +
 +      if (device_run_wake(&dev->dev))
 +              return true;
 +
 +      if (!dev->pme_support)
 +              return false;
 +
 +      while (bus->parent) {
 +              struct pci_dev *bridge = bus->self;
 +
 +              if (device_run_wake(&bridge->dev))
 +                      return true;
 +
 +              bus = bus->parent;
 +      }
 +
 +      /* We have reached the root bus. */
 +      if (bus->bridge)
 +              return device_run_wake(bus->bridge);
 +
 +      return false;
 +}
 +EXPORT_SYMBOL_GPL(pci_dev_run_wake);
 +
  /**
   * pci_pm_init - Initialize PM functions of given PCI device
   * @dev: PCI device to handle.
@@@ -1540,7 -1445,6 +1583,7 @@@ void pci_pm_init(struct pci_dev *dev
        int pm;
        u16 pmc;
  
 +      device_enable_async_suspend(&dev->dev);
        dev->wakeup_prepared = false;
        dev->pm_cap = 0;
  
@@@ -2754,23 -2658,6 +2797,23 @@@ int pci_resource_bar(struct pci_dev *de
        return 0;
  }
  
 +/* Some architectures require additional programming to enable VGA */
 +static arch_set_vga_state_t arch_set_vga_state;
 +
 +void __init pci_register_set_vga_state(arch_set_vga_state_t func)
 +{
 +      arch_set_vga_state = func;      /* NULL disables */
 +}
 +
 +static int pci_set_vga_state_arch(struct pci_dev *dev, bool decode,
 +                    unsigned int command_bits, bool change_bridge)
 +{
 +      if (arch_set_vga_state)
 +              return arch_set_vga_state(dev, decode, command_bits,
 +                                              change_bridge);
 +      return 0;
 +}
 +
  /**
   * pci_set_vga_state - set VGA decode state on device and parents if requested
   * @dev: the PCI device
@@@ -2784,15 -2671,9 +2827,15 @@@ int pci_set_vga_state(struct pci_dev *d
        struct pci_bus *bus;
        struct pci_dev *bridge;
        u16 cmd;
 +      int rc;
  
        WARN_ON(command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY));
  
 +      /* ARCH specific VGA enables */
 +      rc = pci_set_vga_state_arch(dev, decode, command_bits, change_bridge);
 +      if (rc)
 +              return rc;
 +
        pci_read_config_word(dev, PCI_COMMAND, &cmd);
        if (decode == true)
                cmd |= command_bits;
@@@ -3007,7 -2888,6 +3050,7 @@@ EXPORT_SYMBOL(pcim_pin_device)
  EXPORT_SYMBOL(pci_disable_device);
  EXPORT_SYMBOL(pci_find_capability);
  EXPORT_SYMBOL(pci_bus_find_capability);
 +EXPORT_SYMBOL(pci_register_set_vga_state);
  EXPORT_SYMBOL(pci_release_regions);
  EXPORT_SYMBOL(pci_request_regions);
  EXPORT_SYMBOL(pci_request_regions_exclusive);
@@@ -3034,8 -2914,10 +3077,8 @@@ EXPORT_SYMBOL(pci_save_state)
  EXPORT_SYMBOL(pci_restore_state);
  EXPORT_SYMBOL(pci_pme_capable);
  EXPORT_SYMBOL(pci_pme_active);
 -EXPORT_SYMBOL(pci_enable_wake);
  EXPORT_SYMBOL(pci_wake_from_d3);
  EXPORT_SYMBOL(pci_target_state);
  EXPORT_SYMBOL(pci_prepare_to_sleep);
  EXPORT_SYMBOL(pci_back_from_sleep);
  EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);
 -
diff --combined include/linux/pci.h
index ec95ebe629f1f4f8c212ebfbfce7086bea7e01ba,65f8a8f9d3e549c28e22bdaea7ee40d1ca191b31..cd5809a5963ed96039cbbebf3562b96061c359e5
@@@ -187,33 -187,6 +187,33 @@@ enum pci_bus_flags 
        PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2,
  };
  
 +/* Based on the PCI Hotplug Spec, but some values are made up by us */
 +enum pci_bus_speed {
 +      PCI_SPEED_33MHz                 = 0x00,
 +      PCI_SPEED_66MHz                 = 0x01,
 +      PCI_SPEED_66MHz_PCIX            = 0x02,
 +      PCI_SPEED_100MHz_PCIX           = 0x03,
 +      PCI_SPEED_133MHz_PCIX           = 0x04,
 +      PCI_SPEED_66MHz_PCIX_ECC        = 0x05,
 +      PCI_SPEED_100MHz_PCIX_ECC       = 0x06,
 +      PCI_SPEED_133MHz_PCIX_ECC       = 0x07,
 +      PCI_SPEED_66MHz_PCIX_266        = 0x09,
 +      PCI_SPEED_100MHz_PCIX_266       = 0x0a,
 +      PCI_SPEED_133MHz_PCIX_266       = 0x0b,
 +      AGP_UNKNOWN                     = 0x0c,
 +      AGP_1X                          = 0x0d,
 +      AGP_2X                          = 0x0e,
 +      AGP_4X                          = 0x0f,
 +      AGP_8X                          = 0x10,
 +      PCI_SPEED_66MHz_PCIX_533        = 0x11,
 +      PCI_SPEED_100MHz_PCIX_533       = 0x12,
 +      PCI_SPEED_133MHz_PCIX_533       = 0x13,
 +      PCIE_SPEED_2_5GT                = 0x14,
 +      PCIE_SPEED_5_0GT                = 0x15,
 +      PCIE_SPEED_8_0GT                = 0x16,
 +      PCI_SPEED_UNKNOWN               = 0xff,
 +};
 +
  struct pci_cap_saved_state {
        struct hlist_node next;
        char cap_nr;
@@@ -266,7 -239,6 +266,7 @@@ struct pci_dev 
                                           configuration space */
        unsigned int    pme_support:5;  /* Bitmask of states from which PME#
                                           can be generated */
 +      unsigned int    pme_interrupt:1;
        unsigned int    d1_support:1;   /* Low power state D1 is supported */
        unsigned int    d2_support:1;   /* Low power state D2 is supported */
        unsigned int    no_d1d2:1;      /* Only allow D0 and D3 */
        unsigned int    msix_enabled:1;
        unsigned int    ari_enabled:1;  /* ARI forwarding */
        unsigned int    is_managed:1;
 -      unsigned int    is_pcie:1;
 +      unsigned int    is_pcie:1;      /* Obsolete. Will be removed.
 +                                         Use pci_is_pcie() instead */
        unsigned int    needs_freset:1; /* Dev requires fundamental reset */
        unsigned int    state_saved:1;
        unsigned int    is_physfn:1;
@@@ -364,26 -335,9 +364,26 @@@ static inline void pci_add_saved_cap(st
        hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space);
  }
  
 -#ifndef PCI_BUS_NUM_RESOURCES
 -#define PCI_BUS_NUM_RESOURCES 16
 -#endif
 +/*
 + * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond
 + * to P2P or CardBus bridge windows) go in a table.  Additional ones (for
 + * buses below host bridges or subtractive decode bridges) go in the list.
 + * Use pci_bus_for_each_resource() to iterate through all the resources.
 + */
 +
 +/*
 + * PCI_SUBTRACTIVE_DECODE means the bridge forwards the window implicitly
 + * and there's no way to program the bridge with the details of the window.
 + * This does not apply to ACPI _CRS windows, even with the _DEC subtractive-
 + * decode bit set, because they are explicit and can be programmed with _SRS.
 + */
 +#define PCI_SUBTRACTIVE_DECODE        0x1
 +
 +struct pci_bus_resource {
 +      struct list_head list;
 +      struct resource *res;
 +      unsigned int flags;
 +};
  
  #define PCI_REGION_FLAG_MASK  0x0fU   /* These bits of resource flags tell us the PCI region flags */
  
@@@ -394,8 -348,8 +394,8 @@@ struct pci_bus 
        struct list_head devices;       /* list of devices on this bus */
        struct pci_dev  *self;          /* bridge device as seen by parent */
        struct list_head slots;         /* list of slots on this bus */
 -      struct resource *resource[PCI_BUS_NUM_RESOURCES];
 -                                      /* address space routed to this bus */
 +      struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
 +      struct list_head resources;     /* address space routed to this bus */
  
        struct pci_ops  *ops;           /* configuration access functions */
        void            *sysdata;       /* hook for sys-specific extension */
        unsigned char   primary;        /* number of primary bridge */
        unsigned char   secondary;      /* number of secondary bridge */
        unsigned char   subordinate;    /* max number of subordinate buses */
 +      unsigned char   max_bus_speed;  /* enum pci_bus_speed */
 +      unsigned char   cur_bus_speed;  /* enum pci_bus_speed */
  
        char            name[48];
  
@@@ -611,8 -563,7 +611,8 @@@ int __must_check pcibios_enable_device(
  char *pcibios_setup(char *str);
  
  /* Used only when drivers/pci/setup.c is used */
 -void pcibios_align_resource(void *, struct resource *, resource_size_t,
 +resource_size_t pcibios_align_resource(void *, const struct resource *,
 +                              resource_size_t,
                                resource_size_t);
  void pcibios_update_irq(struct pci_dev *, int irq);
  
@@@ -638,7 -589,6 +638,7 @@@ struct pci_bus *pci_create_bus(struct d
                               struct pci_ops *ops, void *sysdata);
  struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
                                int busnr);
 +void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
  struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
                                 const char *name,
                                 struct hotplug_slot *hotplug);
@@@ -662,12 -612,15 +662,12 @@@ extern void pci_remove_bus_device(struc
  extern void pci_stop_bus_device(struct pci_dev *dev);
  void pci_setup_cardbus(struct pci_bus *bus);
  extern void pci_sort_breadthfirst(void);
 +#define dev_is_pci(d) ((d)->bus == &pci_bus_type)
 +#define dev_is_pf(d) ((dev_is_pci(d) ? to_pci_dev(d)->is_physfn : false))
 +#define dev_num_vf(d) ((dev_is_pci(d) ? pci_num_vf(to_pci_dev(d)) : 0))
  
  /* Generic PCI functions exported to card drivers */
  
 -#ifdef CONFIG_PCI_LEGACY
 -struct pci_dev __deprecated *pci_find_device(unsigned int vendor,
 -                                           unsigned int device,
 -                                           struct pci_dev *from);
 -#endif /* CONFIG_PCI_LEGACY */
 -
  enum pci_lost_interrupt_reason {
        PCI_LOST_IRQ_NO_INFORMATION = 0,
        PCI_LOST_IRQ_DISABLE_MSI,
@@@ -678,6 -631,8 +678,8 @@@ enum pci_lost_interrupt_reason pci_lost
  int pci_find_capability(struct pci_dev *dev, int cap);
  int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap);
  int pci_find_ext_capability(struct pci_dev *dev, int cap);
+ int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn,
+                               int cap);
  int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
  int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
  struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
@@@ -797,19 -752,11 +799,19 @@@ int pci_set_power_state(struct pci_dev 
  pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
  bool pci_pme_capable(struct pci_dev *dev, pci_power_t state);
  void pci_pme_active(struct pci_dev *dev, bool enable);
 -int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable);
 +int __pci_enable_wake(struct pci_dev *dev, pci_power_t state,
 +                    bool runtime, bool enable);
  int pci_wake_from_d3(struct pci_dev *dev, bool enable);
  pci_power_t pci_target_state(struct pci_dev *dev);
  int pci_prepare_to_sleep(struct pci_dev *dev);
  int pci_back_from_sleep(struct pci_dev *dev);
 +bool pci_dev_run_wake(struct pci_dev *dev);
 +
 +static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state,
 +                                bool enable)
 +{
 +      return __pci_enable_wake(dev, state, false, enable);
 +}
  
  /* For use by arch with custom probe code */
  void set_pcie_port_type(struct pci_dev *pdev);
@@@ -831,7 -778,6 +833,7 @@@ void pci_bus_assign_resources(const str
  void pci_bus_size_bridges(struct pci_bus *bus);
  int pci_claim_resource(struct pci_dev *, int);
  void pci_assign_unassigned_resources(void);
 +void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge);
  void pdev_enable_device(struct pci_dev *);
  void pdev_sort_resources(struct pci_dev *, struct resource_list *);
  int pci_enable_resources(struct pci_dev *, int mask);
@@@ -849,23 -795,12 +851,23 @@@ int pci_request_selected_regions_exclus
  void pci_release_selected_regions(struct pci_dev *, int);
  
  /* drivers/pci/bus.c */
 +void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, unsigned int flags);
 +struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n);
 +void pci_bus_remove_resources(struct pci_bus *bus);
 +
 +#define pci_bus_for_each_resource(bus, res, i)                                \
 +      for (i = 0;                                                     \
 +          (res = pci_bus_resource_n(bus, i)) || i < PCI_BRIDGE_RESOURCE_NUM; \
 +           i++)
 +
  int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
                        struct resource *res, resource_size_t size,
                        resource_size_t align, resource_size_t min,
                        unsigned int type_mask,
 -                      void (*alignf)(void *, struct resource *,
 -                              resource_size_t, resource_size_t),
 +                      resource_size_t (*alignf)(void *,
 +                                                const struct resource *,
 +                                                resource_size_t,
 +                                                resource_size_t),
                        void *alignf_data);
  void pci_enable_bridges(struct pci_bus *bus);
  
@@@ -1026,11 -961,6 +1028,11 @@@ static inline int pci_proc_domain(struc
  }
  #endif /* CONFIG_PCI_DOMAINS */
  
 +/* some architectures require additional setup to direct VGA traffic */
 +typedef int (*arch_set_vga_state_t)(struct pci_dev *pdev, bool decode,
 +                    unsigned int command_bits, bool change_bridge);
 +extern void pci_register_set_vga_state(arch_set_vga_state_t func);
 +
  #else /* CONFIG_PCI is not enabled */
  
  /*
  _PCI_NOP_ALL(read, *)
  _PCI_NOP_ALL(write,)
  
 -static inline struct pci_dev *pci_find_device(unsigned int vendor,
 -                                            unsigned int device,
 -                                            struct pci_dev *from)
 -{
 -      return NULL;
 -}
 -
  static inline struct pci_dev *pci_get_device(unsigned int vendor,
                                             unsigned int device,
                                             struct pci_dev *from)
@@@ -1198,9 -1135,6 +1200,9 @@@ static inline struct pci_dev *pci_get_b
                                                unsigned int devfn)
  { return NULL; }
  
 +#define dev_is_pci(d) (false)
 +#define dev_is_pf(d) (false)
 +#define dev_num_vf(d) (0)
  #endif /* CONFIG_PCI */
  
  /* Include architecture-dependent settings and functions */
@@@ -1309,12 -1243,8 +1311,12 @@@ enum pci_fixup_pass 
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,                   \
                        suspend##vendor##device##hook, vendor, device, hook)
  
 -
 +#ifdef CONFIG_PCI_QUIRKS
  void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
 +#else
 +static inline void pci_fixup_device(enum pci_fixup_pass pass,
 +                                  struct pci_dev *dev) {}
 +#endif
  
  void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
  void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr);
@@@ -1362,7 -1292,6 +1364,7 @@@ void __iomem *pci_ioremap_bar(struct pc
  extern int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
  extern void pci_disable_sriov(struct pci_dev *dev);
  extern irqreturn_t pci_sriov_migration(struct pci_dev *dev);
 +extern int pci_num_vf(struct pci_dev *dev);
  #else
  static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
  {
@@@ -1375,10 -1304,6 +1377,10 @@@ static inline irqreturn_t pci_sriov_mig
  {
        return IRQ_NONE;
  }
 +static inline int pci_num_vf(struct pci_dev *dev)
 +{
 +      return 0;
 +}
  #endif
  
  #if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
@@@ -1415,93 -1340,5 +1417,93 @@@ static inline bool pci_is_pcie(struct p
  
  void pci_request_acs(void);
  
 +
 +#define PCI_VPD_LRDT                  0x80    /* Large Resource Data Type */
 +#define PCI_VPD_LRDT_ID(x)            (x | PCI_VPD_LRDT)
 +
 +/* Large Resource Data Type Tag Item Names */
 +#define PCI_VPD_LTIN_ID_STRING                0x02    /* Identifier String */
 +#define PCI_VPD_LTIN_RO_DATA          0x10    /* Read-Only Data */
 +#define PCI_VPD_LTIN_RW_DATA          0x11    /* Read-Write Data */
 +
 +#define PCI_VPD_LRDT_ID_STRING                PCI_VPD_LRDT_ID(PCI_VPD_LTIN_ID_STRING)
 +#define PCI_VPD_LRDT_RO_DATA          PCI_VPD_LRDT_ID(PCI_VPD_LTIN_RO_DATA)
 +#define PCI_VPD_LRDT_RW_DATA          PCI_VPD_LRDT_ID(PCI_VPD_LTIN_RW_DATA)
 +
 +/* Small Resource Data Type Tag Item Names */
 +#define PCI_VPD_STIN_END              0x78    /* End */
 +
 +#define PCI_VPD_SRDT_END              PCI_VPD_STIN_END
 +
 +#define PCI_VPD_SRDT_TIN_MASK         0x78
 +#define PCI_VPD_SRDT_LEN_MASK         0x07
 +
 +#define PCI_VPD_LRDT_TAG_SIZE         3
 +#define PCI_VPD_SRDT_TAG_SIZE         1
 +
 +#define PCI_VPD_INFO_FLD_HDR_SIZE     3
 +
 +#define PCI_VPD_RO_KEYWORD_PARTNO     "PN"
 +#define PCI_VPD_RO_KEYWORD_MFR_ID     "MN"
 +#define PCI_VPD_RO_KEYWORD_VENDOR0    "V0"
 +
 +/**
 + * pci_vpd_lrdt_size - Extracts the Large Resource Data Type length
 + * @lrdt: Pointer to the beginning of the Large Resource Data Type tag
 + *
 + * Returns the extracted Large Resource Data Type length.
 + */
 +static inline u16 pci_vpd_lrdt_size(const u8 *lrdt)
 +{
 +      return (u16)lrdt[1] + ((u16)lrdt[2] << 8);
 +}
 +
 +/**
 + * pci_vpd_srdt_size - Extracts the Small Resource Data Type length
 + * @lrdt: Pointer to the beginning of the Small Resource Data Type tag
 + *
 + * Returns the extracted Small Resource Data Type length.
 + */
 +static inline u8 pci_vpd_srdt_size(const u8 *srdt)
 +{
 +      return (*srdt) & PCI_VPD_SRDT_LEN_MASK;
 +}
 +
 +/**
 + * pci_vpd_info_field_size - Extracts the information field length
 + * @lrdt: Pointer to the beginning of an information field header
 + *
 + * Returns the extracted information field length.
 + */
 +static inline u8 pci_vpd_info_field_size(const u8 *info_field)
 +{
 +      return info_field[2];
 +}
 +
 +/**
 + * pci_vpd_find_tag - Locates the Resource Data Type tag provided
 + * @buf: Pointer to buffered vpd data
 + * @off: The offset into the buffer at which to begin the search
 + * @len: The length of the vpd buffer
 + * @rdt: The Resource Data Type to search for
 + *
 + * Returns the index where the Resource Data Type was found or
 + * -ENOENT otherwise.
 + */
 +int pci_vpd_find_tag(const u8 *buf, unsigned int off, unsigned int len, u8 rdt);
 +
 +/**
 + * pci_vpd_find_info_keyword - Locates an information field keyword in the VPD
 + * @buf: Pointer to buffered vpd data
 + * @off: The offset into the buffer at which to begin the search
 + * @len: The length of the buffer area, relative to off, in which to search
 + * @kw: The keyword to search for
 + *
 + * Returns the index where the information field keyword was found or
 + * -ENOENT otherwise.
 + */
 +int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off,
 +                            unsigned int len, const char *kw);
 +
  #endif /* __KERNEL__ */
  #endif /* LINUX_PCI_H */