Merge remote-tracking branch 'kumar/next' into next
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 18 Sep 2012 06:04:33 +0000 (16:04 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 18 Sep 2012 06:04:33 +0000 (16:04 +1000)
174 files changed:
Documentation/ABI/testing/sysfs-bus-pci
Documentation/feature-removal-schedule.txt
Makefile
arch/arm/Kconfig
arch/arm/boot/dts/at91sam9g25ek.dts
arch/arm/configs/armadillo800eva_defconfig
arch/arm/include/asm/dma-mapping.h
arch/arm/mach-at91/at91rm9200_time.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/clock.c
arch/arm/mach-gemini/irq.c
arch/arm/mach-kirkwood/common.c
arch/arm/mach-kirkwood/db88f6281-bp-setup.c
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/board-marzen.c
arch/arm/mach-shmobile/intc-sh73a0.c
arch/arm/mach-tegra/pcie.c
arch/arm/mm/dma-mapping.c
arch/mips/pci/pci-octeon.c
arch/powerpc/Kconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/pseries_defconfig
arch/powerpc/include/asm/eeh.h
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/machdep.h
arch/powerpc/include/asm/mmu-hash64.h
arch/powerpc/include/asm/mmu.h
arch/powerpc/include/asm/paca.h
arch/powerpc/include/asm/page_64.h
arch/powerpc/include/asm/pci-bridge.h
arch/powerpc/include/asm/pgtable-ppc64-4k.h
arch/powerpc/include/asm/pgtable-ppc64-64k.h
arch/powerpc/include/asm/pgtable-ppc64.h
arch/powerpc/include/asm/pgtable.h
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/pte-hash64-64k.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/sparsemem.h
arch/powerpc/include/asm/thread_info.h
arch/powerpc/include/asm/tlbflush.h
arch/powerpc/include/asm/uaccess.h
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/time.c
arch/powerpc/kvm/book3s_32_mmu_host.c
arch/powerpc/kvm/book3s_64_mmu_host.c
arch/powerpc/kvm/trace.h
arch/powerpc/lib/sstep.c
arch/powerpc/mm/hash_low_64.S
arch/powerpc/mm/hash_native_64.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugetlbpage-hash64.c
arch/powerpc/mm/mmu_context_hash64.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/mm/slb_low.S
arch/powerpc/mm/slice.c
arch/powerpc/mm/tlb_hash64.c
arch/powerpc/platforms/cell/beat_htab.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci.h
arch/powerpc/platforms/ps3/htab.c
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_driver.c
arch/powerpc/platforms/pseries/eeh_pe.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/pci_dlpar.c
arch/powerpc/xmon/xmon.c
arch/tile/kernel/pci.c
arch/um/os-Linux/time.c
arch/x86/xen/mmu.c
arch/x86/xen/p2m.c
drivers/base/dma-contiguous.c
drivers/gpio/Kconfig
drivers/gpio/gpio-em.c
drivers/gpio/gpio-rdc321x.c
drivers/gpio/gpiolib-of.c
drivers/gpu/drm/radeon/evergreen.c
drivers/hid/hid-core.c
drivers/hid/hid-logitech-dj.c
drivers/hid/usbhid/hid-quirks.c
drivers/infiniband/hw/mthca/mthca_reset.c
drivers/infiniband/hw/qib/qib_pcie.c
drivers/input/keyboard/imx_keypad.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/edt-ft5x06.c
drivers/iommu/intel-iommu.c
drivers/mmc/card/block.c
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/bfin_sdh.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/mxs-mmc.c
drivers/mmc/host/omap.c
drivers/mmc/host/sdhci-esdhc.h
drivers/mtd/ubi/vtbl.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/mellanox/mlx4/reset.c
drivers/net/ethernet/myricom/myri10ge/myri10ge.c
drivers/net/ethernet/neterion/vxge/vxge-config.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/sun/niu.c
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/iwlegacy/common.h
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/rtlwifi/pci.c
drivers/pci/access.c
drivers/pci/hotplug/pciehp_acpi.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/pcihp_slot.c
drivers/pci/hotplug/rpadlpar_core.c
drivers/pci/iov.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pcie/aer/aer_inject.c
drivers/pci/pcie/aer/aerdrv.c
drivers/pci/pcie/aer/aerdrv_acpi.c
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/aspm.c
drivers/pci/pcie/pme.c
drivers/pci/pcie/portdrv_bus.c
drivers/pci/pcie/portdrv_core.c
drivers/pci/pcie/portdrv_pci.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/search.c
drivers/pci/setup-bus.c
drivers/rapidio/devices/tsi721.c
drivers/rtc/rtc-at91sam9.c
drivers/scsi/qla2xxx/qla_nx.c
drivers/scsi/qla4xxx/ql4_nx.c
drivers/staging/et131x/et131x.c
drivers/staging/rtl8192e/rtl8192e/rtl_pci.c
drivers/video/auo_k190x.c
drivers/video/console/bitblit.c
drivers/video/console/fbcon.c
drivers/video/mb862xx/mb862xxfbdrv.c
drivers/video/omap2/dss/sdi.c
drivers/video/omap2/omapfb/omapfb-main.c
drivers/xen/swiotlb-xen.c
drivers/xen/xen-pciback/pci_stub.c
include/linux/kernel.h
include/linux/mmc/card.h
include/linux/pci.h
include/linux/pci_regs.h
mm/mempolicy.c
net/socket.c
scripts/Makefile.fwinst
scripts/link-vmlinux.sh
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/patch_sigmatel.c
sound/usb/card.c
sound/usb/endpoint.c
sound/usb/endpoint.h
sound/usb/pcm.c

index 34f5110..dff1f48 100644 (file)
@@ -210,3 +210,15 @@ Users:
                firmware assigned instance number of the PCI
                device that can help in understanding the firmware
                intended order of the PCI device.
+
+What:          /sys/bus/pci/devices/.../d3cold_allowed
+Date:          July 2012
+Contact:       Huang Ying <ying.huang@intel.com>
+Description:
+               d3cold_allowed is bit to control whether the corresponding PCI
+               device can be put into D3Cold state.  If it is cleared, the
+               device will never be put into D3Cold state.  If it is set, the
+               device may be put into D3Cold state if other requirements are
+               satisfied too.  Reading this attribute will show the current
+               value of d3cold_allowed bit.  Writing this attribute will set
+               the value of d3cold_allowed bit.
index afaff31..f4d8c71 100644 (file)
@@ -579,7 +579,7 @@ Why:        KVM tracepoints provide mostly equivalent information in a much more
 ----------------------------
 
 What:  at91-mci driver ("CONFIG_MMC_AT91")
-When:  3.7
+When:  3.8
 Why:   There are two mci drivers: at91-mci and atmel-mci. The PDC support
        was added to atmel-mci as a first step to support more chips.
        Then at91-mci was kept only for old IP versions (on at91rm9200 and
index 371ce88..0f66f14 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 6
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc5
 NAME = Saber-toothed Squirrel
 
 # *DOCUMENTATION*
index c5f9ae5..2f88d8d 100644 (file)
@@ -6,7 +6,7 @@ config ARM
        select HAVE_DMA_API_DEBUG
        select HAVE_IDE if PCI || ISA || PCMCIA
        select HAVE_DMA_ATTRS
-       select HAVE_DMA_CONTIGUOUS if (CPU_V6 || CPU_V6K || CPU_V7)
+       select HAVE_DMA_CONTIGUOUS if MMU
        select HAVE_MEMBLOCK
        select RTC_LIB
        select SYS_SUPPORTS_APM_EMULATION
index 7829a4d..96514c1 100644 (file)
@@ -15,7 +15,7 @@
        compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
 
        chosen {
-               bootargs = "128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
+               bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
        };
 
        ahb {
index 7d87184..90610c7 100644 (file)
@@ -33,7 +33,7 @@ CONFIG_AEABI=y
 CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096"
+CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096 rw"
 CONFIG_CMDLINE_FORCE=y
 CONFIG_KEXEC=y
 CONFIG_VFP=y
index 2ae842d..5c44dcb 100644 (file)
@@ -203,6 +203,13 @@ static inline void dma_free_writecombine(struct device *dev, size_t size,
 }
 
 /*
+ * This can be called during early boot to increase the size of the atomic
+ * coherent DMA pool above the default value of 256KiB. It must be called
+ * before postcore_initcall.
+ */
+extern void __init init_dma_coherent_pool_size(unsigned long size);
+
+/*
  * This can be called during boot to increase the size of the consistent
  * DMA region above it's default value of 2MB. It must be called before the
  * memory allocator is initialised, i.e. before any core_initcall.
index 104ca40..aaa443b 100644 (file)
@@ -197,7 +197,7 @@ void __init at91rm9200_timer_init(void)
        at91_st_read(AT91_ST_SR);
 
        /* Make IRQs happen for the system timer */
-       setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
+       setup_irq(NR_IRQS_LEGACY + AT91_ID_SYS, &at91rm9200_timer_irq);
 
        /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
         * directly for the clocksource and all clockevents, after adjusting
index 7b9c2ba..bce572a 100644 (file)
@@ -726,6 +726,8 @@ static struct resource rtt_resources[] = {
                .flags  = IORESOURCE_MEM,
        }, {
                .flags  = IORESOURCE_MEM,
+       }, {
+               .flags  = IORESOURCE_IRQ,
        },
 };
 
@@ -744,10 +746,12 @@ static void __init at91_add_device_rtt_rtc(void)
         * The second resource is needed:
         * GPBR will serve as the storage for RTC time offset
         */
-       at91sam9260_rtt_device.num_resources = 2;
+       at91sam9260_rtt_device.num_resources = 3;
        rtt_resources[1].start = AT91SAM9260_BASE_GPBR +
                                 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
        rtt_resources[1].end = rtt_resources[1].start + 3;
+       rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+       rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
 }
 #else
 static void __init at91_add_device_rtt_rtc(void)
index 8df5c1b..bc2590d 100644 (file)
@@ -609,6 +609,8 @@ static struct resource rtt_resources[] = {
                .flags  = IORESOURCE_MEM,
        }, {
                .flags  = IORESOURCE_MEM,
+       }, {
+               .flags  = IORESOURCE_IRQ,
        }
 };
 
@@ -626,10 +628,12 @@ static void __init at91_add_device_rtt_rtc(void)
         * The second resource is needed:
         * GPBR will serve as the storage for RTC time offset
         */
-       at91sam9261_rtt_device.num_resources = 2;
+       at91sam9261_rtt_device.num_resources = 3;
        rtt_resources[1].start = AT91SAM9261_BASE_GPBR +
                                 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
        rtt_resources[1].end = rtt_resources[1].start + 3;
+       rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+       rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
 }
 #else
 static void __init at91_add_device_rtt_rtc(void)
index eb6bbf8..9b6ca73 100644 (file)
@@ -990,6 +990,8 @@ static struct resource rtt0_resources[] = {
                .flags  = IORESOURCE_MEM,
        }, {
                .flags  = IORESOURCE_MEM,
+       }, {
+               .flags  = IORESOURCE_IRQ,
        }
 };
 
@@ -1006,6 +1008,8 @@ static struct resource rtt1_resources[] = {
                .flags  = IORESOURCE_MEM,
        }, {
                .flags  = IORESOURCE_MEM,
+       }, {
+               .flags  = IORESOURCE_IRQ,
        }
 };
 
@@ -1027,14 +1031,14 @@ static void __init at91_add_device_rtt_rtc(void)
                 * The second resource is needed only for the chosen RTT:
                 * GPBR will serve as the storage for RTC time offset
                 */
-               at91sam9263_rtt0_device.num_resources = 2;
+               at91sam9263_rtt0_device.num_resources = 3;
                at91sam9263_rtt1_device.num_resources = 1;
                pdev = &at91sam9263_rtt0_device;
                r = rtt0_resources;
                break;
        case 1:
                at91sam9263_rtt0_device.num_resources = 1;
-               at91sam9263_rtt1_device.num_resources = 2;
+               at91sam9263_rtt1_device.num_resources = 3;
                pdev = &at91sam9263_rtt1_device;
                r = rtt1_resources;
                break;
@@ -1047,6 +1051,8 @@ static void __init at91_add_device_rtt_rtc(void)
        pdev->name = "rtc-at91sam9";
        r[1].start = AT91SAM9263_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
        r[1].end = r[1].start + 3;
+       r[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+       r[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
 }
 #else
 static void __init at91_add_device_rtt_rtc(void)
index 0607399..1b47319 100644 (file)
@@ -1293,6 +1293,8 @@ static struct resource rtt_resources[] = {
                .flags  = IORESOURCE_MEM,
        }, {
                .flags  = IORESOURCE_MEM,
+       }, {
+               .flags  = IORESOURCE_IRQ,
        }
 };
 
@@ -1310,10 +1312,12 @@ static void __init at91_add_device_rtt_rtc(void)
         * The second resource is needed:
         * GPBR will serve as the storage for RTC time offset
         */
-       at91sam9g45_rtt_device.num_resources = 2;
+       at91sam9g45_rtt_device.num_resources = 3;
        rtt_resources[1].start = AT91SAM9G45_BASE_GPBR +
                                 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
        rtt_resources[1].end = rtt_resources[1].start + 3;
+       rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+       rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
 }
 #else
 static void __init at91_add_device_rtt_rtc(void)
index f09fff9..b3d365d 100644 (file)
@@ -688,6 +688,8 @@ static struct resource rtt_resources[] = {
                .flags  = IORESOURCE_MEM,
        }, {
                .flags  = IORESOURCE_MEM,
+       }, {
+               .flags  = IORESOURCE_IRQ,
        }
 };
 
@@ -705,10 +707,12 @@ static void __init at91_add_device_rtt_rtc(void)
         * The second resource is needed:
         * GPBR will serve as the storage for RTC time offset
         */
-       at91sam9rl_rtt_device.num_resources = 2;
+       at91sam9rl_rtt_device.num_resources = 3;
        rtt_resources[1].start = AT91SAM9RL_BASE_GPBR +
                                 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
        rtt_resources[1].end = rtt_resources[1].start + 3;
+       rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+       rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
 }
 #else
 static void __init at91_add_device_rtt_rtc(void)
index de2ec6b..188c829 100644 (file)
@@ -63,6 +63,12 @@ EXPORT_SYMBOL_GPL(at91_pmc_base);
 
 #define cpu_has_300M_plla()    (cpu_is_at91sam9g10())
 
+#define cpu_has_240M_plla()    (cpu_is_at91sam9261() \
+                               || cpu_is_at91sam9263() \
+                               || cpu_is_at91sam9rl())
+
+#define cpu_has_210M_plla()    (cpu_is_at91sam9260())
+
 #define cpu_has_pllb()         (!(cpu_is_at91sam9rl() \
                                || cpu_is_at91sam9g45() \
                                || cpu_is_at91sam9x5() \
@@ -706,6 +712,12 @@ static int __init at91_pmc_init(unsigned long main_clock)
        } else if (cpu_has_800M_plla()) {
                if (plla.rate_hz > 800000000)
                        pll_overclock = true;
+       } else if (cpu_has_240M_plla()) {
+               if (plla.rate_hz > 240000000)
+                       pll_overclock = true;
+       } else if (cpu_has_210M_plla()) {
+               if (plla.rate_hz > 210000000)
+                       pll_overclock = true;
        } else {
                if (plla.rate_hz > 209000000)
                        pll_overclock = true;
index ca70e5f..020852d 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/sched.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
+#include <asm/system_misc.h>
 #include <mach/hardware.h>
 
 #define IRQ_SOURCE(base_addr)  (base_addr + 0x00)
index 3226077..1201191 100644 (file)
@@ -517,6 +517,13 @@ void __init kirkwood_wdt_init(void)
 void __init kirkwood_init_early(void)
 {
        orion_time_set_base(TIMER_VIRT_BASE);
+
+       /*
+        * Some Kirkwood devices allocate their coherent buffers from atomic
+        * context. Increase size of atomic coherent pool to make sure such
+        * the allocations won't fail.
+        */
+       init_dma_coherent_pool_size(SZ_1M);
 }
 
 int kirkwood_tclk;
index d933593..be90b7d 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/sizes.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/partitions.h>
 #include <linux/ata_platform.h>
index cf10f92..453a6e5 100644 (file)
@@ -520,13 +520,14 @@ static struct platform_device hdmi_lcdc_device = {
 };
 
 /* GPIO KEY */
-#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
+#define GPIO_KEY(c, g, d, ...) \
+       { .code = c, .gpio = g, .desc = d, .active_low = 1, __VA_ARGS__ }
 
 static struct gpio_keys_button gpio_buttons[] = {
-       GPIO_KEY(KEY_POWER,     GPIO_PORT99,    "SW1"),
-       GPIO_KEY(KEY_BACK,      GPIO_PORT100,   "SW2"),
-       GPIO_KEY(KEY_MENU,      GPIO_PORT97,    "SW3"),
-       GPIO_KEY(KEY_HOME,      GPIO_PORT98,    "SW4"),
+       GPIO_KEY(KEY_POWER,     GPIO_PORT99,    "SW3", .wakeup = 1),
+       GPIO_KEY(KEY_BACK,      GPIO_PORT100,   "SW4"),
+       GPIO_KEY(KEY_MENU,      GPIO_PORT97,    "SW5"),
+       GPIO_KEY(KEY_HOME,      GPIO_PORT98,    "SW6"),
 };
 
 static struct gpio_keys_platform_data gpio_key_info = {
@@ -901,8 +902,8 @@ static struct platform_device *eva_devices[] __initdata = {
        &camera_device,
        &ceu0_device,
        &fsi_device,
-       &fsi_hdmi_device,
        &fsi_wm8978_device,
+       &fsi_hdmi_device,
 };
 
 static void __init eva_clock_init(void)
index 7ea2b31..c129542 100644 (file)
@@ -695,6 +695,7 @@ static struct platform_device usbhs0_device = {
  *  - J30 "open"
  *  - modify usbhs1_get_id() USBHS_HOST -> USBHS_GADGET
  *  - add .get_vbus = usbhs_get_vbus in usbhs1_private
+ *  - check usbhs0_device(pio)/usbhs1_device(irq) order in mackerel_devices.
  */
 #define IRQ8 evt2irq(0x0300)
 #define USB_PHY_MODE           (1 << 4)
@@ -1325,8 +1326,8 @@ static struct platform_device *mackerel_devices[] __initdata = {
        &nor_flash_device,
        &smc911x_device,
        &lcdc_device,
-       &usbhs1_device,
        &usbhs0_device,
+       &usbhs1_device,
        &leds_device,
        &fsi_device,
        &fsi_ak4643_device,
index 3a528cf..fcf5a47 100644 (file)
@@ -67,7 +67,7 @@ static struct smsc911x_platform_config smsc911x_platdata = {
 
 static struct platform_device eth_device = {
        .name           = "smsc911x",
-       .id             = 0,
+       .id             = -1,
        .dev  = {
                .platform_data = &smsc911x_platdata,
        },
index ee44740..588555a 100644 (file)
@@ -259,9 +259,9 @@ static int sh73a0_set_wake(struct irq_data *data, unsigned int on)
        return 0; /* always allow wakeup */
 }
 
-#define RELOC_BASE 0x1000
+#define RELOC_BASE 0x1200
 
-/* INTCA IRQ pins at INTCS + 0x1000 to make space for GIC+INTC handling */
+/* INTCA IRQ pins at INTCS + RELOC_BASE to make space for GIC+INTC handling */
 #define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE)
 
 INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
index d3ad515..c25a2a4 100644 (file)
@@ -367,17 +367,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_fixup_class);
 /* Tegra PCIE requires relaxed ordering */
 static void __devinit tegra_pcie_relax_enable(struct pci_dev *dev)
 {
-       u16 val16;
-       int pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
-
-       if (pos <= 0) {
-               dev_err(&dev->dev, "skipping relaxed ordering fixup\n");
-               return;
-       }
-
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &val16);
-       val16 |= PCI_EXP_DEVCTL_RELAX_EN;
-       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, val16);
+       pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN);
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
 
index 4e7d118..051204f 100644 (file)
@@ -267,17 +267,19 @@ static void __dma_free_remap(void *cpu_addr, size_t size)
        vunmap(cpu_addr);
 }
 
+#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K
+
 struct dma_pool {
        size_t size;
        spinlock_t lock;
        unsigned long *bitmap;
        unsigned long nr_pages;
        void *vaddr;
-       struct page *page;
+       struct page **pages;
 };
 
 static struct dma_pool atomic_pool = {
-       .size = SZ_256K,
+       .size = DEFAULT_DMA_COHERENT_POOL_SIZE,
 };
 
 static int __init early_coherent_pool(char *p)
@@ -287,6 +289,21 @@ static int __init early_coherent_pool(char *p)
 }
 early_param("coherent_pool", early_coherent_pool);
 
+void __init init_dma_coherent_pool_size(unsigned long size)
+{
+       /*
+        * Catch any attempt to set the pool size too late.
+        */
+       BUG_ON(atomic_pool.vaddr);
+
+       /*
+        * Set architecture specific coherent pool size only if
+        * it has not been changed by kernel command line parameter.
+        */
+       if (atomic_pool.size == DEFAULT_DMA_COHERENT_POOL_SIZE)
+               atomic_pool.size = size;
+}
+
 /*
  * Initialise the coherent pool for atomic allocations.
  */
@@ -297,6 +314,7 @@ static int __init atomic_pool_init(void)
        unsigned long nr_pages = pool->size >> PAGE_SHIFT;
        unsigned long *bitmap;
        struct page *page;
+       struct page **pages;
        void *ptr;
        int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
 
@@ -304,21 +322,31 @@ static int __init atomic_pool_init(void)
        if (!bitmap)
                goto no_bitmap;
 
+       pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
+       if (!pages)
+               goto no_pages;
+
        if (IS_ENABLED(CONFIG_CMA))
                ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page);
        else
                ptr = __alloc_remap_buffer(NULL, pool->size, GFP_KERNEL, prot,
                                           &page, NULL);
        if (ptr) {
+               int i;
+
+               for (i = 0; i < nr_pages; i++)
+                       pages[i] = page + i;
+
                spin_lock_init(&pool->lock);
                pool->vaddr = ptr;
-               pool->page = page;
+               pool->pages = pages;
                pool->bitmap = bitmap;
                pool->nr_pages = nr_pages;
                pr_info("DMA: preallocated %u KiB pool for atomic coherent allocations\n",
                       (unsigned)pool->size / 1024);
                return 0;
        }
+no_pages:
        kfree(bitmap);
 no_bitmap:
        pr_err("DMA: failed to allocate %u KiB pool for atomic coherent allocation\n",
@@ -443,27 +471,45 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page)
        if (pageno < pool->nr_pages) {
                bitmap_set(pool->bitmap, pageno, count);
                ptr = pool->vaddr + PAGE_SIZE * pageno;
-               *ret_page = pool->page + pageno;
+               *ret_page = pool->pages[pageno];
+       } else {
+               pr_err_once("ERROR: %u KiB atomic DMA coherent pool is too small!\n"
+                           "Please increase it with coherent_pool= kernel parameter!\n",
+                           (unsigned)pool->size / 1024);
        }
        spin_unlock_irqrestore(&pool->lock, flags);
 
        return ptr;
 }
 
+static bool __in_atomic_pool(void *start, size_t size)
+{
+       struct dma_pool *pool = &atomic_pool;
+       void *end = start + size;
+       void *pool_start = pool->vaddr;
+       void *pool_end = pool->vaddr + pool->size;
+
+       if (start < pool_start || start > pool_end)
+               return false;
+
+       if (end <= pool_end)
+               return true;
+
+       WARN(1, "Wrong coherent size(%p-%p) from atomic pool(%p-%p)\n",
+            start, end - 1, pool_start, pool_end - 1);
+
+       return false;
+}
+
 static int __free_from_pool(void *start, size_t size)
 {
        struct dma_pool *pool = &atomic_pool;
        unsigned long pageno, count;
        unsigned long flags;
 
-       if (start < pool->vaddr || start > pool->vaddr + pool->size)
+       if (!__in_atomic_pool(start, size))
                return 0;
 
-       if (start + size > pool->vaddr + pool->size) {
-               WARN(1, "freeing wrong coherent size from pool\n");
-               return 0;
-       }
-
        pageno = (start - pool->vaddr) >> PAGE_SHIFT;
        count = size >> PAGE_SHIFT;
 
@@ -1090,10 +1136,22 @@ static int __iommu_remove_mapping(struct device *dev, dma_addr_t iova, size_t si
        return 0;
 }
 
+static struct page **__atomic_get_pages(void *addr)
+{
+       struct dma_pool *pool = &atomic_pool;
+       struct page **pages = pool->pages;
+       int offs = (addr - pool->vaddr) >> PAGE_SHIFT;
+
+       return pages + offs;
+}
+
 static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
 {
        struct vm_struct *area;
 
+       if (__in_atomic_pool(cpu_addr, PAGE_SIZE))
+               return __atomic_get_pages(cpu_addr);
+
        if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs))
                return cpu_addr;
 
@@ -1103,6 +1161,34 @@ static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
        return NULL;
 }
 
+static void *__iommu_alloc_atomic(struct device *dev, size_t size,
+                                 dma_addr_t *handle)
+{
+       struct page *page;
+       void *addr;
+
+       addr = __alloc_from_pool(size, &page);
+       if (!addr)
+               return NULL;
+
+       *handle = __iommu_create_mapping(dev, &page, size);
+       if (*handle == DMA_ERROR_CODE)
+               goto err_mapping;
+
+       return addr;
+
+err_mapping:
+       __free_from_pool(addr, size);
+       return NULL;
+}
+
+static void __iommu_free_atomic(struct device *dev, struct page **pages,
+                               dma_addr_t handle, size_t size)
+{
+       __iommu_remove_mapping(dev, handle, size);
+       __free_from_pool(page_address(pages[0]), size);
+}
+
 static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
            dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
 {
@@ -1113,6 +1199,9 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
        *handle = DMA_ERROR_CODE;
        size = PAGE_ALIGN(size);
 
+       if (gfp & GFP_ATOMIC)
+               return __iommu_alloc_atomic(dev, size, handle);
+
        pages = __iommu_alloc_buffer(dev, size, gfp);
        if (!pages)
                return NULL;
@@ -1179,6 +1268,11 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
                return;
        }
 
+       if (__in_atomic_pool(cpu_addr, size)) {
+               __iommu_free_atomic(dev, pages, handle, size);
+               return;
+       }
+
        if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) {
                unmap_kernel_range((unsigned long)cpu_addr, size);
                vunmap(cpu_addr);
index 52a1ba7..c5dfb2c 100644 (file)
@@ -117,16 +117,11 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
        }
 
        /* Enable the PCIe normal error reporting */
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
-       if (pos) {
-               /* Update Device Control */
-               pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config);
-               config |= PCI_EXP_DEVCTL_CERE; /* Correctable Error Reporting */
-               config |= PCI_EXP_DEVCTL_NFERE; /* Non-Fatal Error Reporting */
-               config |= PCI_EXP_DEVCTL_FERE;  /* Fatal Error Reporting */
-               config |= PCI_EXP_DEVCTL_URRE;  /* Unsupported Request */
-               pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config);
-       }
+       config = PCI_EXP_DEVCTL_CERE; /* Correctable Error Reporting */
+       config |= PCI_EXP_DEVCTL_NFERE; /* Non-Fatal Error Reporting */
+       config |= PCI_EXP_DEVCTL_FERE;  /* Fatal Error Reporting */
+       config |= PCI_EXP_DEVCTL_URRE;  /* Unsupported Request */
+       pcie_capability_set_word(dev, PCI_EXP_DEVCTL, config);
 
        /* Find the Advanced Error Reporting capability */
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
index b8bab10..4ce0be3 100644 (file)
@@ -562,6 +562,14 @@ config SCHED_SMT
          when dealing with POWER5 cpus at a cost of slightly increased
          overhead in some places. If unsure say N here.
 
+config PPC_DENORMALISATION
+       bool "PowerPC denormalisation exception handling"
+       depends on PPC_BOOK3S_64
+       default "n"
+       ---help---
+         Add support for handling denormalisation of single precision
+         values.  Useful for bare metal only.  If unsure say Y here.
+
 config CMDLINE_BOOL
        bool "Default bootloader kernel arguments"
 
index db27c82..e263e6a 100644 (file)
@@ -51,6 +51,7 @@ CONFIG_KEXEC=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_SCHED_SMT=y
+CONFIG_PPC_DENORMALISATION=y
 CONFIG_PCCARD=y
 CONFIG_ELECTRA_CF=y
 CONFIG_HOTPLUG_PCI=m
index 1f65b3c..c169dfb 100644 (file)
@@ -48,6 +48,7 @@ CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_PPC_64K_PAGES=y
 CONFIG_PPC_SUBPAGE_PROT=y
 CONFIG_SCHED_SMT=y
+CONFIG_PPC_DENORMALISATION=y
 CONFIG_HOTPLUG_PCI=m
 CONFIG_HOTPLUG_PCI_RPA=m
 CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
index 58c5ee6..b0ef738 100644 (file)
@@ -45,9 +45,10 @@ struct device_node;
  * in the corresponding PHB. Therefore, the root PEs should be created
  * against existing PHBs in on-to-one fashion.
  */
-#define EEH_PE_PHB     1       /* PHB PE    */
-#define EEH_PE_DEVICE  2       /* Device PE */
-#define EEH_PE_BUS     3       /* Bus PE    */
+#define EEH_PE_INVALID (1 << 0)        /* Invalid   */
+#define EEH_PE_PHB     (1 << 1)        /* PHB PE    */
+#define EEH_PE_DEVICE  (1 << 2)        /* Device PE */
+#define EEH_PE_BUS     (1 << 3)        /* Bus PE    */
 
 #define EEH_PE_ISOLATED                (1 << 0)        /* Isolated PE          */
 #define EEH_PE_RECOVERING      (1 << 1)        /* Recovering PE        */
@@ -184,7 +185,7 @@ static inline void eeh_unlock(void)
 typedef void *(*eeh_traverse_func)(void *data, void *flag);
 int __devinit eeh_phb_pe_create(struct pci_controller *phb);
 int eeh_add_to_parent_pe(struct eeh_dev *edev);
-int eeh_rmv_from_parent_pe(struct eeh_dev *edev);
+int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe);
 void *eeh_pe_dev_traverse(struct eeh_pe *root,
                eeh_traverse_func fn, void *flag);
 void eeh_pe_restore_bars(struct eeh_pe *pe);
@@ -200,7 +201,7 @@ int eeh_dev_check_failure(struct eeh_dev *edev);
 void __init eeh_addr_cache_build(void);
 void eeh_add_device_tree_early(struct device_node *);
 void eeh_add_device_tree_late(struct pci_bus *);
-void eeh_remove_bus_device(struct pci_dev *);
+void eeh_remove_bus_device(struct pci_dev *, int);
 
 /**
  * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
@@ -239,7 +240,7 @@ static inline void eeh_add_device_tree_early(struct device_node *dn) { }
 
 static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
 
-static inline void eeh_remove_bus_device(struct pci_dev *dev) { }
+static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { }
 
 static inline void eeh_lock(void) { }
 static inline void eeh_unlock(void) { }
index f0e0c6a..7aefdb3 100644 (file)
@@ -59,7 +59,7 @@ struct hpte_cache {
        struct hlist_node list_vpte;
        struct hlist_node list_vpte_long;
        struct rcu_head rcu_head;
-       u64 host_va;
+       u64 host_vpn;
        u64 pfn;
        ulong slot;
        struct kvmppc_pte pte;
index 236b477..c423197 100644 (file)
@@ -34,19 +34,19 @@ struct machdep_calls {
        char            *name;
 #ifdef CONFIG_PPC64
        void            (*hpte_invalidate)(unsigned long slot,
-                                          unsigned long va,
+                                          unsigned long vpn,
                                           int psize, int ssize,
                                           int local);
        long            (*hpte_updatepp)(unsigned long slot, 
                                         unsigned long newpp, 
-                                        unsigned long va,
+                                        unsigned long vpn,
                                         int psize, int ssize,
                                         int local);
        void            (*hpte_updateboltedpp)(unsigned long newpp, 
                                               unsigned long ea,
                                               int psize, int ssize);
        long            (*hpte_insert)(unsigned long hpte_group,
-                                      unsigned long va,
+                                      unsigned long vpn,
                                       unsigned long prpn,
                                       unsigned long rflags,
                                       unsigned long vflags,
@@ -215,6 +215,9 @@ struct machdep_calls {
        /* Called after scan and before resource survey */
        void (*pcibios_fixup_phb)(struct pci_controller *hose);
 
+       /* Called during PCI resource reassignment */
+       resource_size_t (*pcibios_window_alignment)(struct pci_bus *, unsigned long type);
+
        /* Called to shutdown machine specific hardware not already controlled
         * by other drivers.
         */
index 1c65a59..9673f73 100644 (file)
 #include <asm/page.h>
 
 /*
+ * This is necessary to get the definition of PGTABLE_RANGE which we
+ * need for various slices related matters. Note that this isn't the
+ * complete pgtable.h but only a portion of it.
+ */
+#include <asm/pgtable-ppc64.h>
+
+/*
  * Segment table
  */
 
@@ -154,9 +161,25 @@ struct mmu_psize_def
 #define MMU_SEGSIZE_256M       0
 #define MMU_SEGSIZE_1T         1
 
+/*
+ * encode page number shift.
+ * in order to fit the 78 bit va in a 64 bit variable we shift the va by
+ * 12 bits. This enable us to address upto 76 bit va.
+ * For hpt hash from a va we can ignore the page size bits of va and for
+ * hpte encoding we ignore up to 23 bits of va. So ignoring lower 12 bits ensure
+ * we work in all cases including 4k page size.
+ */
+#define VPN_SHIFT      12
 
 #ifndef __ASSEMBLY__
 
+static inline int segment_shift(int ssize)
+{
+       if (ssize == MMU_SEGSIZE_256M)
+               return SID_SHIFT;
+       return SID_SHIFT_1T;
+}
+
 /*
  * The current system page and segment sizes
  */
@@ -180,18 +203,39 @@ extern unsigned long tce_alloc_start, tce_alloc_end;
 extern int mmu_ci_restrictions;
 
 /*
+ * This computes the AVPN and B fields of the first dword of a HPTE,
+ * for use when we want to match an existing PTE.  The bottom 7 bits
+ * of the returned value are zero.
+ */
+static inline unsigned long hpte_encode_avpn(unsigned long vpn, int psize,
+                                            int ssize)
+{
+       unsigned long v;
+       /*
+        * The AVA field omits the low-order 23 bits of the 78 bits VA.
+        * These bits are not needed in the PTE, because the
+        * low-order b of these bits are part of the byte offset
+        * into the virtual page and, if b < 23, the high-order
+        * 23-b of these bits are always used in selecting the
+        * PTEGs to be searched
+        */
+       v = (vpn >> (23 - VPN_SHIFT)) & ~(mmu_psize_defs[psize].avpnm);
+       v <<= HPTE_V_AVPN_SHIFT;
+       v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
+       return v;
+}
+
+/*
  * This function sets the AVPN and L fields of the HPTE  appropriately
  * for the page size
  */
-static inline unsigned long hpte_encode_v(unsigned long va, int psize,
-                                         int ssize)
+static inline unsigned long hpte_encode_v(unsigned long vpn,
+                                         int psize, int ssize)
 {
        unsigned long v;
-       v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
-       v <<= HPTE_V_AVPN_SHIFT;
+       v = hpte_encode_avpn(vpn, psize, ssize);
        if (psize != MMU_PAGE_4K)
                v |= HPTE_V_LARGE;
-       v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
        return v;
 }
 
@@ -216,30 +260,37 @@ static inline unsigned long hpte_encode_r(unsigned long pa, int psize)
 }
 
 /*
- * Build a VA given VSID, EA and segment size
+ * Build a VPN_SHIFT bit shifted va given VSID, EA and segment size.
  */
-static inline unsigned long hpt_va(unsigned long ea, unsigned long vsid,
-                                  int ssize)
+static inline unsigned long hpt_vpn(unsigned long ea,
+                                   unsigned long vsid, int ssize)
 {
-       if (ssize == MMU_SEGSIZE_256M)
-               return (vsid << 28) | (ea & 0xfffffffUL);
-       return (vsid << 40) | (ea & 0xffffffffffUL);
+       unsigned long mask;
+       int s_shift = segment_shift(ssize);
+
+       mask = (1ul << (s_shift - VPN_SHIFT)) - 1;
+       return (vsid << (s_shift - VPN_SHIFT)) | ((ea >> VPN_SHIFT) & mask);
 }
 
 /*
  * This hashes a virtual address
  */
-
-static inline unsigned long hpt_hash(unsigned long va, unsigned int shift,
-                                    int ssize)
+static inline unsigned long hpt_hash(unsigned long vpn,
+                                    unsigned int shift, int ssize)
 {
+       int mask;
        unsigned long hash, vsid;
 
+       /* VPN_SHIFT can be atmost 12 */
        if (ssize == MMU_SEGSIZE_256M) {
-               hash = (va >> 28) ^ ((va & 0x0fffffffUL) >> shift);
+               mask = (1ul << (SID_SHIFT - VPN_SHIFT)) - 1;
+               hash = (vpn >> (SID_SHIFT - VPN_SHIFT)) ^
+                       ((vpn & mask) >> (shift - VPN_SHIFT));
        } else {
-               vsid = va >> 40;
-               hash = vsid ^ (vsid << 25) ^ ((va & 0xffffffffffUL) >> shift);
+               mask = (1ul << (SID_SHIFT_1T - VPN_SHIFT)) - 1;
+               vsid = vpn >> (SID_SHIFT_1T - VPN_SHIFT);
+               hash = vsid ^ (vsid << 25) ^
+                       ((vpn & mask) >> (shift - VPN_SHIFT)) ;
        }
        return hash & 0x7fffffffffUL;
 }
@@ -280,63 +331,61 @@ extern void slb_set_size(u16 size);
 #endif /* __ASSEMBLY__ */
 
 /*
- * VSID allocation
+ * VSID allocation (256MB segment)
+ *
+ * We first generate a 38-bit "proto-VSID".  For kernel addresses this
+ * is equal to the ESID | 1 << 37, for user addresses it is:
+ *     (context << USER_ESID_BITS) | (esid & ((1U << USER_ESID_BITS) - 1)
  *
- * We first generate a 36-bit "proto-VSID".  For kernel addresses this
- * is equal to the ESID, for user addresses it is:
- *     (context << 15) | (esid & 0x7fff)
+ * This splits the proto-VSID into the below range
+ *  0 - (2^(CONTEXT_BITS + USER_ESID_BITS) - 1) : User proto-VSID range
+ *  2^(CONTEXT_BITS + USER_ESID_BITS) - 2^(VSID_BITS) : Kernel proto-VSID range
  *
- * The two forms are distinguishable because the top bit is 0 for user
- * addresses, whereas the top two bits are 1 for kernel addresses.
- * Proto-VSIDs with the top two bits equal to 0b10 are reserved for
- * now.
+ * We also have CONTEXT_BITS + USER_ESID_BITS = VSID_BITS - 1
+ * That is, we assign half of the space to user processes and half
+ * to the kernel.
  *
  * The proto-VSIDs are then scrambled into real VSIDs with the
  * multiplicative hash:
  *
  *     VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
- *     where   VSID_MULTIPLIER = 268435399 = 0xFFFFFC7
- *             VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF
  *
- * This scramble is only well defined for proto-VSIDs below
- * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are
- * reserved.  VSID_MULTIPLIER is prime, so in particular it is
+ * VSID_MULTIPLIER is prime, so in particular it is
  * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
  * Because the modulus is 2^n-1 we can compute it efficiently without
  * a divide or extra multiply (see below).
  *
  * This scheme has several advantages over older methods:
  *
- *     - We have VSIDs allocated for every kernel address
+ *     - We have VSIDs allocated for every kernel address
  * (i.e. everything above 0xC000000000000000), except the very top
  * segment, which simplifies several things.
  *
- *     - We allow for 16 significant bits of ESID and 19 bits of
- * context for user addresses.  i.e. 16T (44 bits) of address space for
- * up to half a million contexts.
+ *     - We allow for USER_ESID_BITS significant bits of ESID and
+ * CONTEXT_BITS  bits of context for user addresses.
+ *  i.e. 64T (46 bits) of address space for up to half a million contexts.
  *
- *     - The scramble function gives robust scattering in the hash
+ *     - The scramble function gives robust scattering in the hash
  * table (at least based on some initial results).  The previous
  * method was more susceptible to pathological cases giving excessive
  * hash collisions.
  */
+
 /*
- * WARNING - If you change these you must make sure the asm
- * implementations in slb_allocate (slb_low.S), do_stab_bolted
- * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly.
+ * This should be computed such that protovosid * vsid_mulitplier
+ * doesn't overflow 64 bits. It should also be co-prime to vsid_modulus
  */
-
-#define VSID_MULTIPLIER_256M   ASM_CONST(200730139)    /* 28-bit prime */
-#define VSID_BITS_256M         36
+#define VSID_MULTIPLIER_256M   ASM_CONST(12538073)     /* 24-bit prime */
+#define VSID_BITS_256M         38
 #define VSID_MODULUS_256M      ((1UL<<VSID_BITS_256M)-1)
 
 #define VSID_MULTIPLIER_1T     ASM_CONST(12538073)     /* 24-bit prime */
-#define VSID_BITS_1T           24
+#define VSID_BITS_1T           26
 #define VSID_MODULUS_1T                ((1UL<<VSID_BITS_1T)-1)
 
 #define CONTEXT_BITS           19
-#define USER_ESID_BITS         16
-#define USER_ESID_BITS_1T      4
+#define USER_ESID_BITS         18
+#define USER_ESID_BITS_1T      6
 
 #define USER_VSID_RANGE        (1UL << (USER_ESID_BITS + SID_SHIFT))
 
@@ -372,6 +421,8 @@ extern void slb_set_size(u16 size);
        srdi    rx,rx,VSID_BITS_##size; /* extract 2^VSID_BITS bit */   \
        add     rt,rt,rx
 
+/* 4 bits per slice and we have one slice per 1TB */
+#define SLICE_ARRAY_SIZE  (PGTABLE_RANGE >> 41)
 
 #ifndef __ASSEMBLY__
 
@@ -416,7 +467,7 @@ typedef struct {
 
 #ifdef CONFIG_PPC_MM_SLICES
        u64 low_slices_psize;   /* SLB page size encodings */
-       u64 high_slices_psize;  /* 4 bits per slice for now */
+       unsigned char high_slices_psize[SLICE_ARRAY_SIZE];
 #else
        u16 sllp;               /* SLB page size encoding */
 #endif
@@ -452,12 +503,32 @@ typedef struct {
        })
 #endif /* 1 */
 
-/* This is only valid for addresses >= PAGE_OFFSET */
+/*
+ * This is only valid for addresses >= PAGE_OFFSET
+ * The proto-VSID space is divided into two class
+ * User:   0 to 2^(CONTEXT_BITS + USER_ESID_BITS) -1
+ * kernel: 2^(CONTEXT_BITS + USER_ESID_BITS) to 2^(VSID_BITS) - 1
+ *
+ * With KERNEL_START at 0xc000000000000000, the proto vsid for
+ * the kernel ends up with 0xc00000000 (36 bits). With 64TB
+ * support we need to have kernel proto-VSID in the
+ * [2^37 to 2^38 - 1] range due to the increased USER_ESID_BITS.
+ */
 static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
 {
-       if (ssize == MMU_SEGSIZE_256M)
-               return vsid_scramble(ea >> SID_SHIFT, 256M);
-       return vsid_scramble(ea >> SID_SHIFT_1T, 1T);
+       unsigned long proto_vsid;
+       /*
+        * We need to make sure proto_vsid for the kernel is
+        * >= 2^(CONTEXT_BITS + USER_ESID_BITS[_1T])
+        */
+       if (ssize == MMU_SEGSIZE_256M) {
+               proto_vsid = ea >> SID_SHIFT;
+               proto_vsid |= (1UL << (CONTEXT_BITS + USER_ESID_BITS));
+               return vsid_scramble(proto_vsid, 256M);
+       }
+       proto_vsid = ea >> SID_SHIFT_1T;
+       proto_vsid |= (1UL << (CONTEXT_BITS + USER_ESID_BITS_1T));
+       return vsid_scramble(proto_vsid, 1T);
 }
 
 /* Returns the segment size indicator for a user address */
index e8a26db..5e38eed 100644 (file)
@@ -146,6 +146,15 @@ extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
 extern u64 ppc64_rma_size;
 #endif /* CONFIG_PPC64 */
 
+struct mm_struct;
+#ifdef CONFIG_DEBUG_VM
+extern void assert_pte_locked(struct mm_struct *mm, unsigned long addr);
+#else /* CONFIG_DEBUG_VM */
+static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
+{
+}
+#endif /* !CONFIG_DEBUG_VM */
+
 #endif /* !__ASSEMBLY__ */
 
 /* The kernel use the constants below to index in the page sizes array.
index 7796519..e9e7a69 100644 (file)
@@ -100,7 +100,7 @@ struct paca_struct {
        /* SLB related definitions */
        u16 vmalloc_sllp;
        u16 slb_cache_ptr;
-       u16 slb_cache[SLB_CACHE_ENTRIES];
+       u32 slb_cache[SLB_CACHE_ENTRIES];
 #endif /* CONFIG_PPC_STD_MMU_64 */
 
 #ifdef CONFIG_PPC_BOOK3E
index fed85e6..cd915d6 100644 (file)
@@ -78,11 +78,19 @@ extern u64 ppc64_pft_size;
 #define GET_LOW_SLICE_INDEX(addr)      ((addr) >> SLICE_LOW_SHIFT)
 #define GET_HIGH_SLICE_INDEX(addr)     ((addr) >> SLICE_HIGH_SHIFT)
 
+/*
+ * 1 bit per slice and we have one slice per 1TB
+ * Right now we support only 64TB.
+ * IF we change this we will have to change the type
+ * of high_slices
+ */
+#define SLICE_MASK_SIZE 8
+
 #ifndef __ASSEMBLY__
 
 struct slice_mask {
        u16 low_slices;
-       u16 high_slices;
+       u64 high_slices;
 };
 
 struct mm_struct;
index 973df4d..025a130 100644 (file)
@@ -182,6 +182,14 @@ static inline int pci_device_from_OF_node(struct device_node *np,
 #if defined(CONFIG_EEH)
 static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn)
 {
+       /*
+        * For those OF nodes whose parent isn't PCI bridge, they
+        * don't have PCI_DN actually. So we have to skip them for
+        * any EEH operations.
+        */
+       if (!dn || !PCI_DN(dn))
+               return NULL;
+
        return PCI_DN(dn)->edev;
 }
 #else
@@ -192,6 +200,7 @@ static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn)
 extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
 
 /** Remove all of the PCI devices under this bus */
+extern void __pcibios_remove_pci_devices(struct pci_bus *bus, int purge_pe);
 extern void pcibios_remove_pci_devices(struct pci_bus *bus);
 
 /** Discover new pci devices under this bus, and add them */
index 6eefdcf..12798c9 100644 (file)
@@ -7,7 +7,7 @@
  */
 #define PTE_INDEX_SIZE  9
 #define PMD_INDEX_SIZE  7
-#define PUD_INDEX_SIZE  7
+#define PUD_INDEX_SIZE  9
 #define PGD_INDEX_SIZE  9
 
 #ifndef __ASSEMBLY__
@@ -19,7 +19,7 @@
 
 #define PTRS_PER_PTE   (1 << PTE_INDEX_SIZE)
 #define PTRS_PER_PMD   (1 << PMD_INDEX_SIZE)
-#define PTRS_PER_PUD   (1 << PMD_INDEX_SIZE)
+#define PTRS_PER_PUD   (1 << PUD_INDEX_SIZE)
 #define PTRS_PER_PGD   (1 << PGD_INDEX_SIZE)
 
 /* PMD_SHIFT determines what a second-level page table entry can map */
index 90533dd..be4e287 100644 (file)
@@ -7,7 +7,7 @@
 #define PTE_INDEX_SIZE  12
 #define PMD_INDEX_SIZE  12
 #define PUD_INDEX_SIZE 0
-#define PGD_INDEX_SIZE  4
+#define PGD_INDEX_SIZE  6
 
 #ifndef __ASSEMBLY__
 #define PTE_TABLE_SIZE (sizeof(real_pte_t) << PTE_INDEX_SIZE)
index c420561..0182c20 100644 (file)
 #define PGTABLE_RANGE (ASM_CONST(1) << PGTABLE_EADDR_SIZE)
 
 
-/* Some sanity checking */
-#if TASK_SIZE_USER64 > PGTABLE_RANGE
-#error TASK_SIZE_USER64 exceeds pagetable range
-#endif
-
-#ifdef CONFIG_PPC_STD_MMU_64
-#if TASK_SIZE_USER64 > (1UL << (USER_ESID_BITS + SID_SHIFT))
-#error TASK_SIZE_USER64 exceeds user VSID range
-#endif
-#endif
-
 /*
  * Define the address range of the kernel non-linear virtual area
  */
@@ -41,7 +30,7 @@
 #else
 #define KERN_VIRT_START ASM_CONST(0xD000000000000000)
 #endif
-#define KERN_VIRT_SIZE PGTABLE_RANGE
+#define KERN_VIRT_SIZE ASM_CONST(0x0000100000000000)
 
 /*
  * The vmalloc space starts at the beginning of that region, and
 
 #ifndef __ASSEMBLY__
 
-#include <linux/stddef.h>
-#include <asm/tlbflush.h>
-
 /*
  * This is the default implementation of various PTE accessors, it's
  * used in all cases except Book3S with 64K pages where we have a
 /* to find an entry in a kernel page-table-directory */
 /* This now only contains the vmalloc pages */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
-
+extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
+                           pte_t *ptep, unsigned long pte, int huge);
 
 /* Atomic PTE updates */
 static inline unsigned long pte_update(struct mm_struct *mm,
index 2e0e411..a9cbd3b 100644 (file)
@@ -9,14 +9,6 @@
 
 struct mm_struct;
 
-#ifdef CONFIG_DEBUG_VM
-extern void assert_pte_locked(struct mm_struct *mm, unsigned long addr);
-#else /* CONFIG_DEBUG_VM */
-static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
-{
-}
-#endif /* !CONFIG_DEBUG_VM */
-
 #endif /* !__ASSEMBLY__ */
 
 #if defined(CONFIG_PPC64)
@@ -27,6 +19,8 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
 
 #ifndef __ASSEMBLY__
 
+#include <asm/tlbflush.h>
+
 /* Generic accessors to PTE bits */
 static inline int pte_write(pte_t pte)         { return pte_val(pte) & _PAGE_RW; }
 static inline int pte_dirty(pte_t pte)         { return pte_val(pte) & _PAGE_DIRTY; }
index 4c25319..5f73ce6 100644 (file)
 #define PPC_INST_TLBIVAX               0x7c000624
 #define PPC_INST_TLBSRX_DOT            0x7c0006a5
 #define PPC_INST_XXLOR                 0xf0000510
+#define PPC_INST_XVCPSGNDP             0xf0000780
 
 #define PPC_INST_NAP                   0x4c000364
 #define PPC_INST_SLEEP                 0x4c0003a4
                                               VSX_XX1((s), a, b))
 #define XXLOR(t, a, b)         stringify_in_c(.long PPC_INST_XXLOR | \
                                               VSX_XX3((t), a, b))
+#define XVCPSGNDP(t, a, b)     stringify_in_c(.long (PPC_INST_XVCPSGNDP | \
+                                              VSX_XX3((t), (a), (b))))
 
 #define PPC_NAP                        stringify_in_c(.long PPC_INST_NAP)
 #define PPC_SLEEP              stringify_in_c(.long PPC_INST_SLEEP)
index 83efc6e..9dc5cd1 100644 (file)
@@ -97,8 +97,8 @@ extern struct task_struct *last_task_used_spe;
 #endif
 
 #ifdef CONFIG_PPC64
-/* 64-bit user address space is 44-bits (16TB user VM) */
-#define TASK_SIZE_USER64 (0x0000100000000000UL)
+/* 64-bit user address space is 46-bits (64TB user VM) */
+#define TASK_SIZE_USER64 (0x0000400000000000UL)
 
 /* 
  * 32-bit user address space is 4GB - 1 page 
index 59247e8..eedf427 100644 (file)
 /* Trick: we set __end to va + 64k, which happens works for
  * a 16M page as well as we want only one iteration
  */
-#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift)         \
-        do {                                                                \
-                unsigned long __end = va + PAGE_SIZE;                       \
-                unsigned __split = (psize == MMU_PAGE_4K ||                 \
-                                   psize == MMU_PAGE_64K_AP);              \
-                shift = mmu_psize_defs[psize].shift;                        \
-               for (index = 0; va < __end; index++, va += (1L << shift)) { \
-                       if (!__split || __rpte_sub_valid(rpte, index)) do { \
+#define pte_iterate_hashed_subpages(rpte, psize, vpn, index, shift)    \
+       do {                                                            \
+               unsigned long __end = vpn + (1UL << (PAGE_SHIFT - VPN_SHIFT));  \
+               unsigned __split = (psize == MMU_PAGE_4K ||             \
+                                   psize == MMU_PAGE_64K_AP);          \
+               shift = mmu_psize_defs[psize].shift;                    \
+               for (index = 0; vpn < __end; index++,                   \
+                            vpn += (1L << (shift - VPN_SHIFT))) {      \
+                       if (!__split || __rpte_sub_valid(rpte, index))  \
+                               do {
 
 #define pte_iterate_hashed_end() } while(0); } } while(0)
 
index 121a90b..a1096fb 100644 (file)
 
 #define SPRN_HSRR0     0x13A   /* Save/Restore Register 0 */
 #define SPRN_HSRR1     0x13B   /* Save/Restore Register 1 */
+#define   HSRR1_DENORM         0x00100000 /* Denorm exception */
 
 #define SPRN_TBCTL     0x35f   /* PA6T Timebase control register */
 #define   TBCTL_FREEZE         0x0000000000000000ull /* Freeze all tbs */
index 0c5fa31..f6fc0ee 100644 (file)
@@ -10,8 +10,8 @@
  */
 #define SECTION_SIZE_BITS       24
 
-#define MAX_PHYSADDR_BITS       44
-#define MAX_PHYSMEM_BITS        44
+#define MAX_PHYSADDR_BITS       46
+#define MAX_PHYSMEM_BITS        46
 
 #endif /* CONFIG_SPARSEMEM */
 
index e942203..8ceea14 100644 (file)
@@ -104,6 +104,8 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_NOTIFY_RESUME      13      /* callback before returning to user */
 #define TIF_UPROBE             14      /* breakpointed or single-stepping */
 #define TIF_SYSCALL_TRACEPOINT 15      /* syscall tracepoint instrumentation */
+#define TIF_EMULATE_STACK_STORE        16      /* Is an instruction emulation
+                                               for stack store? */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
@@ -121,6 +123,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_UPROBE            (1<<TIF_UPROBE)
 #define _TIF_SYSCALL_TRACEPOINT        (1<<TIF_SYSCALL_TRACEPOINT)
+#define _TIF_EMULATE_STACK_STORE       (1<<TIF_EMULATE_STACK_STORE)
 #define _TIF_SYSCALL_T_OR_A    (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
                                 _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)
 
index 81143fc..61a5927 100644 (file)
@@ -95,7 +95,7 @@ struct ppc64_tlb_batch {
        unsigned long           index;
        struct mm_struct        *mm;
        real_pte_t              pte[PPC64_TLB_BATCH_NR];
-       unsigned long           vaddr[PPC64_TLB_BATCH_NR];
+       unsigned long           vpn[PPC64_TLB_BATCH_NR];
        unsigned int            psize;
        int                     ssize;
 };
@@ -103,9 +103,6 @@ DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
 
 extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch);
 
-extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
-                           pte_t *ptep, unsigned long pte, int huge);
-
 #define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
 
 static inline void arch_enter_lazy_mmu_mode(void)
@@ -127,7 +124,7 @@ static inline void arch_leave_lazy_mmu_mode(void)
 #define arch_flush_lazy_mmu_mode()      do {} while (0)
 
 
-extern void flush_hash_page(unsigned long va, real_pte_t pte, int psize,
+extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize,
                            int ssize, int local);
 extern void flush_hash_range(unsigned long number, int local);
 
index 17bb40c..4db4959 100644 (file)
@@ -98,11 +98,6 @@ struct exception_table_entry {
  * PowerPC, we can just do these as direct assignments.  (Of course, the
  * exception handling means that it's no longer "just"...)
  *
- * The "user64" versions of the user access functions are versions that
- * allow access of 64-bit data. The "get_user" functions do not
- * properly handle 64-bit data because the value gets down cast to a long.
- * The "put_user" functions already handle 64-bit data properly but we add
- * "user64" versions for completeness
  */
 #define get_user(x, ptr) \
        __get_user_check((x), (ptr), sizeof(*(ptr)))
@@ -114,12 +109,6 @@ struct exception_table_entry {
 #define __put_user(x, ptr) \
        __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
 
-#ifndef __powerpc64__
-#define __get_user64(x, ptr) \
-       __get_user64_nocheck((x), (ptr), sizeof(*(ptr)))
-#define __put_user64(x, ptr) __put_user(x, ptr)
-#endif
-
 #define __get_user_inatomic(x, ptr) \
        __get_user_nosleep((x), (ptr), sizeof(*(ptr)))
 #define __put_user_inatomic(x, ptr) \
index ead5016..af37528 100644 (file)
@@ -831,19 +831,56 @@ restore_user:
        bnel-   load_dbcr0
 #endif
 
-#ifdef CONFIG_PREEMPT
        b       restore
 
 /* N.B. the only way to get here is from the beq following ret_from_except. */
 resume_kernel:
-       /* check current_thread_info->preempt_count */
+       /* check current_thread_info, _TIF_EMULATE_STACK_STORE */
        CURRENT_THREAD_INFO(r9, r1)
+       lwz     r8,TI_FLAGS(r9)
+       andis.  r8,r8,_TIF_EMULATE_STACK_STORE@h
+       beq+    1f
+
+       addi    r8,r1,INT_FRAME_SIZE    /* Get the kprobed function entry */
+
+       lwz     r3,GPR1(r1)
+       subi    r3,r3,INT_FRAME_SIZE    /* dst: Allocate a trampoline exception frame */
+       mr      r4,r1                   /* src:  current exception frame */
+       mr      r1,r3                   /* Reroute the trampoline frame to r1 */
+
+       /* Copy from the original to the trampoline. */
+       li      r5,INT_FRAME_SIZE/4     /* size: INT_FRAME_SIZE */
+       li      r6,0                    /* start offset: 0 */
+       mtctr   r5
+2:     lwzx    r0,r6,r4
+       stwx    r0,r6,r3
+       addi    r6,r6,4
+       bdnz    2b
+
+       /* Do real store operation to complete stwu */
+       lwz     r5,GPR1(r1)
+       stw     r8,0(r5)
+
+       /* Clear _TIF_EMULATE_STACK_STORE flag */
+       lis     r11,_TIF_EMULATE_STACK_STORE@h
+       addi    r5,r9,TI_FLAGS
+0:     lwarx   r8,0,r5
+       andc    r8,r8,r11
+#ifdef CONFIG_IBM405_ERR77
+       dcbt    0,r5
+#endif
+       stwcx.  r8,0,r5
+       bne-    0b
+1:
+
+#ifdef CONFIG_PREEMPT
+       /* check current_thread_info->preempt_count */
        lwz     r0,TI_PREEMPT(r9)
        cmpwi   0,r0,0          /* if non-zero, just restore regs and return */
        bne     restore
-       lwz     r0,TI_FLAGS(r9)
-       andi.   r0,r0,_TIF_NEED_RESCHED
+       andi.   r8,r8,_TIF_NEED_RESCHED
        beq+    restore
+       lwz     r3,_MSR(r1)
        andi.   r0,r3,MSR_EE    /* interrupts off? */
        beq     restore         /* don't schedule if so */
 #ifdef CONFIG_TRACE_IRQFLAGS
@@ -864,8 +901,6 @@ resume_kernel:
         */
        bl      trace_hardirqs_on
 #endif
-#else
-resume_kernel:
 #endif /* CONFIG_PREEMPT */
 
        /* interrupts are hard-disabled at this point */
index b40e0b4..0e931aa 100644 (file)
@@ -593,6 +593,41 @@ _GLOBAL(ret_from_except_lite)
        b       .ret_from_except
 
 resume_kernel:
+       /* check current_thread_info, _TIF_EMULATE_STACK_STORE */
+       CURRENT_THREAD_INFO(r9, r1)
+       ld      r8,TI_FLAGS(r9)
+       andis.  r8,r8,_TIF_EMULATE_STACK_STORE@h
+       beq+    1f
+
+       addi    r8,r1,INT_FRAME_SIZE    /* Get the kprobed function entry */
+
+       lwz     r3,GPR1(r1)
+       subi    r3,r3,INT_FRAME_SIZE    /* dst: Allocate a trampoline exception frame */
+       mr      r4,r1                   /* src:  current exception frame */
+       mr      r1,r3                   /* Reroute the trampoline frame to r1 */
+
+       /* Copy from the original to the trampoline. */
+       li      r5,INT_FRAME_SIZE/8     /* size: INT_FRAME_SIZE */
+       li      r6,0                    /* start offset: 0 */
+       mtctr   r5
+2:     ldx     r0,r6,r4
+       stdx    r0,r6,r3
+       addi    r6,r6,8
+       bdnz    2b
+
+       /* Do real store operation to complete stwu */
+       lwz     r5,GPR1(r1)
+       std     r8,0(r5)
+
+       /* Clear _TIF_EMULATE_STACK_STORE flag */
+       lis     r11,_TIF_EMULATE_STACK_STORE@h
+       addi    r5,r9,TI_FLAGS
+       ldarx   r4,0,r5
+       andc    r4,r4,r11
+       stdcx.  r4,0,r5
+       bne-    0b
+1:
+
 #ifdef CONFIG_PREEMPT
        /* Check if we need to preempt */
        andi.   r0,r4,_TIF_NEED_RESCHED
index 39aa97d..10b658a 100644 (file)
@@ -275,6 +275,31 @@ vsx_unavailable_pSeries_1:
        STD_EXCEPTION_PSERIES(0x1300, 0x1300, instruction_breakpoint)
        KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_STD, 0x1300)
 
+       . = 0x1500
+       .global denorm_Hypervisor
+denorm_exception_hv:
+       HMT_MEDIUM
+       mtspr   SPRN_SPRG_HSCRATCH0,r13
+       mfspr   r13,SPRN_SPRG_HPACA
+       std     r9,PACA_EXGEN+EX_R9(r13)
+       std     r10,PACA_EXGEN+EX_R10(r13)
+       std     r11,PACA_EXGEN+EX_R11(r13)
+       std     r12,PACA_EXGEN+EX_R12(r13)
+       mfspr   r9,SPRN_SPRG_HSCRATCH0
+       std     r9,PACA_EXGEN+EX_R13(r13)
+       mfcr    r9
+
+#ifdef CONFIG_PPC_DENORMALISATION
+       mfspr   r10,SPRN_HSRR1
+       mfspr   r11,SPRN_HSRR0          /* save HSRR0 */
+       andis.  r10,r10,(HSRR1_DENORM)@h /* denorm? */
+       addi    r11,r11,-4              /* HSRR0 is next instruction */
+       bne+    denorm_assist
+#endif
+
+       EXCEPTION_PROLOG_PSERIES_1(denorm_common, EXC_HV)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x1500)
+
 #ifdef CONFIG_CBE_RAS
        STD_EXCEPTION_HV(0x1600, 0x1602, cbe_maintenance)
        KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
@@ -336,6 +361,103 @@ do_stab_bolted_pSeries:
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x900)
        KVM_HANDLER(PACA_EXGEN, EXC_HV, 0x982)
 
+#ifdef CONFIG_PPC_DENORMALISATION
+denorm_assist:
+BEGIN_FTR_SECTION
+/*
+ * To denormalise we need to move a copy of the register to itself.
+ * For POWER6 do that here for all FP regs.
+ */
+       mfmsr   r10
+       ori     r10,r10,(MSR_FP|MSR_FE0|MSR_FE1)
+       xori    r10,r10,(MSR_FE0|MSR_FE1)
+       mtmsrd  r10
+       sync
+       fmr     0,0
+       fmr     1,1
+       fmr     2,2
+       fmr     3,3
+       fmr     4,4
+       fmr     5,5
+       fmr     6,6
+       fmr     7,7
+       fmr     8,8
+       fmr     9,9
+       fmr     10,10
+       fmr     11,11
+       fmr     12,12
+       fmr     13,13
+       fmr     14,14
+       fmr     15,15
+       fmr     16,16
+       fmr     17,17
+       fmr     18,18
+       fmr     19,19
+       fmr     20,20
+       fmr     21,21
+       fmr     22,22
+       fmr     23,23
+       fmr     24,24
+       fmr     25,25
+       fmr     26,26
+       fmr     27,27
+       fmr     28,28
+       fmr     29,29
+       fmr     30,30
+       fmr     31,31
+FTR_SECTION_ELSE
+/*
+ * To denormalise we need to move a copy of the register to itself.
+ * For POWER7 do that here for the first 32 VSX registers only.
+ */
+       mfmsr   r10
+       oris    r10,r10,MSR_VSX@h
+       mtmsrd  r10
+       sync
+       XVCPSGNDP(0,0,0)
+       XVCPSGNDP(1,1,1)
+       XVCPSGNDP(2,2,2)
+       XVCPSGNDP(3,3,3)
+       XVCPSGNDP(4,4,4)
+       XVCPSGNDP(5,5,5)
+       XVCPSGNDP(6,6,6)
+       XVCPSGNDP(7,7,7)
+       XVCPSGNDP(8,8,8)
+       XVCPSGNDP(9,9,9)
+       XVCPSGNDP(10,10,10)
+       XVCPSGNDP(11,11,11)
+       XVCPSGNDP(12,12,12)
+       XVCPSGNDP(13,13,13)
+       XVCPSGNDP(14,14,14)
+       XVCPSGNDP(15,15,15)
+       XVCPSGNDP(16,16,16)
+       XVCPSGNDP(17,17,17)
+       XVCPSGNDP(18,18,18)
+       XVCPSGNDP(19,19,19)
+       XVCPSGNDP(20,20,20)
+       XVCPSGNDP(21,21,21)
+       XVCPSGNDP(22,22,22)
+       XVCPSGNDP(23,23,23)
+       XVCPSGNDP(24,24,24)
+       XVCPSGNDP(25,25,25)
+       XVCPSGNDP(26,26,26)
+       XVCPSGNDP(27,27,27)
+       XVCPSGNDP(28,28,28)
+       XVCPSGNDP(29,29,29)
+       XVCPSGNDP(30,30,30)
+       XVCPSGNDP(31,31,31)
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_206)
+       mtspr   SPRN_HSRR0,r11
+       mtcrf   0x80,r9
+       ld      r9,PACA_EXGEN+EX_R9(r13)
+       ld      r10,PACA_EXGEN+EX_R10(r13)
+       ld      r11,PACA_EXGEN+EX_R11(r13)
+       ld      r12,PACA_EXGEN+EX_R12(r13)
+       ld      r13,PACA_EXGEN+EX_R13(r13)
+       HRFID
+       b       .
+#endif
+
        .align  7
        /* moved from 0xe00 */
        STD_EXCEPTION_HV(., 0xe02, h_data_storage)
@@ -495,6 +617,7 @@ machine_check_common:
         STD_EXCEPTION_COMMON(0xe60, hmi_exception, .unknown_exception)
        STD_EXCEPTION_COMMON_ASYNC(0xf00, performance_monitor, .performance_monitor_exception)
        STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
+       STD_EXCEPTION_COMMON(0x1502, denorm, .unknown_exception)
 #ifdef CONFIG_ALTIVEC
        STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)
 #else
@@ -960,7 +1083,9 @@ _GLOBAL(do_stab_bolted)
        rldimi  r10,r11,7,52    /* r10 = first ste of the group */
 
        /* Calculate VSID */
-       /* This is a kernel address, so protovsid = ESID */
+       /* This is a kernel address, so protovsid = ESID | 1 << 37 */
+       li      r9,0x1
+       rldimi  r11,r9,(CONTEXT_BITS + USER_ESID_BITS),0
        ASM_VSID_SCRAMBLE(r11, r9, 256M)
        rldic   r9,r11,12,16    /* r9 = vsid << 12 */
 
index 1f017bb..71413f4 100644 (file)
@@ -489,10 +489,10 @@ void do_IRQ(struct pt_regs *regs)
        struct pt_regs *old_regs = set_irq_regs(regs);
        unsigned int irq;
 
-       trace_irq_entry(regs);
-
        irq_enter();
 
+       trace_irq_entry(regs);
+
        check_stack_overflow();
 
        /*
@@ -511,10 +511,10 @@ void do_IRQ(struct pt_regs *regs)
        else
                __get_cpu_var(irq_stat).spurious_irqs++;
 
+       trace_irq_exit(regs);
+
        irq_exit();
        set_irq_regs(old_regs);
-
-       trace_irq_exit(regs);
 }
 
 void __init init_IRQ(void)
index 4cb7147..7f94f76 100644 (file)
@@ -99,6 +99,26 @@ void pcibios_free_controller(struct pci_controller *phb)
                kfree(phb);
 }
 
+/*
+ * The function is used to return the minimal alignment
+ * for memory or I/O windows of the associated P2P bridge.
+ * By default, 4KiB alignment for I/O windows and 1MiB for
+ * memory windows.
+ */
+resource_size_t pcibios_window_alignment(struct pci_bus *bus,
+                                        unsigned long type)
+{
+       if (ppc_md.pcibios_window_alignment)
+               return ppc_md.pcibios_window_alignment(bus, type);
+
+       /*
+        * PCI core will figure out the default
+        * alignment: 4KiB for I/O and 1MiB for
+        * memory window.
+        */
+       return 1;
+}
+
 static resource_size_t pcibios_io_size(const struct pci_controller *hose)
 {
 #ifdef CONFIG_PPC64
index e49e931..bd693a1 100644 (file)
@@ -493,8 +493,6 @@ void timer_interrupt(struct pt_regs * regs)
         */
        may_hard_irq_enable();
 
-       trace_timer_interrupt_entry(regs);
-
        __get_cpu_var(irq_stat).timer_irqs++;
 
 #if defined(CONFIG_PPC32) && defined(CONFIG_PMAC)
@@ -505,6 +503,8 @@ void timer_interrupt(struct pt_regs * regs)
        old_regs = set_irq_regs(regs);
        irq_enter();
 
+       trace_timer_interrupt_entry(regs);
+
        if (test_irq_work_pending()) {
                clear_irq_work_pending();
                irq_work_run();
@@ -529,10 +529,10 @@ void timer_interrupt(struct pt_regs * regs)
        }
 #endif
 
+       trace_timer_interrupt_exit(regs);
+
        irq_exit();
        set_irq_regs(old_regs);
-
-       trace_timer_interrupt_exit(regs);
 }
 
 /*
index 837f13e..00aa612 100644 (file)
@@ -141,7 +141,7 @@ extern char etext[];
 int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 {
        pfn_t hpaddr;
-       u64 va;
+       u64 vpn;
        u64 vsid;
        struct kvmppc_sid_map *map;
        volatile u32 *pteg;
@@ -173,7 +173,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
        BUG_ON(!map);
 
        vsid = map->host_vsid;
-       va = (vsid << SID_SHIFT) | (eaddr & ~ESID_MASK);
+       vpn = (vsid << (SID_SHIFT - VPN_SHIFT)) | ((eaddr & ~ESID_MASK) >> VPN_SHIFT)
 
 next_pteg:
        if (rr == 16) {
@@ -244,11 +244,11 @@ next_pteg:
        dprintk_mmu("KVM: %c%c Map 0x%llx: [%lx] 0x%llx (0x%llx) -> %lx\n",
                    orig_pte->may_write ? 'w' : '-',
                    orig_pte->may_execute ? 'x' : '-',
-                   orig_pte->eaddr, (ulong)pteg, va,
+                   orig_pte->eaddr, (ulong)pteg, vpn,
                    orig_pte->vpage, hpaddr);
 
        pte->slot = (ulong)&pteg[rr];
-       pte->host_va = va;
+       pte->host_vpn = vpn;
        pte->pte = *orig_pte;
        pte->pfn = hpaddr >> PAGE_SHIFT;
 
index 0688b6b..4d72f9e 100644 (file)
@@ -33,7 +33,7 @@
 
 void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
 {
-       ppc_md.hpte_invalidate(pte->slot, pte->host_va,
+       ppc_md.hpte_invalidate(pte->slot, pte->host_vpn,
                               MMU_PAGE_4K, MMU_SEGSIZE_256M,
                               false);
 }
@@ -80,8 +80,9 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
 
 int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 {
+       unsigned long vpn;
        pfn_t hpaddr;
-       ulong hash, hpteg, va;
+       ulong hash, hpteg;
        u64 vsid;
        int ret;
        int rflags = 0x192;
@@ -117,7 +118,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
        }
 
        vsid = map->host_vsid;
-       va = hpt_va(orig_pte->eaddr, vsid, MMU_SEGSIZE_256M);
+       vpn = hpt_vpn(orig_pte->eaddr, vsid, MMU_SEGSIZE_256M);
 
        if (!orig_pte->may_write)
                rflags |= HPTE_R_PP;
@@ -129,7 +130,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
        else
                kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT);
 
-       hash = hpt_hash(va, PTE_SIZE, MMU_SEGSIZE_256M);
+       hash = hpt_hash(vpn, PTE_SIZE, MMU_SEGSIZE_256M);
 
 map_again:
        hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
@@ -141,7 +142,8 @@ map_again:
                        goto out;
                }
 
-       ret = ppc_md.hpte_insert(hpteg, va, hpaddr, rflags, vflags, MMU_PAGE_4K, MMU_SEGSIZE_256M);
+       ret = ppc_md.hpte_insert(hpteg, vpn, hpaddr, rflags, vflags,
+                                MMU_PAGE_4K, MMU_SEGSIZE_256M);
 
        if (ret < 0) {
                /* If we couldn't map a primary PTE, try a secondary */
@@ -152,7 +154,8 @@ map_again:
        } else {
                struct hpte_cache *pte = kvmppc_mmu_hpte_cache_next(vcpu);
 
-               trace_kvm_book3s_64_mmu_map(rflags, hpteg, va, hpaddr, orig_pte);
+               trace_kvm_book3s_64_mmu_map(rflags, hpteg,
+                                           vpn, hpaddr, orig_pte);
 
                /* The ppc_md code may give us a secondary entry even though we
                   asked for a primary. Fix up. */
@@ -162,7 +165,7 @@ map_again:
                }
 
                pte->slot = hpteg + (ret & 7);
-               pte->host_va = va;
+               pte->host_vpn = vpn;
                pte->pte = *orig_pte;
                pte->pfn = hpaddr >> PAGE_SHIFT;
 
index 877186b..ddb6a21 100644 (file)
@@ -189,7 +189,7 @@ TRACE_EVENT(kvm_book3s_mmu_map,
        TP_ARGS(pte),
 
        TP_STRUCT__entry(
-               __field(        u64,            host_v        )
+               __field(        u64,            host_vpn        )
                __field(        u64,            pfn             )
                __field(        ulong,          eaddr           )
                __field(        u64,            vpage           )
@@ -198,7 +198,7 @@ TRACE_EVENT(kvm_book3s_mmu_map,
        ),
 
        TP_fast_assign(
-               __entry->host_va        = pte->host_va;
+               __entry->host_vpn       = pte->host_vpn;
                __entry->pfn            = pte->pfn;
                __entry->eaddr          = pte->pte.eaddr;
                __entry->vpage          = pte->pte.vpage;
@@ -208,8 +208,8 @@ TRACE_EVENT(kvm_book3s_mmu_map,
                                          (pte->pte.may_execute ? 0x1 : 0);
        ),
 
-       TP_printk("Map: hva=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]",
-                 __entry->host_va, __entry->pfn, __entry->eaddr,
+       TP_printk("Map: hvpn=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]",
+                 __entry->host_vpn, __entry->pfn, __entry->eaddr,
                  __entry->vpage, __entry->raddr, __entry->flags)
 );
 
@@ -218,7 +218,7 @@ TRACE_EVENT(kvm_book3s_mmu_invalidate,
        TP_ARGS(pte),
 
        TP_STRUCT__entry(
-               __field(        u64,            host_v        )
+               __field(        u64,            host_vpn        )
                __field(        u64,            pfn             )
                __field(        ulong,          eaddr           )
                __field(        u64,            vpage           )
@@ -227,7 +227,7 @@ TRACE_EVENT(kvm_book3s_mmu_invalidate,
        ),
 
        TP_fast_assign(
-               __entry->host_va        = pte->host_va;
+               __entry->host_vpn       = pte->host_vpn;
                __entry->pfn            = pte->pfn;
                __entry->eaddr          = pte->pte.eaddr;
                __entry->vpage          = pte->pte.vpage;
@@ -238,7 +238,7 @@ TRACE_EVENT(kvm_book3s_mmu_invalidate,
        ),
 
        TP_printk("Flush: hva=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]",
-                 __entry->host_va, __entry->pfn, __entry->eaddr,
+                 __entry->host_vpn, __entry->pfn, __entry->eaddr,
                  __entry->vpage, __entry->raddr, __entry->flags)
 );
 
index 9a52349..e15c521 100644 (file)
@@ -566,7 +566,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
        unsigned long int ea;
        unsigned int cr, mb, me, sh;
        int err;
-       unsigned long old_ra;
+       unsigned long old_ra, val3;
        long ival;
 
        opcode = instr >> 26;
@@ -1486,11 +1486,43 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
                goto ldst_done;
 
        case 36:        /* stw */
-       case 37:        /* stwu */
                val = regs->gpr[rd];
                err = write_mem(val, dform_ea(instr, regs), 4, regs);
                goto ldst_done;
 
+       case 37:        /* stwu */
+               val = regs->gpr[rd];
+               val3 = dform_ea(instr, regs);
+               /*
+                * For PPC32 we always use stwu to change stack point with r1. So
+                * this emulated store may corrupt the exception frame, now we
+                * have to provide the exception frame trampoline, which is pushed
+                * below the kprobed function stack. So we only update gpr[1] but
+                * don't emulate the real store operation. We will do real store
+                * operation safely in exception return code by checking this flag.
+                */
+               if ((ra == 1) && !(regs->msr & MSR_PR) \
+                       && (val3 >= (regs->gpr[1] - STACK_INT_FRAME_SIZE))) {
+                       /*
+                        * Check if we will touch kernel sack overflow
+                        */
+                       if (val3 - STACK_INT_FRAME_SIZE <= current->thread.ksp_limit) {
+                               printk(KERN_CRIT "Can't kprobe this since Kernel stack overflow.\n");
+                               err = -EINVAL;
+                               break;
+                       }
+
+                       /*
+                        * Check if we already set since that means we'll
+                        * lose the previous value.
+                        */
+                       WARN_ON(test_thread_flag(TIF_EMULATE_STACK_STORE));
+                       set_thread_flag(TIF_EMULATE_STACK_STORE);
+                       err = 0;
+               } else
+                       err = write_mem(val, val3, 4, regs);
+               goto ldst_done;
+
        case 38:        /* stb */
        case 39:        /* stbu */
                val = regs->gpr[rd];
index 602aeb0..5658508 100644 (file)
@@ -63,7 +63,7 @@ _GLOBAL(__hash_page_4K)
        /* Save non-volatile registers.
         * r31 will hold "old PTE"
         * r30 is "new PTE"
-        * r29 is "va"
+        * r29 is vpn
         * r28 is a hash value
         * r27 is hashtab mask (maybe dynamic patched instead ?)
         */
@@ -111,10 +111,10 @@ BEGIN_FTR_SECTION
        cmpdi   r9,0                    /* check segment size */
        bne     3f
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
-       /* Calc va and put it in r29 */
-       rldicr  r29,r5,28,63-28
-       rldicl  r3,r3,0,36
-       or      r29,r3,r29
+       /* Calc vpn and put it in r29 */
+       sldi    r29,r5,SID_SHIFT - VPN_SHIFT
+       rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
+       or      r29,r28,r29
 
        /* Calculate hash value for primary slot and store it in r28 */
        rldicl  r5,r5,0,25              /* vsid & 0x0000007fffffffff */
@@ -122,14 +122,19 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        xor     r28,r5,r0
        b       4f
 
-3:     /* Calc VA and hash in r29 and r28 for 1T segment */
-       sldi    r29,r5,40               /* vsid << 40 */
-       clrldi  r3,r3,24                /* ea & 0xffffffffff */
+3:     /* Calc vpn and put it in r29 */
+       sldi    r29,r5,SID_SHIFT_1T - VPN_SHIFT
+       rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
+       or      r29,r28,r29
+
+       /*
+        * calculate hash value for primary slot and
+        * store it in r28 for 1T segment
+        */
        rldic   r28,r5,25,25            /* (vsid << 25) & 0x7fffffffff */
        clrldi  r5,r5,40                /* vsid & 0xffffff */
        rldicl  r0,r3,64-12,36          /* (ea >> 12) & 0xfffffff */
        xor     r28,r28,r5
-       or      r29,r3,r29              /* VA */
        xor     r28,r28,r0              /* hash */
 
        /* Convert linux PTE bits into HW equivalents */
@@ -185,7 +190,7 @@ htab_insert_pte:
 
        /* Call ppc_md.hpte_insert */
        ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
-       mr      r4,r29                  /* Retrieve va */
+       mr      r4,r29                  /* Retrieve vpn */
        li      r7,0                    /* !bolted, !secondary */
        li      r8,MMU_PAGE_4K          /* page size */
        ld      r9,STK_PARAM(R9)(r1)    /* segment size */
@@ -208,7 +213,7 @@ _GLOBAL(htab_call_hpte_insert1)
        
        /* Call ppc_md.hpte_insert */
        ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
-       mr      r4,r29                  /* Retrieve va */
+       mr      r4,r29                  /* Retrieve vpn */
        li      r7,HPTE_V_SECONDARY     /* !bolted, secondary */
        li      r8,MMU_PAGE_4K          /* page size */
        ld      r9,STK_PARAM(R9)(r1)    /* segment size */
@@ -278,7 +283,7 @@ htab_modify_pte:
        add     r3,r0,r3        /* add slot idx */
 
        /* Call ppc_md.hpte_updatepp */
-       mr      r5,r29                  /* va */
+       mr      r5,r29                  /* vpn */
        li      r6,MMU_PAGE_4K          /* page size */
        ld      r7,STK_PARAM(R9)(r1)    /* segment size */
        ld      r8,STK_PARAM(R8)(r1)    /* get "local" param */
@@ -339,7 +344,7 @@ _GLOBAL(__hash_page_4K)
        /* Save non-volatile registers.
         * r31 will hold "old PTE"
         * r30 is "new PTE"
-        * r29 is "va"
+        * r29 is vpn
         * r28 is a hash value
         * r27 is hashtab mask (maybe dynamic patched instead ?)
         * r26 is the hidx mask
@@ -394,10 +399,14 @@ BEGIN_FTR_SECTION
        cmpdi   r9,0                    /* check segment size */
        bne     3f
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
-       /* Calc va and put it in r29 */
-       rldicr  r29,r5,28,63-28         /* r29 = (vsid << 28) */
-       rldicl  r3,r3,0,36              /* r3 = (ea & 0x0fffffff) */
-       or      r29,r3,r29              /* r29 = va */
+       /* Calc vpn and put it in r29 */
+       sldi    r29,r5,SID_SHIFT - VPN_SHIFT
+       /*
+        * clrldi r3,r3,64 - SID_SHIFT -->  ea & 0xfffffff
+        * srdi  r28,r3,VPN_SHIFT
+        */
+       rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
+       or      r29,r28,r29
 
        /* Calculate hash value for primary slot and store it in r28 */
        rldicl  r5,r5,0,25              /* vsid & 0x0000007fffffffff */
@@ -405,14 +414,23 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        xor     r28,r5,r0
        b       4f
 
-3:     /* Calc VA and hash in r29 and r28 for 1T segment */
-       sldi    r29,r5,40               /* vsid << 40 */
-       clrldi  r3,r3,24                /* ea & 0xffffffffff */
+3:     /* Calc vpn and put it in r29 */
+       sldi    r29,r5,SID_SHIFT_1T - VPN_SHIFT
+       /*
+        * clrldi r3,r3,64 - SID_SHIFT_1T -->  ea & 0xffffffffff
+        * srdi r28,r3,VPN_SHIFT
+        */
+       rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
+       or      r29,r28,r29
+
+       /*
+        * Calculate hash value for primary slot and
+        * store it in r28  for 1T segment
+        */
        rldic   r28,r5,25,25            /* (vsid << 25) & 0x7fffffffff */
        clrldi  r5,r5,40                /* vsid & 0xffffff */
        rldicl  r0,r3,64-12,36          /* (ea >> 12) & 0xfffffff */
        xor     r28,r28,r5
-       or      r29,r3,r29              /* VA */
        xor     r28,r28,r0              /* hash */
 
        /* Convert linux PTE bits into HW equivalents */
@@ -488,7 +506,7 @@ htab_special_pfn:
 
        /* Call ppc_md.hpte_insert */
        ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
-       mr      r4,r29                  /* Retrieve va */
+       mr      r4,r29                  /* Retrieve vpn */
        li      r7,0                    /* !bolted, !secondary */
        li      r8,MMU_PAGE_4K          /* page size */
        ld      r9,STK_PARAM(R9)(r1)    /* segment size */
@@ -515,7 +533,7 @@ _GLOBAL(htab_call_hpte_insert1)
 
        /* Call ppc_md.hpte_insert */
        ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
-       mr      r4,r29                  /* Retrieve va */
+       mr      r4,r29                  /* Retrieve vpn */
        li      r7,HPTE_V_SECONDARY     /* !bolted, secondary */
        li      r8,MMU_PAGE_4K          /* page size */
        ld      r9,STK_PARAM(R9)(r1)    /* segment size */
@@ -547,7 +565,7 @@ _GLOBAL(htab_call_hpte_remove)
         * useless now that the segment has been switched to 4k pages.
         */
 htab_inval_old_hpte:
-       mr      r3,r29                  /* virtual addr */
+       mr      r3,r29                  /* vpn */
        mr      r4,r31                  /* PTE.pte */
        li      r5,0                    /* PTE.hidx */
        li      r6,MMU_PAGE_64K         /* psize */
@@ -620,7 +638,7 @@ htab_modify_pte:
        add     r3,r0,r3        /* add slot idx */
 
        /* Call ppc_md.hpte_updatepp */
-       mr      r5,r29                  /* va */
+       mr      r5,r29                  /* vpn */
        li      r6,MMU_PAGE_4K          /* page size */
        ld      r7,STK_PARAM(R9)(r1)    /* segment size */
        ld      r8,STK_PARAM(R8)(r1)    /* get "local" param */
@@ -676,7 +694,7 @@ _GLOBAL(__hash_page_64K)
        /* Save non-volatile registers.
         * r31 will hold "old PTE"
         * r30 is "new PTE"
-        * r29 is "va"
+        * r29 is vpn
         * r28 is a hash value
         * r27 is hashtab mask (maybe dynamic patched instead ?)
         */
@@ -729,10 +747,10 @@ BEGIN_FTR_SECTION
        cmpdi   r9,0                    /* check segment size */
        bne     3f
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
-       /* Calc va and put it in r29 */
-       rldicr  r29,r5,28,63-28
-       rldicl  r3,r3,0,36
-       or      r29,r3,r29
+       /* Calc vpn and put it in r29 */
+       sldi    r29,r5,SID_SHIFT - VPN_SHIFT
+       rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
+       or      r29,r28,r29
 
        /* Calculate hash value for primary slot and store it in r28 */
        rldicl  r5,r5,0,25              /* vsid & 0x0000007fffffffff */
@@ -740,14 +758,19 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        xor     r28,r5,r0
        b       4f
 
-3:     /* Calc VA and hash in r29 and r28 for 1T segment */
-       sldi    r29,r5,40               /* vsid << 40 */
-       clrldi  r3,r3,24                /* ea & 0xffffffffff */
+3:     /* Calc vpn and put it in r29 */
+       sldi    r29,r5,SID_SHIFT_1T - VPN_SHIFT
+       rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
+       or      r29,r28,r29
+
+       /*
+        * calculate hash value for primary slot and
+        * store it in r28 for 1T segment
+        */
        rldic   r28,r5,25,25            /* (vsid << 25) & 0x7fffffffff */
        clrldi  r5,r5,40                /* vsid & 0xffffff */
        rldicl  r0,r3,64-16,40          /* (ea >> 16) & 0xffffff */
        xor     r28,r28,r5
-       or      r29,r3,r29              /* VA */
        xor     r28,r28,r0              /* hash */
 
        /* Convert linux PTE bits into HW equivalents */
@@ -806,7 +829,7 @@ ht64_insert_pte:
 
        /* Call ppc_md.hpte_insert */
        ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
-       mr      r4,r29                  /* Retrieve va */
+       mr      r4,r29                  /* Retrieve vpn */
        li      r7,0                    /* !bolted, !secondary */
        li      r8,MMU_PAGE_64K
        ld      r9,STK_PARAM(R9)(r1)    /* segment size */
@@ -829,7 +852,7 @@ _GLOBAL(ht64_call_hpte_insert1)
 
        /* Call ppc_md.hpte_insert */
        ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
-       mr      r4,r29                  /* Retrieve va */
+       mr      r4,r29                  /* Retrieve vpn */
        li      r7,HPTE_V_SECONDARY     /* !bolted, secondary */
        li      r8,MMU_PAGE_64K
        ld      r9,STK_PARAM(R9)(r1)    /* segment size */
@@ -899,7 +922,7 @@ ht64_modify_pte:
        add     r3,r0,r3        /* add slot idx */
 
        /* Call ppc_md.hpte_updatepp */
-       mr      r5,r29                  /* va */
+       mr      r5,r29                  /* vpn */
        li      r6,MMU_PAGE_64K
        ld      r7,STK_PARAM(R9)(r1)    /* segment size */
        ld      r8,STK_PARAM(R8)(r1)    /* get "local" param */
index f21e8ce..a4a1c72 100644 (file)
 
 DEFINE_RAW_SPINLOCK(native_tlbie_lock);
 
-static inline void __tlbie(unsigned long va, int psize, int ssize)
+static inline void __tlbie(unsigned long vpn, int psize, int ssize)
 {
+       unsigned long va;
        unsigned int penc;
 
-       /* clear top 16 bits, non SLS segment */
+       /*
+        * We need 14 to 65 bits of va for a tlibe of 4K page
+        * With vpn we ignore the lower VPN_SHIFT bits already.
+        * And top two bits are already ignored because we can
+        * only accomadate 76 bits in a 64 bit vpn with a VPN_SHIFT
+        * of 12.
+        */
+       va = vpn << VPN_SHIFT;
+       /*
+        * clear top 16 bits of 64bit va, non SLS segment
+        * Older versions of the architecture (2.02 and earler) require the
+        * masking of the top 16 bits.
+        */
        va &= ~(0xffffULL << 48);
 
        switch (psize) {
        case MMU_PAGE_4K:
-               va &= ~0xffful;
                va |= ssize << 8;
                asm volatile(ASM_FTR_IFCLR("tlbie %0,0", PPC_TLBIE(%1,%0), %2)
                             : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206)
                             : "memory");
                break;
        default:
+               /* We need 14 to 14 + i bits of va */
                penc = mmu_psize_defs[psize].penc;
                va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
                va |= penc << 12;
@@ -67,21 +80,28 @@ static inline void __tlbie(unsigned long va, int psize, int ssize)
        }
 }
 
-static inline void __tlbiel(unsigned long va, int psize, int ssize)
+static inline void __tlbiel(unsigned long vpn, int psize, int ssize)
 {
+       unsigned long va;
        unsigned int penc;
 
-       /* clear top 16 bits, non SLS segment */
+       /* VPN_SHIFT can be atmost 12 */
+       va = vpn << VPN_SHIFT;
+       /*
+        * clear top 16 bits of 64 bit va, non SLS segment
+        * Older versions of the architecture (2.02 and earler) require the
+        * masking of the top 16 bits.
+        */
        va &= ~(0xffffULL << 48);
 
        switch (psize) {
        case MMU_PAGE_4K:
-               va &= ~0xffful;
                va |= ssize << 8;
                asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)"
                             : : "r"(va) : "memory");
                break;
        default:
+               /* We need 14 to 14 + i bits of va */
                penc = mmu_psize_defs[psize].penc;
                va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
                va |= penc << 12;
@@ -94,7 +114,7 @@ static inline void __tlbiel(unsigned long va, int psize, int ssize)
 
 }
 
-static inline void tlbie(unsigned long va, int psize, int ssize, int local)
+static inline void tlbie(unsigned long vpn, int psize, int ssize, int local)
 {
        unsigned int use_local = local && mmu_has_feature(MMU_FTR_TLBIEL);
        int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
@@ -105,10 +125,10 @@ static inline void tlbie(unsigned long va, int psize, int ssize, int local)
                raw_spin_lock(&native_tlbie_lock);
        asm volatile("ptesync": : :"memory");
        if (use_local) {
-               __tlbiel(va, psize, ssize);
+               __tlbiel(vpn, psize, ssize);
                asm volatile("ptesync": : :"memory");
        } else {
-               __tlbie(va, psize, ssize);
+               __tlbie(vpn, psize, ssize);
                asm volatile("eieio; tlbsync; ptesync": : :"memory");
        }
        if (lock_tlbie && !use_local)
@@ -134,7 +154,7 @@ static inline void native_unlock_hpte(struct hash_pte *hptep)
        clear_bit_unlock(HPTE_LOCK_BIT, word);
 }
 
-static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
+static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn,
                        unsigned long pa, unsigned long rflags,
                        unsigned long vflags, int psize, int ssize)
 {
@@ -143,9 +163,9 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
        int i;
 
        if (!(vflags & HPTE_V_BOLTED)) {
-               DBG_LOW("    insert(group=%lx, va=%016lx, pa=%016lx,"
+               DBG_LOW("    insert(group=%lx, vpn=%016lx, pa=%016lx,"
                        " rflags=%lx, vflags=%lx, psize=%d)\n",
-                       hpte_group, va, pa, rflags, vflags, psize);
+                       hpte_group, vpn, pa, rflags, vflags, psize);
        }
 
        for (i = 0; i < HPTES_PER_GROUP; i++) {
@@ -163,7 +183,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
        if (i == HPTES_PER_GROUP)
                return -1;
 
-       hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
+       hpte_v = hpte_encode_v(vpn, psize, ssize) | vflags | HPTE_V_VALID;
        hpte_r = hpte_encode_r(pa, psize) | rflags;
 
        if (!(vflags & HPTE_V_BOLTED)) {
@@ -225,17 +245,17 @@ static long native_hpte_remove(unsigned long hpte_group)
 }
 
 static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
-                                unsigned long va, int psize, int ssize,
+                                unsigned long vpn, int psize, int ssize,
                                 int local)
 {
        struct hash_pte *hptep = htab_address + slot;
        unsigned long hpte_v, want_v;
        int ret = 0;
 
-       want_v = hpte_encode_v(va, psize, ssize);
+       want_v = hpte_encode_v(vpn, psize, ssize);
 
-       DBG_LOW("    update(va=%016lx, avpnv=%016lx, hash=%016lx, newpp=%x)",
-               va, want_v & HPTE_V_AVPN, slot, newpp);
+       DBG_LOW("    update(vpn=%016lx, avpnv=%016lx, group=%lx, newpp=%lx)",
+               vpn, want_v & HPTE_V_AVPN, slot, newpp);
 
        native_lock_hpte(hptep);
 
@@ -254,12 +274,12 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
        native_unlock_hpte(hptep);
 
        /* Ensure it is out of the tlb too. */
-       tlbie(va, psize, ssize, local);
+       tlbie(vpn, psize, ssize, local);
 
        return ret;
 }
 
-static long native_hpte_find(unsigned long va, int psize, int ssize)
+static long native_hpte_find(unsigned long vpn, int psize, int ssize)
 {
        struct hash_pte *hptep;
        unsigned long hash;
@@ -267,8 +287,8 @@ static long native_hpte_find(unsigned long va, int psize, int ssize)
        long slot;
        unsigned long want_v, hpte_v;
 
-       hash = hpt_hash(va, mmu_psize_defs[psize].shift, ssize);
-       want_v = hpte_encode_v(va, psize, ssize);
+       hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, ssize);
+       want_v = hpte_encode_v(vpn, psize, ssize);
 
        /* Bolted mappings are only ever in the primary group */
        slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
@@ -295,14 +315,15 @@ static long native_hpte_find(unsigned long va, int psize, int ssize)
 static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
                                       int psize, int ssize)
 {
-       unsigned long vsid, va;
+       unsigned long vpn;
+       unsigned long vsid;
        long slot;
        struct hash_pte *hptep;
 
        vsid = get_kernel_vsid(ea, ssize);
-       va = hpt_va(ea, vsid, ssize);
+       vpn = hpt_vpn(ea, vsid, ssize);
 
-       slot = native_hpte_find(va, psize, ssize);
+       slot = native_hpte_find(vpn, psize, ssize);
        if (slot == -1)
                panic("could not find page to bolt\n");
        hptep = htab_address + slot;
@@ -312,10 +333,10 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
                (newpp & (HPTE_R_PP | HPTE_R_N));
 
        /* Ensure it is out of the tlb too. */
-       tlbie(va, psize, ssize, 0);
+       tlbie(vpn, psize, ssize, 0);
 }
 
-static void native_hpte_invalidate(unsigned long slot, unsigned long va,
+static void native_hpte_invalidate(unsigned long slot, unsigned long vpn,
                                   int psize, int ssize, int local)
 {
        struct hash_pte *hptep = htab_address + slot;
@@ -325,9 +346,9 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
 
        local_irq_save(flags);
 
-       DBG_LOW("    invalidate(va=%016lx, hash: %x)\n", va, slot);
+       DBG_LOW("    invalidate(vpn=%016lx, hash: %lx)\n", vpn, slot);
 
-       want_v = hpte_encode_v(va, psize, ssize);
+       want_v = hpte_encode_v(vpn, psize, ssize);
        native_lock_hpte(hptep);
        hpte_v = hptep->v;
 
@@ -339,7 +360,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
                hptep->v = 0;
 
        /* Invalidate the TLB */
-       tlbie(va, psize, ssize, local);
+       tlbie(vpn, psize, ssize, local);
 
        local_irq_restore(flags);
 }
@@ -349,11 +370,12 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
 #define LP_MASK(i)     ((0xFF >> (i)) << LP_SHIFT)
 
 static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
-                       int *psize, int *ssize, unsigned long *va)
+                       int *psize, int *ssize, unsigned long *vpn)
 {
+       unsigned long avpn, pteg, vpi;
        unsigned long hpte_r = hpte->r;
        unsigned long hpte_v = hpte->v;
-       unsigned long avpn;
+       unsigned long vsid, seg_off;
        int i, size, shift, penc;
 
        if (!(hpte_v & HPTE_V_LARGE))
@@ -380,32 +402,38 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
        }
 
        /* This works for all page sizes, and for 256M and 1T segments */
+       *ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
        shift = mmu_psize_defs[size].shift;
-       avpn = (HPTE_V_AVPN_VAL(hpte_v) & ~mmu_psize_defs[size].avpnm) << 23;
-
-       if (shift < 23) {
-               unsigned long vpi, vsid, pteg;
 
-               pteg = slot / HPTES_PER_GROUP;
-               if (hpte_v & HPTE_V_SECONDARY)
-                       pteg = ~pteg;
-               switch (hpte_v >> HPTE_V_SSIZE_SHIFT) {
-               case MMU_SEGSIZE_256M:
-                       vpi = ((avpn >> 28) ^ pteg) & htab_hash_mask;
-                       break;
-               case MMU_SEGSIZE_1T:
-                       vsid = avpn >> 40;
+       avpn = (HPTE_V_AVPN_VAL(hpte_v) & ~mmu_psize_defs[size].avpnm);
+       pteg = slot / HPTES_PER_GROUP;
+       if (hpte_v & HPTE_V_SECONDARY)
+               pteg = ~pteg;
+
+       switch (*ssize) {
+       case MMU_SEGSIZE_256M:
+               /* We only have 28 - 23 bits of seg_off in avpn */
+               seg_off = (avpn & 0x1f) << 23;
+               vsid    =  avpn >> 5;
+               /* We can find more bits from the pteg value */
+               if (shift < 23) {
+                       vpi = (vsid ^ pteg) & htab_hash_mask;
+                       seg_off |= vpi << shift;
+               }
+               *vpn = vsid << (SID_SHIFT - VPN_SHIFT) | seg_off >> VPN_SHIFT;
+       case MMU_SEGSIZE_1T:
+               /* We only have 40 - 23 bits of seg_off in avpn */
+               seg_off = (avpn & 0x1ffff) << 23;
+               vsid    = avpn >> 17;
+               if (shift < 23) {
                        vpi = (vsid ^ (vsid << 25) ^ pteg) & htab_hash_mask;
-                       break;
-               default:
-                       avpn = vpi = size = 0;
+                       seg_off |= vpi << shift;
                }
-               avpn |= (vpi << mmu_psize_defs[size].shift);
+               *vpn = vsid << (SID_SHIFT_1T - VPN_SHIFT) | seg_off >> VPN_SHIFT;
+       default:
+               *vpn = size = 0;
        }
-
-       *va = avpn;
        *psize = size;
-       *ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
 }
 
 /*
@@ -418,9 +446,10 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
  */
 static void native_hpte_clear(void)
 {
+       unsigned long vpn = 0;
        unsigned long slot, slots, flags;
        struct hash_pte *hptep = htab_address;
-       unsigned long hpte_v, va;
+       unsigned long hpte_v;
        unsigned long pteg_count;
        int psize, ssize;
 
@@ -448,9 +477,9 @@ static void native_hpte_clear(void)
                 * already hold the native_tlbie_lock.
                 */
                if (hpte_v & HPTE_V_VALID) {
-                       hpte_decode(hptep, slot, &psize, &ssize, &va);
+                       hpte_decode(hptep, slot, &psize, &ssize, &vpn);
                        hptep->v = 0;
-                       __tlbie(va, psize, ssize);
+                       __tlbie(vpn, psize, ssize);
                }
        }
 
@@ -465,7 +494,8 @@ static void native_hpte_clear(void)
  */
 static void native_flush_hash_range(unsigned long number, int local)
 {
-       unsigned long va, hash, index, hidx, shift, slot;
+       unsigned long vpn;
+       unsigned long hash, index, hidx, shift, slot;
        struct hash_pte *hptep;
        unsigned long hpte_v;
        unsigned long want_v;
@@ -479,18 +509,18 @@ static void native_flush_hash_range(unsigned long number, int local)
        local_irq_save(flags);
 
        for (i = 0; i < number; i++) {
-               va = batch->vaddr[i];
+               vpn = batch->vpn[i];
                pte = batch->pte[i];
 
-               pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
-                       hash = hpt_hash(va, shift, ssize);
+               pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
+                       hash = hpt_hash(vpn, shift, ssize);
                        hidx = __rpte_to_hidx(pte, index);
                        if (hidx & _PTEIDX_SECONDARY)
                                hash = ~hash;
                        slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
                        slot += hidx & _PTEIDX_GROUP_IX;
                        hptep = htab_address + slot;
-                       want_v = hpte_encode_v(va, psize, ssize);
+                       want_v = hpte_encode_v(vpn, psize, ssize);
                        native_lock_hpte(hptep);
                        hpte_v = hptep->v;
                        if (!HPTE_V_COMPARE(hpte_v, want_v) ||
@@ -505,12 +535,12 @@ static void native_flush_hash_range(unsigned long number, int local)
            mmu_psize_defs[psize].tlbiel && local) {
                asm volatile("ptesync":::"memory");
                for (i = 0; i < number; i++) {
-                       va = batch->vaddr[i];
+                       vpn = batch->vpn[i];
                        pte = batch->pte[i];
 
-                       pte_iterate_hashed_subpages(pte, psize, va, index,
-                                                   shift) {
-                               __tlbiel(va, psize, ssize);
+                       pte_iterate_hashed_subpages(pte, psize,
+                                                   vpn, index, shift) {
+                               __tlbiel(vpn, psize, ssize);
                        } pte_iterate_hashed_end();
                }
                asm volatile("ptesync":::"memory");
@@ -522,12 +552,12 @@ static void native_flush_hash_range(unsigned long number, int local)
 
                asm volatile("ptesync":::"memory");
                for (i = 0; i < number; i++) {
-                       va = batch->vaddr[i];
+                       vpn = batch->vpn[i];
                        pte = batch->pte[i];
 
-                       pte_iterate_hashed_subpages(pte, psize, va, index,
-                                                   shift) {
-                               __tlbie(va, psize, ssize);
+                       pte_iterate_hashed_subpages(pte, psize,
+                                                   vpn, index, shift) {
+                               __tlbie(vpn, psize, ssize);
                        } pte_iterate_hashed_end();
                }
                asm volatile("eieio; tlbsync; ptesync":::"memory");
index ba45739..3a292be 100644 (file)
@@ -191,18 +191,18 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
             vaddr += step, paddr += step) {
                unsigned long hash, hpteg;
                unsigned long vsid = get_kernel_vsid(vaddr, ssize);
-               unsigned long va = hpt_va(vaddr, vsid, ssize);
+               unsigned long vpn  = hpt_vpn(vaddr, vsid, ssize);
                unsigned long tprot = prot;
 
                /* Make kernel text executable */
                if (overlaps_kernel_text(vaddr, vaddr + step))
                        tprot &= ~HPTE_R_N;
 
-               hash = hpt_hash(va, shift, ssize);
+               hash = hpt_hash(vpn, shift, ssize);
                hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
                BUG_ON(!ppc_md.hpte_insert);
-               ret = ppc_md.hpte_insert(hpteg, va, paddr, tprot,
+               ret = ppc_md.hpte_insert(hpteg, vpn, paddr, tprot,
                                         HPTE_V_BOLTED, psize, ssize);
 
                if (ret < 0)
@@ -803,16 +803,19 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
 #ifdef CONFIG_PPC_MM_SLICES
 unsigned int get_paca_psize(unsigned long addr)
 {
-       unsigned long index, slices;
+       u64 lpsizes;
+       unsigned char *hpsizes;
+       unsigned long index, mask_index;
 
        if (addr < SLICE_LOW_TOP) {
-               slices = get_paca()->context.low_slices_psize;
+               lpsizes = get_paca()->context.low_slices_psize;
                index = GET_LOW_SLICE_INDEX(addr);
-       } else {
-               slices = get_paca()->context.high_slices_psize;
-               index = GET_HIGH_SLICE_INDEX(addr);
+               return (lpsizes >> (index * 4)) & 0xF;
        }
-       return (slices >> (index * 4)) & 0xF;
+       hpsizes = get_paca()->context.high_slices_psize;
+       index = GET_HIGH_SLICE_INDEX(addr);
+       mask_index = index & 0x1;
+       return (hpsizes[index >> 1] >> (mask_index * 4)) & 0xF;
 }
 
 #else
@@ -1152,21 +1155,21 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
 /* WARNING: This is called from hash_low_64.S, if you change this prototype,
  *          do not forget to update the assembly call site !
  */
-void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int ssize,
+void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize,
                     int local)
 {
        unsigned long hash, index, shift, hidx, slot;
 
-       DBG_LOW("flush_hash_page(va=%016lx)\n", va);
-       pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
-               hash = hpt_hash(va, shift, ssize);
+       DBG_LOW("flush_hash_page(vpn=%016lx)\n", vpn);
+       pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
+               hash = hpt_hash(vpn, shift, ssize);
                hidx = __rpte_to_hidx(pte, index);
                if (hidx & _PTEIDX_SECONDARY)
                        hash = ~hash;
                slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
                slot += hidx & _PTEIDX_GROUP_IX;
                DBG_LOW(" sub %ld: hash=%lx, hidx=%lx\n", index, slot, hidx);
-               ppc_md.hpte_invalidate(slot, va, psize, ssize, local);
+               ppc_md.hpte_invalidate(slot, vpn, psize, ssize, local);
        } pte_iterate_hashed_end();
 }
 
@@ -1180,7 +1183,7 @@ void flush_hash_range(unsigned long number, int local)
                        &__get_cpu_var(ppc64_tlb_batch);
 
                for (i = 0; i < number; i++)
-                       flush_hash_page(batch->vaddr[i], batch->pte[i],
+                       flush_hash_page(batch->vpn[i], batch->pte[i],
                                        batch->psize, batch->ssize, local);
        }
 }
@@ -1207,14 +1210,14 @@ static void kernel_map_linear_page(unsigned long vaddr, unsigned long lmi)
 {
        unsigned long hash, hpteg;
        unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize);
-       unsigned long va = hpt_va(vaddr, vsid, mmu_kernel_ssize);
+       unsigned long vpn = hpt_vpn(vaddr, vsid, mmu_kernel_ssize);
        unsigned long mode = htab_convert_pte_flags(PAGE_KERNEL);
        int ret;
 
-       hash = hpt_hash(va, PAGE_SHIFT, mmu_kernel_ssize);
+       hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize);
        hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
-       ret = ppc_md.hpte_insert(hpteg, va, __pa(vaddr),
+       ret = ppc_md.hpte_insert(hpteg, vpn, __pa(vaddr),
                                 mode, HPTE_V_BOLTED,
                                 mmu_linear_psize, mmu_kernel_ssize);
        BUG_ON (ret < 0);
@@ -1228,9 +1231,9 @@ static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi)
 {
        unsigned long hash, hidx, slot;
        unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize);
-       unsigned long va = hpt_va(vaddr, vsid, mmu_kernel_ssize);
+       unsigned long vpn = hpt_vpn(vaddr, vsid, mmu_kernel_ssize);
 
-       hash = hpt_hash(va, PAGE_SHIFT, mmu_kernel_ssize);
+       hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize);
        spin_lock(&linear_map_hash_lock);
        BUG_ON(!(linear_map_hash_slots[lmi] & 0x80));
        hidx = linear_map_hash_slots[lmi] & 0x7f;
@@ -1240,7 +1243,7 @@ static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi)
                hash = ~hash;
        slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
        slot += hidx & _PTEIDX_GROUP_IX;
-       ppc_md.hpte_invalidate(slot, va, mmu_linear_psize, mmu_kernel_ssize, 0);
+       ppc_md.hpte_invalidate(slot, vpn, mmu_linear_psize, mmu_kernel_ssize, 0);
 }
 
 void kernel_map_pages(struct page *page, int numpages, int enable)
index cc5c273..cecad34 100644 (file)
@@ -18,14 +18,15 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
                     pte_t *ptep, unsigned long trap, int local, int ssize,
                     unsigned int shift, unsigned int mmu_psize)
 {
+       unsigned long vpn;
        unsigned long old_pte, new_pte;
-       unsigned long va, rflags, pa, sz;
+       unsigned long rflags, pa, sz;
        long slot;
 
        BUG_ON(shift != mmu_psize_defs[mmu_psize].shift);
 
        /* Search the Linux page table for a match with va */
-       va = hpt_va(ea, vsid, ssize);
+       vpn = hpt_vpn(ea, vsid, ssize);
 
        /* At this point, we have a pte (old_pte) which can be used to build
         * or update an HPTE. There are 2 cases:
@@ -69,19 +70,19 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
                /* There MIGHT be an HPTE for this pte */
                unsigned long hash, slot;
 
-               hash = hpt_hash(va, shift, ssize);
+               hash = hpt_hash(vpn, shift, ssize);
                if (old_pte & _PAGE_F_SECOND)
                        hash = ~hash;
                slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
                slot += (old_pte & _PAGE_F_GIX) >> 12;
 
-               if (ppc_md.hpte_updatepp(slot, rflags, va, mmu_psize,
+               if (ppc_md.hpte_updatepp(slot, rflags, vpn, mmu_psize,
                                         ssize, local) == -1)
                        old_pte &= ~_PAGE_HPTEFLAGS;
        }
 
        if (likely(!(old_pte & _PAGE_HASHPTE))) {
-               unsigned long hash = hpt_hash(va, shift, ssize);
+               unsigned long hash = hpt_hash(vpn, shift, ssize);
                unsigned long hpte_group;
 
                pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT;
@@ -101,14 +102,14 @@ repeat:
                                      _PAGE_COHERENT | _PAGE_GUARDED));
 
                /* Insert into the hash table, primary slot */
-               slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, 0,
+               slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0,
                                          mmu_psize, ssize);
 
                /* Primary is full, try the secondary */
                if (unlikely(slot == -1)) {
                        hpte_group = ((~hash & htab_hash_mask) *
                                      HPTES_PER_GROUP) & ~0x7UL;
-                       slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags,
+                       slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags,
                                                  HPTE_V_SECONDARY,
                                                  mmu_psize, ssize);
                        if (slot == -1) {
index 40677aa..40bc5b0 100644 (file)
@@ -30,11 +30,13 @@ static DEFINE_SPINLOCK(mmu_context_lock);
 static DEFINE_IDA(mmu_context_ida);
 
 /*
- * The proto-VSID space has 2^35 - 1 segments available for user mappings.
- * Each segment contains 2^28 bytes.  Each context maps 2^44 bytes,
- * so we can support 2^19-1 contexts (19 == 35 + 28 - 44).
+ * 256MB segment
+ * The proto-VSID space has 2^(CONTEX_BITS + USER_ESID_BITS) - 1 segments
+ * available for user mappings. Each segment contains 2^28 bytes. Each
+ * context maps 2^46 bytes (64TB) so we can support 2^19-1 contexts
+ * (19 == 37 + 28 - 46).
  */
-#define MAX_CONTEXT    ((1UL << 19) - 1)
+#define MAX_CONTEXT    ((1UL << CONTEXT_BITS) - 1)
 
 int __init_new_context(void)
 {
index 297d495..e212a27 100644 (file)
 
 #include "mmu_decl.h"
 
-unsigned long ioremap_bot = IOREMAP_BASE;
+/* Some sanity checking */
+#if TASK_SIZE_USER64 > PGTABLE_RANGE
+#error TASK_SIZE_USER64 exceeds pagetable range
+#endif
+
+#ifdef CONFIG_PPC_STD_MMU_64
+#if TASK_SIZE_USER64 > (1UL << (USER_ESID_BITS + SID_SHIFT))
+#error TASK_SIZE_USER64 exceeds user VSID range
+#endif
+#endif
 
+unsigned long ioremap_bot = IOREMAP_BASE;
 
 #ifdef CONFIG_PPC_MMU_NOHASH
 static void *early_alloc_pgtable(unsigned long size)
index b9ee79c..1a16ca2 100644 (file)
@@ -56,6 +56,12 @@ _GLOBAL(slb_allocate_realmode)
         */
 _GLOBAL(slb_miss_kernel_load_linear)
        li      r11,0
+       li      r9,0x1
+       /*
+        * for 1T we shift 12 bits more.  slb_finish_load_1T will do
+        * the necessary adjustment
+        */
+       rldimi  r10,r9,(CONTEXT_BITS + USER_ESID_BITS),0
 BEGIN_FTR_SECTION
        b       slb_finish_load
 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
@@ -85,6 +91,12 @@ _GLOBAL(slb_miss_kernel_load_vmemmap)
        _GLOBAL(slb_miss_kernel_load_io)
        li      r11,0
 6:
+       li      r9,0x1
+       /*
+        * for 1T we shift 12 bits more.  slb_finish_load_1T will do
+        * the necessary adjustment
+        */
+       rldimi  r10,r9,(CONTEXT_BITS + USER_ESID_BITS),0
 BEGIN_FTR_SECTION
        b       slb_finish_load
 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
@@ -108,17 +120,31 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
         * between 4k and 64k standard page size
         */
 #ifdef CONFIG_PPC_MM_SLICES
+       /* r10 have esid */
        cmpldi  r10,16
-
-       /* Get the slice index * 4 in r11 and matching slice size mask in r9 */
-       ld      r9,PACALOWSLICESPSIZE(r13)
-       sldi    r11,r10,2
+       /* below SLICE_LOW_TOP */
        blt     5f
-       ld      r9,PACAHIGHSLICEPSIZE(r13)
-       srdi    r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT - 2)
-       andi.   r11,r11,0x3c
+       /*
+        * Handle hpsizes,
+        * r9 is get_paca()->context.high_slices_psize[index], r11 is mask_index
+        */
+       srdi    r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT + 1) /* index */
+       addi    r9,r11,PACAHIGHSLICEPSIZE
+       lbzx    r9,r13,r9               /* r9 is hpsizes[r11] */
+       /* r11 = (r10 >> (SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT)) & 0x1 */
+       rldicl  r11,r10,(64 - (SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT)),63
+       b       6f
 
-5:     /* Extract the psize and multiply to get an array offset */
+5:
+       /*
+        * Handle lpsizes
+        * r9 is get_paca()->context.low_slices_psize, r11 is index
+        */
+       ld      r9,PACALOWSLICESPSIZE(r13)
+       mr      r11,r10
+6:
+       sldi    r11,r11,2  /* index * 4 */
+       /* Extract the psize and multiply to get an array offset */
        srd     r9,r9,r11
        andi.   r9,r9,0xf
        mulli   r9,r9,MMUPSIZEDEFSIZE
@@ -209,7 +235,11 @@ _GLOBAL(slb_allocate_user)
  */
 slb_finish_load:
        ASM_VSID_SCRAMBLE(r10,r9,256M)
-       rldimi  r11,r10,SLB_VSID_SHIFT,16       /* combine VSID and flags */
+       /*
+        * bits above VSID_BITS_256M need to be ignored from r10
+        * also combine VSID and flags
+        */
+       rldimi  r11,r10,SLB_VSID_SHIFT,(64 - (SLB_VSID_SHIFT + VSID_BITS_256M))
 
        /* r3 = EA, r11 = VSID data */
        /*
@@ -252,10 +282,10 @@ _GLOBAL(slb_compare_rr_to_size)
        bge     1f
 
        /* still room in the slb cache */
-       sldi    r11,r3,1                /* r11 = offset * sizeof(u16) */
-       rldicl  r10,r10,36,28           /* get low 16 bits of the ESID */
-       add     r11,r11,r13             /* r11 = (u16 *)paca + offset */
-       sth     r10,PACASLBCACHE(r11)   /* paca->slb_cache[offset] = esid */
+       sldi    r11,r3,2                /* r11 = offset * sizeof(u32) */
+       srdi    r10,r10,28              /* get the 36 bits of the ESID */
+       add     r11,r11,r13             /* r11 = (u32 *)paca + offset */
+       stw     r10,PACASLBCACHE(r11)   /* paca->slb_cache[offset] = esid */
        addi    r3,r3,1                 /* offset++ */
        b       2f
 1:                                     /* offset >= SLB_CACHE_ENTRIES */
@@ -273,7 +303,11 @@ _GLOBAL(slb_compare_rr_to_size)
 slb_finish_load_1T:
        srdi    r10,r10,40-28           /* get 1T ESID */
        ASM_VSID_SCRAMBLE(r10,r9,1T)
-       rldimi  r11,r10,SLB_VSID_SHIFT_1T,16    /* combine VSID and flags */
+       /*
+        * bits above VSID_BITS_1T need to be ignored from r10
+        * also combine VSID and flags
+        */
+       rldimi  r11,r10,SLB_VSID_SHIFT_1T,(64 - (SLB_VSID_SHIFT_1T + VSID_BITS_1T))
        li      r10,MMU_SEGSIZE_1T
        rldimi  r11,r10,SLB_VSID_SSIZE_SHIFT,0  /* insert segment size */
 
index 73709f7..5829d2a 100644 (file)
 #include <asm/mmu.h>
 #include <asm/spu.h>
 
+/* some sanity checks */
+#if (PGTABLE_RANGE >> 43) > SLICE_MASK_SIZE
+#error PGTABLE_RANGE exceeds slice_mask high_slices size
+#endif
+
 static DEFINE_SPINLOCK(slice_convert_lock);
 
 
@@ -42,7 +47,7 @@ int _slice_debug = 1;
 
 static void slice_print_mask(const char *label, struct slice_mask mask)
 {
-       char    *p, buf[16 + 3 + 16 + 1];
+       char    *p, buf[16 + 3 + 64 + 1];
        int     i;
 
        if (!_slice_debug)
@@ -54,7 +59,7 @@ static void slice_print_mask(const char *label, struct slice_mask mask)
        *(p++) = '-';
        *(p++) = ' ';
        for (i = 0; i < SLICE_NUM_HIGH; i++)
-               *(p++) = (mask.high_slices & (1 << i)) ? '1' : '0';
+               *(p++) = (mask.high_slices & (1ul << i)) ? '1' : '0';
        *(p++) = 0;
 
        printk(KERN_DEBUG "%s:%s\n", label, buf);
@@ -84,8 +89,8 @@ static struct slice_mask slice_range_to_mask(unsigned long start,
        }
 
        if ((start + len) > SLICE_LOW_TOP)
-               ret.high_slices = (1u << (GET_HIGH_SLICE_INDEX(end) + 1))
-                       - (1u << GET_HIGH_SLICE_INDEX(start));
+               ret.high_slices = (1ul << (GET_HIGH_SLICE_INDEX(end) + 1))
+                       - (1ul << GET_HIGH_SLICE_INDEX(start));
 
        return ret;
 }
@@ -135,26 +140,31 @@ static struct slice_mask slice_mask_for_free(struct mm_struct *mm)
 
        for (i = 0; i < SLICE_NUM_HIGH; i++)
                if (!slice_high_has_vma(mm, i))
-                       ret.high_slices |= 1u << i;
+                       ret.high_slices |= 1ul << i;
 
        return ret;
 }
 
 static struct slice_mask slice_mask_for_size(struct mm_struct *mm, int psize)
 {
+       unsigned char *hpsizes;
+       int index, mask_index;
        struct slice_mask ret = { 0, 0 };
        unsigned long i;
-       u64 psizes;
+       u64 lpsizes;
 
-       psizes = mm->context.low_slices_psize;
+       lpsizes = mm->context.low_slices_psize;
        for (i = 0; i < SLICE_NUM_LOW; i++)
-               if (((psizes >> (i * 4)) & 0xf) == psize)
+               if (((lpsizes >> (i * 4)) & 0xf) == psize)
                        ret.low_slices |= 1u << i;
 
-       psizes = mm->context.high_slices_psize;
-       for (i = 0; i < SLICE_NUM_HIGH; i++)
-               if (((psizes >> (i * 4)) & 0xf) == psize)
-                       ret.high_slices |= 1u << i;
+       hpsizes = mm->context.high_slices_psize;
+       for (i = 0; i < SLICE_NUM_HIGH; i++) {
+               mask_index = i & 0x1;
+               index = i >> 1;
+               if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize)
+                       ret.high_slices |= 1ul << i;
+       }
 
        return ret;
 }
@@ -183,8 +193,10 @@ static void slice_flush_segments(void *parm)
 
 static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize)
 {
+       int index, mask_index;
        /* Write the new slice psize bits */
-       u64 lpsizes, hpsizes;
+       unsigned char *hpsizes;
+       u64 lpsizes;
        unsigned long i, flags;
 
        slice_dbg("slice_convert(mm=%p, psize=%d)\n", mm, psize);
@@ -201,14 +213,18 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
                        lpsizes = (lpsizes & ~(0xful << (i * 4))) |
                                (((unsigned long)psize) << (i * 4));
 
-       hpsizes = mm->context.high_slices_psize;
-       for (i = 0; i < SLICE_NUM_HIGH; i++)
-               if (mask.high_slices & (1u << i))
-                       hpsizes = (hpsizes & ~(0xful << (i * 4))) |
-                               (((unsigned long)psize) << (i * 4));
-
+       /* Assign the value back */
        mm->context.low_slices_psize = lpsizes;
-       mm->context.high_slices_psize = hpsizes;
+
+       hpsizes = mm->context.high_slices_psize;
+       for (i = 0; i < SLICE_NUM_HIGH; i++) {
+               mask_index = i & 0x1;
+               index = i >> 1;
+               if (mask.high_slices & (1ul << i))
+                       hpsizes[index] = (hpsizes[index] &
+                                         ~(0xf << (mask_index * 4))) |
+                               (((unsigned long)psize) << (mask_index * 4));
+       }
 
        slice_dbg(" lsps=%lx, hsps=%lx\n",
                  mm->context.low_slices_psize,
@@ -587,18 +603,19 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
 
 unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr)
 {
-       u64 psizes;
-       int index;
+       unsigned char *hpsizes;
+       int index, mask_index;
 
        if (addr < SLICE_LOW_TOP) {
-               psizes = mm->context.low_slices_psize;
+               u64 lpsizes;
+               lpsizes = mm->context.low_slices_psize;
                index = GET_LOW_SLICE_INDEX(addr);
-       } else {
-               psizes = mm->context.high_slices_psize;
-               index = GET_HIGH_SLICE_INDEX(addr);
+               return (lpsizes >> (index * 4)) & 0xf;
        }
-
-       return (psizes >> (index * 4)) & 0xf;
+       hpsizes = mm->context.high_slices_psize;
+       index = GET_HIGH_SLICE_INDEX(addr);
+       mask_index = index & 0x1;
+       return (hpsizes[index >> 1] >> (mask_index * 4)) & 0xf;
 }
 EXPORT_SYMBOL_GPL(get_slice_psize);
 
@@ -618,7 +635,9 @@ EXPORT_SYMBOL_GPL(get_slice_psize);
  */
 void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 {
-       unsigned long flags, lpsizes, hpsizes;
+       int index, mask_index;
+       unsigned char *hpsizes;
+       unsigned long flags, lpsizes;
        unsigned int old_psize;
        int i;
 
@@ -639,15 +658,21 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
                if (((lpsizes >> (i * 4)) & 0xf) == old_psize)
                        lpsizes = (lpsizes & ~(0xful << (i * 4))) |
                                (((unsigned long)psize) << (i * 4));
+       /* Assign the value back */
+       mm->context.low_slices_psize = lpsizes;
 
        hpsizes = mm->context.high_slices_psize;
-       for (i = 0; i < SLICE_NUM_HIGH; i++)
-               if (((hpsizes >> (i * 4)) & 0xf) == old_psize)
-                       hpsizes = (hpsizes & ~(0xful << (i * 4))) |
-                               (((unsigned long)psize) << (i * 4));
+       for (i = 0; i < SLICE_NUM_HIGH; i++) {
+               mask_index = i & 0x1;
+               index = i >> 1;
+               if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == old_psize)
+                       hpsizes[index] = (hpsizes[index] &
+                                         ~(0xf << (mask_index * 4))) |
+                               (((unsigned long)psize) << (mask_index * 4));
+       }
+
+
 
-       mm->context.low_slices_psize = lpsizes;
-       mm->context.high_slices_psize = hpsizes;
 
        slice_dbg(" lsps=%lx, hsps=%lx\n",
                  mm->context.low_slices_psize,
@@ -660,18 +685,27 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 void slice_set_psize(struct mm_struct *mm, unsigned long address,
                     unsigned int psize)
 {
+       unsigned char *hpsizes;
        unsigned long i, flags;
-       u64 *p;
+       u64 *lpsizes;
 
        spin_lock_irqsave(&slice_convert_lock, flags);
        if (address < SLICE_LOW_TOP) {
                i = GET_LOW_SLICE_INDEX(address);
-               p = &mm->context.low_slices_psize;
+               lpsizes = &mm->context.low_slices_psize;
+               *lpsizes = (*lpsizes & ~(0xful << (i * 4))) |
+                       ((unsigned long) psize << (i * 4));
        } else {
+               int index, mask_index;
                i = GET_HIGH_SLICE_INDEX(address);
-               p = &mm->context.high_slices_psize;
+               hpsizes = mm->context.high_slices_psize;
+               mask_index = i & 0x1;
+               index = i >> 1;
+               hpsizes[index] = (hpsizes[index] &
+                                 ~(0xf << (mask_index * 4))) |
+                       (((unsigned long)psize) << (mask_index * 4));
        }
-       *p = (*p & ~(0xful << (i * 4))) | ((unsigned long) psize << (i * 4));
+
        spin_unlock_irqrestore(&slice_convert_lock, flags);
 
 #ifdef CONFIG_SPU_BASE
index 31f1820..ae758b3 100644 (file)
@@ -42,8 +42,9 @@ DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
 void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
                     pte_t *ptep, unsigned long pte, int huge)
 {
+       unsigned long vpn;
        struct ppc64_tlb_batch *batch = &get_cpu_var(ppc64_tlb_batch);
-       unsigned long vsid, vaddr;
+       unsigned long vsid;
        unsigned int psize;
        int ssize;
        real_pte_t rpte;
@@ -86,7 +87,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
                vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
                ssize = mmu_kernel_ssize;
        }
-       vaddr = hpt_va(addr, vsid, ssize);
+       vpn = hpt_vpn(addr, vsid, ssize);
        rpte = __real_pte(__pte(pte), ptep);
 
        /*
@@ -96,7 +97,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
         * and decide to use local invalidates instead...
         */
        if (!batch->active) {
-               flush_hash_page(vaddr, rpte, psize, ssize, 0);
+               flush_hash_page(vpn, rpte, psize, ssize, 0);
                put_cpu_var(ppc64_tlb_batch);
                return;
        }
@@ -122,7 +123,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
                batch->ssize = ssize;
        }
        batch->pte[i] = rpte;
-       batch->vaddr[i] = vaddr;
+       batch->vpn[i] = vpn;
        batch->index = ++i;
        if (i >= PPC64_TLB_BATCH_NR)
                __flush_tlb_pending(batch);
@@ -146,7 +147,7 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
        if (cpumask_equal(mm_cpumask(batch->mm), tmp))
                local = 1;
        if (i == 1)
-               flush_hash_page(batch->vaddr[0], batch->pte[0],
+               flush_hash_page(batch->vpn[0], batch->pte[0],
                                batch->psize, batch->ssize, local);
        else
                flush_hash_range(i, local);
index 943c9d3..0f6f839 100644 (file)
@@ -88,7 +88,7 @@ static inline unsigned int beat_read_mask(unsigned hpte_group)
 }
 
 static long beat_lpar_hpte_insert(unsigned long hpte_group,
-                                 unsigned long va, unsigned long pa,
+                                 unsigned long vpn, unsigned long pa,
                                  unsigned long rflags, unsigned long vflags,
                                  int psize, int ssize)
 {
@@ -103,7 +103,7 @@ static long beat_lpar_hpte_insert(unsigned long hpte_group,
                        "rflags=%lx, vflags=%lx, psize=%d)\n",
                hpte_group, va, pa, rflags, vflags, psize);
 
-       hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
+       hpte_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M) |
                vflags | HPTE_V_VALID;
        hpte_r = hpte_encode_r(pa, psize) | rflags;
 
@@ -184,14 +184,14 @@ static void beat_lpar_hptab_clear(void)
  */
 static long beat_lpar_hpte_updatepp(unsigned long slot,
                                    unsigned long newpp,
-                                   unsigned long va,
+                                   unsigned long vpn,
                                    int psize, int ssize, int local)
 {
        unsigned long lpar_rc;
        u64 dummy0, dummy1;
        unsigned long want_v;
 
-       want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+       want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
 
        DBG_LOW("    update: "
                "avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
@@ -220,15 +220,15 @@ static long beat_lpar_hpte_updatepp(unsigned long slot,
        return 0;
 }
 
-static long beat_lpar_hpte_find(unsigned long va, int psize)
+static long beat_lpar_hpte_find(unsigned long vpn, int psize)
 {
        unsigned long hash;
        unsigned long i, j;
        long slot;
        unsigned long want_v, hpte_v;
 
-       hash = hpt_hash(va, mmu_psize_defs[psize].shift, MMU_SEGSIZE_256M);
-       want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+       hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, MMU_SEGSIZE_256M);
+       want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
 
        for (j = 0; j < 2; j++) {
                slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
@@ -255,14 +255,15 @@ static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
                                          unsigned long ea,
                                          int psize, int ssize)
 {
-       unsigned long lpar_rc, slot, vsid, va;
+       unsigned long vpn;
+       unsigned long lpar_rc, slot, vsid;
        u64 dummy0, dummy1;
 
        vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
-       va = (vsid << 28) | (ea & 0x0fffffff);
+       vpn = hpt_vpn(ea, vsid, MMU_SEGSIZE_256M);
 
        raw_spin_lock(&beat_htab_lock);
-       slot = beat_lpar_hpte_find(va, psize);
+       slot = beat_lpar_hpte_find(vpn, psize);
        BUG_ON(slot == -1);
 
        lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7,
@@ -272,7 +273,7 @@ static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
        BUG_ON(lpar_rc != 0);
 }
 
-static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn,
                                         int psize, int ssize, int local)
 {
        unsigned long want_v;
@@ -282,7 +283,7 @@ static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
 
        DBG_LOW("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
                slot, va, psize, local);
-       want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+       want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
 
        raw_spin_lock_irqsave(&beat_htab_lock, flags);
        dummy1 = beat_lpar_hpte_getword0(slot);
@@ -311,7 +312,7 @@ void __init hpte_init_beat(void)
 }
 
 static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
-                                 unsigned long va, unsigned long pa,
+                                 unsigned long vpn, unsigned long pa,
                                  unsigned long rflags, unsigned long vflags,
                                  int psize, int ssize)
 {
@@ -322,11 +323,11 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
                return -1;
 
        if (!(vflags & HPTE_V_BOLTED))
-               DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
+               DBG_LOW("hpte_insert(group=%lx, vpn=%016lx, pa=%016lx, "
                        "rflags=%lx, vflags=%lx, psize=%d)\n",
-               hpte_group, va, pa, rflags, vflags, psize);
+               hpte_group, vpn, pa, rflags, vflags, psize);
 
-       hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
+       hpte_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M) |
                vflags | HPTE_V_VALID;
        hpte_r = hpte_encode_r(pa, psize) | rflags;
 
@@ -364,14 +365,14 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
  */
 static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
                                    unsigned long newpp,
-                                   unsigned long va,
+                                   unsigned long vpn,
                                    int psize, int ssize, int local)
 {
        unsigned long lpar_rc;
        unsigned long want_v;
        unsigned long pss;
 
-       want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+       want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
        pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
 
        DBG_LOW("    update: "
@@ -392,16 +393,16 @@ static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
        return 0;
 }
 
-static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va,
+static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long vpn,
                                         int psize, int ssize, int local)
 {
        unsigned long want_v;
        unsigned long lpar_rc;
        unsigned long pss;
 
-       DBG_LOW("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
-               slot, va, psize, local);
-       want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+       DBG_LOW("    inval : slot=%lx, vpn=%016lx, psize: %d, local: %d\n",
+               slot, vpn, psize, local);
+       want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
        pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
 
        lpar_rc = beat_invalidate_htab_entry3(0, slot, want_v, pss);
index 5e75dcf..471aa3c 100644 (file)
 #include "powernv.h"
 #include "pci.h"
 
-struct resource_wrap {
-       struct list_head        link;
-       resource_size_t         size;
-       resource_size_t         align;
-       struct pci_dev          *dev;   /* Set if it's a device */
-       struct pci_bus          *bus;   /* Set if it's a bridge */
-};
-
 static int __pe_printk(const char *level, const struct pnv_ioda_pe *pe,
                       struct va_format *vaf)
 {
@@ -77,273 +69,6 @@ define_pe_printk_level(pe_err, KERN_ERR);
 define_pe_printk_level(pe_warn, KERN_WARNING);
 define_pe_printk_level(pe_info, KERN_INFO);
 
-
-/* Calculate resource usage & alignment requirement of a single
- * device. This will also assign all resources within the device
- * for a given type starting at 0 for the biggest one and then
- * assigning in decreasing order of size.
- */
-static void __devinit pnv_ioda_calc_dev(struct pci_dev *dev, unsigned int flags,
-                                       resource_size_t *size,
-                                       resource_size_t *align)
-{
-       resource_size_t start;
-       struct resource *r;
-       int i;
-
-       pr_devel("  -> CDR %s\n", pci_name(dev));
-
-       *size = *align = 0;
-
-       /* Clear the resources out and mark them all unset */
-       for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-               r = &dev->resource[i];
-               if (!(r->flags & flags))
-                   continue;
-               if (r->start) {
-                       r->end -= r->start;
-                       r->start = 0;
-               }
-               r->flags |= IORESOURCE_UNSET;
-       }
-
-       /* We currently keep all memory resources together, we
-        * will handle prefetch & 64-bit separately in the future
-        * but for now we stick everybody in M32
-        */
-       start = 0;
-       for (;;) {
-               resource_size_t max_size = 0;
-               int max_no = -1;
-
-               /* Find next biggest resource */
-               for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-                       r = &dev->resource[i];
-                       if (!(r->flags & IORESOURCE_UNSET) ||
-                           !(r->flags & flags))
-                               continue;
-                       if (resource_size(r) > max_size) {
-                               max_size = resource_size(r);
-                               max_no = i;
-                       }
-               }
-               if (max_no < 0)
-                       break;
-               r = &dev->resource[max_no];
-               if (max_size > *align)
-                       *align = max_size;
-               *size += max_size;
-               r->start = start;
-               start += max_size;
-               r->end = r->start + max_size - 1;
-               r->flags &= ~IORESOURCE_UNSET;
-               pr_devel("  ->     R%d %016llx..%016llx\n",
-                        max_no, r->start, r->end);
-       }
-       pr_devel("  <- CDR %s size=%llx align=%llx\n",
-                pci_name(dev), *size, *align);
-}
-
-/* Allocate a resource "wrap" for a given device or bridge and
- * insert it at the right position in the sorted list
- */
-static void __devinit pnv_ioda_add_wrap(struct list_head *list,
-                                       struct pci_bus *bus,
-                                       struct pci_dev *dev,
-                                       resource_size_t size,
-                                       resource_size_t align)
-{
-       struct resource_wrap *w1, *w = kzalloc(sizeof(*w), GFP_KERNEL);
-
-       w->size = size;
-       w->align = align;
-       w->dev = dev;
-       w->bus = bus;
-
-       list_for_each_entry(w1, list, link) {
-               if (w1->align < align) {
-                       list_add_tail(&w->link, &w1->link);
-                       return;
-               }
-       }
-       list_add_tail(&w->link, list);
-}
-
-/* Offset device resources of a given type */
-static void __devinit pnv_ioda_offset_dev(struct pci_dev *dev,
-                                         unsigned int flags,
-                                         resource_size_t offset)
-{
-       struct resource *r;
-       int i;
-
-       pr_devel("  -> ODR %s [%x] +%016llx\n", pci_name(dev), flags, offset);
-
-       for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-               r = &dev->resource[i];
-               if (r->flags & flags) {
-                       dev->resource[i].start += offset;
-                       dev->resource[i].end += offset;
-               }
-       }
-
-       pr_devel("  <- ODR %s [%x] +%016llx\n", pci_name(dev), flags, offset);
-}
-
-/* Offset bus resources (& all children) of a given type */
-static void __devinit pnv_ioda_offset_bus(struct pci_bus *bus,
-                                         unsigned int flags,
-                                         resource_size_t offset)
-{
-       struct resource *r;
-       struct pci_dev *dev;
-       struct pci_bus *cbus;
-       int i;
-
-       pr_devel("  -> OBR %s [%x] +%016llx\n",
-                bus->self ? pci_name(bus->self) : "root", flags, offset);
-
-       pci_bus_for_each_resource(bus, r, i) {
-               if (r && (r->flags & flags)) {
-                       r->start += offset;
-                       r->end += offset;
-               }
-       }
-       list_for_each_entry(dev, &bus->devices, bus_list)
-               pnv_ioda_offset_dev(dev, flags, offset);
-       list_for_each_entry(cbus, &bus->children, node)
-               pnv_ioda_offset_bus(cbus, flags, offset);
-
-       pr_devel("  <- OBR %s [%x]\n",
-                bus->self ? pci_name(bus->self) : "root", flags);
-}
-
-/* This is the guts of our IODA resource allocation. This is called
- * recursively for each bus in the system. It calculates all the
- * necessary size and requirements for children and assign them
- * resources such that:
- *
- *   - Each function fits in it's own contiguous set of IO/M32
- *     segment
- *
- *   - All segments behind a P2P bridge are contiguous and obey
- *     alignment constraints of those bridges
- */
-static void __devinit pnv_ioda_calc_bus(struct pci_bus *bus, unsigned int flags,
-                                       resource_size_t *size,
-                                       resource_size_t *align)
-{
-       struct pci_controller *hose = pci_bus_to_host(bus);
-       struct pnv_phb *phb = hose->private_data;
-       resource_size_t dev_size, dev_align, start;
-       resource_size_t min_align, min_balign;
-       struct pci_dev *cdev;
-       struct pci_bus *cbus;
-       struct list_head head;
-       struct resource_wrap *w;
-       unsigned int bres;
-
-       *size = *align = 0;
-
-       pr_devel("-> CBR %s [%x]\n",
-                bus->self ? pci_name(bus->self) : "root", flags);
-
-       /* Calculate alignment requirements based on the type
-        * of resource we are working on
-        */
-       if (flags & IORESOURCE_IO) {
-               bres = 0;
-               min_align = phb->ioda.io_segsize;
-               min_balign = 0x1000;
-       } else {
-               bres = 1;
-               min_align = phb->ioda.m32_segsize;
-               min_balign = 0x100000;
-       }
-
-       /* Gather all our children resources ordered by alignment */
-       INIT_LIST_HEAD(&head);
-
-       /*   - Busses */
-       list_for_each_entry(cbus, &bus->children, node) {
-               pnv_ioda_calc_bus(cbus, flags, &dev_size, &dev_align);
-               pnv_ioda_add_wrap(&head, cbus, NULL, dev_size, dev_align);
-       }
-
-       /*   - Devices */
-       list_for_each_entry(cdev, &bus->devices, bus_list) {
-               pnv_ioda_calc_dev(cdev, flags, &dev_size, &dev_align);
-               /* Align them to segment size */
-               if (dev_align < min_align)
-                       dev_align = min_align;
-               pnv_ioda_add_wrap(&head, NULL, cdev, dev_size, dev_align);
-       }
-       if (list_empty(&head))
-               goto empty;
-
-       /* Now we can do two things: assign offsets to them within that
-        * level and get our total alignment & size requirements. The
-        * assignment algorithm is going to be uber-trivial for now, we
-        * can try to be smarter later at filling out holes.
-        */
-       if (bus->self) {
-               /* No offset for downstream bridges */
-               start = 0;
-       } else {
-               /* Offset from the root */
-               if (flags & IORESOURCE_IO)
-                       /* Don't hand out IO 0 */
-                       start = hose->io_resource.start + 0x1000;
-               else
-                       start = hose->mem_resources[0].start;
-       }
-       while(!list_empty(&head)) {
-               w = list_first_entry(&head, struct resource_wrap, link);
-               list_del(&w->link);
-               if (w->size) {
-                       if (start) {
-                               start = ALIGN(start, w->align);
-                               if (w->dev)
-                                       pnv_ioda_offset_dev(w->dev,flags,start);
-                               else if (w->bus)
-                                       pnv_ioda_offset_bus(w->bus,flags,start);
-                       }
-                       if (w->align > *align)
-                               *align = w->align;
-               }
-               start += w->size;
-               kfree(w);
-       }
-       *size = start;
-
-       /* Align and setup bridge resources */
-       *align = max_t(resource_size_t, *align,
-                      max_t(resource_size_t, min_align, min_balign));
-       *size = ALIGN(*size,
-                     max_t(resource_size_t, min_align, min_balign));
- empty:
-       /* Only setup P2P's, not the PHB itself */
-       if (bus->self) {
-               struct resource *res = bus->resource[bres];
-
-               if (WARN_ON(res == NULL))
-                       return;
-
-               /*
-                * FIXME: We should probably export and call
-                * pci_bridge_check_ranges() to properly re-initialize
-                * the PCI portion of the flags here, and to detect
-                * what the bridge actually supports.
-                */
-               res->start = 0;
-               res->flags = (*size) ? flags : 0;
-               res->end = (*size) ? (*size - 1) : 0;
-       }
-
-       pr_devel("<- CBR %s [%x] *size=%016llx *align=%016llx\n",
-                bus->self ? pci_name(bus->self) : "root", flags,*size,*align);
-}
-
 static struct pci_dn *pnv_ioda_get_pdn(struct pci_dev *dev)
 {
        struct device_node *np;
@@ -354,172 +79,6 @@ static struct pci_dn *pnv_ioda_get_pdn(struct pci_dev *dev)
        return PCI_DN(np);
 }
 
-static void __devinit pnv_ioda_setup_pe_segments(struct pci_dev *dev)
-{
-       struct pci_controller *hose = pci_bus_to_host(dev->bus);
-       struct pnv_phb *phb = hose->private_data;
-       struct pci_dn *pdn = pnv_ioda_get_pdn(dev);
-       unsigned int pe, i;
-       resource_size_t pos;
-       struct resource io_res;
-       struct resource m32_res;
-       struct pci_bus_region region;
-       int rc;
-
-       /* Anything not referenced in the device-tree gets PE#0 */
-       pe = pdn ? pdn->pe_number : 0;
-
-       /* Calculate the device min/max */
-       io_res.start = m32_res.start = (resource_size_t)-1;
-       io_res.end = m32_res.end = 0;
-       io_res.flags = IORESOURCE_IO;
-       m32_res.flags = IORESOURCE_MEM;
-
-       for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-               struct resource *r = NULL;
-               if (dev->resource[i].flags & IORESOURCE_IO)
-                       r = &io_res;
-               if (dev->resource[i].flags & IORESOURCE_MEM)
-                       r = &m32_res;
-               if (!r)
-                       continue;
-               if (dev->resource[i].start < r->start)
-                       r->start = dev->resource[i].start;
-               if (dev->resource[i].end > r->end)
-                       r->end = dev->resource[i].end;
-       }
-
-       /* Setup IO segments */
-       if (io_res.start < io_res.end) {
-               pcibios_resource_to_bus(dev, &region, &io_res);
-               pos = region.start;
-               i = pos / phb->ioda.io_segsize;
-               while(i < phb->ioda.total_pe && pos <= region.end) {
-                       if (phb->ioda.io_segmap[i]) {
-                               pr_err("%s: Trying to use IO seg #%d which is"
-                                      " already used by PE# %d\n",
-                                      pci_name(dev), i,
-                                      phb->ioda.io_segmap[i]);
-                               /* XXX DO SOMETHING TO DISABLE DEVICE ? */
-                               break;
-                       }
-                       phb->ioda.io_segmap[i] = pe;
-                       rc = opal_pci_map_pe_mmio_window(phb->opal_id, pe,
-                                                        OPAL_IO_WINDOW_TYPE,
-                                                        0, i);
-                       if (rc != OPAL_SUCCESS) {
-                               pr_err("%s: OPAL error %d setting up mapping"
-                                      " for IO seg# %d\n",
-                                      pci_name(dev), rc, i);
-                               /* XXX DO SOMETHING TO DISABLE DEVICE ? */
-                               break;
-                       }
-                       pos += phb->ioda.io_segsize;
-                       i++;
-               };
-       }
-
-       /* Setup M32 segments */
-       if (m32_res.start < m32_res.end) {
-               pcibios_resource_to_bus(dev, &region, &m32_res);
-               pos = region.start;
-               i = pos / phb->ioda.m32_segsize;
-               while(i < phb->ioda.total_pe && pos <= region.end) {
-                       if (phb->ioda.m32_segmap[i]) {
-                               pr_err("%s: Trying to use M32 seg #%d which is"
-                                      " already used by PE# %d\n",
-                                      pci_name(dev), i,
-                                      phb->ioda.m32_segmap[i]);
-                               /* XXX DO SOMETHING TO DISABLE DEVICE ? */
-                               break;
-                       }
-                       phb->ioda.m32_segmap[i] = pe;
-                       rc = opal_pci_map_pe_mmio_window(phb->opal_id, pe,
-                                                        OPAL_M32_WINDOW_TYPE,
-                                                        0, i);
-                       if (rc != OPAL_SUCCESS) {
-                               pr_err("%s: OPAL error %d setting up mapping"
-                                      " for M32 seg# %d\n",
-                                      pci_name(dev), rc, i);
-                               /* XXX DO SOMETHING TO DISABLE DEVICE ? */
-                               break;
-                       }
-                       pos += phb->ioda.m32_segsize;
-                       i++;
-               }
-       }
-}
-
-/* Check if a resource still fits in the total IO or M32 range
- * for a given PHB
- */
-static int __devinit pnv_ioda_resource_fit(struct pci_controller *hose,
-                                          struct resource *r)
-{
-       struct resource *bounds;
-
-       if (r->flags & IORESOURCE_IO)
-               bounds = &hose->io_resource;
-       else if (r->flags & IORESOURCE_MEM)
-               bounds = &hose->mem_resources[0];
-       else
-               return 1;
-
-       if (r->start >= bounds->start && r->end <= bounds->end)
-               return 1;
-       r->flags = 0;
-       return 0;
-}
-
-static void __devinit pnv_ioda_update_resources(struct pci_bus *bus)
-{
-       struct pci_controller *hose = pci_bus_to_host(bus);
-       struct pci_bus *cbus;
-       struct pci_dev *cdev;
-       unsigned int i;
-
-       /* We used to clear all device enables here. However it looks like
-        * clearing MEM enable causes Obsidian (IPR SCS) to go bonkers,
-        * and shoot fatal errors to the PHB which in turns fences itself
-        * and we can't recover from that ... yet. So for now, let's leave
-        * the enables as-is and hope for the best.
-        */
-
-       /* Check if bus resources fit in our IO or M32 range */
-       for (i = 0; bus->self && (i < 2); i++) {
-               struct resource *r = bus->resource[i];
-               if (r && !pnv_ioda_resource_fit(hose, r))
-                       pr_err("%s: Bus %d resource %d disabled, no room\n",
-                              pci_name(bus->self), bus->number, i);
-       }
-
-       /* Update self if it's not a PHB */
-       if (bus->self)
-               pci_setup_bridge(bus);
-
-       /* Update child devices */
-       list_for_each_entry(cdev, &bus->devices, bus_list) {
-               /* Check if resource fits, if not, disabled it */
-               for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-                       struct resource *r = &cdev->resource[i];
-                       if (!pnv_ioda_resource_fit(hose, r))
-                               pr_err("%s: Resource %d disabled, no room\n",
-                                      pci_name(cdev), i);
-               }
-
-               /* Assign segments */
-               pnv_ioda_setup_pe_segments(cdev);
-
-               /* Update HW BARs */
-               for (i = 0; i <= PCI_ROM_RESOURCE; i++)
-                       pci_update_resource(cdev, i);
-       }
-
-       /* Update child busses */
-       list_for_each_entry(cbus, &bus->children, node)
-               pnv_ioda_update_resources(cbus);
-}
-
 static int __devinit pnv_ioda_alloc_pe(struct pnv_phb *phb)
 {
        unsigned long pe;
@@ -547,7 +106,7 @@ static void __devinit pnv_ioda_free_pe(struct pnv_phb *phb, int pe)
  * but in the meantime, we need to protect them to avoid warnings
  */
 #ifdef CONFIG_PCI_MSI
-static struct pnv_ioda_pe * __devinit __pnv_ioda_get_one_pe(struct pci_dev *dev)
+static struct pnv_ioda_pe * __devinit pnv_ioda_get_pe(struct pci_dev *dev)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
        struct pnv_phb *phb = hose->private_data;
@@ -559,19 +118,6 @@ static struct pnv_ioda_pe * __devinit __pnv_ioda_get_one_pe(struct pci_dev *dev)
                return NULL;
        return &phb->ioda.pe_array[pdn->pe_number];
 }
-
-static struct pnv_ioda_pe * __devinit pnv_ioda_get_pe(struct pci_dev *dev)
-{
-       struct pnv_ioda_pe *pe = __pnv_ioda_get_one_pe(dev);
-
-       while (!pe && dev->bus->self) {
-               dev = dev->bus->self;
-               pe = __pnv_ioda_get_one_pe(dev);
-               if (pe)
-                       pe = pe->bus_pe;
-       }
-       return pe;
-}
 #endif /* CONFIG_PCI_MSI */
 
 static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
@@ -588,7 +134,11 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
                dcomp = OPAL_IGNORE_RID_DEVICE_NUMBER;
                fcomp = OPAL_IGNORE_RID_FUNCTION_NUMBER;
                parent = pe->pbus->self;
-               count = pe->pbus->busn_res.end - pe->pbus->busn_res.start + 1;
+               if (pe->flags & PNV_IODA_PE_BUS_ALL)
+                       count = pe->pbus->busn_res.end - pe->pbus->busn_res.start + 1;
+               else
+                       count = 1;
+
                switch(count) {
                case  1: bcomp = OpalPciBusAll;         break;
                case  2: bcomp = OpalPciBus7Bits;       break;
@@ -665,13 +215,13 @@ static void __devinit pnv_ioda_link_pe_by_weight(struct pnv_phb *phb,
 {
        struct pnv_ioda_pe *lpe;
 
-       list_for_each_entry(lpe, &phb->ioda.pe_list, link) {
+       list_for_each_entry(lpe, &phb->ioda.pe_dma_list, dma_link) {
                if (lpe->dma_weight < pe->dma_weight) {
-                       list_add_tail(&pe->link, &lpe->link);
+                       list_add_tail(&pe->dma_link, &lpe->dma_link);
                        return;
                }
        }
-       list_add_tail(&pe->link, &phb->ioda.pe_list);
+       list_add_tail(&pe->dma_link, &phb->ioda.pe_dma_list);
 }
 
 static unsigned int pnv_ioda_dma_weight(struct pci_dev *dev)
@@ -698,6 +248,7 @@ static unsigned int pnv_ioda_dma_weight(struct pci_dev *dev)
        return 10;
 }
 
+#if 0
 static struct pnv_ioda_pe * __devinit pnv_ioda_setup_dev_PE(struct pci_dev *dev)
 {
        struct pci_controller *hose = pci_bus_to_host(dev->bus);
@@ -766,6 +317,7 @@ static struct pnv_ioda_pe * __devinit pnv_ioda_setup_dev_PE(struct pci_dev *dev)
 
        return pe;
 }
+#endif /* Useful for SRIOV case */
 
 static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe)
 {
@@ -783,34 +335,33 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe)
                pdn->pcidev = dev;
                pdn->pe_number = pe->pe_number;
                pe->dma_weight += pnv_ioda_dma_weight(dev);
-               if (dev->subordinate)
+               if ((pe->flags & PNV_IODA_PE_BUS_ALL) && dev->subordinate)
                        pnv_ioda_setup_same_PE(dev->subordinate, pe);
        }
 }
 
-static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
-                                           struct pnv_ioda_pe *ppe)
+/*
+ * There're 2 types of PCI bus sensitive PEs: One that is compromised of
+ * single PCI bus. Another one that contains the primary PCI bus and its
+ * subordinate PCI devices and buses. The second type of PE is normally
+ * orgiriated by PCIe-to-PCI bridge or PLX switch downstream ports.
+ */
+static void __devinit pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all)
 {
-       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+       struct pci_controller *hose = pci_bus_to_host(bus);
        struct pnv_phb *phb = hose->private_data;
-       struct pci_bus *bus = dev->subordinate;
        struct pnv_ioda_pe *pe;
        int pe_num;
 
-       if (!bus) {
-               pr_warning("%s: Bridge without a subordinate bus !\n",
-                          pci_name(dev));
-               return;
-       }
        pe_num = pnv_ioda_alloc_pe(phb);
        if (pe_num == IODA_INVALID_PE) {
-               pr_warning("%s: Not enough PE# available, disabling bus\n",
-                          pci_name(dev));
+               pr_warning("%s: Not enough PE# available for PCI bus %04x:%02x\n",
+                       __func__, pci_domain_nr(bus), bus->number);
                return;
        }
 
        pe = &phb->ioda.pe_array[pe_num];
-       ppe->bus_pe = pe;
+       pe->flags = (all ? PNV_IODA_PE_BUS_ALL : PNV_IODA_PE_BUS);
        pe->pbus = bus;
        pe->pdev = NULL;
        pe->tce32_seg = -1;
@@ -818,8 +369,12 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
        pe->rid = bus->busn_res.start << 8;
        pe->dma_weight = 0;
 
-       pe_info(pe, "Secondary busses %pR associated with PE\n",
-               &bus->busn_res);
+       if (all)
+               pe_info(pe, "Secondary bus %d..%d associated with PE#%d\n",
+                       bus->busn_res.start, bus->busn_res.end, pe_num);
+       else
+               pe_info(pe, "Secondary bus %d associated with PE#%d\n",
+                       bus->busn_res.start, pe_num);
 
        if (pnv_ioda_configure_pe(phb, pe)) {
                /* XXX What do we do here ? */
@@ -832,6 +387,9 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
        /* Associate it with all child devices */
        pnv_ioda_setup_same_PE(bus, pe);
 
+       /* Put PE to the list */
+       list_add_tail(&pe->list, &phb->ioda.pe_list);
+
        /* Account for one DMA PE if at least one DMA capable device exist
         * below the bridge
         */
@@ -847,17 +405,33 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
 static void __devinit pnv_ioda_setup_PEs(struct pci_bus *bus)
 {
        struct pci_dev *dev;
-       struct pnv_ioda_pe *pe;
+
+       pnv_ioda_setup_bus_PE(bus, 0);
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
-               pe = pnv_ioda_setup_dev_PE(dev);
-               if (pe == NULL)
-                       continue;
-               /* Leaving the PCIe domain ... single PE# */
-               if (dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
-                       pnv_ioda_setup_bus_PE(dev, pe);
-               else if (dev->subordinate)
-                       pnv_ioda_setup_PEs(dev->subordinate);
+               if (dev->subordinate) {
+                       if (pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE)
+                               pnv_ioda_setup_bus_PE(dev->subordinate, 1);
+                       else
+                               pnv_ioda_setup_PEs(dev->subordinate);
+               }
+       }
+}
+
+/*
+ * Configure PEs so that the downstream PCI buses and devices
+ * could have their associated PE#. Unfortunately, we didn't
+ * figure out the way to identify the PLX bridge yet. So we
+ * simply put the PCI bus and the subordinate behind the root
+ * port to PE# here. The game rule here is expected to be changed
+ * as soon as we can detected PLX bridge correctly.
+ */
+static void __devinit pnv_pci_ioda_setup_PEs(void)
+{
+       struct pci_controller *hose, *tmp;
+
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+               pnv_ioda_setup_PEs(hose->bus);
        }
 }
 
@@ -999,7 +573,7 @@ static void __devinit pnv_ioda_setup_dma(struct pnv_phb *phb)
        remaining = phb->ioda.tce32_count;
        tw = phb->ioda.dma_weight;
        base = 0;
-       list_for_each_entry(pe, &phb->ioda.pe_list, link) {
+       list_for_each_entry(pe, &phb->ioda.pe_dma_list, dma_link) {
                if (!pe->dma_weight)
                        continue;
                if (!remaining) {
@@ -1108,34 +682,151 @@ static void pnv_pci_init_ioda_msis(struct pnv_phb *phb)
 static void pnv_pci_init_ioda_msis(struct pnv_phb *phb) { }
 #endif /* CONFIG_PCI_MSI */
 
-/* This is the starting point of our IODA specific resource
- * allocation process
+/*
+ * This function is supposed to be called on basis of PE from top
+ * to bottom style. So the the I/O or MMIO segment assigned to
+ * parent PE could be overrided by its child PEs if necessary.
  */
-static void __devinit pnv_pci_ioda_fixup_phb(struct pci_controller *hose)
+static void __devinit pnv_ioda_setup_pe_seg(struct pci_controller *hose,
+                               struct pnv_ioda_pe *pe)
 {
-       resource_size_t size, align;
-       struct pci_bus *child;
+       struct pnv_phb *phb = hose->private_data;
+       struct pci_bus_region region;
+       struct resource *res;
+       int i, index;
+       int rc;
 
-       /* Associate PEs per functions */
-       pnv_ioda_setup_PEs(hose->bus);
+       /*
+        * NOTE: We only care PCI bus based PE for now. For PCI
+        * device based PE, for example SRIOV sensitive VF should
+        * be figured out later.
+        */
+       BUG_ON(!(pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL)));
+
+       pci_bus_for_each_resource(pe->pbus, res, i) {
+               if (!res || !res->flags ||
+                   res->start > res->end)
+                       continue;
+
+               if (res->flags & IORESOURCE_IO) {
+                       region.start = res->start - phb->ioda.io_pci_base;
+                       region.end   = res->end - phb->ioda.io_pci_base;
+                       index = region.start / phb->ioda.io_segsize;
+
+                       while (index < phb->ioda.total_pe &&
+                              region.start <= region.end) {
+                               phb->ioda.io_segmap[index] = pe->pe_number;
+                               rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+                                       pe->pe_number, OPAL_IO_WINDOW_TYPE, 0, index);
+                               if (rc != OPAL_SUCCESS) {
+                                       pr_err("%s: OPAL error %d when mapping IO "
+                                              "segment #%d to PE#%d\n",
+                                              __func__, rc, index, pe->pe_number);
+                                       break;
+                               }
+
+                               region.start += phb->ioda.io_segsize;
+                               index++;
+                       }
+               } else if (res->flags & IORESOURCE_MEM) {
+                       region.start = res->start -
+                                      hose->pci_mem_offset -
+                                      phb->ioda.m32_pci_base;
+                       region.end   = res->end -
+                                      hose->pci_mem_offset -
+                                      phb->ioda.m32_pci_base;
+                       index = region.start / phb->ioda.m32_segsize;
+
+                       while (index < phb->ioda.total_pe &&
+                              region.start <= region.end) {
+                               phb->ioda.m32_segmap[index] = pe->pe_number;
+                               rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+                                       pe->pe_number, OPAL_M32_WINDOW_TYPE, 0, index);
+                               if (rc != OPAL_SUCCESS) {
+                                       pr_err("%s: OPAL error %d when mapping M32 "
+                                              "segment#%d to PE#%d",
+                                              __func__, rc, index, pe->pe_number);
+                                       break;
+                               }
+
+                               region.start += phb->ioda.m32_segsize;
+                               index++;
+                       }
+               }
+       }
+}
 
-       /* Calculate all resources */
-       pnv_ioda_calc_bus(hose->bus, IORESOURCE_IO, &size, &align);
-       pnv_ioda_calc_bus(hose->bus, IORESOURCE_MEM, &size, &align);
+static void __devinit pnv_pci_ioda_setup_seg(void)
+{
+       struct pci_controller *tmp, *hose;
+       struct pnv_phb *phb;
+       struct pnv_ioda_pe *pe;
 
-       /* Apply then to HW */
-       pnv_ioda_update_resources(hose->bus);
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+               phb = hose->private_data;
+               list_for_each_entry(pe, &phb->ioda.pe_list, list) {
+                       pnv_ioda_setup_pe_seg(hose, pe);
+               }
+       }
+}
 
-       /* Setup DMA */
-       pnv_ioda_setup_dma(hose->private_data);
+static void __devinit pnv_pci_ioda_setup_DMA(void)
+{
+       struct pci_controller *hose, *tmp;
+       struct pnv_phb *phb;
 
-       /* Configure PCI Express settings */
-       list_for_each_entry(child, &hose->bus->children, node) {
-               struct pci_dev *self = child->self;
-               if (!self)
-                       continue;
-               pcie_bus_configure_settings(child, self->pcie_mpss);
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+               pnv_ioda_setup_dma(hose->private_data);
+
+               /* Mark the PHB initialization done */
+               phb = hose->private_data;
+               phb->initialized = 1;
+       }
+}
+
+static void __devinit pnv_pci_ioda_fixup(void)
+{
+       pnv_pci_ioda_setup_PEs();
+       pnv_pci_ioda_setup_seg();
+       pnv_pci_ioda_setup_DMA();
+}
+
+/*
+ * Returns the alignment for I/O or memory windows for P2P
+ * bridges. That actually depends on how PEs are segmented.
+ * For now, we return I/O or M32 segment size for PE sensitive
+ * P2P bridges. Otherwise, the default values (4KiB for I/O,
+ * 1MiB for memory) will be returned.
+ *
+ * The current PCI bus might be put into one PE, which was
+ * create against the parent PCI bridge. For that case, we
+ * needn't enlarge the alignment so that we can save some
+ * resources.
+ */
+static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus,
+                                               unsigned long type)
+{
+       struct pci_dev *bridge;
+       struct pci_controller *hose = pci_bus_to_host(bus);
+       struct pnv_phb *phb = hose->private_data;
+       int num_pci_bridges = 0;
+
+       bridge = bus->self;
+       while (bridge) {
+               if (pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE) {
+                       num_pci_bridges++;
+                       if (num_pci_bridges >= 2)
+                               return 1;
+               }
+
+               bridge = bridge->bus->self;
        }
+
+       /* We need support prefetchable memory window later */
+       if (type & IORESOURCE_MEM)
+               return phb->ioda.m32_segsize;
+
+       return phb->ioda.io_segsize;
 }
 
 /* Prevent enabling devices for which we couldn't properly
@@ -1143,10 +834,22 @@ static void __devinit pnv_pci_ioda_fixup_phb(struct pci_controller *hose)
  */
 static int __devinit pnv_pci_enable_device_hook(struct pci_dev *dev)
 {
-       struct pci_dn *pdn = pnv_ioda_get_pdn(dev);
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+       struct pnv_phb *phb = hose->private_data;
+       struct pci_dn *pdn;
+
+       /* The function is probably called while the PEs have
+        * not be created yet. For example, resource reassignment
+        * during PCI probe period. We just skip the check if
+        * PEs isn't ready.
+        */
+       if (!phb->initialized)
+               return 0;
 
+       pdn = pnv_ioda_get_pdn(dev);
        if (!pdn || pdn->pe_number == IODA_INVALID_PE)
                return -EINVAL;
+
        return 0;
 }
 
@@ -1237,9 +940,9 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
        /* Allocate aux data & arrays */
        size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long));
        m32map_off = size;
-       size += phb->ioda.total_pe;
+       size += phb->ioda.total_pe * sizeof(phb->ioda.m32_segmap[0]);
        iomap_off = size;
-       size += phb->ioda.total_pe;
+       size += phb->ioda.total_pe * sizeof(phb->ioda.io_segmap[0]);
        pemap_off = size;
        size += phb->ioda.total_pe * sizeof(struct pnv_ioda_pe);
        aux = alloc_bootmem(size);
@@ -1250,6 +953,7 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
        phb->ioda.pe_array = aux + pemap_off;
        set_bit(0, phb->ioda.pe_alloc);
 
+       INIT_LIST_HEAD(&phb->ioda.pe_dma_list);
        INIT_LIST_HEAD(&phb->ioda.pe_list);
 
        /* Calculate how many 32-bit TCE segments we have */
@@ -1298,14 +1002,17 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
        /* Setup MSI support */
        pnv_pci_init_ioda_msis(phb);
 
-       /* We set both PCI_PROBE_ONLY and PCI_REASSIGN_ALL_RSRC. This is an
-        * odd combination which essentially means that we skip all resource
-        * fixups and assignments in the generic code, and do it all
-        * ourselves here
+       /*
+        * We pass the PCI probe flag PCI_REASSIGN_ALL_RSRC here
+        * to let the PCI core do resource assignment. It's supposed
+        * that the PCI core will do correct I/O and MMIO alignment
+        * for the P2P bridge bars so that each PCI bus (excluding
+        * the child P2P bridges) can form individual PE.
         */
-       ppc_md.pcibios_fixup_phb = pnv_pci_ioda_fixup_phb;
+       ppc_md.pcibios_fixup = pnv_pci_ioda_fixup;
        ppc_md.pcibios_enable_device_hook = pnv_pci_enable_device_hook;
-       pci_add_flags(PCI_PROBE_ONLY | PCI_REASSIGN_ALL_RSRC);
+       ppc_md.pcibios_window_alignment = pnv_pci_window_alignment;
+       pci_add_flags(PCI_REASSIGN_ALL_RSRC);
 
        /* Reset IODA tables to a clean state */
        rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_TABLE_RESET, OPAL_ASSERT_RESET);
index 8bc4796..7cfb7c8 100644 (file)
@@ -17,9 +17,14 @@ enum pnv_phb_model {
 };
 
 #define PNV_PCI_DIAG_BUF_SIZE  4096
+#define PNV_IODA_PE_DEV                (1 << 0)        /* PE has single PCI device     */
+#define PNV_IODA_PE_BUS                (1 << 1)        /* PE has primary PCI bus       */
+#define PNV_IODA_PE_BUS_ALL    (1 << 2)        /* PE has subordinate buses     */
 
 /* Data associated with a PE, including IOMMU tracking etc.. */
 struct pnv_ioda_pe {
+       unsigned long           flags;
+
        /* A PE can be associated with a single device or an
         * entire bus (& children). In the former case, pdev
         * is populated, in the later case, pbus is.
@@ -40,11 +45,6 @@ struct pnv_ioda_pe {
         */
        unsigned int            dma_weight;
 
-       /* This is a PCI-E -> PCI-X bridge, this points to the
-        * corresponding bus PE
-        */
-       struct pnv_ioda_pe      *bus_pe;
-
        /* "Base" iommu table, ie, 4K TCEs, 32-bit DMA */
        int                     tce32_seg;
        int                     tce32_segcount;
@@ -59,7 +59,8 @@ struct pnv_ioda_pe {
        int                     mve_number;
 
        /* Link in list of PE#s */
-       struct list_head        link;
+       struct list_head        dma_link;
+       struct list_head        list;
 };
 
 struct pnv_phb {
@@ -68,6 +69,7 @@ struct pnv_phb {
        enum pnv_phb_model      model;
        u64                     opal_id;
        void __iomem            *regs;
+       int                     initialized;
        spinlock_t              lock;
 
 #ifdef CONFIG_PCI_MSI
@@ -107,6 +109,11 @@ struct pnv_phb {
                        unsigned int            *io_segmap;
                        struct pnv_ioda_pe      *pe_array;
 
+                       /* Sorted list of used PE's based
+                        * on the sequence of creation
+                        */
+                       struct list_head        pe_list;
+
                        /* Reverse map of PEs, will have to extend if
                         * we are to support more than 256 PEs, indexed
                         * bus { bus, devfn }
@@ -125,7 +132,7 @@ struct pnv_phb {
                        /* Sorted list of used PE's, sorted at
                         * boot for resource allocation purposes
                         */
-                       struct list_head        pe_list;
+                       struct list_head        pe_dma_list;
                } ioda;
        };
 
index 3124cf7..d00d7b0 100644 (file)
@@ -43,7 +43,7 @@ enum ps3_lpar_vas_id {
 
 static DEFINE_SPINLOCK(ps3_htab_lock);
 
-static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
+static long ps3_hpte_insert(unsigned long hpte_group, unsigned long vpn,
        unsigned long pa, unsigned long rflags, unsigned long vflags,
        int psize, int ssize)
 {
@@ -61,7 +61,7 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
         */
        vflags &= ~HPTE_V_SECONDARY;
 
-       hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
+       hpte_v = hpte_encode_v(vpn, psize, ssize) | vflags | HPTE_V_VALID;
        hpte_r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize) | rflags;
 
        spin_lock_irqsave(&ps3_htab_lock, flags);
@@ -75,8 +75,8 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
 
        if (result) {
                /* all entries bolted !*/
-               pr_info("%s:result=%d va=%lx pa=%lx ix=%lx v=%llx r=%llx\n",
-                       __func__, result, va, pa, hpte_group, hpte_v, hpte_r);
+               pr_info("%s:result=%d vpn=%lx pa=%lx ix=%lx v=%llx r=%llx\n",
+                       __func__, result, vpn, pa, hpte_group, hpte_v, hpte_r);
                BUG();
        }
 
@@ -107,7 +107,7 @@ static long ps3_hpte_remove(unsigned long hpte_group)
 }
 
 static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
-       unsigned long va, int psize, int ssize, int local)
+       unsigned long vpn, int psize, int ssize, int local)
 {
        int result;
        u64 hpte_v, want_v, hpte_rs;
@@ -115,7 +115,7 @@ static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
        unsigned long flags;
        long ret;
 
-       want_v = hpte_encode_v(va, psize, ssize);
+       want_v = hpte_encode_v(vpn, psize, ssize);
 
        spin_lock_irqsave(&ps3_htab_lock, flags);
 
@@ -125,8 +125,8 @@ static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
                                       &hpte_rs);
 
        if (result) {
-               pr_info("%s: res=%d read va=%lx slot=%lx psize=%d\n",
-                       __func__, result, va, slot, psize);
+               pr_info("%s: res=%d read vpn=%lx slot=%lx psize=%d\n",
+                       __func__, result, vpn, slot, psize);
                BUG();
        }
 
@@ -159,7 +159,7 @@ static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
        panic("ps3_hpte_updateboltedpp() not implemented");
 }
 
-static void ps3_hpte_invalidate(unsigned long slot, unsigned long va,
+static void ps3_hpte_invalidate(unsigned long slot, unsigned long vpn,
        int psize, int ssize, int local)
 {
        unsigned long flags;
@@ -170,8 +170,8 @@ static void ps3_hpte_invalidate(unsigned long slot, unsigned long va,
        result = lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT, slot, 0, 0);
 
        if (result) {
-               pr_info("%s: res=%d va=%lx slot=%lx psize=%d\n",
-                       __func__, result, va, slot, psize);
+               pr_info("%s: res=%d vpn=%lx slot=%lx psize=%d\n",
+                       __func__, result, vpn, slot, psize);
                BUG();
        }
 
index 18c168b..9a04322 100644 (file)
@@ -728,7 +728,7 @@ static void eeh_add_device_early(struct device_node *dn)
 {
        struct pci_controller *phb;
 
-       if (!dn || !of_node_to_eeh_dev(dn))
+       if (!of_node_to_eeh_dev(dn))
                return;
        phb = of_node_to_eeh_dev(dn)->phb;
 
@@ -817,6 +817,7 @@ EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
 /**
  * eeh_remove_device - Undo EEH setup for the indicated pci device
  * @dev: pci device to be removed
+ * @purge_pe: remove the PE or not
  *
  * This routine should be called when a device is removed from
  * a running system (e.g. by hotplug or dlpar).  It unregisters
@@ -824,7 +825,7 @@ EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
  * this device will no longer be detected after this call; thus,
  * i/o errors affecting this slot may leave this device unusable.
  */
-static void eeh_remove_device(struct pci_dev *dev)
+static void eeh_remove_device(struct pci_dev *dev, int purge_pe)
 {
        struct eeh_dev *edev;
 
@@ -843,7 +844,7 @@ static void eeh_remove_device(struct pci_dev *dev)
        dev->dev.archdata.edev = NULL;
        pci_dev_put(dev);
 
-       eeh_rmv_from_parent_pe(edev);
+       eeh_rmv_from_parent_pe(edev, purge_pe);
        eeh_addr_cache_rmv_dev(dev);
        eeh_sysfs_remove_device(dev);
 }
@@ -851,21 +852,22 @@ static void eeh_remove_device(struct pci_dev *dev)
 /**
  * eeh_remove_bus_device - Undo EEH setup for the indicated PCI device
  * @dev: PCI device
+ * @purge_pe: remove the corresponding PE or not
  *
  * This routine must be called when a device is removed from the
  * running system through hotplug or dlpar. The corresponding
  * PCI address cache will be removed.
  */
-void eeh_remove_bus_device(struct pci_dev *dev)
+void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe)
 {
        struct pci_bus *bus = dev->subordinate;
        struct pci_dev *child, *tmp;
 
-       eeh_remove_device(dev);
+       eeh_remove_device(dev, purge_pe);
 
        if (bus && dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
                list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
-                        eeh_remove_bus_device(child);
+                        eeh_remove_bus_device(child, purge_pe);
        }
 }
 EXPORT_SYMBOL_GPL(eeh_remove_bus_device);
index 8370ce7..a3fefb6 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <asm/eeh.h>
 #include <asm/eeh_event.h>
@@ -47,6 +48,41 @@ static inline const char *eeh_pcid_name(struct pci_dev *pdev)
        return "";
 }
 
+/**
+ * eeh_pcid_get - Get the PCI device driver
+ * @pdev: PCI device
+ *
+ * The function is used to retrieve the PCI device driver for
+ * the indicated PCI device. Besides, we will increase the reference
+ * of the PCI device driver to prevent that being unloaded on
+ * the fly. Otherwise, kernel crash would be seen.
+ */
+static inline struct pci_driver *eeh_pcid_get(struct pci_dev *pdev)
+{
+       if (!pdev || !pdev->driver)
+               return NULL;
+
+       if (!try_module_get(pdev->driver->driver.owner))
+               return NULL;
+
+       return pdev->driver;
+}
+
+/**
+ * eeh_pcid_put - Dereference on the PCI device driver
+ * @pdev: PCI device
+ *
+ * The function is called to do dereference on the PCI device
+ * driver of the indicated PCI device.
+ */
+static inline void eeh_pcid_put(struct pci_dev *pdev)
+{
+       if (!pdev || !pdev->driver)
+               return;
+
+       module_put(pdev->driver->driver.owner);
+}
+
 #if 0
 static void print_device_node_tree(struct pci_dn *pdn, int dent)
 {
@@ -128,23 +164,24 @@ static void *eeh_report_error(void *data, void *userdata)
        struct eeh_dev *edev = (struct eeh_dev *)data;
        struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
        enum pci_ers_result rc, *res = userdata;
-       struct pci_driver *driver = dev->driver;
+       struct pci_driver *driver;
 
        /* We might not have the associated PCI device,
         * then we should continue for next one.
         */
        if (!dev) return NULL;
-
        dev->error_state = pci_channel_io_frozen;
 
-       if (!driver)
-               return NULL;
+       driver = eeh_pcid_get(dev);
+       if (!driver) return NULL;
 
        eeh_disable_irq(dev);
 
        if (!driver->err_handler ||
-           !driver->err_handler->error_detected)
+           !driver->err_handler->error_detected) {
+               eeh_pcid_put(dev);
                return NULL;
+       }
 
        rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen);
 
@@ -152,6 +189,7 @@ static void *eeh_report_error(void *data, void *userdata)
        if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
        if (*res == PCI_ERS_RESULT_NONE) *res = rc;
 
+       eeh_pcid_put(dev);
        return NULL;
 }
 
@@ -171,12 +209,14 @@ static void *eeh_report_mmio_enabled(void *data, void *userdata)
        enum pci_ers_result rc, *res = userdata;
        struct pci_driver *driver;
 
-       if (!dev) return NULL;
+       driver = eeh_pcid_get(dev);
+       if (!driver) return NULL;
 
-       if (!(driver = dev->driver) ||
-           !driver->err_handler ||
-           !driver->err_handler->mmio_enabled)
+       if (!driver->err_handler ||
+           !driver->err_handler->mmio_enabled) {
+               eeh_pcid_put(dev);
                return NULL;
+       }
 
        rc = driver->err_handler->mmio_enabled(dev);
 
@@ -184,6 +224,7 @@ static void *eeh_report_mmio_enabled(void *data, void *userdata)
        if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
        if (*res == PCI_ERS_RESULT_NONE) *res = rc;
 
+       eeh_pcid_put(dev);
        return NULL;
 }
 
@@ -204,16 +245,19 @@ static void *eeh_report_reset(void *data, void *userdata)
        enum pci_ers_result rc, *res = userdata;
        struct pci_driver *driver;
 
-       if (!dev || !(driver = dev->driver))
-               return NULL;
-
+       if (!dev) return NULL;
        dev->error_state = pci_channel_io_normal;
 
+       driver = eeh_pcid_get(dev);
+       if (!driver) return NULL;
+
        eeh_enable_irq(dev);
 
        if (!driver->err_handler ||
-           !driver->err_handler->slot_reset)
+           !driver->err_handler->slot_reset) {
+               eeh_pcid_put(dev);
                return NULL;
+       }
 
        rc = driver->err_handler->slot_reset(dev);
        if ((*res == PCI_ERS_RESULT_NONE) ||
@@ -221,6 +265,7 @@ static void *eeh_report_reset(void *data, void *userdata)
        if (*res == PCI_ERS_RESULT_DISCONNECT &&
             rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
 
+       eeh_pcid_put(dev);
        return NULL;
 }
 
@@ -240,20 +285,22 @@ static void *eeh_report_resume(void *data, void *userdata)
        struct pci_driver *driver;
 
        if (!dev) return NULL;
-
        dev->error_state = pci_channel_io_normal;
 
-       if (!(driver = dev->driver))
-               return NULL;
+       driver = eeh_pcid_get(dev);
+       if (!driver) return NULL;
 
        eeh_enable_irq(dev);
 
        if (!driver->err_handler ||
-           !driver->err_handler->resume)
+           !driver->err_handler->resume) {
+               eeh_pcid_put(dev);
                return NULL;
+       }
 
        driver->err_handler->resume(dev);
 
+       eeh_pcid_put(dev);
        return NULL;
 }
 
@@ -272,20 +319,22 @@ static void *eeh_report_failure(void *data, void *userdata)
        struct pci_driver *driver;
 
        if (!dev) return NULL;
-
        dev->error_state = pci_channel_io_perm_failure;
 
-       if (!(driver = dev->driver))
-               return NULL;
+       driver = eeh_pcid_get(dev);
+       if (!driver) return NULL;
 
        eeh_disable_irq(dev);
 
        if (!driver->err_handler ||
-           !driver->err_handler->error_detected)
+           !driver->err_handler->error_detected) {
+               eeh_pcid_put(dev);
                return NULL;
+       }
 
        driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
 
+       eeh_pcid_put(dev);
        return NULL;
 }
 
@@ -305,8 +354,14 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
        /* pcibios will clear the counter; save the value */
        cnt = pe->freeze_count;
 
+       /*
+        * We don't remove the corresponding PE instances because
+        * we need the information afterwords. The attached EEH
+        * devices are expected to be attached soon when calling
+        * into pcibios_add_pci_devices().
+        */
        if (bus)
-               pcibios_remove_pci_devices(bus);
+               __pcibios_remove_pci_devices(bus, 0);
 
        /* Reset the pci controller. (Asserts RST#; resets config space).
         * Reconfigure bridges and devices. Don't try to bring the system
index 904123c..9d35543 100644 (file)
@@ -99,23 +99,19 @@ static struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb)
 {
        struct eeh_pe *pe;
 
-       eeh_lock();
-
        list_for_each_entry(pe, &eeh_phb_pe, child) {
                /*
                 * Actually, we needn't check the type since
                 * the PE for PHB has been determined when that
                 * was created.
                 */
-               if (pe->type == EEH_PE_PHB &&
+               if ((pe->type & EEH_PE_PHB) &&
                    pe->phb == phb) {
                        eeh_unlock();
                        return pe;
                }
        }
 
-       eeh_unlock();
-
        return NULL;
 }
 
@@ -192,14 +188,21 @@ void *eeh_pe_dev_traverse(struct eeh_pe *root,
                return NULL;
        }
 
+       eeh_lock();
+
        /* Traverse root PE */
        for (pe = root; pe; pe = eeh_pe_next(pe, root)) {
                eeh_pe_for_each_dev(pe, edev) {
                        ret = fn(edev, flag);
-                       if (ret) return ret;
+                       if (ret) {
+                               eeh_unlock();
+                               return ret;
+                       }
                }
        }
 
+       eeh_unlock();
+
        return NULL;
 }
 
@@ -219,7 +222,7 @@ static void *__eeh_pe_get(void *data, void *flag)
        struct eeh_dev *edev = (struct eeh_dev *)flag;
 
        /* Unexpected PHB PE */
-       if (pe->type == EEH_PE_PHB)
+       if (pe->type & EEH_PE_PHB)
                return NULL;
 
        /* We prefer PE address */
@@ -251,9 +254,7 @@ static struct eeh_pe *eeh_pe_get(struct eeh_dev *edev)
        struct eeh_pe *root = eeh_phb_pe_get(edev->phb);
        struct eeh_pe *pe;
 
-       eeh_lock();
        pe = eeh_pe_traverse(root, __eeh_pe_get, edev);
-       eeh_unlock();
 
        return pe;
 }
@@ -307,6 +308,8 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
 {
        struct eeh_pe *pe, *parent;
 
+       eeh_lock();
+
        /*
         * Search the PE has been existing or not according
         * to the PE address. If that has been existing, the
@@ -314,8 +317,9 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
         * components.
         */
        pe = eeh_pe_get(edev);
-       if (pe) {
+       if (pe && !(pe->type & EEH_PE_INVALID)) {
                if (!edev->pe_config_addr) {
+                       eeh_unlock();
                        pr_err("%s: PE with addr 0x%x already exists\n",
                                __func__, edev->config_addr);
                        return -EEXIST;
@@ -327,15 +331,36 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
 
                /* Put the edev to PE */
                list_add_tail(&edev->list, &pe->edevs);
+               eeh_unlock();
                pr_debug("EEH: Add %s to Bus PE#%x\n",
                        edev->dn->full_name, pe->addr);
 
                return 0;
+       } else if (pe && (pe->type & EEH_PE_INVALID)) {
+               list_add_tail(&edev->list, &pe->edevs);
+               edev->pe = pe;
+               /*
+                * We're running to here because of PCI hotplug caused by
+                * EEH recovery. We need clear EEH_PE_INVALID until the top.
+                */
+               parent = pe;
+               while (parent) {
+                       if (!(parent->type & EEH_PE_INVALID))
+                               break;
+                       parent->type &= ~EEH_PE_INVALID;
+                       parent = parent->parent;
+               }
+               eeh_unlock();
+               pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
+                       edev->dn->full_name, pe->addr, pe->parent->addr);
+
+               return 0;
        }
 
        /* Create a new EEH PE */
        pe = eeh_pe_alloc(edev->phb, EEH_PE_DEVICE);
        if (!pe) {
+               eeh_unlock();
                pr_err("%s: out of memory!\n", __func__);
                return -ENOMEM;
        }
@@ -352,6 +377,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
        if (!parent) {
                parent = eeh_phb_pe_get(edev->phb);
                if (!parent) {
+                       eeh_unlock();
                        pr_err("%s: No PHB PE is found (PHB Domain=%d)\n",
                                __func__, edev->phb->global_number);
                        edev->pe = NULL;
@@ -368,6 +394,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
        list_add_tail(&pe->child, &parent->child_list);
        list_add_tail(&edev->list, &pe->edevs);
        edev->pe = pe;
+       eeh_unlock();
        pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
                edev->dn->full_name, pe->addr, pe->parent->addr);
 
@@ -377,15 +404,17 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
 /**
  * eeh_rmv_from_parent_pe - Remove one EEH device from the associated PE
  * @edev: EEH device
+ * @purge_pe: remove PE or not
  *
  * The PE hierarchy tree might be changed when doing PCI hotplug.
  * Also, the PCI devices or buses could be removed from the system
  * during EEH recovery. So we have to call the function remove the
  * corresponding PE accordingly if necessary.
  */
-int eeh_rmv_from_parent_pe(struct eeh_dev *edev)
+int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
 {
-       struct eeh_pe *pe, *parent;
+       struct eeh_pe *pe, *parent, *child;
+       int cnt;
 
        if (!edev->pe) {
                pr_warning("%s: No PE found for EEH device %s\n",
@@ -393,6 +422,8 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev)
                return -EEXIST;
        }
 
+       eeh_lock();
+
        /* Remove the EEH device */
        pe = edev->pe;
        edev->pe = NULL;
@@ -406,18 +437,39 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev)
         */
        while (1) {
                parent = pe->parent;
-               if (pe->type == EEH_PE_PHB)
+               if (pe->type & EEH_PE_PHB)
                        break;
 
-               if (list_empty(&pe->edevs) &&
-                   list_empty(&pe->child_list)) {
-                       list_del(&pe->child);
-                       kfree(pe);
+               if (purge_pe) {
+                       if (list_empty(&pe->edevs) &&
+                           list_empty(&pe->child_list)) {
+                               list_del(&pe->child);
+                               kfree(pe);
+                       } else {
+                               break;
+                       }
+               } else {
+                       if (list_empty(&pe->edevs)) {
+                               cnt = 0;
+                               list_for_each_entry(child, &pe->child_list, child) {
+                                       if (!(pe->type & EEH_PE_INVALID)) {
+                                               cnt++;
+                                               break;
+                                       }
+                               }
+
+                               if (!cnt)
+                                       pe->type |= EEH_PE_INVALID;
+                               else
+                                       break;
+                       }
                }
 
                pe = parent;
        }
 
+       eeh_unlock();
+
        return 0;
 }
 
@@ -463,7 +515,9 @@ static void *__eeh_pe_state_mark(void *data, void *flag)
  */
 void eeh_pe_state_mark(struct eeh_pe *pe, int state)
 {
+       eeh_lock();
        eeh_pe_traverse(pe, __eeh_pe_state_mark, &state);
+       eeh_unlock();
 }
 
 /**
@@ -497,7 +551,9 @@ static void *__eeh_pe_state_clear(void *data, void *flag)
  */
 void eeh_pe_state_clear(struct eeh_pe *pe, int state)
 {
+       eeh_lock();
        eeh_pe_traverse(pe, __eeh_pe_state_clear, &state);
+       eeh_unlock();
 }
 
 /**
@@ -559,6 +615,10 @@ static void *eeh_restore_one_device_bars(void *data, void *flag)
  */
 void eeh_pe_restore_bars(struct eeh_pe *pe)
 {
+       /*
+        * We needn't take the EEH lock since eeh_pe_dev_traverse()
+        * will take that.
+        */
        eeh_pe_dev_traverse(pe, eeh_restore_one_device_bars, NULL);
 }
 
@@ -578,14 +638,18 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
        struct eeh_dev *edev;
        struct pci_dev *pdev;
 
-       if (pe->type == EEH_PE_PHB) {
+       eeh_lock();
+
+       if (pe->type & EEH_PE_PHB) {
                bus = pe->phb->bus;
-       } else if (pe->type == EEH_PE_BUS) {
+       } else if (pe->type & EEH_PE_BUS) {
                edev = list_first_entry(&pe->edevs, struct eeh_dev, list);
                pdev = eeh_dev_to_pci_dev(edev);
                if (pdev)
                        bus = pdev->bus;
        }
 
+       eeh_unlock();
+
        return bus;
 }
index 177055d..0da39fe 100644 (file)
@@ -107,9 +107,9 @@ void vpa_init(int cpu)
 }
 
 static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
-                             unsigned long va, unsigned long pa,
-                             unsigned long rflags, unsigned long vflags,
-                             int psize, int ssize)
+                                    unsigned long vpn, unsigned long pa,
+                                    unsigned long rflags, unsigned long vflags,
+                                    int psize, int ssize)
 {
        unsigned long lpar_rc;
        unsigned long flags;
@@ -117,11 +117,11 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
        unsigned long hpte_v, hpte_r;
 
        if (!(vflags & HPTE_V_BOLTED))
-               pr_devel("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
-                        "rflags=%lx, vflags=%lx, psize=%d)\n",
-                        hpte_group, va, pa, rflags, vflags, psize);
+               pr_devel("hpte_insert(group=%lx, vpn=%016lx, "
+                        "pa=%016lx, rflags=%lx, vflags=%lx, psize=%d)\n",
+                        hpte_group, vpn,  pa, rflags, vflags, psize);
 
-       hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
+       hpte_v = hpte_encode_v(vpn, psize, ssize) | vflags | HPTE_V_VALID;
        hpte_r = hpte_encode_r(pa, psize) | rflags;
 
        if (!(vflags & HPTE_V_BOLTED))
@@ -226,22 +226,6 @@ static void pSeries_lpar_hptab_clear(void)
 }
 
 /*
- * This computes the AVPN and B fields of the first dword of a HPTE,
- * for use when we want to match an existing PTE.  The bottom 7 bits
- * of the returned value are zero.
- */
-static inline unsigned long hpte_encode_avpn(unsigned long va, int psize,
-                                            int ssize)
-{
-       unsigned long v;
-
-       v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
-       v <<= HPTE_V_AVPN_SHIFT;
-       v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
-       return v;
-}
-
-/*
  * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
  * the low 3 bits of flags happen to line up.  So no transform is needed.
  * We can probably optimize here and assume the high bits of newpp are
@@ -249,14 +233,14 @@ static inline unsigned long hpte_encode_avpn(unsigned long va, int psize,
  */
 static long pSeries_lpar_hpte_updatepp(unsigned long slot,
                                       unsigned long newpp,
-                                      unsigned long va,
+                                      unsigned long vpn,
                                       int psize, int ssize, int local)
 {
        unsigned long lpar_rc;
        unsigned long flags = (newpp & 7) | H_AVPN;
        unsigned long want_v;
 
-       want_v = hpte_encode_avpn(va, psize, ssize);
+       want_v = hpte_encode_avpn(vpn, psize, ssize);
 
        pr_devel("    update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
                 want_v, slot, flags, psize);
@@ -294,15 +278,15 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
        return dword0;
 }
 
-static long pSeries_lpar_hpte_find(unsigned long va, int psize, int ssize)
+static long pSeries_lpar_hpte_find(unsigned long vpn, int psize, int ssize)
 {
        unsigned long hash;
        unsigned long i;
        long slot;
        unsigned long want_v, hpte_v;
 
-       hash = hpt_hash(va, mmu_psize_defs[psize].shift, ssize);
-       want_v = hpte_encode_avpn(va, psize, ssize);
+       hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, ssize);
+       want_v = hpte_encode_avpn(vpn, psize, ssize);
 
        /* Bolted entries are always in the primary group */
        slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
@@ -322,12 +306,13 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
                                             unsigned long ea,
                                             int psize, int ssize)
 {
-       unsigned long lpar_rc, slot, vsid, va, flags;
+       unsigned long vpn;
+       unsigned long lpar_rc, slot, vsid, flags;
 
        vsid = get_kernel_vsid(ea, ssize);
-       va = hpt_va(ea, vsid, ssize);
+       vpn = hpt_vpn(ea, vsid, ssize);
 
-       slot = pSeries_lpar_hpte_find(va, psize, ssize);
+       slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
        BUG_ON(slot == -1);
 
        flags = newpp & 7;
@@ -336,17 +321,17 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
        BUG_ON(lpar_rc != H_SUCCESS);
 }
 
-static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn,
                                         int psize, int ssize, int local)
 {
        unsigned long want_v;
        unsigned long lpar_rc;
        unsigned long dummy1, dummy2;
 
-       pr_devel("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
-                slot, va, psize, local);
+       pr_devel("    inval : slot=%lx, vpn=%016lx, psize: %d, local: %d\n",
+                slot, vpn, psize, local);
 
-       want_v = hpte_encode_avpn(va, psize, ssize);
+       want_v = hpte_encode_avpn(vpn, psize, ssize);
        lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2);
        if (lpar_rc == H_NOT_FOUND)
                return;
@@ -357,15 +342,16 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
 static void pSeries_lpar_hpte_removebolted(unsigned long ea,
                                           int psize, int ssize)
 {
-       unsigned long slot, vsid, va;
+       unsigned long vpn;
+       unsigned long slot, vsid;
 
        vsid = get_kernel_vsid(ea, ssize);
-       va = hpt_va(ea, vsid, ssize);
+       vpn = hpt_vpn(ea, vsid, ssize);
 
-       slot = pSeries_lpar_hpte_find(va, psize, ssize);
+       slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
        BUG_ON(slot == -1);
 
-       pSeries_lpar_hpte_invalidate(slot, va, psize, ssize, 0);
+       pSeries_lpar_hpte_invalidate(slot, vpn, psize, ssize, 0);
 }
 
 /* Flag bits for H_BULK_REMOVE */
@@ -381,12 +367,12 @@ static void pSeries_lpar_hpte_removebolted(unsigned long ea,
  */
 static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
 {
+       unsigned long vpn;
        unsigned long i, pix, rc;
        unsigned long flags = 0;
        struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
        int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
        unsigned long param[9];
-       unsigned long va;
        unsigned long hash, index, shift, hidx, slot;
        real_pte_t pte;
        int psize, ssize;
@@ -398,21 +384,21 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
        ssize = batch->ssize;
        pix = 0;
        for (i = 0; i < number; i++) {
-               va = batch->vaddr[i];
+               vpn = batch->vpn[i];
                pte = batch->pte[i];
-               pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
-                       hash = hpt_hash(va, shift, ssize);
+               pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
+                       hash = hpt_hash(vpn, shift, ssize);
                        hidx = __rpte_to_hidx(pte, index);
                        if (hidx & _PTEIDX_SECONDARY)
                                hash = ~hash;
                        slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
                        slot += hidx & _PTEIDX_GROUP_IX;
                        if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) {
-                               pSeries_lpar_hpte_invalidate(slot, va, psize,
+                               pSeries_lpar_hpte_invalidate(slot, vpn, psize,
                                                             ssize, local);
                        } else {
                                param[pix] = HBR_REQUEST | HBR_AVPN | slot;
-                               param[pix+1] = hpte_encode_avpn(va, psize,
+                               param[pix+1] = hpte_encode_avpn(vpn, psize,
                                                                ssize);
                                pix += 2;
                                if (pix == 8) {
index 3ccebc8..261a577 100644 (file)
@@ -65,27 +65,43 @@ pcibios_find_pci_bus(struct device_node *dn)
 EXPORT_SYMBOL_GPL(pcibios_find_pci_bus);
 
 /**
- * pcibios_remove_pci_devices - remove all devices under this bus
+ * __pcibios_remove_pci_devices - remove all devices under this bus
+ * @bus: the indicated PCI bus
+ * @purge_pe: destroy the PE on removal of PCI devices
  *
  * Remove all of the PCI devices under this bus both from the
  * linux pci device tree, and from the powerpc EEH address cache.
+ * By default, the corresponding PE will be destroied during the
+ * normal PCI hotplug path. For PCI hotplug during EEH recovery,
+ * the corresponding PE won't be destroied and deallocated.
  */
-void pcibios_remove_pci_devices(struct pci_bus *bus)
+void __pcibios_remove_pci_devices(struct pci_bus *bus, int purge_pe)
 {
-       struct pci_dev *dev, *tmp;
+       struct pci_dev *dev, *tmp;
        struct pci_bus *child_bus;
 
        /* First go down child busses */
        list_for_each_entry(child_bus, &bus->children, node)
-               pcibios_remove_pci_devices(child_bus);
+               __pcibios_remove_pci_devices(child_bus, purge_pe);
 
        pr_debug("PCI: Removing devices on bus %04x:%02x\n",
-                pci_domain_nr(bus),  bus->number);
+               pci_domain_nr(bus),  bus->number);
        list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
                pr_debug("     * Removing %s...\n", pci_name(dev));
-               eeh_remove_bus_device(dev);
-               pci_stop_and_remove_bus_device(dev);
-       }
+               eeh_remove_bus_device(dev, purge_pe);
+               pci_stop_and_remove_bus_device(dev);
+       }
+}
+
+/**
+ * pcibios_remove_pci_devices - remove all devices under this bus
+ *
+ * Remove all of the PCI devices under this bus both from the
+ * linux pci device tree, and from the powerpc EEH address cache.
+ */
+void pcibios_remove_pci_devices(struct pci_bus *bus)
+{
+       __pcibios_remove_pci_devices(bus, 1);
 }
 EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
 
index 987f441..3a56a63 100644 (file)
@@ -60,6 +60,8 @@ static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
 static unsigned long xmon_taken = 1;
 static int xmon_owner;
 static int xmon_gate;
+#else
+#define xmon_owner 0
 #endif /* CONFIG_SMP */
 
 static unsigned long in_xmon __read_mostly = 0;
@@ -202,7 +204,13 @@ Commands:\n\
   di   dump instructions\n\
   df   dump float values\n\
   dd   dump double values\n\
-  dl    dump the kernel log buffer\n\
+  dl    dump the kernel log buffer\n"
+#ifdef CONFIG_PPC64
+  "\
+  dp[#]        dump paca for current cpu, or cpu #\n\
+  dpa  dump paca for all possible cpus\n"
+#endif
+  "\
   dr   dump stream of raw bytes\n\
   e    print exception information\n\
   f    flush cache\n\
@@ -2009,6 +2017,95 @@ static void xmon_rawdump (unsigned long adrs, long ndump)
        printf("\n");
 }
 
+#ifdef CONFIG_PPC64
+static void dump_one_paca(int cpu)
+{
+       struct paca_struct *p;
+
+       if (setjmp(bus_error_jmp) != 0) {
+               printf("*** Error dumping paca for cpu 0x%x!\n", cpu);
+               return;
+       }
+
+       catch_memory_errors = 1;
+       sync();
+
+       p = &paca[cpu];
+
+       printf("paca for cpu 0x%x @ %p:\n", cpu, p);
+
+       printf(" %-*s = %s\n", 16, "possible", cpu_possible(cpu) ? "yes" : "no");
+       printf(" %-*s = %s\n", 16, "present", cpu_present(cpu) ? "yes" : "no");
+       printf(" %-*s = %s\n", 16, "online", cpu_online(cpu) ? "yes" : "no");
+
+#define DUMP(paca, name, format) \
+       printf(" %-*s = %#-*"format"\t(0x%lx)\n", 16, #name, 18, paca->name, \
+               offsetof(struct paca_struct, name));
+
+       DUMP(p, lock_token, "x");
+       DUMP(p, paca_index, "x");
+       DUMP(p, kernel_toc, "lx");
+       DUMP(p, kernelbase, "lx");
+       DUMP(p, kernel_msr, "lx");
+#ifdef CONFIG_PPC_STD_MMU_64
+       DUMP(p, stab_real, "lx");
+       DUMP(p, stab_addr, "lx");
+#endif
+       DUMP(p, emergency_sp, "p");
+       DUMP(p, data_offset, "lx");
+       DUMP(p, hw_cpu_id, "x");
+       DUMP(p, cpu_start, "x");
+       DUMP(p, kexec_state, "x");
+       DUMP(p, __current, "p");
+       DUMP(p, kstack, "lx");
+       DUMP(p, stab_rr, "lx");
+       DUMP(p, saved_r1, "lx");
+       DUMP(p, trap_save, "x");
+       DUMP(p, soft_enabled, "x");
+       DUMP(p, irq_happened, "x");
+       DUMP(p, io_sync, "x");
+       DUMP(p, irq_work_pending, "x");
+       DUMP(p, nap_state_lost, "x");
+
+#undef DUMP
+
+       catch_memory_errors = 0;
+       sync();
+}
+
+static void dump_all_pacas(void)
+{
+       int cpu;
+
+       if (num_possible_cpus() == 0) {
+               printf("No possible cpus, use 'dp #' to dump individual cpus\n");
+               return;
+       }
+
+       for_each_possible_cpu(cpu)
+               dump_one_paca(cpu);
+}
+
+static void dump_pacas(void)
+{
+       unsigned long num;
+       int c;
+
+       c = inchar();
+       if (c == 'a') {
+               dump_all_pacas();
+               return;
+       }
+
+       termch = c;     /* Put c back, it wasn't 'a' */
+
+       if (scanhex(&num))
+               dump_one_paca(num);
+       else
+               dump_one_paca(xmon_owner);
+}
+#endif
+
 #define isxdigit(c)    (('0' <= (c) && (c) <= '9') \
                         || ('a' <= (c) && (c) <= 'f') \
                         || ('A' <= (c) && (c) <= 'F'))
@@ -2018,6 +2115,14 @@ dump(void)
        int c;
 
        c = inchar();
+
+#ifdef CONFIG_PPC64
+       if (c == 'p') {
+               dump_pacas();
+               return;
+       }
+#endif
+
        if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
                termch = c;
        scanhex((void *)&adrs);
index 33c1086..d2292be 100644 (file)
@@ -246,16 +246,13 @@ static void __devinit fixup_read_and_payload_sizes(void)
 
        /* Scan for the smallest maximum payload size. */
        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-               int pcie_caps_offset;
                u32 devcap;
                int max_payload;
 
-               pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP);
-               if (pcie_caps_offset == 0)
+               if (!pci_is_pcie(dev))
                        continue;
 
-               pci_read_config_dword(dev, pcie_caps_offset + PCI_EXP_DEVCAP,
-                                     &devcap);
+               pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &devcap);
                max_payload = devcap & PCI_EXP_DEVCAP_PAYLOAD;
                if (max_payload < smallest_max_payload)
                        smallest_max_payload = max_payload;
@@ -263,21 +260,10 @@ static void __devinit fixup_read_and_payload_sizes(void)
 
        /* Now, set the max_payload_size for all devices to that value. */
        new_values = (max_read_size << 12) | (smallest_max_payload << 5);
-       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-               int pcie_caps_offset;
-               u16 devctl;
-
-               pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP);
-               if (pcie_caps_offset == 0)
-                       continue;
-
-               pci_read_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL,
-                                    &devctl);
-               devctl &= ~(PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ);
-               devctl |= new_values;
-               pci_write_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL,
-                                     devctl);
-       }
+       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
+               pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
+                               PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ,
+                               new_values);
 }
 
 
index f602385..0748fe0 100644 (file)
@@ -114,7 +114,7 @@ static void deliver_alarm(void)
        skew += this_tick - last_tick;
 
        while (skew >= one_tick) {
-               alarm_handler(SIGVTALRM, NULL);
+               alarm_handler(SIGVTALRM, NULL, NULL);
                skew -= one_tick;
        }
 
index b65a761..5141d80 100644 (file)
@@ -1283,7 +1283,7 @@ static void xen_flush_tlb_others(const struct cpumask *cpus,
        cpumask_clear_cpu(smp_processor_id(), to_cpumask(args->mask));
 
        args->op.cmd = MMUEXT_TLB_FLUSH_MULTI;
-       if (start != TLB_FLUSH_ALL && (end - start) <= PAGE_SIZE) {
+       if (end != TLB_FLUSH_ALL && (end - start) <= PAGE_SIZE) {
                args->op.cmd = MMUEXT_INVLPG_MULTI;
                args->op.arg1.linear_addr = start;
        }
index d4b2554..76ba0e9 100644 (file)
@@ -599,7 +599,7 @@ bool __init early_can_reuse_p2m_middle(unsigned long set_pfn, unsigned long set_
        if (p2m_index(set_pfn))
                return false;
 
-       for (pfn = 0; pfn <= MAX_DOMAIN_PAGES; pfn += P2M_PER_PAGE) {
+       for (pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn += P2M_PER_PAGE) {
                topidx = p2m_top_index(pfn);
 
                if (!p2m_top[topidx])
index 78efb03..34d94c7 100644 (file)
@@ -250,7 +250,7 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size,
                return -EINVAL;
 
        /* Sanitise input arguments */
-       alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order);
+       alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
        base = ALIGN(base, alignment);
        size = ALIGN(size, alignment);
        limit &= ~(alignment - 1);
index b16c8a7..ba7926f 100644 (file)
@@ -294,7 +294,7 @@ config GPIO_MAX732X_IRQ
 
 config GPIO_MC9S08DZ60
        bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions"
-       depends on I2C && MACH_MX35_3DS
+       depends on I2C=y && MACH_MX35_3DS
        help
          Select this to enable the MC9S08DZ60 GPIO driver
 
index ae37181..ec48ed5 100644 (file)
@@ -247,9 +247,9 @@ static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p)
 
        p->irq_base = irq_alloc_descs(pdata->irq_base, 0,
                                      pdata->number_of_pins, numa_node_id());
-       if (IS_ERR_VALUE(p->irq_base)) {
+       if (p->irq_base < 0) {
                dev_err(&pdev->dev, "cannot get irq_desc\n");
-               return -ENXIO;
+               return p->irq_base;
        }
        pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n",
                 pdata->gpio_base, pdata->number_of_pins, p->irq_base);
index e97016a..b62d443 100644 (file)
@@ -170,6 +170,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
        rdc321x_gpio_dev->reg2_data_base = r->start + 0x4;
 
        rdc321x_gpio_dev->chip.label = "rdc321x-gpio";
+       rdc321x_gpio_dev->chip.owner = THIS_MODULE;
        rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input;
        rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config;
        rdc321x_gpio_dev->chip.get = rdc_gpio_get_value;
index a18c4aa..f1a4599 100644 (file)
@@ -82,7 +82,7 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
        gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
 
        of_node_put(gg_data.gpiospec.np);
-       pr_debug("%s exited with status %d\n", __func__, ret);
+       pr_debug("%s exited with status %d\n", __func__, gg_data.out_gpio);
        return gg_data.out_gpio;
 }
 EXPORT_SYMBOL(of_get_named_gpio_flags);
index e93b80a..ed3340a 100644 (file)
@@ -77,13 +77,9 @@ void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw,
 void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
 {
        u16 ctl, v;
-       int cap, err;
+       int err;
 
-       cap = pci_pcie_cap(rdev->pdev);
-       if (!cap)
-               return;
-
-       err = pci_read_config_word(rdev->pdev, cap + PCI_EXP_DEVCTL, &ctl);
+       err = pcie_capability_read_word(rdev->pdev, PCI_EXP_DEVCTL, &ctl);
        if (err)
                return;
 
@@ -95,7 +91,7 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
        if ((v == 0) || (v == 6) || (v == 7)) {
                ctl &= ~PCI_EXP_DEVCTL_READRQ;
                ctl |= (2 << 12);
-               pci_write_config_word(rdev->pdev, cap + PCI_EXP_DEVCTL, ctl);
+               pcie_capability_write_word(rdev->pdev, PCI_EXP_DEVCTL, ctl);
        }
 }
 
index 8bf8a64..8bcd168 100644 (file)
@@ -996,7 +996,8 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field,
        struct hid_driver *hdrv = hid->driver;
        int ret;
 
-       hid_dump_input(hid, usage, value);
+       if (!list_empty(&hid->debug_list))
+               hid_dump_input(hid, usage, value);
 
        if (hdrv && hdrv->event && hid_match_usage(hid, usage)) {
                ret = hdrv->event(hid, field, usage, value);
@@ -1558,7 +1559,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+#if IS_ENABLED(CONFIG_HID_LENOVO_TPKBD)
+       { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+#endif
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
index 0f9c146..4d524b5 100644 (file)
@@ -439,7 +439,7 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
        struct dj_report *dj_report;
        int retval;
 
-       dj_report = kzalloc(sizeof(dj_report), GFP_KERNEL);
+       dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
        if (!dj_report)
                return -ENOMEM;
        dj_report->report_id = REPORT_ID_DJ_SHORT;
@@ -456,7 +456,7 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
        struct dj_report *dj_report;
        int retval;
 
-       dj_report = kzalloc(sizeof(dj_report), GFP_KERNEL);
+       dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
        if (!dj_report)
                return -ENOMEM;
        dj_report->report_id = REPORT_ID_DJ_SHORT;
index 903eef3..991e85c 100644 (file)
@@ -70,6 +70,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },
index 4fa3534..74c6a94 100644 (file)
@@ -241,16 +241,16 @@ good:
 
        if (hca_pcie_cap) {
                devctl = hca_header[(hca_pcie_cap + PCI_EXP_DEVCTL) / 4];
-               if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_DEVCTL,
-                                          devctl)) {
+               if (pcie_capability_write_word(mdev->pdev, PCI_EXP_DEVCTL,
+                                              devctl)) {
                        err = -ENODEV;
                        mthca_err(mdev, "Couldn't restore HCA PCI Express "
                                  "Device Control register, aborting.\n");
                        goto out;
                }
                linkctl = hca_header[(hca_pcie_cap + PCI_EXP_LNKCTL) / 4];
-               if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_LNKCTL,
-                                          linkctl)) {
+               if (pcie_capability_write_word(mdev->pdev, PCI_EXP_LNKCTL,
+                                              linkctl)) {
                        err = -ENODEV;
                        mthca_err(mdev, "Couldn't restore HCA PCI Express "
                                  "Link control register, aborting.\n");
index 062c301..9001371 100644 (file)
@@ -273,10 +273,9 @@ int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent,
                    struct qib_msix_entry *entry)
 {
        u16 linkstat, speed;
-       int pos = 0, pose, ret = 1;
+       int pos = 0, ret = 1;
 
-       pose = pci_pcie_cap(dd->pcidev);
-       if (!pose) {
+       if (!pci_is_pcie(dd->pcidev)) {
                qib_dev_err(dd, "Can't find PCI Express capability!\n");
                /* set up something... */
                dd->lbus_width = 1;
@@ -298,7 +297,7 @@ int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent,
        if (!pos)
                qib_enable_intx(dd->pcidev);
 
-       pci_read_config_word(dd->pcidev, pose + PCI_EXP_LNKSTA, &linkstat);
+       pcie_capability_read_word(dd->pcidev, PCI_EXP_LNKSTA, &linkstat);
        /*
         * speed is bits 0-3, linkwidth is bits 4-8
         * no defines for them in headers
@@ -516,7 +515,6 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)
 {
        int r;
        struct pci_dev *parent;
-       int ppos;
        u16 devid;
        u32 mask, bits, val;
 
@@ -529,8 +527,7 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)
                qib_devinfo(dd->pcidev, "Parent not root\n");
                return 1;
        }
-       ppos = pci_pcie_cap(parent);
-       if (!ppos)
+       if (!pci_is_pcie(parent))
                return 1;
        if (parent->vendor != 0x8086)
                return 1;
@@ -587,7 +584,6 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)
 {
        int ret = 1; /* Assume the worst */
        struct pci_dev *parent;
-       int ppos, epos;
        u16 pcaps, pctl, ecaps, ectl;
        int rc_sup, ep_sup;
        int rc_cur, ep_cur;
@@ -598,19 +594,15 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)
                qib_devinfo(dd->pcidev, "Parent not root\n");
                goto bail;
        }
-       ppos = pci_pcie_cap(parent);
-       if (ppos) {
-               pci_read_config_word(parent, ppos + PCI_EXP_DEVCAP, &pcaps);
-               pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl);
-       } else
+
+       if (!pci_is_pcie(parent) || !pci_is_pcie(dd->pcidev))
                goto bail;
+       pcie_capability_read_word(parent, PCI_EXP_DEVCAP, &pcaps);
+       pcie_capability_read_word(parent, PCI_EXP_DEVCTL, &pctl);
        /* Find out supported and configured values for endpoint (us) */
-       epos = pci_pcie_cap(dd->pcidev);
-       if (epos) {
-               pci_read_config_word(dd->pcidev, epos + PCI_EXP_DEVCAP, &ecaps);
-               pci_read_config_word(dd->pcidev, epos + PCI_EXP_DEVCTL, &ectl);
-       } else
-               goto bail;
+       pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVCAP, &ecaps);
+       pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVCTL, &ectl);
+
        ret = 0;
        /* Find max payload supported by root, endpoint */
        rc_sup = fld2val(pcaps, PCI_EXP_DEVCAP_PAYLOAD);
@@ -629,14 +621,14 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)
                rc_cur = rc_sup;
                pctl = (pctl & ~PCI_EXP_DEVCTL_PAYLOAD) |
                        val2fld(rc_cur, PCI_EXP_DEVCTL_PAYLOAD);
-               pci_write_config_word(parent, ppos + PCI_EXP_DEVCTL, pctl);
+               pcie_capability_write_word(parent, PCI_EXP_DEVCTL, pctl);
        }
        /* If less than (allowed, supported), bump endpoint payload */
        if (rc_sup > ep_cur) {
                ep_cur = rc_sup;
                ectl = (ectl & ~PCI_EXP_DEVCTL_PAYLOAD) |
                        val2fld(ep_cur, PCI_EXP_DEVCTL_PAYLOAD);
-               pci_write_config_word(dd->pcidev, epos + PCI_EXP_DEVCTL, ectl);
+               pcie_capability_write_word(dd->pcidev, PCI_EXP_DEVCTL, ectl);
        }
 
        /*
@@ -654,13 +646,13 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)
                rc_cur = rc_sup;
                pctl = (pctl & ~PCI_EXP_DEVCTL_READRQ) |
                        val2fld(rc_cur, PCI_EXP_DEVCTL_READRQ);
-               pci_write_config_word(parent, ppos + PCI_EXP_DEVCTL, pctl);
+               pcie_capability_write_word(parent, PCI_EXP_DEVCTL, pctl);
        }
        if (rc_sup > ep_cur) {
                ep_cur = rc_sup;
                ectl = (ectl & ~PCI_EXP_DEVCTL_READRQ) |
                        val2fld(ep_cur, PCI_EXP_DEVCTL_READRQ);
-               pci_write_config_word(dd->pcidev, epos + PCI_EXP_DEVCTL, ectl);
+               pcie_capability_write_word(dd->pcidev, PCI_EXP_DEVCTL, ectl);
        }
 bail:
        return ret;
index ff4c0a8..ce68e36 100644 (file)
@@ -358,6 +358,7 @@ static void imx_keypad_inhibit(struct imx_keypad *keypad)
        /* Inhibit KDI and KRI interrupts. */
        reg_val = readw(keypad->mmio_base + KPSR);
        reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
+       reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD;
        writew(reg_val, keypad->mmio_base + KPSR);
 
        /* Colums as open drain and disable all rows */
@@ -515,7 +516,9 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev)
        input_set_drvdata(input_dev, keypad);
 
        /* Ensure that the keypad will stay dormant until opened */
+       clk_enable(keypad->clk);
        imx_keypad_inhibit(keypad);
+       clk_disable(keypad->clk);
 
        error = request_irq(irq, imx_keypad_irq_handler, 0,
                            pdev->name, keypad);
index 5ec774d..6918773 100644 (file)
@@ -177,6 +177,20 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
                },
        },
        {
+               /* Gigabyte T1005 - defines wrong chassis type ("Other") */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "T1005"),
+               },
+       },
+       {
+               /* Gigabyte T1005M/P - defines wrong chassis type ("Other") */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"),
+               },
+       },
+       {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"),
index 0020419..532d067 100644 (file)
@@ -1848,7 +1848,10 @@ static const struct wacom_features wacom_features_0x2A =
        { "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS,  44704, 27940, 2047,
          63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xF4 =
-       { "Wacom Cintiq 24HD",    WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
+       { "Wacom Cintiq 24HD",       WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
+         63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xF8 =
+       { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
          63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0x3F =
        { "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023,
@@ -2091,6 +2094,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xEF) },
        { USB_DEVICE_WACOM(0x47) },
        { USB_DEVICE_WACOM(0xF4) },
+       { USB_DEVICE_WACOM(0xF8) },
        { USB_DEVICE_WACOM(0xFA) },
        { USB_DEVICE_LENOVO(0x6004) },
        { }
index 9afc777..b06a5e3 100644 (file)
@@ -602,6 +602,7 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
 {
        if (tsdata->debug_dir)
                debugfs_remove_recursive(tsdata->debug_dir);
+       kfree(tsdata->raw_buffer);
 }
 
 #else
@@ -843,7 +844,6 @@ static int __devexit edt_ft5x06_ts_remove(struct i2c_client *client)
        if (gpio_is_valid(pdata->reset_pin))
                gpio_free(pdata->reset_pin);
 
-       kfree(tsdata->raw_buffer);
        kfree(tsdata);
 
        return 0;
index 2297ec1..db820d7 100644 (file)
@@ -2351,7 +2351,7 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
                        return 0;
                if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
                        return 0;
-       } else if (pdev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
+       } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
                return 0;
 
        /* 
@@ -3546,10 +3546,10 @@ found:
                struct pci_dev *bridge = bus->self;
 
                if (!bridge || !pci_is_pcie(bridge) ||
-                   bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
+                   pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
                        return 0;
 
-               if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
+               if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT) {
                        for (i = 0; i < atsru->devices_cnt; i++)
                                if (atsru->devices[i] == bridge)
                                        return 1;
index f1c84de..172a768 100644 (file)
@@ -1411,7 +1411,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                /* complete ongoing async transfer before issuing discard */
                if (card->host->areq)
                        mmc_blk_issue_rw_rq(mq, NULL);
-               if (req->cmd_flags & REQ_SECURE)
+               if (req->cmd_flags & REQ_SECURE &&
+                       !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN))
                        ret = mmc_blk_issue_secdiscard_rq(mq, req);
                else
                        ret = mmc_blk_issue_discard_rq(mq, req);
@@ -1716,6 +1717,7 @@ force_ro_fail:
 #define CID_MANFID_SANDISK     0x2
 #define CID_MANFID_TOSHIBA     0x11
 #define CID_MANFID_MICRON      0x13
+#define CID_MANFID_SAMSUNG     0x15
 
 static const struct mmc_fixup blk_fixups[] =
 {
@@ -1752,6 +1754,28 @@ static const struct mmc_fixup blk_fixups[] =
        MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc,
                  MMC_QUIRK_LONG_READ_TIME),
 
+       /*
+        * On these Samsung MoviNAND parts, performing secure erase or
+        * secure trim can result in unrecoverable corruption due to a
+        * firmware bug.
+        */
+       MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+
        END_FIXUP
 };
 
index 322412c..a53c7c4 100644 (file)
@@ -81,6 +81,7 @@ struct atmel_mci_caps {
        bool    has_bad_data_ordering;
        bool    need_reset_after_xfer;
        bool    need_blksz_mul_4;
+       bool    need_notbusy_for_read_ops;
 };
 
 struct atmel_mci_dma {
@@ -1625,7 +1626,8 @@ static void atmci_tasklet_func(unsigned long priv)
                                __func__);
                        atmci_set_completed(host, EVENT_XFER_COMPLETE);
 
-                       if (host->data->flags & MMC_DATA_WRITE) {
+                       if (host->caps.need_notbusy_for_read_ops ||
+                          (host->data->flags & MMC_DATA_WRITE)) {
                                atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
                                state = STATE_WAITING_NOTBUSY;
                        } else if (host->mrq->stop) {
@@ -2218,6 +2220,7 @@ static void __init atmci_get_cap(struct atmel_mci *host)
        host->caps.has_bad_data_ordering = 1;
        host->caps.need_reset_after_xfer = 1;
        host->caps.need_blksz_mul_4 = 1;
+       host->caps.need_notbusy_for_read_ops = 0;
 
        /* keep only major version number */
        switch (version & 0xf00) {
@@ -2238,6 +2241,7 @@ static void __init atmci_get_cap(struct atmel_mci *host)
        case 0x200:
                host->caps.has_rwproof = 1;
                host->caps.need_blksz_mul_4 = 0;
+               host->caps.need_notbusy_for_read_ops = 1;
        case 0x100:
                host->caps.has_bad_data_ordering = 0;
                host->caps.need_reset_after_xfer = 0;
index 0366617..a17dd73 100644 (file)
 #define bfin_write_SDH_CFG             bfin_write_RSI_CFG
 #endif
 
-struct dma_desc_array {
-       unsigned long   start_addr;
-       unsigned short  cfg;
-       unsigned short  x_count;
-       short           x_modify;
-} __packed;
-
 struct sdh_host {
        struct mmc_host         *mmc;
        spinlock_t              lock;
index 72dc3cd..af40d22 100644 (file)
@@ -627,6 +627,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
 {
        struct dw_mci *host = slot->host;
        u32 div;
+       u32 clk_en_a;
 
        if (slot->clock != host->current_speed) {
                div = host->bus_hz / slot->clock;
@@ -659,9 +660,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
                mci_send_cmd(slot,
                             SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
 
-               /* enable clock */
-               mci_writel(host, CLKENA, ((SDMMC_CLKEN_ENABLE |
-                          SDMMC_CLKEN_LOW_PWR) << slot->id));
+               /* enable clock; only low power if no SDIO */
+               clk_en_a = SDMMC_CLKEN_ENABLE << slot->id;
+               if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id)))
+                       clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id;
+               mci_writel(host, CLKENA, clk_en_a);
 
                /* inform CIU */
                mci_send_cmd(slot,
@@ -862,6 +865,30 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
        return present;
 }
 
+/*
+ * Disable lower power mode.
+ *
+ * Low power mode will stop the card clock when idle.  According to the
+ * description of the CLKENA register we should disable low power mode
+ * for SDIO cards if we need SDIO interrupts to work.
+ *
+ * This function is fast if low power mode is already disabled.
+ */
+static void dw_mci_disable_low_power(struct dw_mci_slot *slot)
+{
+       struct dw_mci *host = slot->host;
+       u32 clk_en_a;
+       const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id;
+
+       clk_en_a = mci_readl(host, CLKENA);
+
+       if (clk_en_a & clken_low_pwr) {
+               mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr);
+               mci_send_cmd(slot, SDMMC_CMD_UPD_CLK |
+                            SDMMC_CMD_PRV_DAT_WAIT, 0);
+       }
+}
+
 static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
 {
        struct dw_mci_slot *slot = mmc_priv(mmc);
@@ -871,6 +898,14 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
        /* Enable/disable Slot Specific SDIO interrupt */
        int_mask = mci_readl(host, INTMASK);
        if (enb) {
+               /*
+                * Turn off low power mode if it was enabled.  This is a bit of
+                * a heavy operation and we disable / enable IRQs a lot, so
+                * we'll leave low power mode disabled and it will get
+                * re-enabled again in dw_mci_setup_bus().
+                */
+               dw_mci_disable_low_power(slot);
+
                mci_writel(host, INTMASK,
                           (int_mask | SDMMC_INT_SDIO(slot->id)));
        } else {
@@ -1429,22 +1464,10 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
                        nbytes += len;
                        remain -= len;
                } while (remain);
-               sg_miter->consumed = offset;
 
+               sg_miter->consumed = offset;
                status = mci_readl(host, MINTSTS);
                mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
-               if (status & DW_MCI_DATA_ERROR_FLAGS) {
-                       host->data_status = status;
-                       data->bytes_xfered += nbytes;
-                       sg_miter_stop(sg_miter);
-                       host->sg = NULL;
-                       smp_wmb();
-
-                       set_bit(EVENT_DATA_ERROR, &host->pending_events);
-
-                       tasklet_schedule(&host->tasklet);
-                       return;
-               }
        } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/
        data->bytes_xfered += nbytes;
 
@@ -1497,23 +1520,10 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
                        nbytes += len;
                        remain -= len;
                } while (remain);
-               sg_miter->consumed = offset;
 
+               sg_miter->consumed = offset;
                status = mci_readl(host, MINTSTS);
                mci_writel(host, RINTSTS, SDMMC_INT_TXDR);
-               if (status & DW_MCI_DATA_ERROR_FLAGS) {
-                       host->data_status = status;
-                       data->bytes_xfered += nbytes;
-                       sg_miter_stop(sg_miter);
-                       host->sg = NULL;
-
-                       smp_wmb();
-
-                       set_bit(EVENT_DATA_ERROR, &host->pending_events);
-
-                       tasklet_schedule(&host->tasklet);
-                       return;
-               }
        } while (status & SDMMC_INT_TXDR); /* if TXDR write again */
        data->bytes_xfered += nbytes;
 
@@ -1547,12 +1557,11 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status)
 static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 {
        struct dw_mci *host = dev_id;
-       u32 status, pending;
+       u32 pending;
        unsigned int pass_count = 0;
        int i;
 
        do {
-               status = mci_readl(host, RINTSTS);
                pending = mci_readl(host, MINTSTS); /* read-only mask reg */
 
                /*
@@ -1570,7 +1579,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 
                if (pending & DW_MCI_CMD_ERROR_FLAGS) {
                        mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);
-                       host->cmd_status = status;
+                       host->cmd_status = pending;
                        smp_wmb();
                        set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
                }
@@ -1578,18 +1587,16 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
                if (pending & DW_MCI_DATA_ERROR_FLAGS) {
                        /* if there is an error report DATA_ERROR */
                        mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS);
-                       host->data_status = status;
+                       host->data_status = pending;
                        smp_wmb();
                        set_bit(EVENT_DATA_ERROR, &host->pending_events);
-                       if (!(pending & (SDMMC_INT_DTO | SDMMC_INT_DCRC |
-                                        SDMMC_INT_SBE | SDMMC_INT_EBE)))
-                               tasklet_schedule(&host->tasklet);
+                       tasklet_schedule(&host->tasklet);
                }
 
                if (pending & SDMMC_INT_DATA_OVER) {
                        mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER);
                        if (!host->data_status)
-                               host->data_status = status;
+                               host->data_status = pending;
                        smp_wmb();
                        if (host->dir_status == DW_MCI_RECV_STATUS) {
                                if (host->sg != NULL)
@@ -1613,7 +1620,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 
                if (pending & SDMMC_INT_CMD_DONE) {
                        mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE);
-                       dw_mci_cmd_interrupt(host, status);
+                       dw_mci_cmd_interrupt(host, pending);
                }
 
                if (pending & SDMMC_INT_CD) {
index a51f930..ad3fcea 100644 (file)
@@ -285,11 +285,11 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
        writel(stat & MXS_MMC_IRQ_BITS,
               host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR);
 
+       spin_unlock(&host->lock);
+
        if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN))
                mmc_signal_sdio_irq(host->mmc);
 
-       spin_unlock(&host->lock);
-
        if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ)
                cmd->error = -ETIMEDOUT;
        else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ)
@@ -644,11 +644,6 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
                       host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
                writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
                       host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET);
-
-               if (readl(host->base + HW_SSP_STATUS(host)) &
-                               BM_SSP_STATUS_SDIO_IRQ)
-                       mmc_signal_sdio_irq(host->mmc);
-
        } else {
                writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
                       host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
@@ -657,6 +652,11 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
        }
 
        spin_unlock_irqrestore(&host->lock, flags);
+
+       if (enable && readl(host->base + HW_SSP_STATUS(host)) &
+                       BM_SSP_STATUS_SDIO_IRQ)
+               mmc_signal_sdio_irq(host->mmc);
+
 }
 
 static const struct mmc_host_ops mxs_mmc_ops = {
index 50e08f0..a5999a7 100644 (file)
@@ -668,7 +668,7 @@ mmc_omap_clk_timer(unsigned long data)
 static void
 mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
 {
-       int n;
+       int n, nwords;
 
        if (host->buffer_bytes_left == 0) {
                host->sg_idx++;
@@ -678,15 +678,23 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
        n = 64;
        if (n > host->buffer_bytes_left)
                n = host->buffer_bytes_left;
+
+       nwords = n / 2;
+       nwords += n & 1; /* handle odd number of bytes to transfer */
+
        host->buffer_bytes_left -= n;
        host->total_bytes_left -= n;
        host->data->bytes_xfered += n;
 
        if (write) {
-               __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n);
+               __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA),
+                             host->buffer, nwords);
        } else {
-               __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n);
+               __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA),
+                            host->buffer, nwords);
        }
+
+       host->buffer += nwords;
 }
 
 static inline void mmc_omap_report_irq(u16 status)
index b97b2f5..d25f9ab 100644 (file)
@@ -48,14 +48,14 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
        int div = 1;
        u32 temp;
 
+       if (clock == 0)
+               goto out;
+
        temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
        temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
                | ESDHC_CLOCK_MASK);
        sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
 
-       if (clock == 0)
-               goto out;
-
        while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
                pre_div *= 2;
 
index 437bc19..568307c 100644 (file)
@@ -340,7 +340,7 @@ retry:
         * of this LEB as it will be deleted and freed in 'ubi_add_to_av()'.
         */
        err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0);
-       kfree(new_aeb);
+       kmem_cache_free(ai->aeb_slab_cache, new_aeb);
        ubi_free_vid_hdr(ubi, vid_hdr);
        return err;
 
@@ -353,7 +353,7 @@ write_error:
                list_add(&new_aeb->u.list, &ai->erase);
                goto retry;
        }
-       kfree(new_aeb);
+       kmem_cache_free(ai->aeb_slab_cache, new_aeb);
 out_free:
        ubi_free_vid_hdr(ubi, vid_hdr);
        return err;
index 1bf5bbf..8892e2b 100644 (file)
@@ -149,7 +149,7 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
        data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP);
        pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data);
        /* clear error status */
-       pci_write_config_word(pdev, pci_pcie_cap(pdev) + PCI_EXP_DEVSTA,
+       pcie_capability_write_word(pdev, PCI_EXP_DEVSTA,
                        PCI_EXP_DEVSTA_NFED |
                        PCI_EXP_DEVSTA_FED |
                        PCI_EXP_DEVSTA_CED |
index 2105498..605c457 100644 (file)
@@ -1162,14 +1162,9 @@ static int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func,
 
 static u8 bnx2x_is_pcie_pending(struct pci_dev *dev)
 {
-       int pos;
        u16 status;
 
-       pos = pci_pcie_cap(dev);
-       if (!pos)
-               return false;
-
-       pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status);
+       pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status);
        return status & PCI_EXP_DEVSTA_TRPND;
 }
 
@@ -6135,8 +6130,7 @@ static void bnx2x_init_pxp(struct bnx2x *bp)
        u16 devctl;
        int r_order, w_order;
 
-       pci_read_config_word(bp->pdev,
-                            pci_pcie_cap(bp->pdev) + PCI_EXP_DEVCTL, &devctl);
+       pcie_capability_read_word(bp->pdev, PCI_EXP_DEVCTL, &devctl);
        DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl);
        w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
        if (bp->mrrs == -1)
@@ -9374,7 +9368,7 @@ static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp)
 
 static int __devinit bnx2x_do_flr(struct bnx2x *bp)
 {
-       int i, pos;
+       int i;
        u16 status;
        struct pci_dev *dev = bp->pdev;
 
@@ -9391,16 +9385,12 @@ static int __devinit bnx2x_do_flr(struct bnx2x *bp)
                return -EINVAL;
        }
 
-       pos = pci_pcie_cap(dev);
-       if (!pos)
-               return -ENOTTY;
-
        /* Wait for Transaction Pending bit clean */
        for (i = 0; i < 4; i++) {
                if (i)
                        msleep((1 << (i - 1)) * 100);
 
-               pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status);
+               pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status);
                if (!(status & PCI_EXP_DEVSTA_TRPND))
                        goto clear;
        }
index bf906c5..8325fd8 100644 (file)
@@ -3653,17 +3653,9 @@ static int tg3_power_down_prepare(struct tg3 *tp)
        tg3_enable_register_access(tp);
 
        /* Restore the CLKREQ setting. */
-       if (tg3_flag(tp, CLKREQ_BUG)) {
-               u16 lnkctl;
-
-               pci_read_config_word(tp->pdev,
-                                    pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
-                                    &lnkctl);
-               lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN;
-               pci_write_config_word(tp->pdev,
-                                     pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
-                                     lnkctl);
-       }
+       if (tg3_flag(tp, CLKREQ_BUG))
+               pcie_capability_set_word(tp->pdev, PCI_EXP_LNKCTL,
+                                        PCI_EXP_LNKCTL_CLKREQ_EN);
 
        misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
        tw32(TG3PCI_MISC_HOST_CTRL,
@@ -4434,20 +4426,13 @@ relink:
 
        /* Prevent send BD corruption. */
        if (tg3_flag(tp, CLKREQ_BUG)) {
-               u16 oldlnkctl, newlnkctl;
-
-               pci_read_config_word(tp->pdev,
-                                    pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
-                                    &oldlnkctl);
                if (tp->link_config.active_speed == SPEED_100 ||
                    tp->link_config.active_speed == SPEED_10)
-                       newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN;
+                       pcie_capability_clear_word(tp->pdev, PCI_EXP_LNKCTL,
+                                                  PCI_EXP_LNKCTL_CLKREQ_EN);
                else
-                       newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
-               if (newlnkctl != oldlnkctl)
-                       pci_write_config_word(tp->pdev,
-                                             pci_pcie_cap(tp->pdev) +
-                                             PCI_EXP_LNKCTL, newlnkctl);
+                       pcie_capability_set_word(tp->pdev, PCI_EXP_LNKCTL,
+                                                PCI_EXP_LNKCTL_CLKREQ_EN);
        }
 
        if (current_link_up != netif_carrier_ok(tp->dev)) {
@@ -8054,7 +8039,7 @@ static int tg3_chip_reset(struct tg3 *tp)
 
        udelay(120);
 
-       if (tg3_flag(tp, PCI_EXPRESS) && pci_pcie_cap(tp->pdev)) {
+       if (tg3_flag(tp, PCI_EXPRESS) && pci_is_pcie(tp->pdev)) {
                u16 val16;
 
                if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
@@ -8071,24 +8056,17 @@ static int tg3_chip_reset(struct tg3 *tp)
                }
 
                /* Clear the "no snoop" and "relaxed ordering" bits. */
-               pci_read_config_word(tp->pdev,
-                                    pci_pcie_cap(tp->pdev) + PCI_EXP_DEVCTL,
-                                    &val16);
-               val16 &= ~(PCI_EXP_DEVCTL_RELAX_EN |
-                          PCI_EXP_DEVCTL_NOSNOOP_EN);
+               val16 = PCI_EXP_DEVCTL_RELAX_EN | PCI_EXP_DEVCTL_NOSNOOP_EN;
                /*
                 * Older PCIe devices only support the 128 byte
                 * MPS setting.  Enforce the restriction.
                 */
                if (!tg3_flag(tp, CPMU_PRESENT))
-                       val16 &= ~PCI_EXP_DEVCTL_PAYLOAD;
-               pci_write_config_word(tp->pdev,
-                                     pci_pcie_cap(tp->pdev) + PCI_EXP_DEVCTL,
-                                     val16);
+                       val16 |= PCI_EXP_DEVCTL_PAYLOAD;
+               pcie_capability_clear_word(tp->pdev, PCI_EXP_DEVCTL, val16);
 
                /* Clear error status */
-               pci_write_config_word(tp->pdev,
-                                     pci_pcie_cap(tp->pdev) + PCI_EXP_DEVSTA,
+               pcie_capability_write_word(tp->pdev, PCI_EXP_DEVSTA,
                                      PCI_EXP_DEVSTA_CED |
                                      PCI_EXP_DEVSTA_NFED |
                                      PCI_EXP_DEVSTA_FED |
@@ -14565,9 +14543,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 
                tg3_flag_set(tp, PCI_EXPRESS);
 
-               pci_read_config_word(tp->pdev,
-                                    pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
-                                    &lnkctl);
+               pcie_capability_read_word(tp->pdev, PCI_EXP_LNKCTL, &lnkctl);
                if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) {
                        if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
                            ASIC_REV_5906) {
index bff8a3c..aef45d3 100644 (file)
@@ -3289,22 +3289,18 @@ static void config_pcie(struct adapter *adap)
        unsigned int log2_width, pldsize;
        unsigned int fst_trn_rx, fst_trn_tx, acklat, rpllmt;
 
-       pci_read_config_word(adap->pdev,
-                            adap->pdev->pcie_cap + PCI_EXP_DEVCTL,
-                            &val);
+       pcie_capability_read_word(adap->pdev, PCI_EXP_DEVCTL, &val);
        pldsize = (val & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
 
        pci_read_config_word(adap->pdev, 0x2, &devid);
        if (devid == 0x37) {
-               pci_write_config_word(adap->pdev,
-                                     adap->pdev->pcie_cap + PCI_EXP_DEVCTL,
-                                     val & ~PCI_EXP_DEVCTL_READRQ &
-                                     ~PCI_EXP_DEVCTL_PAYLOAD);
+               pcie_capability_write_word(adap->pdev, PCI_EXP_DEVCTL,
+                                          val & ~PCI_EXP_DEVCTL_READRQ &
+                                          ~PCI_EXP_DEVCTL_PAYLOAD);
                pldsize = 0;
        }
 
-       pci_read_config_word(adap->pdev, adap->pdev->pcie_cap + PCI_EXP_LNKCTL,
-                            &val);
+       pcie_capability_read_word(adap->pdev, PCI_EXP_LNKCTL, &val);
 
        fst_trn_tx = G_NUMFSTTRNSEQ(t3_read_reg(adap, A_PCIE_PEX_CTRL0));
        fst_trn_rx = adap->params.rev == 0 ? fst_trn_tx :
@@ -3425,15 +3421,13 @@ out_err:
 static void get_pci_mode(struct adapter *adapter, struct pci_params *p)
 {
        static unsigned short speed_map[] = { 33, 66, 100, 133 };
-       u32 pci_mode, pcie_cap;
+       u32 pci_mode;
 
-       pcie_cap = pci_pcie_cap(adapter->pdev);
-       if (pcie_cap) {
+       if (pci_is_pcie(adapter->pdev)) {
                u16 val;
 
                p->variant = PCI_VARIANT_PCIE;
-               pci_read_config_word(adapter->pdev, pcie_cap + PCI_EXP_LNKSTA,
-                                       &val);
+               pcie_capability_read_word(adapter->pdev, PCI_EXP_LNKSTA, &val);
                p->width = (val >> 4) & 0x3f;
                return;
        }
index 5ed49af..4a20821 100644 (file)
@@ -3694,15 +3694,7 @@ static void __devinit print_port_info(const struct net_device *dev)
 
 static void __devinit enable_pcie_relaxed_ordering(struct pci_dev *dev)
 {
-       u16 v;
-       int pos;
-
-       pos = pci_pcie_cap(dev);
-       if (pos > 0) {
-               pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &v);
-               v |= PCI_EXP_DEVCTL_RELAX_EN;
-               pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, v);
-       }
+       pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN);
 }
 
 /*
index fa947df..af16013 100644 (file)
@@ -2741,11 +2741,9 @@ static void __devinit get_pci_mode(struct adapter *adapter,
                                   struct pci_params *p)
 {
        u16 val;
-       u32 pcie_cap = pci_pcie_cap(adapter->pdev);
 
-       if (pcie_cap) {
-               pci_read_config_word(adapter->pdev, pcie_cap + PCI_EXP_LNKSTA,
-                                    &val);
+       if (pci_is_pcie(adapter->pdev)) {
+               pcie_capability_read_word(adapter->pdev, PCI_EXP_LNKSTA, &val);
                p->speed = val & PCI_EXP_LNKSTA_CLS;
                p->width = (val & PCI_EXP_LNKSTA_NLW) >> 4;
        }
index d01a099..acc030e 100644 (file)
@@ -5584,16 +5584,15 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
         */
        if (adapter->flags & FLAG_IS_QUAD_PORT) {
                struct pci_dev *us_dev = pdev->bus->self;
-               int pos = pci_pcie_cap(us_dev);
                u16 devctl;
 
-               pci_read_config_word(us_dev, pos + PCI_EXP_DEVCTL, &devctl);
-               pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL,
-                                     (devctl & ~PCI_EXP_DEVCTL_CERE));
+               pcie_capability_read_word(us_dev, PCI_EXP_DEVCTL, &devctl);
+               pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL,
+                                          (devctl & ~PCI_EXP_DEVCTL_CERE));
 
                e1000_power_off(pdev, sleep, wake);
 
-               pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL, devctl);
+               pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, devctl);
        } else {
                e1000_power_off(pdev, sleep, wake);
        }
@@ -5607,25 +5606,15 @@ static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
 #else
 static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
 {
-       int pos;
-       u16 reg16;
-
        /*
         * Both device and parent should have the same ASPM setting.
         * Disable ASPM in downstream component first and then upstream.
         */
-       pos = pci_pcie_cap(pdev);
-       pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
-       reg16 &= ~state;
-       pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
-
-       if (!pdev->bus->self)
-               return;
+       pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, state);
 
-       pos = pci_pcie_cap(pdev->bus->self);
-       pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, &reg16);
-       reg16 &= ~state;
-       pci_write_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, reg16);
+       if (pdev->bus->self)
+               pcie_capability_clear_word(pdev->bus->self, PCI_EXP_LNKCTL,
+                                          state);
 }
 #endif
 static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
index 48cc4fb..2036ae3 100644 (file)
@@ -6538,28 +6538,20 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
 {
        struct igb_adapter *adapter = hw->back;
-       u16 cap_offset;
 
-       cap_offset = adapter->pdev->pcie_cap;
-       if (!cap_offset)
+       if (pcie_capability_read_word(adapter->pdev, reg, value))
                return -E1000_ERR_CONFIG;
 
-       pci_read_config_word(adapter->pdev, cap_offset + reg, value);
-
        return 0;
 }
 
 s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
 {
        struct igb_adapter *adapter = hw->back;
-       u16 cap_offset;
 
-       cap_offset = adapter->pdev->pcie_cap;
-       if (!cap_offset)
+       if (pcie_capability_write_word(adapter->pdev, reg, *value))
                return -E1000_ERR_CONFIG;
 
-       pci_write_config_word(adapter->pdev, cap_offset + reg, *value);
-
        return 0;
 }
 
index 4326f74..976570d 100644 (file)
@@ -7527,7 +7527,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
                goto skip_bad_vf_detection;
 
        bdev = pdev->bus->self;
-       while (bdev && (bdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT))
+       while (bdev && (pci_pcie_type(bdev) != PCI_EXP_TYPE_ROOT_PORT))
                bdev = bdev->bus->self;
 
        if (!bdev)
index 11e7c1c..dd1b509 100644 (file)
@@ -141,16 +141,16 @@ int mlx4_reset(struct mlx4_dev *dev)
        /* Now restore the PCI headers */
        if (pcie_cap) {
                devctl = hca_header[(pcie_cap + PCI_EXP_DEVCTL) / 4];
-               if (pci_write_config_word(dev->pdev, pcie_cap + PCI_EXP_DEVCTL,
-                                          devctl)) {
+               if (pcie_capability_write_word(dev->pdev, PCI_EXP_DEVCTL,
+                                              devctl)) {
                        err = -ENODEV;
                        mlx4_err(dev, "Couldn't restore HCA PCI Express "
                                 "Device Control register, aborting.\n");
                        goto out;
                }
                linkctl = hca_header[(pcie_cap + PCI_EXP_LNKCTL) / 4];
-               if (pci_write_config_word(dev->pdev, pcie_cap + PCI_EXP_LNKCTL,
-                                          linkctl)) {
+               if (pcie_capability_write_word(dev->pdev, PCI_EXP_LNKCTL,
+                                              linkctl)) {
                        err = -ENODEV;
                        mlx4_err(dev, "Couldn't restore HCA PCI Express "
                                 "Link control register, aborting.\n");
index fa85cf1..83516e3 100644 (file)
@@ -1078,22 +1078,16 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
 #ifdef CONFIG_MYRI10GE_DCA
 static int myri10ge_toggle_relaxed(struct pci_dev *pdev, int on)
 {
-       int ret, cap, err;
+       int ret;
        u16 ctl;
 
-       cap = pci_pcie_cap(pdev);
-       if (!cap)
-               return 0;
-
-       err = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
-       if (err)
-               return 0;
+       pcie_capability_read_word(pdev, PCI_EXP_DEVCTL, &ctl);
 
        ret = (ctl & PCI_EXP_DEVCTL_RELAX_EN) >> 4;
        if (ret != on) {
                ctl &= ~PCI_EXP_DEVCTL_RELAX_EN;
                ctl |= (on << 4);
-               pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
+               pcie_capability_write_word(pdev, PCI_EXP_DEVCTL, ctl);
        }
        return ret;
 }
@@ -3192,18 +3186,13 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
        struct device *dev = &mgp->pdev->dev;
        int cap;
        unsigned err_cap;
-       u16 val;
-       u8 ext_type;
        int ret;
 
        if (!myri10ge_ecrc_enable || !bridge)
                return;
 
        /* check that the bridge is a root port */
-       cap = pci_pcie_cap(bridge);
-       pci_read_config_word(bridge, cap + PCI_CAP_FLAGS, &val);
-       ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4;
-       if (ext_type != PCI_EXP_TYPE_ROOT_PORT) {
+       if (pci_pcie_type(bridge) != PCI_EXP_TYPE_ROOT_PORT) {
                if (myri10ge_ecrc_enable > 1) {
                        struct pci_dev *prev_bridge, *old_bridge = bridge;
 
@@ -3218,11 +3207,8 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
                                                " to force ECRC\n");
                                        return;
                                }
-                               cap = pci_pcie_cap(bridge);
-                               pci_read_config_word(bridge,
-                                                    cap + PCI_CAP_FLAGS, &val);
-                               ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4;
-                       } while (ext_type != PCI_EXP_TYPE_ROOT_PORT);
+                       } while (pci_pcie_type(bridge) !=
+                                PCI_EXP_TYPE_ROOT_PORT);
 
                        dev_info(dev,
                                 "Forcing ECRC on non-root port %s"
@@ -3335,11 +3321,10 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
        int overridden = 0;
 
        if (myri10ge_force_firmware == 0) {
-               int link_width, exp_cap;
+               int link_width;
                u16 lnk;
 
-               exp_cap = pci_pcie_cap(mgp->pdev);
-               pci_read_config_word(mgp->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
+               pcie_capability_read_word(mgp->pdev, PCI_EXP_LNKSTA, &lnk);
                link_width = (lnk >> 4) & 0x3f;
 
                /* Check to see if Link is less than 8 or if the
index 32d0682..c2e420a 100644 (file)
@@ -757,7 +757,7 @@ __vxge_hw_verify_pci_e_info(struct __vxge_hw_device *hldev)
        u16 lnk;
 
        /* Get the negotiated link width and speed from PCI config space */
-       pci_read_config_word(dev, dev->pcie_cap + PCI_EXP_LNKSTA, &lnk);
+       pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnk);
 
        if ((lnk & PCI_EXP_LNKSTA_CLS) != 1)
                return VXGE_HW_ERR_INVALID_PCI_INFO;
@@ -1982,7 +1982,7 @@ u16 vxge_hw_device_link_width_get(struct __vxge_hw_device *hldev)
        struct pci_dev *dev = hldev->pdev;
        u16 lnk;
 
-       pci_read_config_word(dev, dev->pcie_cap + PCI_EXP_LNKSTA, &lnk);
+       pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnk);
        return (lnk & VXGE_HW_PCI_EXP_LNKCAP_LNK_WIDTH) >> 4;
 }
 
index 342b3a7..01d6141 100644 (file)
@@ -1382,7 +1382,7 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter)
                adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP)
                return;
 
-       if (root->pcie_type != PCI_EXP_TYPE_ROOT_PORT)
+       if (pci_pcie_type(root) != PCI_EXP_TYPE_ROOT_PORT)
                return;
 
        aer_pos = pci_find_ext_capability(root, PCI_EXT_CAP_ID_ERR);
index b47d5b3..a7cc560 100644 (file)
@@ -833,15 +833,8 @@ static void rtl_unlock_work(struct rtl8169_private *tp)
 
 static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
 {
-       int cap = pci_pcie_cap(pdev);
-
-       if (cap) {
-               u16 ctl;
-
-               pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
-               ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force;
-               pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
-       }
+       pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
+                                          PCI_EXP_DEVCTL_READRQ, force);
 }
 
 struct rtl_cond {
@@ -4739,28 +4732,14 @@ static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e,
 
 static void rtl_disable_clock_request(struct pci_dev *pdev)
 {
-       int cap = pci_pcie_cap(pdev);
-
-       if (cap) {
-               u16 ctl;
-
-               pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl);
-               ctl &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
-               pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl);
-       }
+       pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
+                                  PCI_EXP_LNKCTL_CLKREQ_EN);
 }
 
 static void rtl_enable_clock_request(struct pci_dev *pdev)
 {
-       int cap = pci_pcie_cap(pdev);
-
-       if (cap) {
-               u16 ctl;
-
-               pci_read_config_word(pdev, cap + PCI_EXP_LNKCTL, &ctl);
-               ctl |= PCI_EXP_LNKCTL_CLKREQ_EN;
-               pci_write_config_word(pdev, cap + PCI_EXP_LNKCTL, ctl);
-       }
+       pcie_capability_set_word(pdev, PCI_EXP_LNKCTL,
+                                PCI_EXP_LNKCTL_CLKREQ_EN);
 }
 
 #define R8168_CPCMD_QUIRK_MASK (\
@@ -5405,14 +5384,9 @@ static void rtl_hw_start_8101(struct net_device *dev)
                tp->event_slow &= ~RxFIFOOver;
 
        if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
-           tp->mac_version == RTL_GIGA_MAC_VER_16) {
-               int cap = pci_pcie_cap(pdev);
-
-               if (cap) {
-                       pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL,
-                                             PCI_EXP_DEVCTL_NOSNOOP_EN);
-               }
-       }
+           tp->mac_version == RTL_GIGA_MAC_VER_16)
+               pcie_capability_set_word(pdev, PCI_EXP_DEVCTL,
+                                        PCI_EXP_DEVCTL_NOSNOOP_EN);
 
        RTL_W8(Cfg9346, Cfg9346_Unlock);
 
index c2a0fe3..3208dca 100644 (file)
@@ -9762,9 +9762,8 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev,
        union niu_parent_id parent_id;
        struct net_device *dev;
        struct niu *np;
-       int err, pos;
+       int err;
        u64 dma_mask;
-       u16 val16;
 
        niu_driver_version();
 
@@ -9787,8 +9786,7 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev,
                goto err_out_disable_pdev;
        }
 
-       pos = pci_pcie_cap(pdev);
-       if (pos <= 0) {
+       if (!pci_is_pcie(pdev)) {
                dev_err(&pdev->dev, "Cannot find PCI Express capability, aborting\n");
                goto err_out_free_res;
        }
@@ -9813,14 +9811,11 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev,
                goto err_out_free_dev;
        }
 
-       pci_read_config_word(pdev, pos + PCI_EXP_DEVCTL, &val16);
-       val16 &= ~PCI_EXP_DEVCTL_NOSNOOP_EN;
-       val16 |= (PCI_EXP_DEVCTL_CERE |
-                 PCI_EXP_DEVCTL_NFERE |
-                 PCI_EXP_DEVCTL_FERE |
-                 PCI_EXP_DEVCTL_URRE |
-                 PCI_EXP_DEVCTL_RELAX_EN);
-       pci_write_config_word(pdev, pos + PCI_EXP_DEVCTL, val16);
+       pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
+               PCI_EXP_DEVCTL_NOSNOOP_EN,
+               PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE |
+               PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE |
+               PCI_EXP_DEVCTL_RELAX_EN);
 
        dma_mask = DMA_BIT_MASK(44);
        err = pci_set_dma_mask(pdev, dma_mask);
index a978984..ef11dc6 100644 (file)
@@ -113,41 +113,32 @@ static void ath_pci_aspm_init(struct ath_common *common)
        struct ath_hw *ah = sc->sc_ah;
        struct pci_dev *pdev = to_pci_dev(sc->dev);
        struct pci_dev *parent;
-       int pos;
-       u8 aspm;
+       u16 aspm;
 
        if (!ah->is_pciexpress)
                return;
 
-       pos = pci_pcie_cap(pdev);
-       if (!pos)
-               return;
-
        parent = pdev->bus->self;
        if (!parent)
                return;
 
        if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
                /* Bluetooth coexistance requires disabling ASPM. */
-               pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm);
-               aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
-               pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm);
+               pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
+                       PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
 
                /*
                 * Both upstream and downstream PCIe components should
                 * have the same ASPM settings.
                 */
-               pos = pci_pcie_cap(parent);
-               pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm);
-               aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
-               pci_write_config_byte(parent, pos + PCI_EXP_LNKCTL, aspm);
+               pcie_capability_clear_word(parent, PCI_EXP_LNKCTL,
+                       PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
 
                ath_info(common, "Disabling ASPM since BTCOEX is enabled\n");
                return;
        }
 
-       pos = pci_pcie_cap(parent);
-       pci_read_config_byte(parent, pos +  PCI_EXP_LNKCTL, &aspm);
+       pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &aspm);
        if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
                ah->aspm_enabled = true;
                /* Initialize PCIe PM and SERDES registers. */
index 5f50177..7246826 100644 (file)
@@ -1832,10 +1832,8 @@ int il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd);
 static inline u16
 il_pcie_link_ctl(struct il_priv *il)
 {
-       int pos;
        u16 pci_lnk_ctl;
-       pos = pci_pcie_cap(il->pci_dev);
-       pci_read_config_word(il->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
+       pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &pci_lnk_ctl);
        return pci_lnk_ctl;
 }
 
index 1e86ea2..e316ca4 100644 (file)
@@ -675,13 +675,10 @@ static void iwl_set_pwr_vmain(struct iwl_trans *trans)
 static u16 iwl_pciexp_link_ctrl(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       int pos;
        u16 pci_lnk_ctl;
 
-       struct pci_dev *pci_dev = trans_pcie->pci_dev;
-
-       pos = pci_pcie_cap(pci_dev);
-       pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
+       pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL,
+                                 &pci_lnk_ctl);
        return pci_lnk_ctl;
 }
 
index 80f75d3..5983631 100644 (file)
@@ -372,13 +372,11 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev,
        struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
 
        u8 tmp;
-       int pos;
-       u8 linkctrl_reg;
+       u16 linkctrl_reg;
 
        /*Link Control Register */
-       pos = pci_pcie_cap(pdev);
-       pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &linkctrl_reg);
-       pcipriv->ndis_adapter.linkctrl_reg = linkctrl_reg;
+       pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &linkctrl_reg);
+       pcipriv->ndis_adapter.linkctrl_reg = (u8)linkctrl_reg;
 
        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Link Control Register =%x\n",
                 pcipriv->ndis_adapter.linkctrl_reg);
index ba91a7e..3af0478 100644 (file)
@@ -469,3 +469,205 @@ void pci_cfg_access_unlock(struct pci_dev *dev)
        raw_spin_unlock_irqrestore(&pci_lock, flags);
 }
 EXPORT_SYMBOL_GPL(pci_cfg_access_unlock);
+
+static inline int pcie_cap_version(const struct pci_dev *dev)
+{
+       return dev->pcie_flags_reg & PCI_EXP_FLAGS_VERS;
+}
+
+static inline bool pcie_cap_has_devctl(const struct pci_dev *dev)
+{
+       return true;
+}
+
+static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
+{
+       int type = pci_pcie_type(dev);
+
+       return pcie_cap_version(dev) > 1 ||
+              type == PCI_EXP_TYPE_ROOT_PORT ||
+              type == PCI_EXP_TYPE_ENDPOINT ||
+              type == PCI_EXP_TYPE_LEG_END;
+}
+
+static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev)
+{
+       int type = pci_pcie_type(dev);
+
+       return pcie_cap_version(dev) > 1 ||
+              type == PCI_EXP_TYPE_ROOT_PORT ||
+              (type == PCI_EXP_TYPE_DOWNSTREAM &&
+               dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT);
+}
+
+static inline bool pcie_cap_has_rtctl(const struct pci_dev *dev)
+{
+       int type = pci_pcie_type(dev);
+
+       return pcie_cap_version(dev) > 1 ||
+              type == PCI_EXP_TYPE_ROOT_PORT ||
+              type == PCI_EXP_TYPE_RC_EC;
+}
+
+static bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos)
+{
+       if (!pci_is_pcie(dev))
+               return false;
+
+       switch (pos) {
+       case PCI_EXP_FLAGS_TYPE:
+               return true;
+       case PCI_EXP_DEVCAP:
+       case PCI_EXP_DEVCTL:
+       case PCI_EXP_DEVSTA:
+               return pcie_cap_has_devctl(dev);
+       case PCI_EXP_LNKCAP:
+       case PCI_EXP_LNKCTL:
+       case PCI_EXP_LNKSTA:
+               return pcie_cap_has_lnkctl(dev);
+       case PCI_EXP_SLTCAP:
+       case PCI_EXP_SLTCTL:
+       case PCI_EXP_SLTSTA:
+               return pcie_cap_has_sltctl(dev);
+       case PCI_EXP_RTCTL:
+       case PCI_EXP_RTCAP:
+       case PCI_EXP_RTSTA:
+               return pcie_cap_has_rtctl(dev);
+       case PCI_EXP_DEVCAP2:
+       case PCI_EXP_DEVCTL2:
+       case PCI_EXP_LNKCAP2:
+       case PCI_EXP_LNKCTL2:
+       case PCI_EXP_LNKSTA2:
+               return pcie_cap_version(dev) > 1;
+       default:
+               return false;
+       }
+}
+
+/*
+ * Note that these accessor functions are only for the "PCI Express
+ * Capability" (see PCIe spec r3.0, sec 7.8).  They do not apply to the
+ * other "PCI Express Extended Capabilities" (AER, VC, ACS, MFVC, etc.)
+ */
+int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val)
+{
+       int ret;
+
+       *val = 0;
+       if (pos & 1)
+               return -EINVAL;
+
+       if (pcie_capability_reg_implemented(dev, pos)) {
+               ret = pci_read_config_word(dev, pci_pcie_cap(dev) + pos, val);
+               /*
+                * Reset *val to 0 if pci_read_config_word() fails, it may
+                * have been written as 0xFFFF if hardware error happens
+                * during pci_read_config_word().
+                */
+               if (ret)
+                       *val = 0;
+               return ret;
+       }
+
+       /*
+        * For Functions that do not implement the Slot Capabilities,
+        * Slot Status, and Slot Control registers, these spaces must
+        * be hardwired to 0b, with the exception of the Presence Detect
+        * State bit in the Slot Status register of Downstream Ports,
+        * which must be hardwired to 1b.  (PCIe Base Spec 3.0, sec 7.8)
+        */
+       if (pci_is_pcie(dev) && pos == PCI_EXP_SLTSTA &&
+                pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) {
+               *val = PCI_EXP_SLTSTA_PDS;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(pcie_capability_read_word);
+
+int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val)
+{
+       int ret;
+
+       *val = 0;
+       if (pos & 3)
+               return -EINVAL;
+
+       if (pcie_capability_reg_implemented(dev, pos)) {
+               ret = pci_read_config_dword(dev, pci_pcie_cap(dev) + pos, val);
+               /*
+                * Reset *val to 0 if pci_read_config_dword() fails, it may
+                * have been written as 0xFFFFFFFF if hardware error happens
+                * during pci_read_config_dword().
+                */
+               if (ret)
+                       *val = 0;
+               return ret;
+       }
+
+       if (pci_is_pcie(dev) && pos == PCI_EXP_SLTCTL &&
+                pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) {
+               *val = PCI_EXP_SLTSTA_PDS;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(pcie_capability_read_dword);
+
+int pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val)
+{
+       if (pos & 1)
+               return -EINVAL;
+
+       if (!pcie_capability_reg_implemented(dev, pos))
+               return 0;
+
+       return pci_write_config_word(dev, pci_pcie_cap(dev) + pos, val);
+}
+EXPORT_SYMBOL(pcie_capability_write_word);
+
+int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val)
+{
+       if (pos & 3)
+               return -EINVAL;
+
+       if (!pcie_capability_reg_implemented(dev, pos))
+               return 0;
+
+       return pci_write_config_dword(dev, pci_pcie_cap(dev) + pos, val);
+}
+EXPORT_SYMBOL(pcie_capability_write_dword);
+
+int pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos,
+                                      u16 clear, u16 set)
+{
+       int ret;
+       u16 val;
+
+       ret = pcie_capability_read_word(dev, pos, &val);
+       if (!ret) {
+               val &= ~clear;
+               val |= set;
+               ret = pcie_capability_write_word(dev, pos, val);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(pcie_capability_clear_and_set_word);
+
+int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos,
+                                       u32 clear, u32 set)
+{
+       int ret;
+       u32 val;
+
+       ret = pcie_capability_read_dword(dev, pos, &val);
+       if (!ret) {
+               val &= ~clear;
+               val |= set;
+               ret = pcie_capability_write_dword(dev, pos, val);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(pcie_capability_clear_and_set_dword);
index 376d70d..24d709b 100644 (file)
@@ -81,16 +81,12 @@ static struct list_head __initdata dummy_slots = LIST_HEAD_INIT(dummy_slots);
 /* Dummy driver for dumplicate name detection */
 static int __init dummy_probe(struct pcie_device *dev)
 {
-       int pos;
        u32 slot_cap;
        acpi_handle handle;
        struct dummy_slot *slot, *tmp;
        struct pci_dev *pdev = dev->port;
 
-       pos = pci_pcie_cap(pdev);
-       if (!pos)
-               return -ENODEV;
-       pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap);
+       pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap);
        slot = kzalloc(sizeof(*slot), GFP_KERNEL);
        if (!slot)
                return -ENOMEM;
index 302451e..13b2eaf 100644 (file)
 static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value)
 {
        struct pci_dev *dev = ctrl->pcie->port;
-       return pci_read_config_word(dev, pci_pcie_cap(dev) + reg, value);
+       return pcie_capability_read_word(dev, reg, value);
 }
 
 static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value)
 {
        struct pci_dev *dev = ctrl->pcie->port;
-       return pci_read_config_dword(dev, pci_pcie_cap(dev) + reg, value);
+       return pcie_capability_read_dword(dev, reg, value);
 }
 
 static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value)
 {
        struct pci_dev *dev = ctrl->pcie->port;
-       return pci_write_config_word(dev, pci_pcie_cap(dev) + reg, value);
+       return pcie_capability_write_word(dev, reg, value);
 }
 
 static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
 {
        struct pci_dev *dev = ctrl->pcie->port;
-       return pci_write_config_dword(dev, pci_pcie_cap(dev) + reg, value);
+       return pcie_capability_write_dword(dev, reg, value);
 }
 
 /* Power Control Command */
@@ -855,10 +855,6 @@ struct controller *pcie_init(struct pcie_device *dev)
                goto abort;
        }
        ctrl->pcie = dev;
-       if (!pci_pcie_cap(pdev)) {
-               ctrl_err(ctrl, "Cannot find PCI Express capability\n");
-               goto abort_ctrl;
-       }
        if (pciehp_readl(ctrl, PCI_EXP_SLTCAP, &slot_cap)) {
                ctrl_err(ctrl, "Cannot read SLOTCAP register\n");
                goto abort_ctrl;
index 8c05a18..fec2d5b 100644 (file)
@@ -96,17 +96,11 @@ static void program_hpp_type1(struct pci_dev *dev, struct hpp_type1 *hpp)
 static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
 {
        int pos;
-       u16 reg16;
        u32 reg32;
 
        if (!hpp)
                return;
 
-       /* Find PCI Express capability */
-       pos = pci_pcie_cap(dev);
-       if (!pos)
-               return;
-
        if (hpp->revision > 1) {
                dev_warn(&dev->dev, "PCIe settings rev %d not supported\n",
                         hpp->revision);
@@ -114,17 +108,13 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
        }
 
        /* Initialize Device Control Register */
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &reg16);
-       reg16 = (reg16 & hpp->pci_exp_devctl_and) | hpp->pci_exp_devctl_or;
-       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16);
+       pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
+                       ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or);
 
        /* Initialize Link Control Register */
-       if (dev->subordinate) {
-               pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &reg16);
-               reg16 = (reg16 & hpp->pci_exp_lnkctl_and)
-                       | hpp->pci_exp_lnkctl_or;
-               pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, reg16);
-       }
+       if (dev->subordinate)
+               pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
+                       ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or);
 
        /* Find Advanced Error Reporting Enhanced Capability */
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
index 1e117c2..b29e20b 100644 (file)
@@ -388,7 +388,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
        /* Remove the EADS bridge device itself */
        BUG_ON(!bus->self);
        pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self));
-       eeh_remove_bus_device(bus->self);
+       eeh_remove_bus_device(bus->self, true);
        pci_stop_and_remove_bus_device(bus->self);
 
        return 0;
index 74bbaf8..aeccc91 100644 (file)
@@ -433,8 +433,8 @@ static int sriov_init(struct pci_dev *dev, int pos)
        struct resource *res;
        struct pci_dev *pdev;
 
-       if (dev->pcie_type != PCI_EXP_TYPE_RC_END &&
-           dev->pcie_type != PCI_EXP_TYPE_ENDPOINT)
+       if (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_END &&
+           pci_pcie_type(dev) != PCI_EXP_TYPE_ENDPOINT)
                return -ENODEV;
 
        pci_read_config_word(dev, pos + PCI_SRIOV_CTRL, &ctrl);
@@ -503,7 +503,7 @@ found:
        iov->self = dev;
        pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap);
        pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link);
-       if (dev->pcie_type == PCI_EXP_TYPE_RC_END)
+       if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END)
                iov->link = PCI_DEVFN(PCI_SLOT(dev->devfn), iov->link);
 
        if (pdev)
index 5270f1a..d6fd6b6 100644 (file)
@@ -280,8 +280,12 @@ static long local_pci_probe(void *_ddi)
 {
        struct drv_dev_and_id *ddi = _ddi;
        struct device *dev = &ddi->dev->dev;
+       struct device *parent = dev->parent;
        int rc;
 
+       /* The parent bridge must be in active state when probing */
+       if (parent)
+               pm_runtime_get_sync(parent);
        /* Unbound PCI devices are always set to disabled and suspended.
         * During probe, the device is set to enabled and active and the
         * usage count is incremented.  If the driver supports runtime PM,
@@ -298,6 +302,8 @@ static long local_pci_probe(void *_ddi)
                pm_runtime_set_suspended(dev);
                pm_runtime_put_noidle(dev);
        }
+       if (parent)
+               pm_runtime_put(parent);
        return rc;
 }
 
index 6869009..02d107b 100644 (file)
@@ -458,6 +458,40 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 struct device_attribute vga_attr = __ATTR_RO(boot_vga);
 
+static void
+pci_config_pm_runtime_get(struct pci_dev *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device *parent = dev->parent;
+
+       if (parent)
+               pm_runtime_get_sync(parent);
+       pm_runtime_get_noresume(dev);
+       /*
+        * pdev->current_state is set to PCI_D3cold during suspending,
+        * so wait until suspending completes
+        */
+       pm_runtime_barrier(dev);
+       /*
+        * Only need to resume devices in D3cold, because config
+        * registers are still accessible for devices suspended but
+        * not in D3cold.
+        */
+       if (pdev->current_state == PCI_D3cold)
+               pm_runtime_resume(dev);
+}
+
+static void
+pci_config_pm_runtime_put(struct pci_dev *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device *parent = dev->parent;
+
+       pm_runtime_put(dev);
+       if (parent)
+               pm_runtime_put_sync(parent);
+}
+
 static ssize_t
 pci_read_config(struct file *filp, struct kobject *kobj,
                struct bin_attribute *bin_attr,
@@ -484,6 +518,8 @@ pci_read_config(struct file *filp, struct kobject *kobj,
                size = count;
        }
 
+       pci_config_pm_runtime_get(dev);
+
        if ((off & 1) && size) {
                u8 val;
                pci_user_read_config_byte(dev, off, &val);
@@ -529,6 +565,8 @@ pci_read_config(struct file *filp, struct kobject *kobj,
                --size;
        }
 
+       pci_config_pm_runtime_put(dev);
+
        return count;
 }
 
@@ -549,6 +587,8 @@ pci_write_config(struct file* filp, struct kobject *kobj,
                count = size;
        }
        
+       pci_config_pm_runtime_get(dev);
+
        if ((off & 1) && size) {
                pci_user_write_config_byte(dev, off, data[off - init_off]);
                off++;
@@ -587,6 +627,8 @@ pci_write_config(struct file* filp, struct kobject *kobj,
                --size;
        }
 
+       pci_config_pm_runtime_put(dev);
+
        return count;
 }
 
index f3ea977..292cb2e 100644 (file)
@@ -254,38 +254,6 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
 }
 
 /**
- * pci_pcie_cap2 - query for devices' PCI_CAP_ID_EXP v2 capability structure
- * @dev: PCI device to check
- *
- * Like pci_pcie_cap() but also checks that the PCIe capability version is
- * >= 2.  Note that v1 capability structures could be sparse in that not
- * all register fields were required.  v2 requires the entire structure to
- * be present size wise, while still allowing for non-implemented registers
- * to exist but they must be hardwired to 0.
- *
- * Due to the differences in the versions of capability structures, one
- * must be careful not to try and access non-existant registers that may
- * exist in early versions - v1 - of Express devices.
- *
- * Returns the offset of the PCIe capability structure as long as the
- * capability version is >= 2; otherwise 0 is returned.
- */
-static int pci_pcie_cap2(struct pci_dev *dev)
-{
-       u16 flags;
-       int pos;
-
-       pos = pci_pcie_cap(dev);
-       if (pos) {
-               pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags);
-               if ((flags & PCI_EXP_FLAGS_VERS) < 2)
-                       pos = 0;
-       }
-
-       return pos;
-}
-
-/**
  * pci_find_ext_capability - Find an extended capability
  * @dev: PCI device to query
  * @cap: capability code
@@ -854,21 +822,6 @@ EXPORT_SYMBOL(pci_choose_state);
 
 #define PCI_EXP_SAVE_REGS      7
 
-#define pcie_cap_has_devctl(type, flags)       1
-#define pcie_cap_has_lnkctl(type, flags)               \
-               ((flags & PCI_EXP_FLAGS_VERS) > 1 ||    \
-                (type == PCI_EXP_TYPE_ROOT_PORT ||     \
-                 type == PCI_EXP_TYPE_ENDPOINT ||      \
-                 type == PCI_EXP_TYPE_LEG_END))
-#define pcie_cap_has_sltctl(type, flags)               \
-               ((flags & PCI_EXP_FLAGS_VERS) > 1 ||    \
-                ((type == PCI_EXP_TYPE_ROOT_PORT) ||   \
-                 (type == PCI_EXP_TYPE_DOWNSTREAM &&   \
-                  (flags & PCI_EXP_FLAGS_SLOT))))
-#define pcie_cap_has_rtctl(type, flags)                        \
-               ((flags & PCI_EXP_FLAGS_VERS) > 1 ||    \
-                (type == PCI_EXP_TYPE_ROOT_PORT ||     \
-                 type == PCI_EXP_TYPE_RC_EC))
 
 static struct pci_cap_saved_state *pci_find_saved_cap(
        struct pci_dev *pci_dev, char cap)
@@ -885,13 +838,11 @@ static struct pci_cap_saved_state *pci_find_saved_cap(
 
 static int pci_save_pcie_state(struct pci_dev *dev)
 {
-       int pos, i = 0;
+       int i = 0;
        struct pci_cap_saved_state *save_state;
        u16 *cap;
-       u16 flags;
 
-       pos = pci_pcie_cap(dev);
-       if (!pos)
+       if (!pci_is_pcie(dev))
                return 0;
 
        save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
@@ -899,60 +850,37 @@ static int pci_save_pcie_state(struct pci_dev *dev)
                dev_err(&dev->dev, "buffer not found in %s\n", __func__);
                return -ENOMEM;
        }
-       cap = (u16 *)&save_state->cap.data[0];
-
-       pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags);
 
-       if (pcie_cap_has_devctl(dev->pcie_type, flags))
-               pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &cap[i++]);
-       if (pcie_cap_has_lnkctl(dev->pcie_type, flags))
-               pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
-       if (pcie_cap_has_sltctl(dev->pcie_type, flags))
-               pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
-       if (pcie_cap_has_rtctl(dev->pcie_type, flags))
-               pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
-
-       pos = pci_pcie_cap2(dev);
-       if (!pos)
-               return 0;
+       cap = (u16 *)&save_state->cap.data[0];
+       pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &cap[i++]);
+       pcie_capability_read_word(dev, PCI_EXP_LNKCTL, &cap[i++]);
+       pcie_capability_read_word(dev, PCI_EXP_SLTCTL, &cap[i++]);
+       pcie_capability_read_word(dev, PCI_EXP_RTCTL,  &cap[i++]);
+       pcie_capability_read_word(dev, PCI_EXP_DEVCTL2, &cap[i++]);
+       pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &cap[i++]);
+       pcie_capability_read_word(dev, PCI_EXP_SLTCTL2, &cap[i++]);
 
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]);
-       pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]);
-       pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]);
        return 0;
 }
 
 static void pci_restore_pcie_state(struct pci_dev *dev)
 {
-       int i = 0, pos;
+       int i = 0;
        struct pci_cap_saved_state *save_state;
        u16 *cap;
-       u16 flags;
 
        save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
-       if (!save_state || pos <= 0)
-               return;
-       cap = (u16 *)&save_state->cap.data[0];
-
-       pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags);
-
-       if (pcie_cap_has_devctl(dev->pcie_type, flags))
-               pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, cap[i++]);
-       if (pcie_cap_has_lnkctl(dev->pcie_type, flags))
-               pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]);
-       if (pcie_cap_has_sltctl(dev->pcie_type, flags))
-               pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]);
-       if (pcie_cap_has_rtctl(dev->pcie_type, flags))
-               pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]);
-
-       pos = pci_pcie_cap2(dev);
-       if (!pos)
+       if (!save_state)
                return;
 
-       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]);
-       pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]);
-       pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]);
+       cap = (u16 *)&save_state->cap.data[0];
+       pcie_capability_write_word(dev, PCI_EXP_DEVCTL, cap[i++]);
+       pcie_capability_write_word(dev, PCI_EXP_LNKCTL, cap[i++]);
+       pcie_capability_write_word(dev, PCI_EXP_SLTCTL, cap[i++]);
+       pcie_capability_write_word(dev, PCI_EXP_RTCTL, cap[i++]);
+       pcie_capability_write_word(dev, PCI_EXP_DEVCTL2, cap[i++]);
+       pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, cap[i++]);
+       pcie_capability_write_word(dev, PCI_EXP_SLTCTL2, cap[i++]);
 }
 
 
@@ -1941,6 +1869,7 @@ void pci_pm_init(struct pci_dev *dev)
        dev->pm_cap = pm;
        dev->d3_delay = PCI_PM_D3_WAIT;
        dev->d3cold_delay = PCI_PM_D3COLD_WAIT;
+       dev->d3cold_allowed = true;
 
        dev->d1_support = false;
        dev->d2_support = false;
@@ -2066,35 +1995,24 @@ void pci_free_cap_save_buffers(struct pci_dev *dev)
  */
 void pci_enable_ari(struct pci_dev *dev)
 {
-       int pos;
        u32 cap;
-       u16 ctrl;
        struct pci_dev *bridge;
 
        if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn)
                return;
 
-       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
-       if (!pos)
+       if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI))
                return;
 
        bridge = dev->bus->self;
        if (!bridge)
                return;
 
-       /* ARI is a PCIe cap v2 feature */
-       pos = pci_pcie_cap2(bridge);
-       if (!pos)
-               return;
-
-       pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap);
+       pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap);
        if (!(cap & PCI_EXP_DEVCAP2_ARI))
                return;
 
-       pci_read_config_word(bridge, pos + PCI_EXP_DEVCTL2, &ctrl);
-       ctrl |= PCI_EXP_DEVCTL2_ARI;
-       pci_write_config_word(bridge, pos + PCI_EXP_DEVCTL2, ctrl);
-
+       pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_ARI);
        bridge->ari_enabled = 1;
 }
 
@@ -2109,20 +2027,14 @@ void pci_enable_ari(struct pci_dev *dev)
  */
 void pci_enable_ido(struct pci_dev *dev, unsigned long type)
 {
-       int pos;
-       u16 ctrl;
+       u16 ctrl = 0;
 
-       /* ID-based Ordering is a PCIe cap v2 feature */
-       pos = pci_pcie_cap2(dev);
-       if (!pos)
-               return;
-
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
        if (type & PCI_EXP_IDO_REQUEST)
                ctrl |= PCI_EXP_IDO_REQ_EN;
        if (type & PCI_EXP_IDO_COMPLETION)
                ctrl |= PCI_EXP_IDO_CMP_EN;
-       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
+       if (ctrl)
+               pcie_capability_set_word(dev, PCI_EXP_DEVCTL2, ctrl);
 }
 EXPORT_SYMBOL(pci_enable_ido);
 
@@ -2133,20 +2045,14 @@ EXPORT_SYMBOL(pci_enable_ido);
  */
 void pci_disable_ido(struct pci_dev *dev, unsigned long type)
 {
-       int pos;
-       u16 ctrl;
+       u16 ctrl = 0;
 
-       /* ID-based Ordering is a PCIe cap v2 feature */
-       pos = pci_pcie_cap2(dev);
-       if (!pos)
-               return;
-
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
        if (type & PCI_EXP_IDO_REQUEST)
-               ctrl &= ~PCI_EXP_IDO_REQ_EN;
+               ctrl |= PCI_EXP_IDO_REQ_EN;
        if (type & PCI_EXP_IDO_COMPLETION)
-               ctrl &= ~PCI_EXP_IDO_CMP_EN;
-       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
+               ctrl |= PCI_EXP_IDO_CMP_EN;
+       if (ctrl)
+               pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2, ctrl);
 }
 EXPORT_SYMBOL(pci_disable_ido);
 
@@ -2171,17 +2077,11 @@ EXPORT_SYMBOL(pci_disable_ido);
  */
 int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type)
 {
-       int pos;
        u32 cap;
        u16 ctrl;
        int ret;
 
-       /* OBFF is a PCIe cap v2 feature */
-       pos = pci_pcie_cap2(dev);
-       if (!pos)
-               return -ENOTSUPP;
-
-       pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap);
+       pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap);
        if (!(cap & PCI_EXP_OBFF_MASK))
                return -ENOTSUPP; /* no OBFF support at all */
 
@@ -2192,7 +2092,7 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type)
                        return ret;
        }
 
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
+       pcie_capability_read_word(dev, PCI_EXP_DEVCTL2, &ctrl);
        if (cap & PCI_EXP_OBFF_WAKE)
                ctrl |= PCI_EXP_OBFF_WAKE_EN;
        else {
@@ -2210,7 +2110,7 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type)
                        return -ENOTSUPP;
                }
        }
-       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
+       pcie_capability_write_word(dev, PCI_EXP_DEVCTL2, ctrl);
 
        return 0;
 }
@@ -2224,17 +2124,7 @@ EXPORT_SYMBOL(pci_enable_obff);
  */
 void pci_disable_obff(struct pci_dev *dev)
 {
-       int pos;
-       u16 ctrl;
-
-       /* OBFF is a PCIe cap v2 feature */
-       pos = pci_pcie_cap2(dev);
-       if (!pos)
-               return;
-
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
-       ctrl &= ~PCI_EXP_OBFF_WAKE_EN;
-       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
+       pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2, PCI_EXP_OBFF_WAKE_EN);
 }
 EXPORT_SYMBOL(pci_disable_obff);
 
@@ -2247,15 +2137,9 @@ EXPORT_SYMBOL(pci_disable_obff);
  */
 static bool pci_ltr_supported(struct pci_dev *dev)
 {
-       int pos;
        u32 cap;
 
-       /* LTR is a PCIe cap v2 feature */
-       pos = pci_pcie_cap2(dev);
-       if (!pos)
-               return false;
-
-       pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap);
+       pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap);
 
        return cap & PCI_EXP_DEVCAP2_LTR;
 }
@@ -2272,22 +2156,15 @@ static bool pci_ltr_supported(struct pci_dev *dev)
  */
 int pci_enable_ltr(struct pci_dev *dev)
 {
-       int pos;
-       u16 ctrl;
        int ret;
 
-       if (!pci_ltr_supported(dev))
-               return -ENOTSUPP;
-
-       /* LTR is a PCIe cap v2 feature */
-       pos = pci_pcie_cap2(dev);
-       if (!pos)
-               return -ENOTSUPP;
-
        /* Only primary function can enable/disable LTR */
        if (PCI_FUNC(dev->devfn) != 0)
                return -EINVAL;
 
+       if (!pci_ltr_supported(dev))
+               return -ENOTSUPP;
+
        /* Enable upstream ports first */
        if (dev->bus->self) {
                ret = pci_enable_ltr(dev->bus->self);
@@ -2295,11 +2172,7 @@ int pci_enable_ltr(struct pci_dev *dev)
                        return ret;
        }
 
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
-       ctrl |= PCI_EXP_LTR_EN;
-       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
-
-       return 0;
+       return pcie_capability_set_word(dev, PCI_EXP_DEVCTL2, PCI_EXP_LTR_EN);
 }
 EXPORT_SYMBOL(pci_enable_ltr);
 
@@ -2309,24 +2182,14 @@ EXPORT_SYMBOL(pci_enable_ltr);
  */
 void pci_disable_ltr(struct pci_dev *dev)
 {
-       int pos;
-       u16 ctrl;
-
-       if (!pci_ltr_supported(dev))
-               return;
-
-       /* LTR is a PCIe cap v2 feature */
-       pos = pci_pcie_cap2(dev);
-       if (!pos)
-               return;
-
        /* Only primary function can enable/disable LTR */
        if (PCI_FUNC(dev->devfn) != 0)
                return;
 
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
-       ctrl &= ~PCI_EXP_LTR_EN;
-       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
+       if (!pci_ltr_supported(dev))
+               return;
+
+       pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2, PCI_EXP_LTR_EN);
 }
 EXPORT_SYMBOL(pci_disable_ltr);
 
@@ -2409,9 +2272,6 @@ void pci_enable_acs(struct pci_dev *dev)
        if (!pci_acs_enable)
                return;
 
-       if (!pci_is_pcie(dev))
-               return;
-
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
        if (!pos)
                return;
@@ -2459,8 +2319,8 @@ bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags)
                acs_flags &= (PCI_ACS_RR | PCI_ACS_CR |
                              PCI_ACS_EC | PCI_ACS_DT);
 
-       if (pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM ||
-           pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
+       if (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM ||
+           pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
            pdev->multifunction) {
                pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS);
                if (!pos)
@@ -3176,15 +3036,10 @@ EXPORT_SYMBOL(pci_set_dma_seg_boundary);
 static int pcie_flr(struct pci_dev *dev, int probe)
 {
        int i;
-       int pos;
        u32 cap;
-       u16 status, control;
-
-       pos = pci_pcie_cap(dev);
-       if (!pos)
-               return -ENOTTY;
+       u16 status;
 
-       pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP, &cap);
+       pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap);
        if (!(cap & PCI_EXP_DEVCAP_FLR))
                return -ENOTTY;
 
@@ -3196,7 +3051,7 @@ static int pcie_flr(struct pci_dev *dev, int probe)
                if (i)
                        msleep((1 << (i - 1)) * 100);
 
-               pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status);
+               pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status);
                if (!(status & PCI_EXP_DEVSTA_TRPND))
                        goto clear;
        }
@@ -3205,9 +3060,7 @@ static int pcie_flr(struct pci_dev *dev, int probe)
                        "proceeding with reset anyway\n");
 
 clear:
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &control);
-       control |= PCI_EXP_DEVCTL_BCR_FLR;
-       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, control);
+       pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
 
        msleep(100);
 
@@ -3575,18 +3428,11 @@ EXPORT_SYMBOL(pcix_set_mmrbc);
  */
 int pcie_get_readrq(struct pci_dev *dev)
 {
-       int ret, cap;
        u16 ctl;
 
-       cap = pci_pcie_cap(dev);
-       if (!cap)
-               return -EINVAL;
-
-       ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
-       if (!ret)
-               ret = 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12);
+       pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl);
 
-       return ret;
+       return 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12);
 }
 EXPORT_SYMBOL(pcie_get_readrq);
 
@@ -3600,19 +3446,11 @@ EXPORT_SYMBOL(pcie_get_readrq);
  */
 int pcie_set_readrq(struct pci_dev *dev, int rq)
 {
-       int cap, err = -EINVAL;
-       u16 ctl, v;
+       u16 v;
 
        if (rq < 128 || rq > 4096 || !is_power_of_2(rq))
-               goto out;
-
-       cap = pci_pcie_cap(dev);
-       if (!cap)
-               goto out;
+               return -EINVAL;
 
-       err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
-       if (err)
-               goto out;
        /*
         * If using the "performance" PCIe config, we clamp the
         * read rq size to the max packet size to prevent the
@@ -3630,14 +3468,8 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
 
        v = (ffs(rq) - 8) << 12;
 
-       if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) {
-               ctl &= ~PCI_EXP_DEVCTL_READRQ;
-               ctl |= v;
-               err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl);
-       }
-
-out:
-       return err;
+       return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
+                                                 PCI_EXP_DEVCTL_READRQ, v);
 }
 EXPORT_SYMBOL(pcie_set_readrq);
 
@@ -3650,18 +3482,11 @@ EXPORT_SYMBOL(pcie_set_readrq);
  */
 int pcie_get_mps(struct pci_dev *dev)
 {
-       int ret, cap;
        u16 ctl;
 
-       cap = pci_pcie_cap(dev);
-       if (!cap)
-               return -EINVAL;
-
-       ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
-       if (!ret)
-               ret = 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
+       pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl);
 
-       return ret;
+       return 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
 }
 
 /**
@@ -3674,32 +3499,18 @@ int pcie_get_mps(struct pci_dev *dev)
  */
 int pcie_set_mps(struct pci_dev *dev, int mps)
 {
-       int cap, err = -EINVAL;
-       u16 ctl, v;
+       u16 v;
 
        if (mps < 128 || mps > 4096 || !is_power_of_2(mps))
-               goto out;
+               return -EINVAL;
 
        v = ffs(mps) - 8;
        if (v > dev->pcie_mpss) 
-               goto out;
+               return -EINVAL;
        v <<= 5;
 
-       cap = pci_pcie_cap(dev);
-       if (!cap)
-               goto out;
-
-       err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
-       if (err)
-               goto out;
-
-       if ((ctl & PCI_EXP_DEVCTL_PAYLOAD) != v) {
-               ctl &= ~PCI_EXP_DEVCTL_PAYLOAD;
-               ctl |= v;
-               err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl);
-       }
-out:
-       return err;
+       return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
+                                                 PCI_EXP_DEVCTL_PAYLOAD, v);
 }
 
 /**
index 5222986..4e24cb8 100644 (file)
@@ -288,7 +288,7 @@ static struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
        while (1) {
                if (!pci_is_pcie(dev))
                        break;
-               if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
+               if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
                        return dev;
                if (!dev->bus->self)
                        break;
index 58ad791..c78778f 100644 (file)
@@ -81,10 +81,11 @@ bool pci_aer_available(void)
 static int set_device_error_reporting(struct pci_dev *dev, void *data)
 {
        bool enable = *((bool *)data);
+       int type = pci_pcie_type(dev);
 
-       if ((dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) ||
-           (dev->pcie_type == PCI_EXP_TYPE_UPSTREAM) ||
-           (dev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)) {
+       if ((type == PCI_EXP_TYPE_ROOT_PORT) ||
+           (type == PCI_EXP_TYPE_UPSTREAM) ||
+           (type == PCI_EXP_TYPE_DOWNSTREAM)) {
                if (enable)
                        pci_enable_pcie_error_reporting(dev);
                else
@@ -121,19 +122,17 @@ static void set_downstream_devices_error_reporting(struct pci_dev *dev,
 static void aer_enable_rootport(struct aer_rpc *rpc)
 {
        struct pci_dev *pdev = rpc->rpd->port;
-       int pos, aer_pos;
+       int aer_pos;
        u16 reg16;
        u32 reg32;
 
-       pos = pci_pcie_cap(pdev);
        /* Clear PCIe Capability's Device Status */
-       pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, &reg16);
-       pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16);
+       pcie_capability_read_word(pdev, PCI_EXP_DEVSTA, &reg16);
+       pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, reg16);
 
        /* Disable system error generation in response to error messages */
-       pci_read_config_word(pdev, pos + PCI_EXP_RTCTL, &reg16);
-       reg16 &= ~(SYSTEM_ERROR_INTR_ON_MESG_MASK);
-       pci_write_config_word(pdev, pos + PCI_EXP_RTCTL, reg16);
+       pcie_capability_clear_word(pdev, PCI_EXP_RTCTL,
+                                  SYSTEM_ERROR_INTR_ON_MESG_MASK);
 
        aer_pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
        /* Clear error status */
@@ -395,9 +394,8 @@ static void aer_error_resume(struct pci_dev *dev)
        u16 reg16;
 
        /* Clean up Root device status */
-       pos = pci_pcie_cap(dev);
-       pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
-       pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16);
+       pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &reg16);
+       pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16);
 
        /* Clean AER Root Error Status */
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
index 124f20f..5194a7d 100644 (file)
@@ -60,7 +60,7 @@ static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)
        p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
        if (p->flags & ACPI_HEST_GLOBAL) {
                if ((pci_is_pcie(info->pci_dev) &&
-                    info->pci_dev->pcie_type == pcie_type) || bridge)
+                    pci_pcie_type(info->pci_dev) == pcie_type) || bridge)
                        ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
        } else
                if (hest_match_pci(p, info->pci_dev))
index 0ca0535..cefc0dd 100644 (file)
@@ -32,53 +32,28 @@ static bool nosourceid;
 module_param(forceload, bool, 0);
 module_param(nosourceid, bool, 0);
 
+#define        PCI_EXP_AER_FLAGS       (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \
+                                PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE)
+
 int pci_enable_pcie_error_reporting(struct pci_dev *dev)
 {
-       u16 reg16 = 0;
-       int pos;
-
        if (pcie_aer_get_firmware_first(dev))
                return -EIO;
 
-       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
-       if (!pos)
-               return -EIO;
-
-       pos = pci_pcie_cap(dev);
-       if (!pos)
+       if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR))
                return -EIO;
 
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &reg16);
-       reg16 |= (PCI_EXP_DEVCTL_CERE |
-               PCI_EXP_DEVCTL_NFERE |
-               PCI_EXP_DEVCTL_FERE |
-               PCI_EXP_DEVCTL_URRE);
-       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16);
-
-       return 0;
+       return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS);
 }
 EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
 
 int pci_disable_pcie_error_reporting(struct pci_dev *dev)
 {
-       u16 reg16 = 0;
-       int pos;
-
        if (pcie_aer_get_firmware_first(dev))
                return -EIO;
 
-       pos = pci_pcie_cap(dev);
-       if (!pos)
-               return -EIO;
-
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &reg16);
-       reg16 &= ~(PCI_EXP_DEVCTL_CERE |
-               PCI_EXP_DEVCTL_NFERE |
-               PCI_EXP_DEVCTL_FERE |
-               PCI_EXP_DEVCTL_URRE);
-       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16);
-
-       return 0;
+       return pcie_capability_clear_word(dev, PCI_EXP_DEVCTL,
+                                         PCI_EXP_AER_FLAGS);
 }
 EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
 
@@ -151,18 +126,12 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
         */
        if (atomic_read(&dev->enable_cnt) == 0)
                return false;
-       pos = pci_pcie_cap(dev);
-       if (!pos)
-               return false;
 
        /* Check if AER is enabled */
-       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &reg16);
-       if (!(reg16 & (
-               PCI_EXP_DEVCTL_CERE |
-               PCI_EXP_DEVCTL_NFERE |
-               PCI_EXP_DEVCTL_FERE |
-               PCI_EXP_DEVCTL_URRE)))
+       pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &reg16);
+       if (!(reg16 & PCI_EXP_AER_FLAGS))
                return false;
+
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
        if (!pos)
                return false;
@@ -465,7 +434,7 @@ static pci_ers_result_t reset_link(struct pci_dev *dev)
 
        if (driver && driver->reset_link) {
                status = driver->reset_link(udev);
-       } else if (udev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) {
+       } else if (pci_pcie_type(udev) == PCI_EXP_TYPE_DOWNSTREAM) {
                status = default_downstream_reset_link(udev);
        } else {
                dev_printk(KERN_DEBUG, &dev->dev,
index b500840..213753b 100644 (file)
@@ -125,21 +125,16 @@ static int policy_to_clkpm_state(struct pcie_link_state *link)
 
 static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable)
 {
-       int pos;
-       u16 reg16;
        struct pci_dev *child;
        struct pci_bus *linkbus = link->pdev->subordinate;
 
        list_for_each_entry(child, &linkbus->devices, bus_list) {
-               pos = pci_pcie_cap(child);
-               if (!pos)
-                       return;
-               pci_read_config_word(child, pos + PCI_EXP_LNKCTL, &reg16);
                if (enable)
-                       reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN;
+                       pcie_capability_set_word(child, PCI_EXP_LNKCTL,
+                                                PCI_EXP_LNKCTL_CLKREQ_EN);
                else
-                       reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
-               pci_write_config_word(child, pos + PCI_EXP_LNKCTL, reg16);
+                       pcie_capability_clear_word(child, PCI_EXP_LNKCTL,
+                                                  PCI_EXP_LNKCTL_CLKREQ_EN);
        }
        link->clkpm_enabled = !!enable;
 }
@@ -157,7 +152,7 @@ static void pcie_set_clkpm(struct pcie_link_state *link, int enable)
 
 static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
 {
-       int pos, capable = 1, enabled = 1;
+       int capable = 1, enabled = 1;
        u32 reg32;
        u16 reg16;
        struct pci_dev *child;
@@ -165,16 +160,13 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
 
        /* All functions should have the same cap and state, take the worst */
        list_for_each_entry(child, &linkbus->devices, bus_list) {
-               pos = pci_pcie_cap(child);
-               if (!pos)
-                       return;
-               pci_read_config_dword(child, pos + PCI_EXP_LNKCAP, &reg32);
+               pcie_capability_read_dword(child, PCI_EXP_LNKCAP, &reg32);
                if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) {
                        capable = 0;
                        enabled = 0;
                        break;
                }
-               pci_read_config_word(child, pos + PCI_EXP_LNKCTL, &reg16);
+               pcie_capability_read_word(child, PCI_EXP_LNKCTL, &reg16);
                if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
                        enabled = 0;
        }
@@ -190,7 +182,7 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
  */
 static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
 {
-       int ppos, cpos, same_clock = 1;
+       int same_clock = 1;
        u16 reg16, parent_reg, child_reg[8];
        unsigned long start_jiffies;
        struct pci_dev *child, *parent = link->pdev;
@@ -203,46 +195,43 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
        BUG_ON(!pci_is_pcie(child));
 
        /* Check downstream component if bit Slot Clock Configuration is 1 */
-       cpos = pci_pcie_cap(child);
-       pci_read_config_word(child, cpos + PCI_EXP_LNKSTA, &reg16);
+       pcie_capability_read_word(child, PCI_EXP_LNKSTA, &reg16);
        if (!(reg16 & PCI_EXP_LNKSTA_SLC))
                same_clock = 0;
 
        /* Check upstream component if bit Slot Clock Configuration is 1 */
-       ppos = pci_pcie_cap(parent);
-       pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, &reg16);
+       pcie_capability_read_word(parent, PCI_EXP_LNKSTA, &reg16);
        if (!(reg16 & PCI_EXP_LNKSTA_SLC))
                same_clock = 0;
 
        /* Configure downstream component, all functions */
        list_for_each_entry(child, &linkbus->devices, bus_list) {
-               cpos = pci_pcie_cap(child);
-               pci_read_config_word(child, cpos + PCI_EXP_LNKCTL, &reg16);
+               pcie_capability_read_word(child, PCI_EXP_LNKCTL, &reg16);
                child_reg[PCI_FUNC(child->devfn)] = reg16;
                if (same_clock)
                        reg16 |= PCI_EXP_LNKCTL_CCC;
                else
                        reg16 &= ~PCI_EXP_LNKCTL_CCC;
-               pci_write_config_word(child, cpos + PCI_EXP_LNKCTL, reg16);
+               pcie_capability_write_word(child, PCI_EXP_LNKCTL, reg16);
        }
 
        /* Configure upstream component */
-       pci_read_config_word(parent, ppos + PCI_EXP_LNKCTL, &reg16);
+       pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &reg16);
        parent_reg = reg16;
        if (same_clock)
                reg16 |= PCI_EXP_LNKCTL_CCC;
        else
                reg16 &= ~PCI_EXP_LNKCTL_CCC;
-       pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, reg16);
+       pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
 
        /* Retrain link */
        reg16 |= PCI_EXP_LNKCTL_RL;
-       pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, reg16);
+       pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
 
        /* Wait for link training end. Break out after waiting for timeout */
        start_jiffies = jiffies;
        for (;;) {
-               pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, &reg16);
+               pcie_capability_read_word(parent, PCI_EXP_LNKSTA, &reg16);
                if (!(reg16 & PCI_EXP_LNKSTA_LT))
                        break;
                if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT))
@@ -255,12 +244,10 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
        /* Training failed. Restore common clock configurations */
        dev_printk(KERN_ERR, &parent->dev,
                   "ASPM: Could not configure common clock\n");
-       list_for_each_entry(child, &linkbus->devices, bus_list) {
-               cpos = pci_pcie_cap(child);
-               pci_write_config_word(child, cpos + PCI_EXP_LNKCTL,
-                                     child_reg[PCI_FUNC(child->devfn)]);
-       }
-       pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, parent_reg);
+       list_for_each_entry(child, &linkbus->devices, bus_list)
+               pcie_capability_write_word(child, PCI_EXP_LNKCTL,
+                                          child_reg[PCI_FUNC(child->devfn)]);
+       pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg);
 }
 
 /* Convert L0s latency encoding to ns */
@@ -305,16 +292,14 @@ struct aspm_register_info {
 static void pcie_get_aspm_reg(struct pci_dev *pdev,
                              struct aspm_register_info *info)
 {
-       int pos;
        u16 reg16;
        u32 reg32;
 
-       pos = pci_pcie_cap(pdev);
-       pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
+       pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &reg32);
        info->support = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
        info->latency_encoding_l0s = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
        info->latency_encoding_l1  = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
-       pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+       pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &reg16);
        info->enabled = reg16 & PCI_EXP_LNKCTL_ASPMC;
 }
 
@@ -412,7 +397,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
         * do ASPM for now.
         */
        list_for_each_entry(child, &linkbus->devices, bus_list) {
-               if (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
+               if (pci_pcie_type(child) == PCI_EXP_TYPE_PCI_BRIDGE) {
                        link->aspm_disable = ASPM_STATE_ALL;
                        break;
                }
@@ -420,17 +405,15 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
 
        /* Get and check endpoint acceptable latencies */
        list_for_each_entry(child, &linkbus->devices, bus_list) {
-               int pos;
                u32 reg32, encoding;
                struct aspm_latency *acceptable =
                        &link->acceptable[PCI_FUNC(child->devfn)];
 
-               if (child->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
-                   child->pcie_type != PCI_EXP_TYPE_LEG_END)
+               if (pci_pcie_type(child) != PCI_EXP_TYPE_ENDPOINT &&
+                   pci_pcie_type(child) != PCI_EXP_TYPE_LEG_END)
                        continue;
 
-               pos = pci_pcie_cap(child);
-               pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, &reg32);
+               pcie_capability_read_dword(child, PCI_EXP_DEVCAP, &reg32);
                /* Calculate endpoint L0s acceptable latency */
                encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
                acceptable->l0s = calc_l0s_acceptable(encoding);
@@ -444,13 +427,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
 
 static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val)
 {
-       u16 reg16;
-       int pos = pci_pcie_cap(pdev);
-
-       pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
-       reg16 &= ~0x3;
-       reg16 |= val;
-       pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+       pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, 0x3, val);
 }
 
 static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
@@ -505,7 +482,6 @@ static void free_link_state(struct pcie_link_state *link)
 static int pcie_aspm_sanity_check(struct pci_dev *pdev)
 {
        struct pci_dev *child;
-       int pos;
        u32 reg32;
 
        /*
@@ -513,8 +489,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
         * very strange. Disable ASPM for the whole slot
         */
        list_for_each_entry(child, &pdev->subordinate->devices, bus_list) {
-               pos = pci_pcie_cap(child);
-               if (!pos)
+               if (!pci_is_pcie(child))
                        return -EINVAL;
 
                /*
@@ -530,7 +505,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
                 * Disable ASPM for pre-1.1 PCIe device, we follow MS to use
                 * RBER bit to determine if a function is 1.1 version device
                 */
-               pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, &reg32);
+               pcie_capability_read_dword(child, PCI_EXP_DEVCAP, &reg32);
                if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
                        dev_printk(KERN_INFO, &child->dev, "disabling ASPM"
                                " on pre-1.1 PCIe device.  You can enable it"
@@ -552,7 +527,7 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev)
        INIT_LIST_HEAD(&link->children);
        INIT_LIST_HEAD(&link->link);
        link->pdev = pdev;
-       if (pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) {
+       if (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM) {
                struct pcie_link_state *parent;
                parent = pdev->bus->parent->self->link_state;
                if (!parent) {
@@ -585,12 +560,12 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
 
        if (!pci_is_pcie(pdev) || pdev->link_state)
                return;
-       if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-           pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+       if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT &&
+           pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)
                return;
 
        /* VIA has a strange chipset, root port is under a bridge */
-       if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT &&
+       if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT &&
            pdev->bus->self)
                return;
 
@@ -647,8 +622,8 @@ static void pcie_update_aspm_capable(struct pcie_link_state *root)
                if (link->root != root)
                        continue;
                list_for_each_entry(child, &linkbus->devices, bus_list) {
-                       if ((child->pcie_type != PCI_EXP_TYPE_ENDPOINT) &&
-                           (child->pcie_type != PCI_EXP_TYPE_LEG_END))
+                       if ((pci_pcie_type(child) != PCI_EXP_TYPE_ENDPOINT) &&
+                           (pci_pcie_type(child) != PCI_EXP_TYPE_LEG_END))
                                continue;
                        pcie_aspm_check_latency(child);
                }
@@ -663,8 +638,8 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
 
        if (!pci_is_pcie(pdev) || !parent || !parent->link_state)
                return;
-       if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
-           (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
+       if ((pci_pcie_type(parent) != PCI_EXP_TYPE_ROOT_PORT) &&
+           (pci_pcie_type(parent) != PCI_EXP_TYPE_DOWNSTREAM))
                return;
 
        down_read(&pci_bus_sem);
@@ -704,8 +679,8 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev)
 
        if (aspm_disabled || !pci_is_pcie(pdev) || !link)
                return;
-       if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
-           (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
+       if ((pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) &&
+           (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM))
                return;
        /*
         * Devices changed PM state, we should recheck if latency
@@ -729,8 +704,8 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
        if (aspm_policy != POLICY_POWERSAVE)
                return;
 
-       if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
-           (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
+       if ((pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) &&
+           (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM))
                return;
 
        down_read(&pci_bus_sem);
@@ -757,8 +732,8 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
        if (!pci_is_pcie(pdev))
                return;
 
-       if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
-           pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
+       if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
+           pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM)
                parent = pdev;
        if (!parent || !parent->link_state)
                return;
@@ -933,8 +908,8 @@ void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
        struct pcie_link_state *link_state = pdev->link_state;
 
        if (!pci_is_pcie(pdev) ||
-           (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-            pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
+           (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT &&
+            pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
                return;
 
        if (link_state->aspm_support)
@@ -950,8 +925,8 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
        struct pcie_link_state *link_state = pdev->link_state;
 
        if (!pci_is_pcie(pdev) ||
-           (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-            pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
+           (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT &&
+            pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
                return;
 
        if (link_state->aspm_support)
index 001f1b7..9ca0dc9 100644 (file)
@@ -57,17 +57,12 @@ struct pcie_pme_service_data {
  */
 void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable)
 {
-       int rtctl_pos;
-       u16 rtctl;
-
-       rtctl_pos = pci_pcie_cap(dev) + PCI_EXP_RTCTL;
-
-       pci_read_config_word(dev, rtctl_pos, &rtctl);
        if (enable)
-               rtctl |= PCI_EXP_RTCTL_PMEIE;
+               pcie_capability_set_word(dev, PCI_EXP_RTCTL,
+                                        PCI_EXP_RTCTL_PMEIE);
        else
-               rtctl &= ~PCI_EXP_RTCTL_PMEIE;
-       pci_write_config_word(dev, rtctl_pos, rtctl);
+               pcie_capability_clear_word(dev, PCI_EXP_RTCTL,
+                                          PCI_EXP_RTCTL_PMEIE);
 }
 
 /**
@@ -120,7 +115,7 @@ static bool pcie_pme_from_pci_bridge(struct pci_bus *bus, u8 devfn)
        if (!dev)
                return false;
 
-       if (pci_is_pcie(dev) && dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
+       if (pci_is_pcie(dev) && pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE) {
                down_read(&pci_bus_sem);
                if (pcie_pme_walk_bus(bus))
                        found = true;
@@ -226,18 +221,15 @@ static void pcie_pme_work_fn(struct work_struct *work)
        struct pcie_pme_service_data *data =
                        container_of(work, struct pcie_pme_service_data, work);
        struct pci_dev *port = data->srv->port;
-       int rtsta_pos;
        u32 rtsta;
 
-       rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA;
-
        spin_lock_irq(&data->lock);
 
        for (;;) {
                if (data->noirq)
                        break;
 
-               pci_read_config_dword(port, rtsta_pos, &rtsta);
+               pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta);
                if (rtsta & PCI_EXP_RTSTA_PME) {
                        /*
                         * Clear PME status of the port.  If there are other
@@ -276,17 +268,14 @@ static irqreturn_t pcie_pme_irq(int irq, void *context)
 {
        struct pci_dev *port;
        struct pcie_pme_service_data *data;
-       int rtsta_pos;
        u32 rtsta;
        unsigned long flags;
 
        port = ((struct pcie_device *)context)->port;
        data = get_service_data((struct pcie_device *)context);
 
-       rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA;
-
        spin_lock_irqsave(&data->lock, flags);
-       pci_read_config_dword(port, rtsta_pos, &rtsta);
+       pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta);
 
        if (!(rtsta & PCI_EXP_RTSTA_PME)) {
                spin_unlock_irqrestore(&data->lock, flags);
@@ -335,13 +324,13 @@ static void pcie_pme_mark_devices(struct pci_dev *port)
                struct pci_dev *dev;
 
                /* Check if this is a root port event collector. */
-               if (port->pcie_type != PCI_EXP_TYPE_RC_EC || !bus)
+               if (pci_pcie_type(port) != PCI_EXP_TYPE_RC_EC || !bus)
                        return;
 
                down_read(&pci_bus_sem);
                list_for_each_entry(dev, &bus->devices, bus_list)
                        if (pci_is_pcie(dev)
-                           && dev->pcie_type == PCI_EXP_TYPE_RC_END)
+                           && pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END)
                                pcie_pme_set_native(dev, NULL);
                up_read(&pci_bus_sem);
        }
index 18bf90f..67be55a 100644 (file)
@@ -38,7 +38,7 @@ static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
                return 0;
 
        if ((driver->port_type != PCIE_ANY_PORT) &&
-           (driver->port_type != pciedev->port->pcie_type))
+           (driver->port_type != pci_pcie_type(pciedev->port)))
                return 0;
 
        return 1;
index 75915b3..aede991 100644 (file)
@@ -246,8 +246,7 @@ static void cleanup_service_irqs(struct pci_dev *dev)
  */
 static int get_port_device_capability(struct pci_dev *dev)
 {
-       int services = 0, pos;
-       u16 reg16;
+       int services = 0;
        u32 reg32;
        int cap_mask = 0;
        int err;
@@ -265,11 +264,9 @@ static int get_port_device_capability(struct pci_dev *dev)
                        return 0;
        }
 
-       pos = pci_pcie_cap(dev);
-       pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
        /* Hot-Plug Capable */
-       if ((cap_mask & PCIE_PORT_SERVICE_HP) && (reg16 & PCI_EXP_FLAGS_SLOT)) {
-               pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, &reg32);
+       if (cap_mask & PCIE_PORT_SERVICE_HP) {
+               pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, &reg32);
                if (reg32 & PCI_EXP_SLTCAP_HPC) {
                        services |= PCIE_PORT_SERVICE_HP;
                        /*
@@ -277,10 +274,8 @@ static int get_port_device_capability(struct pci_dev *dev)
                         * enabled by the BIOS and the hot-plug service driver
                         * is not loaded.
                         */
-                       pos += PCI_EXP_SLTCTL;
-                       pci_read_config_word(dev, pos, &reg16);
-                       reg16 &= ~(PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE);
-                       pci_write_config_word(dev, pos, reg16);
+                       pcie_capability_clear_word(dev, PCI_EXP_SLTCTL,
+                               PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE);
                }
        }
        /* AER capable */
@@ -298,7 +293,7 @@ static int get_port_device_capability(struct pci_dev *dev)
                services |= PCIE_PORT_SERVICE_VC;
        /* Root ports are capable of generating PME too */
        if ((cap_mask & PCIE_PORT_SERVICE_PME)
-           && dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
+           && pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) {
                services |= PCIE_PORT_SERVICE_PME;
                /*
                 * Disable PME interrupt on this port in case it's been enabled
@@ -336,7 +331,7 @@ static int pcie_device_init(struct pci_dev *pdev, int service, int irq)
        device->release = release_pcie_device;  /* callback to free pcie dev */
        dev_set_name(device, "%s:pcie%02x",
                     pci_name(pdev),
-                    get_descriptor_id(pdev->pcie_type, service));
+                    get_descriptor_id(pci_pcie_type(pdev), service));
        device->parent = &pdev->dev;
        device_enable_async_suspend(device);
 
index 3a7eefc..b0340bc 100644 (file)
@@ -64,14 +64,7 @@ __setup("pcie_ports=", pcie_port_setup);
  */
 void pcie_clear_root_pme_status(struct pci_dev *dev)
 {
-       int rtsta_pos;
-       u32 rtsta;
-
-       rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA;
-
-       pci_read_config_dword(dev, rtsta_pos, &rtsta);
-       rtsta |= PCI_EXP_RTSTA_PME;
-       pci_write_config_dword(dev, rtsta_pos, rtsta);
+       pcie_capability_set_dword(dev, PCI_EXP_RTSTA, PCI_EXP_RTSTA_PME);
 }
 
 static int pcie_portdrv_restore_config(struct pci_dev *dev)
@@ -95,7 +88,7 @@ static int pcie_port_resume_noirq(struct device *dev)
         * which breaks ACPI-based runtime wakeup on PCI Express, so clear those
         * bits now just in case (shouldn't hurt).
         */
-       if(pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
+       if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT)
                pcie_clear_root_pme_status(pdev);
        return 0;
 }
@@ -140,9 +133,17 @@ static int pcie_port_runtime_resume(struct device *dev)
 {
        return 0;
 }
+
+static int pcie_port_runtime_idle(struct device *dev)
+{
+       /* Delay for a short while to prevent too frequent suspend/resume */
+       pm_schedule_suspend(dev, 10);
+       return -EBUSY;
+}
 #else
 #define pcie_port_runtime_suspend      NULL
 #define pcie_port_runtime_resume       NULL
+#define pcie_port_runtime_idle         NULL
 #endif
 
 static const struct dev_pm_ops pcie_portdrv_pm_ops = {
@@ -155,6 +156,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
        .resume_noirq   = pcie_port_resume_noirq,
        .runtime_suspend = pcie_port_runtime_suspend,
        .runtime_resume = pcie_port_runtime_resume,
+       .runtime_idle   = pcie_port_runtime_idle,
 };
 
 #define PCIE_PORTDRV_PM_OPS    (&pcie_portdrv_pm_ops)
@@ -186,9 +188,9 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
        int status;
 
        if (!pci_is_pcie(dev) ||
-           ((dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
-            (dev->pcie_type != PCI_EXP_TYPE_UPSTREAM) &&
-            (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)))
+           ((pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) &&
+            (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM) &&
+            (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)))
                return -ENODEV;
 
        if (!dev->irq && dev->pin) {
@@ -200,6 +202,11 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
                return status;
 
        pci_save_state(dev);
+       /*
+        * D3cold may not work properly on some PCIe port, so disable
+        * it by default.
+        */
+       dev->d3cold_allowed = false;
        if (!pci_match_id(port_runtime_pm_black_list, dev))
                pm_runtime_put_noidle(&dev->dev);
 
index 6c143b4..3cdba8b 100644 (file)
@@ -144,15 +144,13 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar)
        case PCI_BASE_ADDRESS_MEM_TYPE_32:
                break;
        case PCI_BASE_ADDRESS_MEM_TYPE_1M:
-               dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n");
+               /* 1M mem BAR treated as 32-bit BAR */
                break;
        case PCI_BASE_ADDRESS_MEM_TYPE_64:
                flags |= IORESOURCE_MEM_64;
                break;
        default:
-               dev_warn(&dev->dev,
-                        "mem unknown type %x treated as 32-bit BAR\n",
-                        mem_type);
+               /* mem unknown type treated as 32-bit BAR */
                break;
        }
        return flags;
@@ -173,9 +171,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
        u32 l, sz, mask;
        u16 orig_cmd;
        struct pci_bus_region region;
+       bool bar_too_big = false, bar_disabled = false;
 
        mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
 
+       /* No printks while decoding is disabled! */
        if (!dev->mmio_always_on) {
                pci_read_config_word(dev, PCI_COMMAND, &orig_cmd);
                pci_write_config_word(dev, PCI_COMMAND,
@@ -240,8 +240,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                        goto fail;
 
                if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) {
-                       dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n",
-                               pos);
+                       bar_too_big = true;
                        goto fail;
                }
 
@@ -252,12 +251,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                        region.start = 0;
                        region.end = sz64;
                        pcibios_bus_to_resource(dev, res, &region);
+                       bar_disabled = true;
                } else {
                        region.start = l64;
                        region.end = l64 + sz64;
                        pcibios_bus_to_resource(dev, res, &region);
-                       dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n",
-                                  pos, res);
                }
        } else {
                sz = pci_size(l, sz, mask);
@@ -268,18 +266,23 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                region.start = l;
                region.end = l + sz;
                pcibios_bus_to_resource(dev, res, &region);
-
-               dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
        }
 
- out:
+       goto out;
+
+
+fail:
+       res->flags = 0;
+out:
        if (!dev->mmio_always_on)
                pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
 
+       if (bar_too_big)
+               dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos);
+       if (res->flags && !bar_disabled)
+               dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
+
        return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
- fail:
-       res->flags = 0;
-       goto out;
 }
 
 static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
@@ -603,10 +606,10 @@ static void pci_set_bus_speed(struct pci_bus *bus)
                u32 linkcap;
                u16 linksta;
 
-               pci_read_config_dword(bridge, pos + PCI_EXP_LNKCAP, &linkcap);
+               pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap);
                bus->max_bus_speed = pcie_link_speed[linkcap & 0xf];
 
-               pci_read_config_word(bridge, pos + PCI_EXP_LNKSTA, &linksta);
+               pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta);
                pcie_update_link_speed(bus, linksta);
        }
 }
@@ -929,24 +932,16 @@ void set_pcie_port_type(struct pci_dev *pdev)
        pdev->is_pcie = 1;
        pdev->pcie_cap = pos;
        pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
-       pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4;
+       pdev->pcie_flags_reg = reg16;
        pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, &reg16);
        pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD;
 }
 
 void set_pcie_hotplug_bridge(struct pci_dev *pdev)
 {
-       int pos;
-       u16 reg16;
        u32 reg32;
 
-       pos = pci_pcie_cap(pdev);
-       if (!pos)
-               return;
-       pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
-       if (!(reg16 & PCI_EXP_FLAGS_SLOT))
-               return;
-       pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &reg32);
+       pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &reg32);
        if (reg32 & PCI_EXP_SLTCAP_HPC)
                pdev->is_hotplug_bridge = 1;
 }
@@ -1160,8 +1155,7 @@ int pci_cfg_space_size(struct pci_dev *dev)
        if (class == PCI_CLASS_BRIDGE_HOST)
                return pci_cfg_space_size_ext(dev);
 
-       pos = pci_pcie_cap(dev);
-       if (!pos) {
+       if (!pci_is_pcie(dev)) {
                pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
                if (!pos)
                        goto fail;
@@ -1383,9 +1377,9 @@ static int only_one_child(struct pci_bus *bus)
 
        if (!parent || !pci_is_pcie(parent))
                return 0;
-       if (parent->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
+       if (pci_pcie_type(parent) == PCI_EXP_TYPE_ROOT_PORT)
                return 1;
-       if (parent->pcie_type == PCI_EXP_TYPE_DOWNSTREAM &&
+       if (pci_pcie_type(parent) == PCI_EXP_TYPE_DOWNSTREAM &&
            !pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS))
                return 1;
        return 0;
@@ -1462,7 +1456,7 @@ static int pcie_find_smpss(struct pci_dev *dev, void *data)
         */
        if (dev->is_hotplug_bridge && (!list_is_singular(&dev->bus->devices) ||
             (dev->bus->self &&
-             dev->bus->self->pcie_type != PCI_EXP_TYPE_ROOT_PORT)))
+             pci_pcie_type(dev->bus->self) != PCI_EXP_TYPE_ROOT_PORT)))
                *smpss = 0;
 
        if (*smpss > dev->pcie_mpss)
@@ -1478,7 +1472,8 @@ static void pcie_write_mps(struct pci_dev *dev, int mps)
        if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
                mps = 128 << dev->pcie_mpss;
 
-               if (dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && dev->bus->self)
+               if (pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT &&
+                   dev->bus->self)
                        /* For "Performance", the assumption is made that
                         * downstream communication will never be larger than
                         * the MRRS.  So, the MPS only needs to be configured
index 5155317..7a451ff 100644 (file)
@@ -3081,17 +3081,36 @@ static int reset_intel_generic_dev(struct pci_dev *dev, int probe)
 
 static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe)
 {
-       int pos;
+       int i;
+       u16 status;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
-       if (!pos)
-               return -ENOTTY;
+       /*
+        * http://www.intel.com/content/dam/doc/datasheet/82599-10-gbe-controller-datasheet.pdf
+        *
+        * The 82599 supports FLR on VFs, but FLR support is reported only
+        * in the PF DEVCAP (sec 9.3.10.4), not in the VF DEVCAP (sec 9.5).
+        * Therefore, we can't use pcie_flr(), which checks the VF DEVCAP.
+        */
 
        if (probe)
                return 0;
 
-       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL,
-                               PCI_EXP_DEVCTL_BCR_FLR);
+       /* Wait for Transaction Pending bit clean */
+       for (i = 0; i < 4; i++) {
+               if (i)
+                       msleep((1 << (i - 1)) * 100);
+
+               pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status);
+               if (!(status & PCI_EXP_DEVSTA_TRPND))
+                       goto clear;
+       }
+
+       dev_err(&dev->dev, "transaction is not cleared; "
+                       "proceeding with reset anyway\n");
+
+clear:
+       pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
+
        msleep(100);
 
        return 0;
index 993d4a0..621b162 100644 (file)
@@ -41,7 +41,7 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
                        continue;
                }
                /* PCI device should connect to a PCIe bridge */
-               if (pdev->pcie_type != PCI_EXP_TYPE_PCI_BRIDGE) {
+               if (pci_pcie_type(pdev) != PCI_EXP_TYPE_PCI_BRIDGE) {
                        /* Busted hardware? */
                        WARN_ON_ONCE(1);
                        return NULL;
index fb50613..1e808ca 100644 (file)
@@ -697,6 +697,38 @@ static resource_size_t calculate_memsize(resource_size_t size,
        return size;
 }
 
+resource_size_t __weak pcibios_window_alignment(struct pci_bus *bus,
+                                               unsigned long type)
+{
+       return 1;
+}
+
+#define PCI_P2P_DEFAULT_MEM_ALIGN      0x100000        /* 1MiB */
+#define PCI_P2P_DEFAULT_IO_ALIGN       0x1000          /* 4KiB */
+#define PCI_P2P_DEFAULT_IO_ALIGN_1K    0x400           /* 1KiB */
+
+static resource_size_t window_alignment(struct pci_bus *bus,
+                                       unsigned long type)
+{
+       resource_size_t align = 1, arch_align;
+
+       if (type & IORESOURCE_MEM)
+               align = PCI_P2P_DEFAULT_MEM_ALIGN;
+       else if (type & IORESOURCE_IO) {
+               /*
+                * Per spec, I/O windows are 4K-aligned, but some
+                * bridges have an extension to support 1K alignment.
+                */
+               if (bus->self->io_window_1k)
+                       align = PCI_P2P_DEFAULT_IO_ALIGN_1K;
+               else
+                       align = PCI_P2P_DEFAULT_IO_ALIGN;
+       }
+
+       arch_align = pcibios_window_alignment(bus, type);
+       return max(align, arch_align);
+}
+
 /**
  * pbus_size_io() - size the io window of a given bus
  *
@@ -717,17 +749,12 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
        struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
        unsigned long size = 0, size0 = 0, size1 = 0;
        resource_size_t children_add_size = 0;
-       resource_size_t min_align = 4096, align;
+       resource_size_t min_align, io_align, align;
 
        if (!b_res)
                return;
 
-       /*
-        * Per spec, I/O windows are 4K-aligned, but some bridges have an
-        * extension to support 1K alignment.
-        */
-       if (bus->self->io_window_1k)
-               min_align = 1024;
+       io_align = min_align = window_alignment(bus, IORESOURCE_IO);
        list_for_each_entry(dev, &bus->devices, bus_list) {
                int i;
 
@@ -754,8 +781,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
                }
        }
 
-       if (min_align > 4096)
-               min_align = 4096;
+       if (min_align > io_align)
+               min_align = io_align;
 
        size0 = calculate_iosize(size, min_size, size1,
                        resource_size(b_res), min_align);
@@ -785,6 +812,28 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
        }
 }
 
+static inline resource_size_t calculate_mem_align(resource_size_t *aligns,
+                                                 int max_order)
+{
+       resource_size_t align = 0;
+       resource_size_t min_align = 0;
+       int order;
+
+       for (order = 0; order <= max_order; order++) {
+               resource_size_t align1 = 1;
+
+               align1 <<= (order + 20);
+
+               if (!align)
+                       min_align = align1;
+               else if (ALIGN(align + min_align, min_align) < align1)
+                       min_align = align1 >> 1;
+               align += aligns[order];
+       }
+
+       return min_align;
+}
+
 /**
  * pbus_size_mem() - size the memory window of a given bus
  *
@@ -864,19 +913,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
                                children_add_size += get_res_add_size(realloc_head, r);
                }
        }
-       align = 0;
-       min_align = 0;
-       for (order = 0; order <= max_order; order++) {
-               resource_size_t align1 = 1;
 
-               align1 <<= (order + 20);
-
-               if (!align)
-                       min_align = align1;
-               else if (ALIGN(align + min_align, min_align) < align1)
-                       min_align = align1 >> 1;
-               align += aligns[order];
-       }
+       min_align = calculate_mem_align(aligns, max_order);
+       min_align = max(min_align, window_alignment(bus, b_res->flags & mask));
        size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
        if (children_add_size > add_size)
                add_size = children_add_size;
index 5d44252..d5e1625 100644 (file)
@@ -2219,9 +2219,7 @@ static int __devinit tsi721_probe(struct pci_dev *pdev,
                                  const struct pci_device_id *id)
 {
        struct tsi721_device *priv;
-       int cap;
        int err;
-       u32 regval;
 
        priv = kzalloc(sizeof(struct tsi721_device), GFP_KERNEL);
        if (priv == NULL) {
@@ -2330,20 +2328,16 @@ static int __devinit tsi721_probe(struct pci_dev *pdev,
                        dev_info(&pdev->dev, "Unable to set consistent DMA mask\n");
        }
 
-       cap = pci_pcie_cap(pdev);
-       BUG_ON(cap == 0);
+       BUG_ON(!pci_is_pcie(pdev));
 
        /* Clear "no snoop" and "relaxed ordering" bits, use default MRRS. */
-       pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL, &regval);
-       regval &= ~(PCI_EXP_DEVCTL_READRQ | PCI_EXP_DEVCTL_RELAX_EN |
-                   PCI_EXP_DEVCTL_NOSNOOP_EN);
-       regval |= 0x2 << MAX_READ_REQUEST_SZ_SHIFT;
-       pci_write_config_dword(pdev, cap + PCI_EXP_DEVCTL, regval);
+       pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
+               PCI_EXP_DEVCTL_READRQ | PCI_EXP_DEVCTL_RELAX_EN |
+               PCI_EXP_DEVCTL_NOSNOOP_EN,
+               0x2 << MAX_READ_REQUEST_SZ_SHIFT);
 
        /* Adjust PCIe completion timeout. */
-       pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL2, &regval);
-       regval &= ~(0x0f);
-       pci_write_config_dword(pdev, cap + PCI_EXP_DEVCTL2, regval | 0x2);
+       pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL2, 0xf, 0x2);
 
        /*
         * FIXUP: correct offsets of MSI-X tables in the MSI-X Capability Block
index 8318689..1dd61f4 100644 (file)
@@ -58,6 +58,7 @@ struct sam9_rtc {
        struct rtc_device       *rtcdev;
        u32                     imr;
        void __iomem            *gpbr;
+       int                     irq;
 };
 
 #define rtt_readl(rtc, field) \
@@ -292,7 +293,7 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev)
 {
        struct resource *r, *r_gpbr;
        struct sam9_rtc *rtc;
-       int             ret;
+       int             ret, irq;
        u32             mr;
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -302,10 +303,18 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "failed to get interrupt resource\n");
+               return irq;
+       }
+
        rtc = kzalloc(sizeof *rtc, GFP_KERNEL);
        if (!rtc)
                return -ENOMEM;
 
+       rtc->irq = irq;
+
        /* platform setup code should have handled this; sigh */
        if (!device_can_wakeup(&pdev->dev))
                device_init_wakeup(&pdev->dev, 1);
@@ -345,11 +354,10 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev)
        }
 
        /* register irq handler after we know what name we'll use */
-       ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
-                               IRQF_SHARED,
+       ret = request_irq(rtc->irq, at91_rtc_interrupt, IRQF_SHARED,
                                dev_name(&rtc->rtcdev->dev), rtc);
        if (ret) {
-               dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS);
+               dev_dbg(&pdev->dev, "can't share IRQ %d?\n", rtc->irq);
                rtc_device_unregister(rtc->rtcdev);
                goto fail_register;
        }
@@ -386,7 +394,7 @@ static int __devexit at91_rtc_remove(struct platform_device *pdev)
 
        /* disable all interrupts */
        rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
-       free_irq(AT91_ID_SYS, rtc);
+       free_irq(rtc->irq, rtc);
 
        rtc_device_unregister(rtc->rtcdev);
 
@@ -423,7 +431,7 @@ static int at91_rtc_suspend(struct platform_device *pdev,
        rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
        if (rtc->imr) {
                if (device_may_wakeup(&pdev->dev) && (mr & AT91_RTT_ALMIEN)) {
-                       enable_irq_wake(AT91_ID_SYS);
+                       enable_irq_wake(rtc->irq);
                        /* don't let RTTINC cause wakeups */
                        if (mr & AT91_RTT_RTTINCIEN)
                                rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN);
@@ -441,7 +449,7 @@ static int at91_rtc_resume(struct platform_device *pdev)
 
        if (rtc->imr) {
                if (device_may_wakeup(&pdev->dev))
-                       disable_irq_wake(AT91_ID_SYS);
+                       disable_irq_wake(rtc->irq);
                mr = rtt_readl(rtc, MR);
                rtt_writel(rtc, MR, mr | rtc->imr);
        }
index 9ce3a8f..7cfdf2b 100644 (file)
@@ -1615,13 +1615,11 @@ qla82xx_get_fw_offs(struct qla_hw_data *ha)
 char *
 qla82xx_pci_info_str(struct scsi_qla_host *vha, char *str)
 {
-       int pcie_reg;
        struct qla_hw_data *ha = vha->hw;
        char lwstr[6];
        uint16_t lnk;
 
-       pcie_reg = pci_pcie_cap(ha->pdev);
-       pci_read_config_word(ha->pdev, pcie_reg + PCI_EXP_LNKSTA, &lnk);
+       pcie_capability_read_word(ha->pdev, PCI_EXP_LNKSTA, &lnk);
        ha->link_width = (lnk >> 4) & 0x3f;
 
        strcpy(str, "PCIe (");
@@ -2497,7 +2495,6 @@ fw_load_failed:
 int
 qla82xx_start_firmware(scsi_qla_host_t *vha)
 {
-       int           pcie_cap;
        uint16_t      lnk;
        struct qla_hw_data *ha = vha->hw;
 
@@ -2528,8 +2525,7 @@ qla82xx_start_firmware(scsi_qla_host_t *vha)
        }
 
        /* Negotiated Link width */
-       pcie_cap = pci_pcie_cap(ha->pdev);
-       pci_read_config_word(ha->pdev, pcie_cap + PCI_EXP_LNKSTA, &lnk);
+       pcie_capability_read_word(ha->pdev, PCI_EXP_LNKSTA, &lnk);
        ha->link_width = (lnk >> 4) & 0x3f;
 
        /* Synchronize with Receive peg */
index 939d726..807bf76 100644 (file)
@@ -1566,7 +1566,6 @@ qla4_8xxx_set_qsnt_ready(struct scsi_qla_host *ha)
 static int
 qla4_8xxx_start_firmware(struct scsi_qla_host *ha, uint32_t image_start)
 {
-       int pcie_cap;
        uint16_t lnk;
 
        /* scrub dma mask expansion register */
@@ -1590,8 +1589,7 @@ qla4_8xxx_start_firmware(struct scsi_qla_host *ha, uint32_t image_start)
        }
 
        /* Negotiated Link width */
-       pcie_cap = pci_pcie_cap(ha->pdev);
-       pci_read_config_word(ha->pdev, pcie_cap + PCI_EXP_LNKSTA, &lnk);
+       pcie_capability_read_word(ha->pdev, PCI_EXP_LNKSTA, &lnk);
        ha->link_width = (lnk >> 4) & 0x3f;
 
        /* Synchronize with Receive peg */
index 029725c..49553f8 100644 (file)
@@ -3995,16 +3995,14 @@ static void et131x_hwaddr_init(struct et131x_adapter *adapter)
 static int et131x_pci_init(struct et131x_adapter *adapter,
                                                struct pci_dev *pdev)
 {
-       int cap = pci_pcie_cap(pdev);
        u16 max_payload;
-       u16 ctl;
        int i, rc;
 
        rc = et131x_init_eeprom(adapter);
        if (rc < 0)
                goto out;
 
-       if (!cap) {
+       if (!pci_is_pcie(pdev)) {
                dev_err(&pdev->dev, "Missing PCIe capabilities\n");
                goto err_out;
        }
@@ -4012,7 +4010,7 @@ static int et131x_pci_init(struct et131x_adapter *adapter,
        /* Let's set up the PORT LOGIC Register.  First we need to know what
         * the max_payload_size is
         */
-       if (pci_read_config_word(pdev, cap + PCI_EXP_DEVCAP, &max_payload)) {
+       if (pcie_capability_read_word(pdev, PCI_EXP_DEVCAP, &max_payload)) {
                dev_err(&pdev->dev,
                    "Could not read PCI config space for Max Payload Size\n");
                goto err_out;
@@ -4049,17 +4047,10 @@ static int et131x_pci_init(struct et131x_adapter *adapter,
        }
 
        /* Change the max read size to 2k */
-       if (pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl)) {
+       if (pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
+                               PCI_EXP_DEVCTL_READRQ, 0x4 << 12)) {
                dev_err(&pdev->dev,
-                       "Could not read PCI config space for Max read size\n");
-               goto err_out;
-       }
-
-       ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | (0x04 << 12);
-
-       if (pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl)) {
-               dev_err(&pdev->dev,
-                     "Could not write PCI config space for Max read size\n");
+                       "Couldn't change PCI config space for Max read size\n");
                goto err_out;
        }
 
index ddadcc3..5abbee3 100644 (file)
@@ -31,12 +31,10 @@ static void rtl8192_parse_pci_configuration(struct pci_dev *pdev,
        struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
 
        u8 tmp;
-       int pos;
-       u8 LinkCtrlReg;
+       u16 LinkCtrlReg;
 
-       pos = pci_find_capability(priv->pdev, PCI_CAP_ID_EXP);
-       pci_read_config_byte(priv->pdev, pos + PCI_EXP_LNKCTL, &LinkCtrlReg);
-       priv->NdisAdapter.LinkCtrlReg = LinkCtrlReg;
+       pcie_capability_read_word(priv->pdev, PCI_EXP_LNKCTL, &LinkCtrlReg);
+       priv->NdisAdapter.LinkCtrlReg = (u8)LinkCtrlReg;
 
        RT_TRACE(COMP_INIT, "Link Control Register =%x\n",
                 priv->NdisAdapter.LinkCtrlReg);
index 77da6a2..c03ecdd 100644 (file)
@@ -987,7 +987,6 @@ err_regfb:
        fb_dealloc_cmap(&info->cmap);
 err_cmap:
        fb_deferred_io_cleanup(info);
-       kfree(info->fbdefio);
 err_defio:
        vfree((void *)info->screen_base);
 err_irq:
@@ -1022,7 +1021,6 @@ int  __devexit auok190x_common_remove(struct platform_device *pdev)
        fb_dealloc_cmap(&info->cmap);
 
        fb_deferred_io_cleanup(info);
-       kfree(info->fbdefio);
 
        vfree((void *)info->screen_base);
 
index 28b1a83..61b182b 100644 (file)
@@ -162,7 +162,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
        image.depth = 1;
 
        if (attribute) {
-               buf = kmalloc(cellsize, GFP_KERNEL);
+               buf = kmalloc(cellsize, GFP_ATOMIC);
                if (!buf)
                        return;
        }
index 88e9204..fdefa8f 100644 (file)
@@ -449,7 +449,7 @@ static int __init fb_console_setup(char *this_opt)
 
        while ((options = strsep(&this_opt, ",")) != NULL) {
                if (!strncmp(options, "font:", 5))
-                       strcpy(fontname, options + 5);
+                       strlcpy(fontname, options + 5, sizeof(fontname));
                
                if (!strncmp(options, "scrollback:", 11)) {
                        options += 11;
index 00ce1f3..57d940b 100644 (file)
@@ -328,6 +328,8 @@ static int mb862xxfb_ioctl(struct fb_info *fbi, unsigned int cmd,
        case MB862XX_L1_SET_CFG:
                if (copy_from_user(l1_cfg, argp, sizeof(*l1_cfg)))
                        return -EFAULT;
+               if (l1_cfg->dh == 0 || l1_cfg->dw == 0)
+                       return -EINVAL;
                if ((l1_cfg->sw >= l1_cfg->dw) && (l1_cfg->sh >= l1_cfg->dh)) {
                        /* downscaling */
                        outreg(cap, GC_CAP_CSC,
index 5d31699..f43bfe1 100644 (file)
@@ -105,6 +105,20 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 
        sdi_config_lcd_manager(dssdev);
 
+       /*
+        * LCLK and PCLK divisors are located in shadow registers, and we
+        * normally write them to DISPC registers when enabling the output.
+        * However, SDI uses pck-free as source clock for its PLL, and pck-free
+        * is affected by the divisors. And as we need the PLL before enabling
+        * the output, we need to write the divisors early.
+        *
+        * It seems just writing to the DISPC register is enough, and we don't
+        * need to care about the shadow register mechanism for pck-free. The
+        * exact reason for this is unknown.
+        */
+       dispc_mgr_set_clock_div(dssdev->manager->id,
+                       &sdi.mgr_config.clock_info);
+
        dss_sdi_init(dssdev->phy.sdi.datapairs);
        r = dss_sdi_enable();
        if (r)
index 08ec1a7..fc671d3 100644 (file)
@@ -1192,7 +1192,7 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
                        break;
 
                if (regno < 16) {
-                       u16 pal;
+                       u32 pal;
                        pal = ((red >> (16 - var->red.length)) <<
                                        var->red.offset) |
                                ((green >> (16 - var->green.length)) <<
index 1afb4fb..4d51948 100644 (file)
@@ -232,7 +232,7 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
                return ret;
 
        if (hwdev && hwdev->coherent_dma_mask)
-               dma_mask = hwdev->coherent_dma_mask;
+               dma_mask = dma_alloc_coherent_mask(hwdev, flags);
 
        phys = virt_to_phys(ret);
        dev_addr = xen_phys_to_bus(phys);
index 097e536..0334272 100644 (file)
@@ -353,16 +353,16 @@ static int __devinit pcistub_init_device(struct pci_dev *dev)
        if (err)
                goto config_release;
 
-       dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n");
-       __pci_reset_function_locked(dev);
-
        /* We need the device active to save the state. */
        dev_dbg(&dev->dev, "save state of device\n");
        pci_save_state(dev);
        dev_data->pci_saved_state = pci_store_saved_state(dev);
        if (!dev_data->pci_saved_state)
                dev_err(&dev->dev, "Could not store PCI conf saved state!\n");
-
+       else {
+               dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n");
+               __pci_reset_function_locked(dev);
+       }
        /* Now disable the device (this also ensures some private device
         * data is setup before we export)
         */
index 6043821..594b419 100644 (file)
        __x - (__x % (y));                              \
 }                                                      \
 )
+
+/*
+ * Divide positive or negative dividend by positive divisor and round
+ * to closest integer. Result is undefined for negative divisors.
+ */
 #define DIV_ROUND_CLOSEST(x, divisor)(                 \
 {                                                      \
-       typeof(divisor) __divisor = divisor;            \
-       (((x) + ((__divisor) / 2)) / (__divisor));      \
+       typeof(x) __x = x;                              \
+       typeof(divisor) __d = divisor;                  \
+       (((typeof(x))-1) >= 0 || (__x) >= 0) ?          \
+               (((__x) + ((__d) / 2)) / (__d)) :       \
+               (((__x) - ((__d) / 2)) / (__d));        \
 }                                                      \
 )
 
index 111aca5..4b27f9f 100644 (file)
@@ -239,6 +239,7 @@ struct mmc_card {
 #define MMC_QUIRK_BLK_NO_CMD23 (1<<7)          /* Avoid CMD23 for regular multiblock */
 #define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8)  /* Avoid sending 512 bytes in */
 #define MMC_QUIRK_LONG_READ_TIME (1<<9)                /* Data read time > CSD says */
+#define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10)        /* Skip secure for erase/trim */
                                                /* byte mode */
        unsigned int    poweroff_notify_state;  /* eMMC4.5 notify feature */
 #define MMC_NO_POWER_NOTIFICATION      0
index 5faa831..2c75524 100644 (file)
@@ -254,10 +254,10 @@ struct pci_dev {
        u8              revision;       /* PCI revision, low byte of class word */
        u8              hdr_type;       /* PCI header type (`multi' flag masked out) */
        u8              pcie_cap;       /* PCI-E capability offset */
-       u8              pcie_type:4;    /* PCI-E device/port type */
        u8              pcie_mpss:3;    /* PCI-E Max Payload Size Supported */
        u8              rom_base_reg;   /* which config register controls the ROM */
        u8              pin;            /* which interrupt pin this device uses */
+       u16             pcie_flags_reg; /* cached PCI-E Capabilities Register */
 
        struct pci_driver *driver;      /* which driver has allocated this device */
        u64             dma_mask;       /* Mask of the bits of bus address this
@@ -816,6 +816,39 @@ static inline int pci_write_config_dword(const struct pci_dev *dev, int where,
        return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
 }
 
+int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val);
+int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val);
+int pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val);
+int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val);
+int pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos,
+                                      u16 clear, u16 set);
+int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos,
+                                       u32 clear, u32 set);
+
+static inline int pcie_capability_set_word(struct pci_dev *dev, int pos,
+                                          u16 set)
+{
+       return pcie_capability_clear_and_set_word(dev, pos, 0, set);
+}
+
+static inline int pcie_capability_set_dword(struct pci_dev *dev, int pos,
+                                           u32 set)
+{
+       return pcie_capability_clear_and_set_dword(dev, pos, 0, set);
+}
+
+static inline int pcie_capability_clear_word(struct pci_dev *dev, int pos,
+                                            u16 clear)
+{
+       return pcie_capability_clear_and_set_word(dev, pos, clear, 0);
+}
+
+static inline int pcie_capability_clear_dword(struct pci_dev *dev, int pos,
+                                             u32 clear)
+{
+       return pcie_capability_clear_and_set_dword(dev, pos, clear, 0);
+}
+
 /* user-space driven config access */
 int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
 int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
@@ -1031,6 +1064,8 @@ int pci_cfg_space_size_ext(struct pci_dev *dev);
 int pci_cfg_space_size(struct pci_dev *dev);
 unsigned char pci_bus_max_busnr(struct pci_bus *bus);
 void pci_setup_bridge(struct pci_bus *bus);
+resource_size_t pcibios_window_alignment(struct pci_bus *bus,
+                                        unsigned long type);
 
 #define PCI_VGA_STATE_CHANGE_BRIDGE (1 << 0)
 #define PCI_VGA_STATE_CHANGE_DECODES (1 << 1)
@@ -1650,6 +1685,15 @@ static inline bool pci_is_pcie(struct pci_dev *dev)
        return !!pci_pcie_cap(dev);
 }
 
+/**
+ * pci_pcie_type - get the PCIe device/port type
+ * @dev: PCI device
+ */
+static inline int pci_pcie_type(const struct pci_dev *dev)
+{
+       return (dev->pcie_flags_reg & PCI_EXP_FLAGS_TYPE) >> 4;
+}
+
 void pci_request_acs(void);
 bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags);
 bool pci_acs_path_enabled(struct pci_dev *start,
index 7fb75b1..3958f70 100644 (file)
 #define  PCI_EXP_LNKCAP2_SLS_8_0GB 0x04        /* Current Link Speed 8.0GT/s */
 #define  PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */
 #define PCI_EXP_LNKCTL2                48      /* Link Control 2 */
+#define PCI_EXP_LNKSTA2                50      /* Link Status 2 */
 #define PCI_EXP_SLTCTL2                56      /* Slot Control 2 */
 
 /* Extended Capabilities (PCI-X 2.0 and Express) */
index bd92431..4ada3be 100644 (file)
@@ -2562,7 +2562,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context)
                break;
 
        default:
-               BUG();
+               return -EINVAL;
        }
 
        l = strlen(policy_modes[mode]);
index a5471f8..edc3c4a 100644 (file)
@@ -2604,7 +2604,7 @@ static int do_siocgstamp(struct net *net, struct socket *sock,
        err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
        set_fs(old_fs);
        if (!err)
-               err = compat_put_timeval(up, &ktv);
+               err = compat_put_timeval(&ktv, up);
 
        return err;
 }
@@ -2620,7 +2620,7 @@ static int do_siocgstampns(struct net *net, struct socket *sock,
        err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
        set_fs(old_fs);
        if (!err)
-               err = compat_put_timespec(up, &kts);
+               err = compat_put_timespec(&kts, up);
 
        return err;
 }
index 6bf8e87..c3f69ae 100644 (file)
@@ -42,7 +42,7 @@ quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@)
 $(installed-fw-dirs):
        $(call cmd,mkdir)
 
-$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $(INSTALL_FW_PATH)/$$(dir %)
+$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $$(dir $(INSTALL_FW_PATH)/%)
        $(call cmd,install)
 
 PHONY +=  __fw_install __fw_modinst FORCE
index 4629038..4235a63 100644 (file)
@@ -211,7 +211,7 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
 
        if ! cmp -s System.map .tmp_System.map; then
                echo >&2 Inconsistent kallsyms data
-               echo >&2 echo Try "make KALLSYMS_EXTRA_PASS=1" as a workaround
+               echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround
                cleanup
                exit 1
        fi
index f560051..f25c24c 100644 (file)
@@ -1209,6 +1209,9 @@ static void snd_hda_codec_free(struct hda_codec *codec)
        kfree(codec);
 }
 
+static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec,
+                               hda_nid_t fg, unsigned int power_state);
+
 static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
                                unsigned int power_state);
 
@@ -1317,6 +1320,10 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
                                           AC_VERB_GET_SUBSYSTEM_ID, 0);
        }
 
+       codec->epss = snd_hda_codec_get_supported_ps(codec,
+                                       codec->afg ? codec->afg : codec->mfg,
+                                       AC_PWRST_EPSS);
+
        /* power-up all before initialization */
        hda_set_power_state(codec,
                            codec->afg ? codec->afg : codec->mfg,
@@ -3543,8 +3550,7 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
        /* this delay seems necessary to avoid click noise at power-down */
        if (power_state == AC_PWRST_D3) {
                /* transition time less than 10ms for power down */
-               bool epss = snd_hda_codec_get_supported_ps(codec, fg, AC_PWRST_EPSS);
-               msleep(epss ? 10 : 100);
+               msleep(codec->epss ? 10 : 100);
        }
 
        /* repeat power states setting at most 10 times*/
index 7fbc1bc..e5a7e19 100644 (file)
@@ -862,6 +862,7 @@ struct hda_codec {
        unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */
        unsigned int no_jack_detect:1;  /* Machine has no jack-detection */
        unsigned int pcm_format_first:1; /* PCM format must be set first */
+       unsigned int epss:1;            /* supporting EPSS? */
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        unsigned int power_on :1;       /* current (global) power-state */
        int power_transition;   /* power-state in transition */
index ea5775a..6f806d3 100644 (file)
@@ -4543,6 +4543,9 @@ static void stac92xx_line_out_detect(struct hda_codec *codec,
        struct auto_pin_cfg *cfg = &spec->autocfg;
        int i;
 
+       if (cfg->speaker_outs == 0)
+               return;
+
        for (i = 0; i < cfg->line_outs; i++) {
                if (presence)
                        break;
@@ -5531,6 +5534,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
                snd_hda_codec_set_pincfg(codec, 0xf, 0x2181205e);
        }
 
+       codec->epss = 0; /* longer delay needed for D3 */
        codec->no_trigger_sense = 1;
        codec->spec = spec;
 
index d5b5c33..4a469f0 100644 (file)
@@ -553,7 +553,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
                                     struct snd_usb_audio *chip)
 {
        struct snd_card *card;
-       struct list_head *p;
+       struct list_head *p, *n;
 
        if (chip == (void *)-1L)
                return;
@@ -570,7 +570,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
                        snd_usb_stream_disconnect(p);
                }
                /* release the endpoint resources */
-               list_for_each(p, &chip->ep_list) {
+               list_for_each_safe(p, n, &chip->ep_list) {
                        snd_usb_endpoint_free(p);
                }
                /* release the midi resources */
index c411812..d6e2bb4 100644 (file)
@@ -141,7 +141,7 @@ int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep)
  *
  * For implicit feedback, next_packet_size() is unused.
  */
-static int next_packet_size(struct snd_usb_endpoint *ep)
+int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep)
 {
        unsigned long flags;
        int ret;
@@ -177,15 +177,6 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep,
                ep->retire_data_urb(ep->data_subs, urb);
 }
 
-static void prepare_outbound_urb_sizes(struct snd_usb_endpoint *ep,
-                                      struct snd_urb_ctx *ctx)
-{
-       int i;
-
-       for (i = 0; i < ctx->packets; ++i)
-               ctx->packet_size[i] = next_packet_size(ep);
-}
-
 /*
  * Prepare a PLAYBACK urb for submission to the bus.
  */
@@ -370,7 +361,6 @@ static void snd_complete_urb(struct urb *urb)
                        goto exit_clear;
                }
 
-               prepare_outbound_urb_sizes(ep, ctx);
                prepare_outbound_urb(ep, ctx);
        } else {
                retire_inbound_urb(ep, ctx);
@@ -799,7 +789,9 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 /**
  * snd_usb_endpoint_start: start an snd_usb_endpoint
  *
- * @ep: the endpoint to start
+ * @ep:                the endpoint to start
+ * @can_sleep: flag indicating whether the operation is executed in
+ *             non-atomic context
  *
  * A call to this function will increment the use count of the endpoint.
  * In case it is not already running, the URBs for this endpoint will be
@@ -809,7 +801,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
  *
  * Returns an error if the URB submission failed, 0 in all other cases.
  */
-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
 {
        int err;
        unsigned int i;
@@ -821,6 +813,11 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
        if (++ep->use_count != 1)
                return 0;
 
+       /* just to be sure */
+       deactivate_urbs(ep, 0, can_sleep);
+       if (can_sleep)
+               wait_clear_urbs(ep);
+
        ep->active_mask = 0;
        ep->unlink_mask = 0;
        ep->phase = 0;
@@ -850,7 +847,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
                        goto __error;
 
                if (usb_pipeout(ep->pipe)) {
-                       prepare_outbound_urb_sizes(ep, urb->context);
                        prepare_outbound_urb(ep, urb->context);
                } else {
                        prepare_inbound_urb(ep, urb->context);
index ee2723f..cbbbdf2 100644 (file)
@@ -13,7 +13,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
                                struct audioformat *fmt,
                                struct snd_usb_endpoint *sync_ep);
 
-int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep);
+int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep);
 void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
                           int force, int can_sleep, int wait);
 int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
@@ -21,6 +21,7 @@ int  snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_free(struct list_head *head);
 
 int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep);
+int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep);
 
 void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
                             struct snd_usb_endpoint *sender,
index 62ec808..fd5e982 100644 (file)
@@ -212,7 +212,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
        }
 }
 
-static int start_endpoints(struct snd_usb_substream *subs)
+static int start_endpoints(struct snd_usb_substream *subs, int can_sleep)
 {
        int err;
 
@@ -225,7 +225,7 @@ static int start_endpoints(struct snd_usb_substream *subs)
                snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep);
 
                ep->data_subs = subs;
-               err = snd_usb_endpoint_start(ep);
+               err = snd_usb_endpoint_start(ep, can_sleep);
                if (err < 0) {
                        clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
                        return err;
@@ -236,10 +236,25 @@ static int start_endpoints(struct snd_usb_substream *subs)
            !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
                struct snd_usb_endpoint *ep = subs->sync_endpoint;
 
+               if (subs->data_endpoint->iface != subs->sync_endpoint->iface ||
+                   subs->data_endpoint->alt_idx != subs->sync_endpoint->alt_idx) {
+                       err = usb_set_interface(subs->dev,
+                                               subs->sync_endpoint->iface,
+                                               subs->sync_endpoint->alt_idx);
+                       if (err < 0) {
+                               snd_printk(KERN_ERR
+                                          "%d:%d:%d: cannot set interface (%d)\n",
+                                          subs->dev->devnum,
+                                          subs->sync_endpoint->iface,
+                                          subs->sync_endpoint->alt_idx, err);
+                               return -EIO;
+                       }
+               }
+
                snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep);
 
                ep->sync_slave = subs->data_endpoint;
-               err = snd_usb_endpoint_start(ep);
+               err = snd_usb_endpoint_start(ep, can_sleep);
                if (err < 0) {
                        clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
                        return err;
@@ -544,13 +559,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
        subs->last_frame_number = 0;
        runtime->delay = 0;
 
-       /* clear the pending deactivation on the target EPs */
-       deactivate_endpoints(subs);
-
        /* for playback, submit the URBs now; otherwise, the first hwptr_done
         * updates for all URBs would happen at the same time when starting */
        if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
-               return start_endpoints(subs);
+               return start_endpoints(subs, 1);
 
        return 0;
 }
@@ -1032,6 +1044,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
                                 struct urb *urb)
 {
        struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
+       struct snd_usb_endpoint *ep = subs->data_endpoint;
        struct snd_urb_ctx *ctx = urb->context;
        unsigned int counts, frames, bytes;
        int i, stride, period_elapsed = 0;
@@ -1043,7 +1056,11 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
        urb->number_of_packets = 0;
        spin_lock_irqsave(&subs->lock, flags);
        for (i = 0; i < ctx->packets; i++) {
-               counts = ctx->packet_size[i];
+               if (ctx->packet_size[i])
+                       counts = ctx->packet_size[i];
+               else
+                       counts = snd_usb_endpoint_next_packet_size(ep);
+
                /* set up descriptor */
                urb->iso_frame_desc[i].offset = frames * stride;
                urb->iso_frame_desc[i].length = counts * stride;
@@ -1094,7 +1111,16 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
        subs->hwptr_done += bytes;
        if (subs->hwptr_done >= runtime->buffer_size * stride)
                subs->hwptr_done -= runtime->buffer_size * stride;
+
+       /* update delay with exact number of samples queued */
+       runtime->delay = subs->last_delay;
        runtime->delay += frames;
+       subs->last_delay = runtime->delay;
+
+       /* realign last_frame_number */
+       subs->last_frame_number = usb_get_current_frame_number(subs->dev);
+       subs->last_frame_number &= 0xFF; /* keep 8 LSBs */
+
        spin_unlock_irqrestore(&subs->lock, flags);
        urb->transfer_buffer_length = bytes;
        if (period_elapsed)
@@ -1112,12 +1138,26 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
        struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
        int stride = runtime->frame_bits >> 3;
        int processed = urb->transfer_buffer_length / stride;
+       int est_delay;
 
        spin_lock_irqsave(&subs->lock, flags);
-       if (processed > runtime->delay)
-               runtime->delay = 0;
+       est_delay = snd_usb_pcm_delay(subs, runtime->rate);
+       /* update delay with exact number of samples played */
+       if (processed > subs->last_delay)
+               subs->last_delay = 0;
        else
-               runtime->delay -= processed;
+               subs->last_delay -= processed;
+       runtime->delay = subs->last_delay;
+
+       /*
+        * Report when delay estimate is off by more than 2ms.
+        * The error should be lower than 2ms since the estimate relies
+        * on two reads of a counter updated every ms.
+        */
+       if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
+               snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n",
+                       est_delay, subs->last_delay);
+
        spin_unlock_irqrestore(&subs->lock, flags);
 }
 
@@ -1175,7 +1215,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               err = start_endpoints(subs);
+               err = start_endpoints(subs, 0);
                if (err < 0)
                        return err;